diff --git a/.all-contributorsrc b/.all-contributorsrc index 4e9f44a082..8107ba2cd0 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -1650,6 +1650,168 @@ "contributions": [ "code" ] + }, + { + "login": "jwhulette", + "name": "Wes Hulette", + "avatar_url": "https://avatars1.githubusercontent.com/u/4930051?v=4", + "profile": "http://macfoo.wordpress.com/", + "contributions": [ + "code" + ] + }, + { + "login": "patrict", + "name": "patrict", + "avatar_url": "https://avatars0.githubusercontent.com/u/8134591?v=4", + "profile": "https://github.com/patrict", + "contributions": [ + "code" + ] + }, + { + "login": "VELIKII-DIVAN", + "name": "Dmitriy Minaev", + "avatar_url": "https://avatars3.githubusercontent.com/u/2611616?v=4", + "profile": "https://github.com/VELIKII-DIVAN", + "contributions": [ + "code" + ] + }, + { + "login": "liquidhorse", + "name": "liquidhorse", + "avatar_url": "https://avatars0.githubusercontent.com/u/5132245?v=4", + "profile": "https://github.com/liquidhorse", + "contributions": [ + "code" + ] + }, + { + "login": "Seldaek", + "name": "Jordi Boggiano", + "avatar_url": "https://avatars1.githubusercontent.com/u/183678?v=4", + "profile": "https://seld.be/", + "contributions": [ + "code" + ] + }, + { + "login": "inietov", + "name": "Ivan Nieto", + "avatar_url": "https://avatars0.githubusercontent.com/u/653557?v=4", + "profile": "https://github.com/inietov", + "contributions": [ + "code" + ] + }, + { + "login": "benrubson", + "name": "Ben RUBSON", + "avatar_url": "https://avatars2.githubusercontent.com/u/6764151?v=4", + "profile": "https://github.com/benrubson", + "contributions": [ + "code" + ] + }, + { + "login": "NMathar", + "name": "NMathar", + "avatar_url": "https://avatars2.githubusercontent.com/u/8554558?v=4", + "profile": "https://github.com/NMathar", + "contributions": [ + "code" + ] + }, + { + "login": "smb", + "name": "Steffen", + "avatar_url": "https://avatars1.githubusercontent.com/u/139566?v=4", + "profile": "https://github.com/smb", + "contributions": [ + "code" + ] + }, + { + "login": "Sxderp", + "name": "Sxderp", + "avatar_url": "https://avatars0.githubusercontent.com/u/6609453?v=4", + "profile": "https://github.com/Sxderp", + "contributions": [ + "code" + ] + }, + { + "login": "fanta8897", + "name": "fanta8897", + "avatar_url": "https://avatars1.githubusercontent.com/u/4807843?v=4", + "profile": "https://github.com/fanta8897", + "contributions": [ + "code" + ] + }, + { + "login": "andreybolonin", + "name": "Andrey Bolonin", + "avatar_url": "https://avatars2.githubusercontent.com/u/2576509?v=4", + "profile": "https://andreybolonin.com/phpconsulting/", + "contributions": [ + "code" + ] + }, + { + "login": "shinayoshi", + "name": "shinayoshi", + "avatar_url": "https://avatars3.githubusercontent.com/u/2173307?v=4", + "profile": "http://www.shinayoshi.net/", + "contributions": [ + "code" + ] + }, + { + "login": "reuser", + "name": "Hubert", + "avatar_url": "https://avatars3.githubusercontent.com/u/2130159?v=4", + "profile": "https://github.com/reuser", + "contributions": [ + "code" + ] + }, + { + "login": "KeenRivals", + "name": "KeenRivals", + "avatar_url": "https://avatars0.githubusercontent.com/u/6865789?v=4", + "profile": "https://brashear.me", + "contributions": [ + "code" + ] + }, + { + "login": "omyno", + "name": "omyno", + "avatar_url": "https://avatars3.githubusercontent.com/u/2902513?v=4", + "profile": "https://github.com/omyno", + "contributions": [ + "code" + ] + }, + { + "login": "jackka", + "name": "Evgeny", + "avatar_url": "https://avatars1.githubusercontent.com/u/6271335?v=4", + "profile": "https://github.com/jackka", + "contributions": [ + "code" + ] + }, + { + "login": "colin-campbell", + "name": "Colin Campbell", + "avatar_url": "https://avatars2.githubusercontent.com/u/1169963?v=4", + "profile": "https://digitalist.se", + "contributions": [ + "code" + ] } ] } diff --git a/.dockerignore b/.dockerignore index 23ec116755..89521f1d96 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,5 +1,13 @@ .git +.github +.gitattributes +.gitignore .dockerignore app/storage/logs/* app/storage/views/* vendor/* +storage/framework/cache/* +node_modules +.vagrant +.idea + diff --git a/.env.example b/.env.example index ae6cbe6b7e..347570b795 100644 --- a/.env.example +++ b/.env.example @@ -43,6 +43,8 @@ MAIL_FROM_ADDR=you@example.com MAIL_FROM_NAME='Snipe-IT' MAIL_REPLYTO_ADDR=you@example.com MAIL_REPLYTO_NAME='Snipe-IT' +MAIL_AUTO_EMBED=true +MAIL_AUTO_EMBED_METHOD=base64 # -------------------------------------------- # REQUIRED: IMAGE LIBRARY @@ -59,6 +61,7 @@ ENCRYPT=false COOKIE_NAME=snipeit_session COOKIE_DOMAIN=null SECURE_COOKIES=false +SESSION_PATH=null # -------------------------------------------- # OPTIONAL: SECURITY HEADER SETTINGS @@ -90,10 +93,12 @@ MEMCACHED_PORT=null # -------------------------------------------- # OPTIONAL: AWS S3 SETTINGS # -------------------------------------------- -AWS_SECRET=null -AWS_KEY=null -AWS_REGION=null +AWS_SECRET_ACCESS_KEY=null +AWS_ACCESS_KEY_ID=null +AWS_DEFAULT_REGION=null AWS_BUCKET=null +AWS_BUCKET_ROOT=null +AWS_URL=null # -------------------------------------------- # OPTIONAL: LOGIN THROTTLING @@ -106,7 +111,7 @@ LOGIN_LOCKOUT_DURATION=60 # -------------------------------------------- APP_LOG=single APP_LOG_MAX_FILES=10 -APP_LOCKED=false +APP_LOG_LEVEL=debug FILESYSTEM_DISK=local APP_TRUSTED_PROXIES=192.168.1.1,10.0.0.1 ALLOW_IFRAMING=false diff --git a/.env.testing b/.env.testing index f84dd82e9f..980f24f09e 100644 --- a/.env.testing +++ b/.env.testing @@ -40,10 +40,12 @@ IMAGE_LIB=gd # -------------------------------------------- # OPTIONAL: AWS S3 SETTINGS # -------------------------------------------- -AWS_SECRET=null -AWS_KEY=null -AWS_REGION=null +AWS_SECRET_ACCESS_KEY=null +AWS_ACCESS_KEY_ID=null +AWS_DEFAULT_REGION=null AWS_BUCKET=null +AWS_BUCKET_ROOT=null +AWS_URL=null # -------------------------------------------- diff --git a/.env.testing-ci b/.env.testing-ci index b12a99d442..978c1895a3 100644 --- a/.env.testing-ci +++ b/.env.testing-ci @@ -40,10 +40,12 @@ IMAGE_LIB=gd # -------------------------------------------- # OPTIONAL: AWS S3 SETTINGS # -------------------------------------------- -AWS_SECRET=null -AWS_KEY=null -AWS_REGION=null +AWS_SECRET_ACCESS_KEY=null +AWS_ACCESS_KEY_ID=null +AWS_DEFAULT_REGION=null AWS_BUCKET=null +AWS_BUCKET_ROOT=null +AWS_URL=null # -------------------------------------------- diff --git a/.github/config.yml b/.github/config.yml new file mode 100644 index 0000000000..67a78c7c26 --- /dev/null +++ b/.github/config.yml @@ -0,0 +1,33 @@ +# Configuration for new-issue-welcome - https://github.com/behaviorbot/new-issue-welcome + +# Comment to be posted to on first time issues +newIssueWelcomeComment: | + 👋 Thanks for opening your first issue here! If you're reporting a 🐞 bug, please make sure you include steps to reproduce it. We get a lot of issues on this repo, so please be patient and we will get back to you as soon as we can. + +# Configuration for new-pr-welcome - https://github.com/behaviorbot/new-pr-welcome + +# Comment to be posted to on PRs from first time contributors in your repository +newPRWelcomeComment: | + 💖 Thanks for this pull request! 💖 + + We use [semantic commit messages](https://snipe-it.readme.io/docs/contributing-overview#section-pull-request-guidelines) to streamline the release process and easily generate changelogs between versions. Before your pull request can be merged, you should **update your pull request title** to start with a semantic prefix if it doesn't have one already. + + Examples of commit messages with semantic prefixes: + + - `Fixed #: don't overwrite prevent_default if default wasn't prevented` + - `Added #: add checkout functionality to assets` + - `Improved Asset Checkout: use new notification method for checkout` + + Things that will help get your PR across the finish line: + + - Document any user-facing changes you've made. + - Include tests when adding/changing behavior. + - Include screenshots and animated GIFs whenever possible. + + We get a lot of pull requests on this repo, so please be patient and we will get back to you as soon as we can. + +# Configuration for first-pr-merge - https://github.com/behaviorbot/first-pr-merge + +# Comment to be posted to on pull requests merged by a first time user +firstPRMergeComment: > + Congrats on merging your first pull request! 🎉🎉🎉 diff --git a/.gitignore b/.gitignore index 5012c49a8f..c310b79d57 100755 --- a/.gitignore +++ b/.gitignore @@ -50,4 +50,10 @@ tests/_support/_generated/* /storage/oauth-public.key *.cache + +.vagrant + +\.php_cs\.dist + +phpmd\.xml /public/storage diff --git a/.travis.yml b/.travis.yml index 4012e16e4c..f112d46807 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,15 +14,11 @@ services: # list any PHP version you want to test against php: - - 5.6 - - 7.0 - - 7.1 + - 7.1.3 + - 7.1.4 - 7.2 - - 7.3 + - 7.3.0 -matrix: - allow_failures: - - php: 7.3 # execute any number of scripts before the test run, custom env's are available as variables before_script: @@ -33,6 +29,7 @@ before_script: - mysql -e 'CREATE USER "travis'@'localhost";' - mysql -e 'GRANT ALL PRIVILEGES ON * . * TO "travis'@'localhost";' - mysql -e 'FLUSH PRIVILEGES;' + - cp .env.testing-ci .env - composer self-update - composer install -n --prefer-source - chmod -R 777 storage diff --git a/Dockerfile b/Dockerfile index f13fa9ea61..46ad8682d1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,35 +1,58 @@ -FROM ubuntu:xenial -MAINTAINER Brady Wetherington +FROM ubuntu:bionic +LABEL maintainer Brady Wetherington -RUN apt-get update && apt-get install -y \ +RUN export DEBIAN_FRONTEND=noninteractive; \ + export DEBCONF_NONINTERACTIVE_SEEN=true; \ + echo 'tzdata tzdata/Areas select Etc' | debconf-set-selections; \ + echo 'tzdata tzdata/Zones/Etc select UTC' | debconf-set-selections; \ + apt-get update -qqy \ + && apt-get install -qqy --no-install-recommends \ +apt-utils \ apache2 \ apache2-bin \ -libapache2-mod-php7.0 \ -php7.0-curl \ -php7.0-ldap \ -php7.0-mysql \ -php7.0-mcrypt \ -php7.0-gd \ -php7.0-xml \ -php7.0-mbstring \ -php7.0-zip \ -php7.0-bcmath \ +libapache2-mod-php7.2 \ +php7.2-curl \ +php7.2-ldap \ +php7.2-mysql \ +php7.2-gd \ +php7.2-xml \ +php7.2-mbstring \ +php7.2-zip \ +php7.2-bcmath \ patch \ curl \ +wget \ vim \ git \ cron \ mysql-client \ cron \ +gcc \ +make \ +autoconf \ +libc-dev \ +pkg-config \ +libmcrypt-dev \ +php7.2-dev \ +ca-certificates \ +unzip \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* + +RUN curl -L -O https://github.com/pear/pearweb_phars/raw/master/go-pear.phar +RUN php go-pear.phar + +RUN pecl install mcrypt-1.0.2 + +RUN bash -c "echo extension=/usr/lib/php/20170718/mcrypt.so > /etc/php/7.2/mods-available/mcrypt.ini" + RUN phpenmod mcrypt RUN phpenmod gd RUN phpenmod bcmath -RUN sed -i 's/variables_order = .*/variables_order = "EGPCS"/' /etc/php/7.0/apache2/php.ini -RUN sed -i 's/variables_order = .*/variables_order = "EGPCS"/' /etc/php/7.0/cli/php.ini +RUN sed -i 's/variables_order = .*/variables_order = "EGPCS"/' /etc/php/7.2/apache2/php.ini +RUN sed -i 's/variables_order = .*/variables_order = "EGPCS"/' /etc/php/7.2/cli/php.ini RUN useradd -m --uid 1000 --gid 50 docker @@ -40,11 +63,11 @@ COPY docker/000-default.conf /etc/apache2/sites-enabled/000-default.conf #SSL RUN mkdir -p /var/lib/snipeit/ssl -COPY docker/001-default-ssl.conf /etc/apache2/sites-enabled/001-default-ssl.conf -#COPY docker/001-default-ssl.conf /etc/apache2/sites-available/001-default-ssl.conf +#COPY docker/001-default-ssl.conf /etc/apache2/sites-enabled/001-default-ssl.conf +COPY docker/001-default-ssl.conf /etc/apache2/sites-available/001-default-ssl.conf RUN a2enmod ssl -#RUN a2ensite 001-default-ssl.conf +RUN a2ensite 001-default-ssl.conf COPY . /var/www/html @@ -67,18 +90,18 @@ RUN \ rm -r "/var/www/html/storage/private_uploads" && ln -fs "/var/lib/snipeit/data/private_uploads" "/var/www/html/storage/private_uploads" \ && rm -rf "/var/www/html/public/uploads" && ln -fs "/var/lib/snipeit/data/uploads" "/var/www/html/public/uploads" \ && rm -r "/var/www/html/storage/app/backups" && ln -fs "/var/lib/snipeit/dumps" "/var/www/html/storage/app/backups" \ - && mkdir "/var/lib/snipeit/keys" && ln -fs "/var/lib/snipeit/keys/oauth-private.key" "/var/www/html/storage/oauth-private.key" \ + && mkdir -p "/var/lib/snipeit/keys" && ln -fs "/var/lib/snipeit/keys/oauth-private.key" "/var/www/html/storage/oauth-private.key" \ && ln -fs "/var/lib/snipeit/keys/oauth-public.key" "/var/www/html/storage/oauth-public.key" \ && chown docker "/var/lib/snipeit/keys/" ############## DEPENDENCIES via COMPOSER ################### #global install of composer -RUN cd /tmp;curl -sS https://getcomposer.org/installer | php;mv /tmp/composer.phar /usr/local/bin/composer +COPY --from=composer:latest /usr/bin/composer /usr/bin/composer # Get dependencies USER docker -RUN cd /var/www/html;composer install && rm -rf /home/docker/.composer/cache +RUN composer install --no-dev --working-dir=/var/www/html USER root ############### APPLICATION INSTALL/INIT ################# diff --git a/Dockerfile.alpine b/Dockerfile.alpine new file mode 100644 index 0000000000..f00650daf6 --- /dev/null +++ b/Dockerfile.alpine @@ -0,0 +1,80 @@ +FROM alpine:3.8 +# Apache + PHP +RUN apk add --update --no-cache \ + apache2 \ + php7 \ + php7-common \ + php7-apache2 \ + php7-curl \ + php7-ldap \ + php7-mysqli \ + php7-gd \ + php7-xml \ + php7-mbstring \ + php7-zip \ + php7-ctype \ + php7-tokenizer \ + php7-pdo_mysql \ + php7-openssl \ + php7-bcmath \ + php7-phar \ + php7-json \ + php7-iconv \ + php7-fileinfo \ + php7-simplexml \ + php7-session \ + curl \ + wget \ + vim \ + git \ + mysql-client \ + tini + +# Where apache's PID lives +RUN mkdir -p /run/apache2 && chown apache:apache /run/apache2 + +RUN sed -i 's/variables_order = .*/variables_order = "EGPCS"/' /etc/php7/php.ini +COPY docker/000-default-2.4.conf /etc/apache2/conf.d/default.conf + +# Enable mod_rewrite +RUN sed -i '/LoadModule rewrite_module/s/^#//g' /etc/apache2/httpd.conf + +COPY . /var/www/html + +WORKDIR /var/www/html + +COPY docker/docker.env /var/www/html/.env + +RUN chown -R apache:apache /var/www/html + +RUN \ + rm -r "/var/www/html/storage/private_uploads" \ + && mkdir -p "/var/lib/snipeit/data/private_uploads" && ln -fs "/var/lib/snipeit/data/private_uploads" "/var/www/html/storage/private_uploads" \ + && rm -rf "/var/www/html/public/uploads" \ + && mkdir -p "/var/lib/snipeit/data/uploads" && ln -fs "/var/lib/snipeit/data/uploads" "/var/www/html/public/uploads" \ + && mkdir -p "/var/lib/snipeit/dumps" && rm -r "/var/www/html/storage/app/backups" && ln -fs "/var/lib/snipeit/dumps" "/var/www/html/storage/app/backups" \ + && mkdir -p "/var/lib/snipeit/keys" && ln -fs "/var/lib/snipeit/keys/oauth-private.key" "/var/www/html/storage/oauth-private.key" \ + && ln -fs "/var/lib/snipeit/keys/oauth-public.key" "/var/www/html/storage/oauth-public.key" \ + && chown -R apache "/var/lib/snipeit" + +# Install composer +COPY --from=composer:latest /usr/bin/composer /usr/bin/composer +RUN mkdir -p /var/www/.composer && chown apache /var/www/.composer + +# Install dependencies +USER apache +RUN COMPOSER_CACHE_DIR=/dev/null composer install --no-dev --working-dir=/var/www/html + +USER root + +VOLUME ["/var/lib/snipeit"] + +# Entrypoints +COPY docker/entrypoint_alpine.sh /entrypoint.sh +RUN chmod +x /entrypoint.sh + +ENTRYPOINT ["/sbin/tini", "--"] + +CMD ["/entrypoint.sh"] + +EXPOSE 80 diff --git a/README.md b/README.md index d5d21ac588..f0a5052f8c 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ [![Build Status](https://travis-ci.org/snipe/snipe-it.svg?branch=master)](https://travis-ci.org/snipe/snipe-it) [![Crowdin](https://d322cqt584bo4o.cloudfront.net/snipe-it/localized.svg)](https://crowdin.com/project/snipe-it) [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/snipe/snipe-it?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Docker Pulls](https://img.shields.io/docker/pulls/snipe/snipe-it.svg)](https://hub.docker.com/r/snipe/snipe-it/) [![Twitter Follow](https://img.shields.io/twitter/follow/snipeitapp.svg?style=social)](https://twitter.com/snipeitapp) [![Codacy Badge](https://api.codacy.com/project/badge/Grade/553ce52037fc43ea99149785afcfe641)](https://www.codacy.com/app/snipe/snipe-it?utm_source=github.com&utm_medium=referral&utm_content=snipe/snipe-it&utm_campaign=Badge_Grade) -[![All Contributors](https://img.shields.io/badge/all_contributors-180-orange.svg?style=flat-square)](#contributors) [![Open Source Helpers](https://www.codetriage.com/snipe/snipe-it/badges/users.svg)](https://www.codetriage.com/snipe/snipe-it) +[![All Contributors](https://img.shields.io/badge/all_contributors-198-orange.svg?style=flat-square)](#contributors) [![Open Source Helpers](https://www.codetriage.com/snipe/snipe-it/badges/users.svg)](https://www.codetriage.com/snipe/snipe-it) ## Snipe-IT - Open Source Asset Management System @@ -64,6 +64,21 @@ As these were created by third-parties, Snipe-IT cannot provide support for thes ----- +### Contributing + +Please see the documentation on [contributing and developing for Snipe-IT](https://snipe-it.readme.io/docs/contributing-overview). + + +Please note that this project is released with a [Contributor Code of Conduct](CODE_OF_CONDUCT.md). By participating in this project you agree to abide by its terms. + +----- + +### Security + +To report a security vulnerability, please email security@snipeitapp.com instead of using the issue tracker. + +----- + ### Contributors Thanks goes to all of these wonderful people ([emoji key](https://github.com/kentcdodds/all-contributors#emoji-key)) who have helped Snipe-IT get this far: @@ -95,22 +110,11 @@ Thanks goes to all of these wonderful people ([emoji key](https://github.com/ken | [
Martin Stub](http://martinstub.dk)
[🌍](#translation-stubben "Translation") | [
Meyer Flavio](https://github.com/meyerf99)
[🌍](#translation-meyerf99 "Translation") | [
Micael Rodrigues](https://github.com/MicaelRodrigues)
[🌍](#translation-MicaelRodrigues "Translation") | [
Mikael Rasmussen](http://rubixy.com/)
[🌍](#translation-mikaelssen "Translation") | [
IxFail](https://github.com/IxFail)
[🌍](#translation-IxFail "Translation") | [
Mohammed Fota](http://www.mohammedfota.com)
[🌍](#translation-MohammedFota "Translation") | [
Moayad Alserihi](https://github.com/omego)
[🌍](#translation-omego "Translation") | | [
saymd](https://github.com/saymd)
[🌍](#translation-saymd "Translation") | [
Patrik Larsson](https://nordsken.se)
[🌍](#translation-pooot "Translation") | [
drcryo](https://github.com/drcryo)
[🌍](#translation-drcryo "Translation") | [
pawel1615](https://github.com/pawel1615)
[🌍](#translation-pawel1615 "Translation") | [
bodrovics](https://github.com/bodrovics)
[🌍](#translation-bodrovics "Translation") | [
priatna](https://github.com/priatna)
[🌍](#translation-priatna "Translation") | [
Fan Jiang](https://amayume.net)
[🌍](#translation-ProfFan "Translation") | | [
ragnarcx](https://github.com/ragnarcx)
[🌍](#translation-ragnarcx "Translation") | [
Rein van Haaren](http://www.reinvanhaaren.nl/)
[🌍](#translation-reinvanhaaren "Translation") | [
Teguh Dwicaksana](http://dheche.songolimo.net)
[🌍](#translation-dheche "Translation") | [
fraccie](https://github.com/FRaccie)
[🌍](#translation-FRaccie "Translation") | [
vinzruzell](https://github.com/vinzruzell)
[🌍](#translation-vinzruzell "Translation") | [
Kevin Austin](http://kevinaustin.com)
[🌍](#translation-vipsystem "Translation") | [
Wira Sandy](http://azuraweb.xyz)
[🌍](#translation-wira-sandy "Translation") | -| [
Илья](https://github.com/GrayHoax)
[🌍](#translation-GrayHoax "Translation") | [
GodUseVPN](https://github.com/godusevpn)
[🌍](#translation-godusevpn "Translation") | [
周周](https://github.com/EngrZhou)
[🌍](#translation-EngrZhou "Translation") | [
Sam](https://github.com/takuy)
[💻](https://github.com/snipe/snipe-it/commits?author=takuy "Code") | [
Azerothian](https://www.illisian.com.au)
[💻](https://github.com/snipe/snipe-it/commits?author=Azerothian "Code") | +| [
Илья](https://github.com/GrayHoax)
[🌍](#translation-GrayHoax "Translation") | [
GodUseVPN](https://github.com/godusevpn)
[🌍](#translation-godusevpn "Translation") | [
周周](https://github.com/EngrZhou)
[🌍](#translation-EngrZhou "Translation") | [
Sam](https://github.com/takuy)
[💻](https://github.com/snipe/snipe-it/commits?author=takuy "Code") | [
Azerothian](https://www.illisian.com.au)
[💻](https://github.com/snipe/snipe-it/commits?author=Azerothian "Code") | [
Wes Hulette](http://macfoo.wordpress.com/)
[💻](https://github.com/snipe/snipe-it/commits?author=jwhulette "Code") | [
patrict](https://github.com/patrict)
[💻](https://github.com/snipe/snipe-it/commits?author=patrict "Code") | +| [
Dmitriy Minaev](https://github.com/VELIKII-DIVAN)
[💻](https://github.com/snipe/snipe-it/commits?author=VELIKII-DIVAN "Code") | [
liquidhorse](https://github.com/liquidhorse)
[💻](https://github.com/snipe/snipe-it/commits?author=liquidhorse "Code") | [
Jordi Boggiano](https://seld.be/)
[💻](https://github.com/snipe/snipe-it/commits?author=Seldaek "Code") | [
Ivan Nieto](https://github.com/inietov)
[💻](https://github.com/snipe/snipe-it/commits?author=inietov "Code") | [
Ben RUBSON](https://github.com/benrubson)
[💻](https://github.com/snipe/snipe-it/commits?author=benrubson "Code") | [
NMathar](https://github.com/NMathar)
[💻](https://github.com/snipe/snipe-it/commits?author=NMathar "Code") | [
Steffen](https://github.com/smb)
[💻](https://github.com/snipe/snipe-it/commits?author=smb "Code") | +| [
Sxderp](https://github.com/Sxderp)
[💻](https://github.com/snipe/snipe-it/commits?author=Sxderp "Code") | [
fanta8897](https://github.com/fanta8897)
[💻](https://github.com/snipe/snipe-it/commits?author=fanta8897 "Code") | [
Andrey Bolonin](https://andreybolonin.com/phpconsulting/)
[💻](https://github.com/snipe/snipe-it/commits?author=andreybolonin "Code") | [
shinayoshi](http://www.shinayoshi.net/)
[💻](https://github.com/snipe/snipe-it/commits?author=shinayoshi "Code") | [
Hubert](https://github.com/reuser)
[💻](https://github.com/snipe/snipe-it/commits?author=reuser "Code") | [
KeenRivals](https://brashear.me)
[💻](https://github.com/snipe/snipe-it/commits?author=KeenRivals "Code") | [
omyno](https://github.com/omyno)
[💻](https://github.com/snipe/snipe-it/commits?author=omyno "Code") | +| [
Evgeny](https://github.com/jackka)
[💻](https://github.com/snipe/snipe-it/commits?author=jackka "Code") | [
Colin Campbell](https://digitalist.se)
[💻](https://github.com/snipe/snipe-it/commits?author=colin-campbell "Code") | This project follows the [all-contributors](https://github.com/kentcdodds/all-contributors) specification. Contributions of any kind welcome! ------ - -### Contributing - -Please see the documentation on [contributing and developing for Snipe-IT](https://snipe-it.readme.io/docs/contributing-overview). - - -Please note that this project is released with a [Contributor Code of Conduct](CODE_OF_CONDUCT.md). By participating in this project you agree to abide by its terms. - ------ - -### Security - -To report a security vulnerability, please email security@snipeitapp.com instead of using the issue tracker. diff --git a/Vagrantfile b/Vagrantfile index b65979b7e9..0c5f8798a6 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -81,4 +81,22 @@ Vagrant.configure("2") do |config| fedora26.vm.provision :shell, :inline => "wget #{SNIPEIT_SH_URL}" fedora26.vm.provision :shell, :inline => "chmod 755 snipeit.sh" end + + config.vm.define "freebsd" do |freebsd| + freebsd.vm.box = "freebsd/FreeBSD-11.2-RELEASE" + freebsd.vm.hostname = 'freebsd12' + freebsd.vm.network "forwarded_port", guest: 80, host: 8080 + freebsd.vm.network "forwarded_port", guest:3306, host:3306 # mysql + freebsd.vm.network "private_network", type: "dhcp" + freebsd.ssh.shell = "sh" + freebsd.vm.base_mac = "080027D14C66" + freebsd.vm.synced_folder ".", "/vagrant", :nfs => true, id: "vagrant-root", + :mount_options => ['rw', 'vers=3', 'tcp', 'actimeo=2'] + freebsd.vm.provision "shell", inline: <<-SHELL + pkg install -y python27; + SHELL + freebsd.vm.provision "ansible" do |ansible| + ansible.playbook = "ansible/freebsd/vagrant_playbook.yml" + end + end end diff --git a/ansible/freebsd/vagrant_playbook.yml b/ansible/freebsd/vagrant_playbook.yml new file mode 100644 index 0000000000..7e10ca0d86 --- /dev/null +++ b/ansible/freebsd/vagrant_playbook.yml @@ -0,0 +1,260 @@ +--- +- name: Set up local server + hosts: all + remote_user: vagrant + become_user: root + become_method: sudo + vars: + - ansible_python_interpreter: /usr/local/bin/python2.7 + gather_facts: no + +# Tasks + tasks: + + # + # Update the PKG database + # + - name: Upgrade PKG database + raw: sudo pkg upgrade -y + + # + # Mount the shared folders + # + - name: Update Vagrant Shared Folders + command: "{{ item }}" + with_items: + - sysrc rpc_lockd_enable=YES + - sysrc rpc_statd_enable=YES + become: true + + # + # Install required utilities + # + - name: Install Utilities + pkgng: + name: "{{ item }}" + state: present + with_items: + - openssl + - node + - npm + - git + - nano + - wget + - bash + become: true + + # + # Install php and php dependancies + # + - name: Install PHP dependancies + pkgng: + name: "{{ item }}" + state: present + with_items: + - php72 + - php72-zip + - php72-zlib + - php72-extensions + - php72-mbstring + - php72-openssl + # - php72-mysqli + - php72-curl + - php72-soap + - php72-pdo_mysql + # - php72-pdo_pgsql + - php72-ldap + - php72-curl + - php72-fileinfo + - php72-bcmath + - php72-gd + become: true + + # + # Create a php.ini file + # + - name: PHP INI check + stat: + path: /usr/local/etc/php.ini + register: php_ini_exits + + - name: Create PHP ini + command: cp /usr/local/etc/php.ini-development /usr/local/etc/php.ini + become: true + when: not php_ini_exits.stat.exists + + - name: Enable PHP-FPM auto-start + command: sysrc php_fpm_enable=YES + become: true + + - name: Start PHP-FPM service + service: + name: php-fpm + state: started + become: true + + # + # Install the lastest version of composer + # + - name: Composer check + stat: + path: /usr/local/bin/composer + register: composer_exits + + - name: Install Composer + shell: | + EXPECTED_SIGNATURE=$(wget -q -O - https://composer.github.io/installer.sig) + php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" + ACTUAL_SIGNATURE=$(php -r "echo hash_file('SHA384', 'composer-setup.php');") + + if [ "$EXPECTED_SIGNATURE" != "$ACTUAL_SIGNATURE" ] + then + >&2 echo 'ERROR: Invalid installer signature' + rm composer-setup.php + exit 1 + fi + + php composer-setup.php --quiet + RESULT=$? + rm composer-setup.php + mv composer.phar /usr/local/bin/composer + exit $RESULT + when: not composer_exits.stat.exists + become: true + + # + # Install MySQL Server + + - name: Install MySQL 5.7 + pkgng: + name: mysql57-server + state: present + become: true + register: sql_server + + - name: Start MySQL server + service: + name: mysql-server + state: started + become: true + + - name: MySQL 5.7 auto-start + command: sysrc mysql_enable=YES + become: true + when: sql_server.changed == true + + - name: Get MySQL root password + command: tail -1 /root/.mysql_secret + register: myql_root_pwd + become: true + when: sql_server.changed == true + + - name: Change MySQL root password + command: mysqladmin -u root -p'{{myql_root_pwd.stdout}}' password vagrant + when: sql_server.changed == true + + - name: Enable remote mysql + replace: + path: /usr/local/etc/mysql/my.cnf + regexp: "127.0.0.1" + replace: "0.0.0.0" + become: true + when: sql_server.changed == true + + - name: Grant user vagrant privelages + shell: mysql -u root -pvagrant -e "GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'vagrant' WITH GRANT OPTION; FLUSH PRIVILEGES;" + become: true + when: sql_server.changed == true + ignore_errors: true + + - name: Restart MySQL server + service: + name: mysql-server + state: restarted + become: true + + + # + # Install Apache Web Server + # + - name: Install Apache 2.4 + pkgng: + name: apache24 + state: present + become: true + register: apache24_server + + - name: Apache 2.4 auto-start + command: sysrc apache24_enable=YES + become: true + when: apache24_server.changed == true + + - name: Enable Apache modules + replace: + path: /usr/local/etc/apache24/httpd.conf + regexp: "#{{ item }}" + replace: "{{ item }}" + become: true + with_items: + - LoadModule rewrite_module libexec/apache24/mod_rewrite.so + - LoadModule vhost_alias_module libexec/apache24/mod_vhost_alias.so + - LoadModule deflate_module libexec/apache24/mod_deflate.so + - LoadModule expires_module libexec/apache24/mod_expires.so + - LoadModule mpm_worker_module libexec/apache24/mod_mpm_worker.so + - LoadModule proxy_fcgi_module libexec/apache24/mod_proxy_fcgi.so + - LoadModule proxy_module libexec/apache24/mod_proxy.so + - Include etc/apache24/extra/httpd-vhosts.conf + when: apache24_server.changed == true + + - name: Disable Apache modules + replace: + path: /usr/local/etc/apache24/httpd.conf + regexp: "{{ item }}" + replace: "#{{ item }}" + become: true + with_items: + - LoadModule mpm_prefork_module libexec/apache24/mod_mpm_prefork.so + when: apache24_server.changed == true + + - name: Backup vhosts + command: cp /usr/local/etc/apache24/extra/httpd-vhosts.conf /usr/local/etc/apache24/extra/httpd-vhosts.conf.bak + become: true + when: apache24_server.changed == true + + - name: Truncate vhosts + command: truncate -s 0 /usr/local/etc/apache24/extra/httpd-vhosts.conf + become: true + when: apache24_server.changed == true + + - name: Set up vhost + blockinfile: + path: "/usr/local/etc/apache24/extra/httpd-vhosts.conf" + block: | + + DocumentRoot /usr/local/www/apache24/data/public + ServerName vagrant.app + ProxyPassMatch ^/(.*\.php(/.*)?)$ fcgi://127.0.0.1:9000/usr/local/www/apache24/data/public/$1 + DirectoryIndex /index.php index.php + + Options -Indexes +FollowSymLinks + AllowOverride All + Require all granted + + + become: true + when: apache24_server.changed == true + + - name: Map apache dir to local folder + shell: | + if ! [ -L /var/www ]; then + rm -rf /usr/local/www/apache24/data; + ln -fs /vagrant /usr/local/www/apache24/data; + fi + become: true + when: apache24_server.changed == true + + - name: Start Apache 2.4 server + service: + name: apache24 + state: started + become: true \ No newline at end of file diff --git a/app/Console/Commands/CreateAdmin.php b/app/Console/Commands/CreateAdmin.php index 89b564091e..7a2c9a1feb 100644 --- a/app/Console/Commands/CreateAdmin.php +++ b/app/Console/Commands/CreateAdmin.php @@ -76,10 +76,4 @@ class CreateAdmin extends Command } - // protected function getArguments() - // { - // return array( - // array('username', InputArgument::REQUIRED, 'Username'), - // ); - // } } diff --git a/app/Console/Commands/DisableLDAP.php b/app/Console/Commands/DisableLDAP.php index 8e9d8c8d69..5522df37cc 100644 --- a/app/Console/Commands/DisableLDAP.php +++ b/app/Console/Commands/DisableLDAP.php @@ -41,7 +41,7 @@ class DisableLDAP extends Command if ($this->confirm("\n****************************************************\nThis will disable LDAP support. You will not be able \nto login with an account that does not exist \nlocally in the Snipe-IT local database. \n****************************************************\n\nDo you wish to continue? [y|N]")) { - $setting = Setting::first(); + $setting = Setting::getSettings(); $setting->ldap_enabled = 0; if ($setting->save()) { $this->info('LDAP has been set to disabled.'); diff --git a/app/Console/Commands/FixDoubleEscape.php b/app/Console/Commands/FixDoubleEscape.php index 648e209950..64f6aad572 100644 --- a/app/Console/Commands/FixDoubleEscape.php +++ b/app/Console/Commands/FixDoubleEscape.php @@ -71,7 +71,7 @@ class FixDoubleEscape extends Command foreach($classname::where("$field",'LIKE','%&%')->get() as $row) { $this->info('Updating '.$field.' for '.$classname); - $row->{$field} = html_entity_decode($row->{$field}); + $row->{$field} = html_entity_decode($row->{$field},ENT_QUOTES); $row->save(); $count[$classname][$field]++; diff --git a/app/Console/Commands/LdapSync.php b/app/Console/Commands/LdapSync.php index 6045796fa7..c8a0fecd65 100755 --- a/app/Console/Commands/LdapSync.php +++ b/app/Console/Commands/LdapSync.php @@ -1,14 +1,23 @@ + * + * @since 5.0.0 + */ class LdapSync extends Command { /** @@ -16,23 +25,75 @@ class LdapSync extends Command * * @var string */ - protected $signature = 'snipeit:ldap-sync {--location=} {--location_id=} {--base_dn=} {--summary} {--json_summary}'; + protected $signature = 'snipeit:ldap-sync + {--location= : A location name } + {--location_id= : A location id} + {--base_dn= : A diffrent base DN to use } + {--summary : Print summary } + {--json_summary : Print summary in json format } + {--dryrun : Run the sync process but don\'t update the database}'; /** * The console command description. * * @var string */ - protected $description = 'Command line LDAP sync'; + protected $description = 'Command line LDAP/AD sync'; + + /** + * An LdapAd instance. + * + * @var \App\Models\LdapAd + */ + private $ldap; + + /** + * A default location collection. + * + * @var \Illuminate\Support\Collection + */ + private $defaultLocation = null; + + /** + * Mapped locations collection. + * + * @var \Illuminate\Support\Collection + */ + private $mappedLocations = null; + + /** + * The summary collection. + * + * @var \Illuminate\Support\Collection + */ + private $summary; + + /** + * Is dry-run? + * + * @var bool + */ + private $dryrun = false; + + /** + * Show users to be imported. + * + * @var array + */ + private $userlist = []; /** * Create a new command instance. * - * @return void + * @param LdapAd $ldap */ - public function __construct() + public function __construct(LdapAd $ldap) { + parent::__construct(); + $this->summary = collect(); + + $this->ldap = $ldap; } /** @@ -42,207 +103,280 @@ class LdapSync extends Command */ public function handle() { - ini_set('max_execution_time', 600); //600 seconds = 10 minutes + ini_set('max_execution_time', '600'); //600 seconds = 10 minutes ini_set('memory_limit', '500M'); - $ldap_result_username = Setting::getSettings()->ldap_username_field; - $ldap_result_last_name = Setting::getSettings()->ldap_lname_field; - $ldap_result_first_name = Setting::getSettings()->ldap_fname_field; - - $ldap_result_active_flag = Setting::getSettings()->ldap_active_flag_field; - $ldap_result_emp_num = Setting::getSettings()->ldap_emp_num; - $ldap_result_email = Setting::getSettings()->ldap_email; - - try { - $ldapconn = Ldap::connectToLdap(); - Ldap::bindAdminToLdap($ldapconn); - } catch (\Exception $e) { - if ($this->option('json_summary')) { - $json_summary = [ "error" => true, "error_message" => $e->getMessage(), "summary" => [] ]; - $this->info(json_encode($json_summary)); - } - LOG::error($e); - return []; + if ($this->option('dryrun')) { + $this->dryrun = true; } - $summary = array(); + $this->checkIfLdapIsEnabled(); + $this->checkLdapConnetion(); + $this->setBaseDn(); + $this->getUserDefaultLocation(); + /* + * Use the default location if set, this is needed for the LDAP users sync page + */ + if (!$this->option('base_dn') && null == $this->defaultLocation) { + $this->getMappedLocations(); + } + $this->processLdapUsers(); - try { - if ($this->option('base_dn') != '') { - $search_base = $this->option('base_dn'); - LOG::debug('Importing users from specified base DN: \"'.$search_base.'\".'); - } else { - $search_base = null; - } - $results = Ldap::findLdapUsers($search_base); - } catch (\Exception $e) { - if ($this->option('json_summary')) { - $json_summary = [ "error" => true, "error_message" => $e->getMessage(), "summary" => [] ]; - $this->info(json_encode($json_summary)); - } - LOG::error($e); - return []; + // Print table of users + if ($this->dryrun) { + $this->info('The following users will be synced!'); + $headers = ['First Name', 'Last Name', 'Username', 'Email', 'Employee #', 'Location Id', 'Status']; + $this->table($headers, $this->summary->toArray()); } - /* Determine which location to assign users to by default. */ - $location = NULL; - - if ($this->option('location')!='') { - $location = Location::where('name', '=', $this->option('location'))->first(); - LOG::debug('Location name '.$this->option('location').' passed'); - LOG::debug('Importing to '.$location->name.' ('.$location->id.')'); - } elseif ($this->option('location_id')!='') { - $location = Location::where('id', '=', $this->option('location_id'))->first(); - LOG::debug('Location ID '.$this->option('location_id').' passed'); - LOG::debug('Importing to '.$location->name.' ('.$location->id.')'); - } - - if (!isset($location)) { - LOG::debug('That location is invalid or a location was not provided, so no location will be assigned by default.'); - } - - /* Process locations with explicitly defined OUs, if doing a full import. */ - if ($this->option('base_dn')=='') { - // Retrieve locations with a mapped OU, and sort them from the shallowest to deepest OU (see #3993) - $ldap_ou_locations = Location::where('ldap_ou', '!=', '')->get()->toArray(); - $ldap_ou_lengths = array(); - - foreach ($ldap_ou_locations as $location) { - $ldap_ou_lengths[] = strlen($location["ldap_ou"]); - } - - array_multisort($ldap_ou_lengths, SORT_ASC, $ldap_ou_locations); - - if (sizeof($ldap_ou_locations) > 0) { - LOG::debug('Some locations have special OUs set. Locations will be automatically set for users in those OUs.'); - } - - // Inject location information fields - for ($i = 0; $i < $results["count"]; $i++) { - $results[$i]["ldap_location_override"] = false; - $results[$i]["location_id"] = 0; - } - - // Grab subsets based on location-specific DNs, and overwrite location for these users. - foreach ($ldap_ou_locations as $ldap_loc) { - $location_users = Ldap::findLdapUsers($ldap_loc["ldap_ou"]); - $usernames = array(); - for ($i = 0; $i < $location_users["count"]; $i++) { - - if (array_key_exists($ldap_result_username, $location_users[$i])) { - $location_users[$i]["ldap_location_override"] = true; - $location_users[$i]["location_id"] = $ldap_loc["id"]; - $usernames[] = $location_users[$i][$ldap_result_username][0]; - } + return $this->getSummary(); + } + /** + * Generate the LDAP sync summary. + * + * @author Wes Hulette + * + * @since 5.0.0 + * + * @return string + */ + private function getSummary(): string + { + if ($this->option('summary') && !$this->dryrun) { + $this->summary->each(function ($item) { + if ('ERROR' === $item['status']) { + $this->error('ERROR: '.$item['note']); } - - // Delete located users from the general group. - foreach ($results as $key => $generic_entry) { - if ((is_array($generic_entry)) && (array_key_exists($ldap_result_username, $generic_entry))) { - if (in_array($generic_entry[$ldap_result_username][0], $usernames)) { - unset($results[$key]); - } - } + else { + $this->info('USER: '.$item['note']); } - - $global_count = $results['count']; - $results = array_merge($location_users, $results); - $results['count'] = $global_count; - } - } - - /* Create user account entries in Snipe-IT */ - $tmp_pass = substr(str_shuffle("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"), 0, 20); - $pass = bcrypt($tmp_pass); - - for ($i = 0; $i < $results["count"]; $i++) { - if (empty($ldap_result_active_flag) || $results[$i][$ldap_result_active_flag][0] == "TRUE") { - - $item = array(); - $item["username"] = isset($results[$i][$ldap_result_username][0]) ? $results[$i][$ldap_result_username][0] : ""; - $item["employee_number"] = isset($results[$i][$ldap_result_emp_num][0]) ? $results[$i][$ldap_result_emp_num][0] : ""; - $item["lastname"] = isset($results[$i][$ldap_result_last_name][0]) ? $results[$i][$ldap_result_last_name][0] : ""; - $item["firstname"] = isset($results[$i][$ldap_result_first_name][0]) ? $results[$i][$ldap_result_first_name][0] : ""; - $item["email"] = isset($results[$i][$ldap_result_email][0]) ? $results[$i][$ldap_result_email][0] : "" ; - $item["ldap_location_override"] = isset($results[$i]["ldap_location_override"]) ? $results[$i]["ldap_location_override"]:""; - $item["location_id"] = isset($results[$i]["location_id"]) ? $results[$i]["location_id"]:""; - - - // This is active directory, not regular LDAP - if ( array_key_exists('useraccountcontrol', $results[$i]) ) { - $enabled_accounts = [ - '512', '544', '66048', '66080', '262656', '262688', '328192', '328224' - ]; - $item['activated'] = ( in_array($results[$i]['useraccountcontrol'][0], $enabled_accounts) ) ? 1 : 0; - - // Fall through to LDAP - } else { - $item['activated'] = 0; - } - - // User exists - $item["createorupdate"] = 'updated'; - if (!$user = User::where('username', $item["username"])->first()) { - $user = new User; - $user->password = $pass; - $item["createorupdate"] = 'created'; - } - - // Create the user if they don't exist. - $user->first_name = e($item["firstname"]); - $user->last_name = e($item["lastname"]); - $user->username = e($item["username"]); - $user->email = e($item["email"]); - $user->employee_num = e($item["employee_number"]); - $user->activated = $item['activated']; - - if ($item['ldap_location_override'] == true) { - $user->location_id = $item['location_id']; - } elseif ((isset($location)) && (!empty($location))) { - - if ((is_array($location)) && (array_key_exists('id', $location))) { - $user->location_id = $location['id']; - } elseif (is_object($location)) { - $user->location_id = $location->id; - } - - } - - $user->notes = 'Imported from LDAP'; - $user->ldap_import = 1; - - $errors = ''; - - if ($user->save()) { - $item["note"] = $item["createorupdate"]; - $item["status"]='success'; - } else { - foreach ($user->getErrors()->getMessages() as $key => $err) { - $errors .= $err[0]; - } - $item["note"] = $errors; - $item["status"]='error'; - } - - array_push($summary, $item); - } - - } - - if ($this->option('summary')) { - for ($x = 0; $x < count($summary); $x++) { - if ($summary[$x]['status']=='error') { - $this->error('ERROR: '.$summary[$x]['firstname'].' '.$summary[$x]['lastname'].' (username: '.$summary[$x]['username'].') was not imported: '.$summary[$x]['note']); - } else { - $this->info('User '.$summary[$x]['firstname'].' '.$summary[$x]['lastname'].' (username: '.$summary[$x]['username'].') was '.strtoupper($summary[$x]['createorupdate']).'.'); - } - } - } else if ($this->option('json_summary')) { - $json_summary = [ "error" => false, "error_message" => "", "summary" => $summary ]; + }); + } elseif ($this->option('json_summary')) { + $json_summary = [ + 'error' => false, + 'error_message' => '', + 'summary' => $this->summary->toArray(), + ]; $this->info(json_encode($json_summary)); - } else { - return $summary; + } + + return ''; + } + + /** + * Create a new user or update an existing user. + * + * @author Wes Hulette + * + * @since 5.0.0 + * + * @param \Adldap\Models\User $snipeUser + */ + private function updateCreateUser(AdldapUser $snipeUser): void + { + $user = $this->ldap->processUser($snipeUser, $this->defaultLocation, $this->mappedLocations); + if(!$user) { + $summary['note'] = sprintf("'%s' was not imported. REASON: User inactive or not found", $snipeUser->ou); + $summary['status'] = 'ERROR'; + $this->summary->push($summary); + return; + } + $summary = [ + 'firstname' => $user->first_name, + 'lastname' => $user->last_name, + 'username' => $user->username, + 'employee_number' => $user->employee_num, + 'email' => $user->email, + 'location_id' => $user->location_id, + ]; + // Only update the database if is not a dry run + if (!$this->dryrun) { + if ($user->save()) { + $summary['note'] = sprintf("'%s' %s", $user->username, ($user->wasRecentlyCreated ? 'CREATED' : 'UPDATED')); + $summary['status'] = 'SUCCESS'; + } else { + $errors = ''; + foreach ($user->getErrors()->getMessages() as $error) { + $errors .= $error[0]; + } + $summary['note'] = sprintf("'%s' was not imported. REASON: %s", $user->username, $errors); + $summary['status'] = 'ERROR'; + } + } + + //$summary['note'] = ($user->getOriginal('username') ? 'UPDATED' : 'CREATED'); + $this->summary->push($summary); + } + + /** + * Process the users to update / create. + * + * @author Wes Hulette + * + * @since 5.0.0 + * + * @param int $page The page to get the result set + */ + private function processLdapUsers(int $page=0): void + { + try { + $ldapUsers = $this->ldap->getLdapUsers($page); + } catch (Exception $e) { + $this->outputError($e); + exit($e->getMessage()); + } + + if (0 == $ldapUsers->count()) { + $msg = 'ERROR: No users found!'; + Log::error($msg); + if ($this->dryrun) { + $this->error($msg); + } + exit($msg); + } + + // Process each individual users + foreach ($ldapUsers as $user) { + $this->updateCreateUser($user); + } + + if ($ldapUsers->getCurrentPage() < $ldapUsers->getPages()) { + $this->processLdapUsers($ldapUsers->getCurrentPage() + 1); } } + + /** + * Get the mapped locations if a base_dn is provided. + * + * @author Wes Hulette + * + * @since 5.0.0 + */ + private function getMappedLocations() + { + $ldapOuLocation = Location::where('ldap_ou', '!=', '')->select(['id', 'ldap_ou'])->get(); + $locations = $ldapOuLocation->sortBy(function ($ou, $key) { + return strlen($ou->ldap_ou); + }); + if ($locations->count() > 0) { + $msg = 'Some locations have special OUs set. Locations will be automatically set for users in those OUs.'; + LOG::debug($msg); + if ($this->dryrun) { + $this->info($msg); + } + + $this->mappedLocations = $locations->pluck('ldap_ou', 'id'); + } + } + + /** + * Set the base dn if supplied. + * + * @author Wes Hulette + * + * @since 5.0.0 + */ + private function setBaseDn(): void + { + if ($this->option('base_dn')) { + $this->ldap->baseDn = $this->option('base_dn'); + $msg = sprintf('Importing users from specified base DN: "%s"', $this->ldap->baseDn); + LOG::debug($msg); + if ($this->dryrun) { + $this->info($msg); + } + } + } + + /** + * Get a default location id for imported users. + * + * @author Wes Hulette + * + * @since 5.0.0 + */ + private function getUserDefaultLocation(): void + { + $location = $this->option('location_id') ?? $this->option('location'); + if ($location) { + $userLocation = Location::where('name', '=', $location) + ->orWhere('id', '=', intval($location)) + ->select(['name', 'id']) + ->first(); + if ($userLocation) { + $msg = 'Importing users with default location: '.$userLocation->name.' ('.$userLocation->id.')'; + LOG::debug($msg); + + if ($this->dryrun) { + $this->info($msg); + } + + $this->defaultLocation = collect([ + $userLocation->id => $userLocation->name, + ]); + } else { + $msg = 'The supplied location is invalid!'; + LOG::error($msg); + if ($this->dryrun) { + $this->error($msg); + } + exit(0); + } + } + } + + /** + * Check if LDAP intergration is enabled. + * + * @author Wes Hulette + * + * @since 5.0.0 + */ + private function checkIfLdapIsEnabled(): void + { + if (!$this->ldap->init()) { + $msg = 'LDAP intergration is not enabled. Exiting sync process.'; + $this->info($msg); + Log::info($msg); + exit(0); + } + } + + /** + * Check to make sure we can access the server. + * + * @author Wes Hulette + * + * @since 5.0.0 + */ + private function checkLdapConnetion(): void + { + try { + $this->ldap->testLdapAdUserConnection(); + $this->ldap->testLdapAdBindConnection(); + } catch (Exception $e) { + $this->outputError($e); + exit(0); + } + } + + /** + * Output the json summary to the screen if enabled. + * + * @param Exception $error + */ + private function outputError($error): void + { + if ($this->option('json_summary')) { + $json_summary = [ + 'error' => true, + 'error_message' => $error->getMessage(), + 'summary' => [], + ]; + $this->info(json_encode($json_summary)); + } + $this->error($error->getMessage()); + LOG::error($error); + } } diff --git a/app/Console/Commands/MoveUploadsToNewDisk.php b/app/Console/Commands/MoveUploadsToNewDisk.php new file mode 100644 index 0000000000..505e260ce0 --- /dev/null +++ b/app/Console/Commands/MoveUploadsToNewDisk.php @@ -0,0 +1,183 @@ +error('Your current disk is set to local so we cannot proceed.'); + $this->warn("Please configure your .env settings for S3 or Rackspace, \nand change your FILESYSTEM_DISK value to 's3' or 'rackspace'."); + return false; + } + $delete_local = $this->argument('delete_local'); + + $public_uploads['accessories'] = glob('storage/app/public/accessories'."/*.*"); + $public_uploads['assets'] = glob('storage/app/public/assets'."/*.*"); + $public_uploads['avatars'] = glob('storage/app/public/avatars'."/*.*"); + $public_uploads['barcodes'] = glob('storage/app/public/barcodes'."/*.*"); + $public_uploads['categories'] = glob('storage/app/public/categories'."/*.*"); + $public_uploads['companies'] = glob('storage/app/public/companies'."/*.*"); + $public_uploads['components'] = glob('storage/app/public/components'."/*.*"); + $public_uploads['consumables'] = glob('storage/app/public/consumables'."/*.*"); + $public_uploads['departments'] = glob('storage/app/public/departments'."/*.*"); + $public_uploads['locations'] = glob('storage/app/public/locations'."/*.*"); + $public_uploads['manufacturers'] = glob('storage/app/public/manufacturers'."/*.*"); + $public_uploads['suppliers'] = glob('storage/app/public/suppliers'."/*.*"); + $public_uploads['assetmodels'] = glob('storage/app/public/models'."/*.*"); + + + // iterate files + foreach($public_uploads as $public_type => $public_upload) + { + $type_count = 0; + $this->info("\nThere are ".count($public_upload).' PUBLIC '.$public_type.' files.'); + + for ($i = 0; $i < count($public_upload); $i++) { + $type_count++; + $filename = basename($public_upload[$i]); + + try { + Storage::disk('public')->put($public_type.'/'.$filename, file_get_contents($public_upload[$i])); + $new_url = Storage::disk('public')->url($public_type.'/'.$filename, $filename); + $this->info($type_count.'. PUBLIC: '.$filename.' was copied to '.$new_url); + } catch (\Exception $e) { + \Log::debug($e); + $this->error($e); + } + + } + + } + + $logos = glob('public/uploads'."/logo*.*"); + $this->info("\nThere are ".count($logos).' files that might be logos.'); + $type_count=0; + + for ($l = 0; $l < count($logos); $l++) { + $type_count++; + $filename = basename($logos[$l]); + $new_url = Storage::disk('public')->url($logos[$l], file_get_contents($public_upload[$i])); + $this->info($type_count.'. LOGO: '.$filename.' was copied to '.$new_url); + } + + $private_uploads['assets'] = glob('storage/private_uploads/assets'."/*.*"); + $private_uploads['signatures'] = glob('storage/private_uploads/signatures'."/*.*"); + $private_uploads['audits'] = glob('storage/private_uploads/audits'."/*.*"); + $private_uploads['assetmodels'] = glob('storage/private_uploads/assetmodels'."/*.*"); + $private_uploads['imports'] = glob('storage/private_uploads/imports'."/*.*"); + $private_uploads['licenses'] = glob('storage/private_uploads/licenses'."/*.*"); + $private_uploads['users'] = glob('storage/private_uploads/users'."/*.*"); + + + foreach($private_uploads as $private_type => $private_upload) + { + $this->info("\nThere are ".count($private_upload).' PRIVATE '.$private_type.' files.'); + // $this->info(print_r($private_upload, true)); + + $type_count = 0; + for ($x = 0; $x < count($private_upload); $x++) { + $type_count++; + $filename = basename($private_upload[$x]); + + try { + Storage::disk('private_uploads')->put($private_type.'/'.$filename, file_get_contents($public_upload[$i])); + $new_url = Storage::url($private_type.'/'.$filename, $filename); + $this->info($type_count.'. PRIVATE: '.$filename.' was copied to '.$new_url); + + } catch (\Exception $e) { + \Log::debug($e); + $this->error($e); + } + + } + + } + + + if ($delete_local=='true') { + $public_delete_count = 0; + $private_delete_count = 0; + + $this->info("\n\n"); + $this->error('!!!!!!!!!!!!!!!!!!!!!!!!!!!!! WARNING!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!'); + $this->warn("\nTHIS WILL DELETE ALL OF YOUR LOCAL UPLOADED FILES. \n\nThis cannot be undone, so you should take a backup of your system before you proceed.\n"); + $this->error('!!!!!!!!!!!!!!!!!!!!!!!!!!!!! WARNING!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!'); + + if ($this->confirm("Do you wish to continue?")) { + + foreach($public_uploads as $public_type => $public_upload) { + + for ($i = 0; $i < count($public_upload); $i++) { + $filename = $public_upload[$i]; + try { + unlink($filename); + $public_delete_count++; + } catch (\Exception $e) { + \Log::debug($e); + $this->error($e); + } + + } + } + + foreach($private_uploads as $private_type => $private_upload) + { + + for ($i = 0; $i < count($private_upload); $i++) { + $filename = $private_upload[$i]; + try { + unlink($filename); + $private_delete_count++; + } catch (\Exception $e) { + \Log::debug($e); + $this->error($e); + } + + } + } + + $this->info($public_delete_count." PUBLIC local files and ".$private_delete_count." PRIVATE local files were delete from your filesystem."); + } + } + + + + + } +} diff --git a/app/Console/Commands/ObjectImportCommand.php b/app/Console/Commands/ObjectImportCommand.php index c848111bce..9f09ea7184 100644 --- a/app/Console/Commands/ObjectImportCommand.php +++ b/app/Console/Commands/ObjectImportCommand.php @@ -65,7 +65,7 @@ class ObjectImportCommand extends Command * * @return mixed */ - public function fire() + public function handle() { $filename = $this->argument('filename'); $class = title_case($this->option('item-type')); diff --git a/app/Console/Commands/SendCurrentInventoryToUsers.php b/app/Console/Commands/SendCurrentInventoryToUsers.php new file mode 100644 index 0000000000..be267e73e4 --- /dev/null +++ b/app/Console/Commands/SendCurrentInventoryToUsers.php @@ -0,0 +1,61 @@ +whereNotNull('email')->with('assets', 'accessories', 'licenses')->get(); + + $count = 0; + foreach ($users as $user) { + + if (($user->assets->count() > 0) || ($user->accessories->count() > 0) || ($user->licenses->count() > 0)) + { + $count++; + $user->notify((new CurrentInventory($user))); + } + + } + + $this->info($count.' users notified.'); + + + } +} diff --git a/app/Console/Commands/SendExpectedCheckinAlerts.php b/app/Console/Commands/SendExpectedCheckinAlerts.php index cd04aa1193..d10791200d 100644 --- a/app/Console/Commands/SendExpectedCheckinAlerts.php +++ b/app/Console/Commands/SendExpectedCheckinAlerts.php @@ -2,17 +2,15 @@ namespace App\Console\Commands; - use App\Models\Asset; use App\Models\Setting; -use Illuminate\Console\Command; -use App\Notifications\ExpectedCheckinNotification; use App\Notifications\ExpectedCheckinAdminNotification; +use App\Notifications\ExpectedCheckinNotification; use Carbon\Carbon; +use Illuminate\Console\Command; class SendExpectedCheckinAlerts extends Command { - /** * The console command name. * @@ -29,8 +27,6 @@ class SendExpectedCheckinAlerts extends Command /** * Create a new command instance. - * - * @return void */ public function __construct() { @@ -42,17 +38,17 @@ class SendExpectedCheckinAlerts extends Command * * @return mixed */ - public function fire() + public function handle() { - $settings = Setting::getSettings(); + $settings = Setting::getSettings(); $whenNotify = Carbon::now()->addDays(7); - $assets = Asset::with('assignedTo')->whereNotNull('assigned_to')->whereNotNull('expected_checkin')->where('expected_checkin', '<=', $whenNotify)->get(); + $assets = Asset::with('assignedTo')->whereNotNull('assigned_to')->whereNotNull('expected_checkin')->where('expected_checkin', '<=', $whenNotify)->get(); - $this->info($whenNotify.' is deadline'); - $this->info($assets->count().' assets'); + $this->info($whenNotify . ' is deadline'); + $this->info($assets->count() . ' assets'); foreach ($assets as $asset) { - if ($asset->assigned && $asset->checkedOutToUser()) { + if ($asset->assigned && $asset->checkedOutToUser()) { $asset->assigned->notify((new ExpectedCheckinNotification($asset))); } } @@ -60,14 +56,9 @@ class SendExpectedCheckinAlerts extends Command if (($assets) && ($assets->count() > 0) && ($settings->alert_email != '')) { // Send a rollup to the admin, if settings dictate $recipients = collect(explode(',', $settings->alert_email))->map(function ($item, $key) { - return new \App\Models\Recipients\AlertRecipient($item); + return new AlertRecipient($item); }); - \Notification::send($recipients, new ExpectedCheckinAdminNotification($assets)); + Notification::send($recipients, new ExpectedCheckinAdminNotification($assets)); } - - - - - } } diff --git a/app/Console/Commands/SendExpirationAlerts.php b/app/Console/Commands/SendExpirationAlerts.php index 29809a35b3..858f33b345 100644 --- a/app/Console/Commands/SendExpirationAlerts.php +++ b/app/Console/Commands/SendExpirationAlerts.php @@ -4,16 +4,14 @@ namespace App\Console\Commands; use App\Models\Asset; use App\Models\License; +use App\Models\Recipients\AlertRecipient; use App\Models\Setting; -use DB; -use App\Notifications\ExpiringLicenseNotification; use App\Notifications\ExpiringAssetsNotification; - +use App\Notifications\ExpiringLicenseNotification; use Illuminate\Console\Command; class SendExpirationAlerts extends Command { - /** * The console command name. * @@ -30,8 +28,6 @@ class SendExpirationAlerts extends Command /** * Create a new command instance. - * - * @return void */ public function __construct() { @@ -43,50 +39,37 @@ class SendExpirationAlerts extends Command * * @return mixed */ - public function fire() + public function handle() { - - $settings = Setting::getSettings(); + $settings = Setting::getSettings(); $threshold = $settings->alert_interval; - if (($settings->alert_email != '') && ($settings->alerts_enabled == 1)) { // Send a rollup to the admin, if settings dictate $recipients = collect(explode(',', $settings->alert_email))->map(function ($item, $key) { - return new \App\Models\Recipients\AlertRecipient($item); + return new AlertRecipient($item); }); // Expiring Assets - $assets = Asset::getExpiringWarrantee(Setting::getSettings()->alert_interval); + $assets = Asset::getExpiringWarrantee($threshold); if ($assets->count() > 0) { - $this->info(trans_choice('mail.assets_warrantee_alert', $assets->count(), - ['count' => $assets->count(), 'threshold' => $threshold])); - \Notification::send($recipients, new ExpiringAssetsNotification($assets, $threshold)); + $this->info(trans_choice('mail.assets_warrantee_alert', $assets->count(), ['count' => $assets->count(), 'threshold' => $threshold])); + Notification::send($recipients, new ExpiringAssetsNotification($assets, $threshold)); } // Expiring licenses $licenses = License::getExpiringLicenses($threshold); - - if ($licenses->count() > 0) { $this->info(trans_choice('mail.license_expiring_alert', $licenses->count(), ['count' => $licenses->count(), 'threshold' => $threshold])); - \Notification::send($recipients, new ExpiringLicenseNotification($licenses, $threshold)); + Notification::send($recipients, new ExpiringLicenseNotification($licenses, $threshold)); } - - } else { - - if ($settings->alert_email=='') { + if ($settings->alert_email == '') { $this->error('Could not send email. No alert email configured in settings'); - } elseif ($settings->alerts_enabled!=1) { + } elseif (1 != $settings->alerts_enabled) { $this->info('Alerts are disabled in the settings. No mail will be sent'); } - } - - - - } } diff --git a/app/Console/Commands/SendInventoryAlerts.php b/app/Console/Commands/SendInventoryAlerts.php index cd9627e81a..93b04978b0 100644 --- a/app/Console/Commands/SendInventoryAlerts.php +++ b/app/Console/Commands/SendInventoryAlerts.php @@ -2,13 +2,12 @@ namespace App\Console\Commands; -use App\Models\Setting; -use DB; -use Mail; use App\Helpers\Helper; +use App\Models\Recipients\AlertRecipient; +use App\Models\Setting; use App\Notifications\InventoryAlert; - use Illuminate\Console\Command; +use Illuminate\Support\Facades\Notification; class SendInventoryAlerts extends Command { @@ -28,8 +27,6 @@ class SendInventoryAlerts extends Command /** * Create a new command instance. - * - * @return void */ public function __construct() { @@ -45,29 +42,24 @@ class SendInventoryAlerts extends Command { $settings = Setting::getSettings(); - if (($settings->alert_email!='') && ($settings->alerts_enabled==1)) { - + if (($settings->alert_email != '') && ($settings->alerts_enabled == 1)) { $items = Helper::checkLowInventory(); - // Send a rollup to the admin, if settings dictate - if (($items) && (count($items) > 0)) { $this->info(trans_choice('mail.low_inventory_alert', count($items))); // Send a rollup to the admin, if settings dictate $recipients = collect(explode(',', $settings->alert_email))->map(function ($item, $key) { - return new \App\Models\Recipients\AlertRecipient($item); + return new AlertRecipient($item); }); - \Notification::send($recipients, new InventoryAlert($items, $settings->alert_threshold)); - } + Notification::send($recipients, new InventoryAlert($items, $settings->alert_threshold)); + } } else { - if (Setting::getSettings()->alert_email=='') { + if ($settings->alert_email == '') { $this->error('Could not send email. No alert email configured in settings'); - } elseif (Setting::getSettings()->alerts_enabled!=1) { + } elseif (1 != $settings->alerts_enabled) { $this->info('Alerts are disabled in the settings. No mail will be sent'); } } - - } } diff --git a/app/Console/Commands/SyncAssetCounters.php b/app/Console/Commands/SyncAssetCounters.php index bf63eaff9d..33fee840d6 100644 --- a/app/Console/Commands/SyncAssetCounters.php +++ b/app/Console/Commands/SyncAssetCounters.php @@ -39,7 +39,7 @@ class SyncAssetCounters extends Command public function handle() { $start = microtime(true); - $assets = Asset::withCount('checkins', 'checkouts', 'userRequests') + $assets = Asset::withCount('checkins as checkins_count', 'checkouts as checkouts_count', 'userRequests as user_requests_count') ->withTrashed()->get(); if ($assets) { diff --git a/app/Console/Commands/SystemBackup.php b/app/Console/Commands/SystemBackup.php index 26b1c0c750..2e4965c28b 100644 --- a/app/Console/Commands/SystemBackup.php +++ b/app/Console/Commands/SystemBackup.php @@ -36,7 +36,7 @@ class SystemBackup extends Command * * @return mixed */ - public function fire() + public function handle() { // $this->call('backup:run'); diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index 3713624422..3a68afdb1b 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -31,17 +31,17 @@ class Kernel extends ConsoleKernel Commands\RegenerateAssetTags::class, Commands\SyncAssetCounters::class, Commands\RestoreDeletedUsers::class, + Commands\SendCurrentInventoryToUsers::class, + Commands\MoveUploadsToNewDisk::class, ]; /** * Define the application's command schedule. * - * @param \Illuminate\Console\Scheduling\Schedule $schedule - * @return void + * @param \Illuminate\Console\Scheduling\Schedule $schedule */ protected function schedule(Schedule $schedule) { - $schedule->command('snipeit:inventory-alerts')->daily(); $schedule->command('snipeit:expiring-alerts')->daily(); $schedule->command('snipeit:expected-checkin')->daily(); @@ -49,6 +49,10 @@ class Kernel extends ConsoleKernel $schedule->command('backup:clean')->daily(); } + /** + * This method is required by Laravel to handle any console routes + * that are defined in routes/console.php. + */ protected function commands() { require base_path('routes/console.php'); diff --git a/app/Events/CheckoutAccepted.php b/app/Events/CheckoutAccepted.php new file mode 100644 index 0000000000..0b26e69475 --- /dev/null +++ b/app/Events/CheckoutAccepted.php @@ -0,0 +1,27 @@ +acceptance = $acceptance; + } +} diff --git a/app/Events/CheckoutDeclined.php b/app/Events/CheckoutDeclined.php new file mode 100644 index 0000000000..2aae6dd914 --- /dev/null +++ b/app/Events/CheckoutDeclined.php @@ -0,0 +1,27 @@ +acceptance = $acceptance; + } +} diff --git a/app/Events/CheckoutableCheckedIn.php b/app/Events/CheckoutableCheckedIn.php new file mode 100644 index 0000000000..0f6a96491a --- /dev/null +++ b/app/Events/CheckoutableCheckedIn.php @@ -0,0 +1,30 @@ +checkoutable = $checkoutable; + $this->checkedOutTo = $checkedOutTo; + $this->checkedInBy = $checkedInBy; + $this->note = $note; + } +} diff --git a/app/Events/CheckoutableCheckedOut.php b/app/Events/CheckoutableCheckedOut.php new file mode 100644 index 0000000000..5e6ffd243a --- /dev/null +++ b/app/Events/CheckoutableCheckedOut.php @@ -0,0 +1,30 @@ +checkoutable = $checkoutable; + $this->checkedOutTo = $checkedOutTo; + $this->checkedOutBy = $checkedOutBy; + $this->note = $note; + } +} diff --git a/app/Events/SettingSaved.php b/app/Events/SettingSaved.php new file mode 100644 index 0000000000..e8423789b7 --- /dev/null +++ b/app/Events/SettingSaved.php @@ -0,0 +1,20 @@ +settings = $settings; + } +} \ No newline at end of file diff --git a/app/Helpers/Helper.php b/app/Helpers/Helper.php index bd4b137590..5b4ca1fde0 100644 --- a/app/Helpers/Helper.php +++ b/app/Helpers/Helper.php @@ -225,8 +225,9 @@ class Helper */ public static function predefined_formats() { - $keys = array_keys(CustomField::$PredefinedFormats); + $keys = array_keys(CustomField::PREDEFINED_FORMATS); $stuff = array_combine($keys, $keys); + return $stuff; } @@ -281,9 +282,9 @@ class Helper */ public static function checkLowInventory() { - $consumables = Consumable::withCount('consumableAssignments')->whereNotNull('min_amt')->get(); - $accessories = Accessory::withCount('users')->whereNotNull('min_amt')->get(); - $components = Component::withCount('assets')->whereNotNull('min_amt')->get(); + $consumables = Consumable::withCount('consumableAssignments as consumable_assignments_count')->whereNotNull('min_amt')->get(); + $accessories = Accessory::withCount('users as users_count')->whereNotNull('min_amt')->get(); + $components = Component::withCount('assets as assets_count')->whereNotNull('min_amt')->get(); $avail_consumables = 0; $items_array = array(); @@ -669,7 +670,37 @@ class Helper return false; } + /** + * Generate a random encrypted password. + * + * @author Wes Hulette + * + * @since 5.0.0 + * + * @return string + */ + public static function generateEncyrptedPassword(): string + { + return bcrypt(Helper::generateUnencryptedPassword()); + } + /** + * Get a random unencrypted password. + * + * @author Steffen Buehl + * + * @since 5.0.0 + * + * @return string + */ + public static function generateUnencryptedPassword(): string + { + $chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; - + $password = ''; + for ( $i = 0; $i < 20; $i++ ) { + $password .= substr( $chars, random_int( 0, strlen( $chars ) - 1 ), 1 ); + } + return $password; + } } diff --git a/app/Http/Controllers/Accessories/AccessoriesController.php b/app/Http/Controllers/Accessories/AccessoriesController.php new file mode 100755 index 0000000000..0570297064 --- /dev/null +++ b/app/Http/Controllers/Accessories/AccessoriesController.php @@ -0,0 +1,208 @@ +] + * @see AccessoriesController::getDatatable() method that generates the JSON response + * @since [v1.0] + * @return View + * @throws \Illuminate\Auth\Access\AuthorizationException + */ + public function index() + { + $this->authorize('index', Accessory::class); + return view('accessories/index'); + } + + + /** + * Returns a view with a form to create a new Accessory. + * + * @author [A. Gianotto] [] + * @return View + * @throws \Illuminate\Auth\Access\AuthorizationException + */ + public function create() + { + $this->authorize('create', Accessory::class); + $category_type = 'accessory'; + return view('accessories/edit')->with('category_type', $category_type) + ->with('item', new Accessory); + } + + + /** + * Validate and save new Accessory from form post + * + * @author [A. Gianotto] [] + * @param ImageUploadRequest $request + * @return Redirect + * @throws \Illuminate\Auth\Access\AuthorizationException + */ + public function store(ImageUploadRequest $request) + { + $this->authorize(Accessory::class); + // create a new model instance + $accessory = new Accessory(); + + // Update the accessory data + $accessory->name = request('name'); + $accessory->category_id = request('category_id'); + $accessory->location_id = request('location_id'); + $accessory->min_amt = request('min_amt'); + $accessory->company_id = Company::getIdForCurrentUser(request('company_id')); + $accessory->order_number = request('order_number'); + $accessory->manufacturer_id = request('manufacturer_id'); + $accessory->model_number = request('model_number'); + $accessory->purchase_date = request('purchase_date'); + $accessory->purchase_cost = Helper::ParseFloat(request('purchase_cost')); + $accessory->qty = request('qty'); + $accessory->user_id = Auth::user()->id; + $accessory->supplier_id = request('supplier_id'); + + $accessory = $request->handleImages($accessory); + + // Was the accessory created? + if ($accessory->save()) { + // Redirect to the new accessory page + return redirect()->route('accessories.index')->with('success', trans('admin/accessories/message.create.success')); + } + return redirect()->back()->withInput()->withErrors($accessory->getErrors()); + } + + /** + * Return view for the Accessory update form, prepopulated with existing data + * + * @author [A. Gianotto] [] + * @param int $accessoryId + * @return View + * @throws \Illuminate\Auth\Access\AuthorizationException + */ + public function edit($accessoryId = null) + { + + if ($item = Accessory::find($accessoryId)) { + $this->authorize($item); + return view('accessories/edit', compact('item'))->with('category_type', 'accessory'); + } + + return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.does_not_exist')); + + } + + + /** + * Save edited Accessory from form post + * + * @author [A. Gianotto] [] + * @param ImageUploadRequest $request + * @param int $accessoryId + * @return Redirect + * @throws \Illuminate\Auth\Access\AuthorizationException + */ + public function update(ImageUploadRequest $request, $accessoryId = null) + { + if (is_null($accessory = Accessory::find($accessoryId))) { + return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.does_not_exist')); + } + + $this->authorize($accessory); + + // Update the accessory data + $accessory->name = request('name'); + $accessory->location_id = request('location_id'); + $accessory->min_amt = request('min_amt'); + $accessory->category_id = request('category_id'); + $accessory->company_id = Company::getIdForCurrentUser(request('company_id')); + $accessory->manufacturer_id = request('manufacturer_id'); + $accessory->order_number = request('order_number'); + $accessory->model_number = request('model_number'); + $accessory->purchase_date = request('purchase_date'); + $accessory->purchase_cost = request('purchase_cost'); + $accessory->qty = request('qty'); + $accessory->supplier_id = request('supplier_id'); + + $accessory = $request->handleImages($accessory); + + // Was the accessory updated? + if ($accessory->save()) { + return redirect()->route('accessories.index')->with('success', trans('admin/accessories/message.update.success')); + } + return redirect()->back()->withInput()->withErrors($accessory->getErrors()); + } + + /** + * Delete the given accessory. + * + * @author [A. Gianotto] [] + * @param int $accessoryId + * @return Redirect + * @throws \Illuminate\Auth\Access\AuthorizationException + */ + public function destroy($accessoryId) + { + if (is_null($accessory = Accessory::find($accessoryId))) { + return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.not_found')); + } + + $this->authorize($accessory); + + + if ($accessory->hasUsers() > 0) { + return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.assoc_users', array('count'=> $accessory->hasUsers()))); + } + + if ($accessory->image) { + try { + Storage::disk('public')->delete('accessories'.'/'.$accessory->image); + } catch (\Exception $e) { + \Log::debug($e); + } + } + + $accessory->delete(); + return redirect()->route('accessories.index')->with('success', trans('admin/accessories/message.delete.success')); + } + + + /** + * Returns a view that invokes the ajax table which contains + * the content for the accessory detail view, which is generated in getDataView. + * + * @author [A. Gianotto] [] + * @param int $accessoryID + * @see AccessoriesController::getDataView() method that generates the JSON response + * @since [v1.0] + * @return View + * @throws \Illuminate\Auth\Access\AuthorizationException + */ + public function show($accessoryID = null) + { + $accessory = Accessory::find($accessoryID); + $this->authorize('view', $accessory); + if (isset($accessory->id)) { + return view('accessories/view', compact('accessory')); + } + return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.does_not_exist', ['id' => $accessoryID])); + } +} diff --git a/app/Http/Controllers/Accessories/AccessoryCheckinController.php b/app/Http/Controllers/Accessories/AccessoryCheckinController.php new file mode 100644 index 0000000000..930e9b6619 --- /dev/null +++ b/app/Http/Controllers/Accessories/AccessoryCheckinController.php @@ -0,0 +1,74 @@ +] + * @param Request $request + * @param integer $accessoryUserId + * @param string $backto + * @return View + * @internal param int $accessoryId + * @throws \Illuminate\Auth\Access\AuthorizationException + */ + public function create($accessoryUserId = null, $backto = null) + { + // Check if the accessory exists + if (is_null($accessory_user = DB::table('accessories_users')->find($accessoryUserId))) { + // Redirect to the accessory management page with error + return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.not_found')); + } + + $accessory = Accessory::find($accessory_user->accessory_id); + $this->authorize('checkin', $accessory); + return view('accessories/checkin', compact('accessory'))->with('backto', $backto); + } + + /** + * Check in the item so that it can be checked out again to someone else + * + * @uses Accessory::checkin_email() to determine if an email can and should be sent + * @author [A. Gianotto] [] + * @param null $accessoryUserId + * @param string $backto + * @return Redirect + * @throws \Illuminate\Auth\Access\AuthorizationException + * @internal param int $accessoryId + */ + public function store(Request $request, $accessoryUserId = null, $backto = null) + { + // Check if the accessory exists + if (is_null($accessory_user = DB::table('accessories_users')->find($accessoryUserId))) { + // Redirect to the accessory management page with error + return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.does_not_exist')); + } + + $accessory = Accessory::find($accessory_user->accessory_id); + + $this->authorize('checkin', $accessory); + + // Was the accessory updated? + if (DB::table('accessories_users')->where('id', '=', $accessory_user->id)->delete()) { + $return_to = e($accessory_user->assigned_to); + + event(new CheckoutableCheckedIn($accessory, User::find($return_to), Auth::user(), $request->input('note'))); + + return redirect()->route("accessories.show", $accessory->id)->with('success', trans('admin/accessories/message.checkin.success')); + } + // Redirect to the accessory management page with error + return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.checkin.error')); + } +} diff --git a/app/Http/Controllers/Accessories/AccessoryCheckoutController.php b/app/Http/Controllers/Accessories/AccessoryCheckoutController.php new file mode 100644 index 0000000000..5ec8a8704f --- /dev/null +++ b/app/Http/Controllers/Accessories/AccessoryCheckoutController.php @@ -0,0 +1,88 @@ +] + * @param int $accessoryId + * @return View + * @throws \Illuminate\Auth\Access\AuthorizationException + */ + public function create($accessoryId) + { + // Check if the accessory exists + if (is_null($accessory = Accessory::find($accessoryId))) { + // Redirect to the accessory management page with error + return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.not_found')); + } + + if ($accessory->category) { + + $this->authorize('checkout', $accessory); + + // Get the dropdown of users and then pass it to the checkout view + return view('accessories/checkout', compact('accessory')); + } + + return redirect()->back()->with('error', 'The category type for this accessory is not valid. Edit the accessory and select a valid accessory category.'); + } + + /** + * Save the Accessory checkout information. + * + * If Slack is enabled and/or asset acceptance is enabled, it will also + * trigger a Slack message and send an email. + * + * @author [A. Gianotto] [] + * @param Request $request + * @param int $accessoryId + * @return Redirect + * @throws \Illuminate\Auth\Access\AuthorizationException + */ + public function store(Request $request, $accessoryId) + { + // Check if the accessory exists + if (is_null($accessory = Accessory::find($accessoryId))) { + // Redirect to the accessory management page with error + return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.user_not_found')); + } + + $this->authorize('checkout', $accessory); + + if (!$user = User::find(Input::get('assigned_to'))) { + return redirect()->route('checkout/accessory', $accessory->id)->with('error', trans('admin/accessories/message.checkout.user_does_not_exist')); + } + + // Update the accessory data + $accessory->assigned_to = e(Input::get('assigned_to')); + + $accessory->users()->attach($accessory->id, [ + 'accessory_id' => $accessory->id, + 'created_at' => Carbon::now(), + 'user_id' => Auth::id(), + 'assigned_to' => $request->get('assigned_to') + ]); + + DB::table('accessories_users')->where('assigned_to', '=', $accessory->assigned_to)->where('accessory_id', '=', $accessory->id)->first(); + + event(new CheckoutableCheckedOut($accessory, $user, Auth::user(), $request->input('note'))); + + // Redirect to the new accessory page + return redirect()->route('accessories.index')->with('success', trans('admin/accessories/message.checkout.success')); + } +} diff --git a/app/Http/Controllers/AccessoriesController.php b/app/Http/Controllers/AccessoriesController.php deleted file mode 100755 index c98b739ab0..0000000000 --- a/app/Http/Controllers/AccessoriesController.php +++ /dev/null @@ -1,400 +0,0 @@ -] - * @see AccessoriesController::getDatatable() method that generates the JSON response - * @since [v1.0] - * @return View - */ - public function index(Request $request) - { - $this->authorize('index', Accessory::class); - return view('accessories/index'); - } - - - /** - * Returns a view with a form to create a new Accessory. - * - * @author [A. Gianotto] [] - * @return View - */ - public function create(Request $request) - { - $this->authorize('create', Accessory::class); - $category_type = 'accessory'; - return view('accessories/edit')->with('category_type', $category_type) - ->with('item', new Accessory); - } - - - /** - * Validate and save new Accessory from form post - * - * @author [A. Gianotto] [] - * @return Redirect - */ - public function store(ImageUploadRequest $request) - { - $this->authorize(Accessory::class); - // create a new model instance - $accessory = new Accessory(); - - // Update the accessory data - $accessory->name = request('name'); - $accessory->category_id = request('category_id'); - $accessory->location_id = request('location_id'); - $accessory->min_amt = request('min_amt'); - $accessory->company_id = Company::getIdForCurrentUser(request('company_id')); - $accessory->order_number = request('order_number'); - $accessory->manufacturer_id = request('manufacturer_id'); - $accessory->model_number = request('model_number'); - $accessory->purchase_date = request('purchase_date'); - $accessory->purchase_cost = Helper::ParseFloat(request('purchase_cost')); - $accessory->qty = request('qty'); - $accessory->user_id = Auth::user()->id; - $accessory->supplier_id = request('supplier_id'); - - if ($request->hasFile('image')) { - - if (!config('app.lock_passwords')) { - $image = $request->file('image'); - $ext = $image->getClientOriginalExtension(); - $file_name = "accessory-".str_random(18).'.'.$ext; - $path = public_path('/uploads/accessories'); - if ($image->getClientOriginalExtension()!='svg') { - Image::make($image->getRealPath())->resize(null, 250, function ($constraint) { - $constraint->aspectRatio(); - $constraint->upsize(); - })->save($path.'/'.$file_name); - } else { - $image->move($path, $file_name); - } - $accessory->image = $file_name; - } - } - - - - // Was the accessory created? - if ($accessory->save()) { - // Redirect to the new accessory page - return redirect()->route('accessories.index')->with('success', trans('admin/accessories/message.create.success')); - } - return redirect()->back()->withInput()->withErrors($accessory->getErrors()); - } - - /** - * Return view for the Accessory update form, prepopulated with existing data - * - * @author [A. Gianotto] [] - * @param int $accessoryId - * @return View - */ - public function edit(Request $request, $accessoryId = null) - { - - if ($item = Accessory::find($accessoryId)) { - $this->authorize($item); - $category_type = 'accessory'; - return view('accessories/edit', compact('item'))->with('category_type', $category_type); - } - - return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.does_not_exist')); - - } - - - /** - * Save edited Accessory from form post - * - * @author [A. Gianotto] [] - * @param int $accessoryId - * @return Redirect - */ - public function update(ImageUploadRequest $request, $accessoryId = null) - { - if (is_null($accessory = Accessory::find($accessoryId))) { - return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.does_not_exist')); - } - - $this->authorize($accessory); - - // Update the accessory data - $accessory->name = request('name'); - $accessory->location_id = request('location_id'); - $accessory->min_amt = request('min_amt'); - $accessory->category_id = request('category_id'); - $accessory->company_id = Company::getIdForCurrentUser(request('company_id')); - $accessory->manufacturer_id = request('manufacturer_id'); - $accessory->order_number = request('order_number'); - $accessory->model_number = request('model_number'); - $accessory->purchase_date = request('purchase_date'); - $accessory->purchase_cost = request('purchase_cost'); - $accessory->qty = request('qty'); - $accessory->supplier_id = request('supplier_id'); - - if ($request->hasFile('image')) { - - if (!config('app.lock_passwords')) { - $image = $request->file('image'); - $ext = $image->getClientOriginalExtension(); - $file_name = "accessory-".str_random(18).'.'.$ext; - $path = public_path('/uploads/accessories'); - if ($image->getClientOriginalExtension()!='svg') { - Image::make($image->getRealPath())->resize(null, 250, function ($constraint) { - $constraint->aspectRatio(); - $constraint->upsize(); - })->save($path.'/'.$file_name); - } else { - $image->move($path, $file_name); - } - if (($accessory->image) && (file_exists($path.'/'.$accessory->image))) { - unlink($path.'/'.$accessory->image); - } - - $accessory->image = $file_name; - } - } - - - // Was the accessory updated? - if ($accessory->save()) { - return redirect()->route('accessories.index')->with('success', trans('admin/accessories/message.update.success')); - } - return redirect()->back()->withInput()->withErrors($accessory->getErrors()); - } - - /** - * Delete the given accessory. - * - * @author [A. Gianotto] [] - * @param int $accessoryId - * @return Redirect - */ - public function destroy(Request $request, $accessoryId) - { - if (is_null($accessory = Accessory::find($accessoryId))) { - return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.not_found')); - } - - $this->authorize($accessory); - - - if ($accessory->hasUsers() > 0) { - return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.assoc_users', array('count'=> $accessory->hasUsers()))); - } - $accessory->delete(); - return redirect()->route('accessories.index')->with('success', trans('admin/accessories/message.delete.success')); - } - - - - /** - * Returns a view that invokes the ajax table which contains - * the content for the accessory detail view, which is generated in getDataView. - * - * @author [A. Gianotto] [] - * @param int $accessoryID - * @see AccessoriesController::getDataView() method that generates the JSON response - * @since [v1.0] - * @return View - */ - public function show(Request $request, $accessoryID = null) - { - $accessory = Accessory::find($accessoryID); - $this->authorize('view', $accessory); - if (isset($accessory->id)) { - return view('accessories/view', compact('accessory')); - } - return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.does_not_exist', compact('id'))); - } - - /** - * Return the form to checkout an Accessory to a user. - * - * @author [A. Gianotto] [] - * @param int $accessoryId - * @return View - */ - public function getCheckout(Request $request, $accessoryId) - { - // Check if the accessory exists - if (is_null($accessory = Accessory::find($accessoryId))) { - // Redirect to the accessory management page with error - return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.not_found')); - } - - if ($accessory->category) { - - $this->authorize('checkout', $accessory); - - // Get the dropdown of users and then pass it to the checkout view - return view('accessories/checkout', compact('accessory')); - } - - return redirect()->back()->with('error', 'The category type for this accessory is not valid. Edit the accessory and select a valid accessory category.'); - - - - } - - /** - * Save the Accessory checkout information. - * - * If Slack is enabled and/or asset acceptance is enabled, it will also - * trigger a Slack message and send an email. - * - * @author [A. Gianotto] [] - * @param int $accessoryId - * @return Redirect - */ - public function postCheckout(Request $request, $accessoryId) - { - // Check if the accessory exists - if (is_null($accessory = Accessory::find($accessoryId))) { - // Redirect to the accessory management page with error - return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.user_not_found')); - } - - $this->authorize('checkout', $accessory); - - if (!$user = User::find(Input::get('assigned_to'))) { - return redirect()->route('checkout/accessory', $accessory->id)->with('error', trans('admin/accessories/message.checkout.user_does_not_exist')); - } - - // Update the accessory data - $accessory->assigned_to = e(Input::get('assigned_to')); - - $accessory->users()->attach($accessory->id, [ - 'accessory_id' => $accessory->id, - 'created_at' => Carbon::now(), - 'user_id' => Auth::id(), - 'assigned_to' => $request->get('assigned_to') - ]); - - $logaction = $accessory->logCheckout(e(Input::get('note')), $user); - - DB::table('accessories_users')->where('assigned_to', '=', $accessory->assigned_to)->where('accessory_id', '=', $accessory->id)->first(); - - $data['log_id'] = $logaction->id; - $data['eula'] = $accessory->getEula(); - $data['first_name'] = $user->first_name; - $data['item_name'] = $accessory->name; - $data['checkout_date'] = $logaction->created_at; - $data['item_tag'] = ''; - $data['expected_checkin'] = ''; - $data['note'] = $logaction->note; - $data['require_acceptance'] = $accessory->requireAcceptance(); - - // Redirect to the new accessory page - return redirect()->route('accessories.index')->with('success', trans('admin/accessories/message.checkout.success')); - } - - - /** - * Check the accessory back into inventory - * - * @author [A. Gianotto] [] - * @param Request $request - * @param integer $accessoryUserId - * @param string $backto - * @return View - * @internal param int $accessoryId - */ - public function getCheckin(Request $request, $accessoryUserId = null, $backto = null) - { - // Check if the accessory exists - if (is_null($accessory_user = DB::table('accessories_users')->find($accessoryUserId))) { - // Redirect to the accessory management page with error - return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.not_found')); - } - - $accessory = Accessory::find($accessory_user->accessory_id); - $this->authorize('checkin', $accessory); - return view('accessories/checkin', compact('accessory'))->with('backto', $backto); - } - - - /** - * Check in the item so that it can be checked out again to someone else - * - * @uses Accessory::checkin_email() to determine if an email can and should be sent - * @author [A. Gianotto] [] - * @param Request $request - * @param integer $accessoryUserId - * @param string $backto - * @return Redirect - * @internal param int $accessoryId - */ - public function postCheckin(Request $request, $accessoryUserId = null, $backto = null) - { - // Check if the accessory exists - if (is_null($accessory_user = DB::table('accessories_users')->find($accessoryUserId))) { - // Redirect to the accessory management page with error - return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.does_not_exist')); - } - - $accessory = Accessory::find($accessory_user->accessory_id); - - $this->authorize('checkin', $accessory); - - $return_to = e($accessory_user->assigned_to); - $logaction = $accessory->logCheckin(User::find($return_to), e(Input::get('note'))); - - // Was the accessory updated? - if (DB::table('accessories_users')->where('id', '=', $accessory_user->id)->delete()) { - if (!is_null($accessory_user->assigned_to)) { - $user = User::find($accessory_user->assigned_to); - } - - $data['log_id'] = $logaction->id; - $data['first_name'] = e($user->first_name); - $data['last_name'] = e($user->last_name); - $data['item_name'] = e($accessory->name); - $data['checkin_date'] = e($logaction->created_at); - $data['item_tag'] = ''; - $data['note'] = e($logaction->note); - - if ($backto=='user') { - return redirect()->route("users.show", $return_to)->with('success', trans('admin/accessories/message.checkin.success')); - } - return redirect()->route("accessories.show", $accessory->id)->with('success', trans('admin/accessories/message.checkin.success')); - } - // Redirect to the accessory management page with error - return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.checkin.error')); - } - - -} diff --git a/app/Http/Controllers/Account/AcceptanceController.php b/app/Http/Controllers/Account/AcceptanceController.php new file mode 100644 index 0000000000..23cd29d2d0 --- /dev/null +++ b/app/Http/Controllers/Account/AcceptanceController.php @@ -0,0 +1,130 @@ +pending()->get(); + + return view('account/accept.index', compact('acceptances')); + } + + /** + * Shows a form to either accept or decline the checkout acceptance + * + * @param int $id + * @return mixed + */ + public function create($id) { + + $acceptance = CheckoutAcceptance::find($id); + + if (is_null($acceptance)) { + return redirect()->route('account.accept')->with('error', trans('admin/hardware/message.does_not_exist')); + } + + if (! $acceptance->isPending()) { + return redirect()->route('account.accept')->with('error', trans('admin/users/message.error.asset_already_accepted')); + } + + if (! $acceptance->isCheckedOutTo(Auth::user())) { + return redirect()->route('account.accept')->with('error', trans('admin/users/message.error.incorrect_user_accepted')); + } + + if (!Company::isCurrentUserHasAccess($acceptance->checkoutable)) { + return redirect()->route('account.accept')->with('error', trans('general.insufficient_permissions')); + } + + return view('account/accept.create', compact('acceptance')); + } + + /** + * Stores the accept/decline of the checkout acceptance + * + * @param Request $request + * @param int $id + * @return Redirect + */ + public function store(Request $request, $id) { + + $acceptance = CheckoutAcceptance::find($id); + + if (is_null($acceptance)) { + return redirect()->route('account.accept')->with('error', trans('admin/hardware/message.does_not_exist')); + } + + if (! $acceptance->isPending()) { + return redirect()->route('account.accept')->with('error', trans('admin/users/message.error.asset_already_accepted')); + } + + if (! $acceptance->isCheckedOutTo(Auth::user())) { + return redirect()->route('account.accept')->with('error', trans('admin/users/message.error.incorrect_user_accepted')); + } + + if (!Company::isCurrentUserHasAccess($acceptance->checkoutable)) { + return redirect()->route('account.accept')->with('error', trans('general.insufficient_permissions')); + } + + if (!$request->filled('asset_acceptance')) { + return redirect()->back()->with('error', trans('admin/users/message.error.accept_or_decline')); + } + + /** + * Get the signature and save it + */ + + if (!Storage::exists('private_uploads/signatures')) Storage::makeDirectory('private_uploads/signatures', 775); + + + + if ($request->filled('signature_output')) { + $sig_filename = "siglog-" .Str::uuid() . '-'.date('Y-m-d-his').".png"; + $data_uri = e($request->input('signature_output')); + $encoded_image = explode(",", $data_uri); + $decoded_image = base64_decode($encoded_image[1]); + Storage::put('private_uploads/signatures/'.$sig_filename, (string)$decoded_image); + } + + + if ($request->input('asset_acceptance') == 'accepted') { + + $acceptance->accept($sig_filename); + + event(new CheckoutAccepted($acceptance)); + + $return_msg = trans('admin/users/message.accepted'); + + } else { + + $acceptance->decline($sig_filename); + + event(new CheckoutDeclined($acceptance)); + + $return_msg = trans('admin/users/message.declined'); + + } + + return redirect()->to('account/accept')->with('success', $return_msg); + } +} diff --git a/app/Http/Controllers/Api/AccessoriesController.php b/app/Http/Controllers/Api/AccessoriesController.php index fcdc52d210..4e4793dcfa 100644 --- a/app/Http/Controllers/Api/AccessoriesController.php +++ b/app/Http/Controllers/Api/AccessoriesController.php @@ -26,23 +26,23 @@ class AccessoriesController extends Controller $accessories = Accessory::with('category', 'company', 'manufacturer', 'users', 'location'); - if ($request->has('search')) { + if ($request->filled('search')) { $accessories = $accessories->TextSearch($request->input('search')); } - if ($request->has('company_id')) { + if ($request->filled('company_id')) { $accessories->where('company_id','=',$request->input('company_id')); } - if ($request->has('category_id')) { + if ($request->filled('category_id')) { $accessories->where('category_id','=',$request->input('category_id')); } - if ($request->has('manufacturer_id')) { + if ($request->filled('manufacturer_id')) { $accessories->where('manufacturer_id','=',$request->input('manufacturer_id')); } - if ($request->has('supplier_id')) { + if ($request->filled('supplier_id')) { $accessories->where('supplier_id','=',$request->input('supplier_id')); } @@ -132,18 +132,28 @@ class AccessoriesController extends Controller * @param int $id * @return \Illuminate\Http\Response */ - public function checkedout($id) + public function checkedout($id, Request $request) { $this->authorize('view', Accessory::class); - $accessory = Accessory::findOrFail($id); + $accessory = Accessory::with('lastCheckout')->findOrFail($id); if (!Company::isCurrentUserHasAccess($accessory)) { return ['total' => 0, 'rows' => []]; } - $accessory_users = $accessory->users; - $total = $accessory_users->count(); - return (new AccessoriesTransformer)->transformCheckedoutAccessory($accessory_users, $total); + $accessory->lastCheckoutArray = $accessory->lastCheckout->toArray(); + $accessory_users = $accessory->users; + + if ($request->filled('search')) { + $accessory_users = $accessory->users() + ->where('first_name', 'like', '%'.$request->input('search').'%') + ->orWhere('last_name', 'like', '%'.$request->input('search').'%') + ->get(); + } + + $total = $accessory_users->count(); + + return (new AccessoriesTransformer)->transformCheckedoutAccessory($accessory, $accessory_users, $total); } diff --git a/app/Http/Controllers/Api/AssetMaintenancesController.php b/app/Http/Controllers/Api/AssetMaintenancesController.php index 682d3d2db0..e292ac11af 100644 --- a/app/Http/Controllers/Api/AssetMaintenancesController.php +++ b/app/Http/Controllers/Api/AssetMaintenancesController.php @@ -34,13 +34,13 @@ class AssetMaintenancesController extends Controller */ public function index(Request $request) { - $maintenances = AssetMaintenance::with('asset', 'supplier', 'asset.company', 'admin'); + $maintenances = AssetMaintenance::with('asset', 'asset.model','asset.location', 'supplier', 'asset.company', 'admin'); - if (Input::has('search')) { - $maintenances = $maintenances->TextSearch(e($request->input('search'))); + if ($request->filled('search')) { + $maintenances = $maintenances->TextSearch($request->input('search')); } - if ($request->has('asset_id')) { + if ($request->filled('asset_id')) { $maintenances->where('asset_id', '=', $request->input('asset_id')); } diff --git a/app/Http/Controllers/Api/AssetModelsController.php b/app/Http/Controllers/Api/AssetModelsController.php index 1d9d9c4d4a..289348f17c 100644 --- a/app/Http/Controllers/Api/AssetModelsController.php +++ b/app/Http/Controllers/Api/AssetModelsController.php @@ -9,6 +9,7 @@ use Illuminate\Http\Request; use App\Http\Transformers\AssetModelsTransformer; use App\Http\Transformers\AssetsTransformer; use App\Http\Transformers\SelectlistTransformer; +use Illuminate\Support\Facades\Storage; /** @@ -48,15 +49,15 @@ class AssetModelsController extends Controller 'models.updated_at', ]) ->with('category','depreciation', 'manufacturer','fieldset') - ->withCount('assets'); + ->withCount('assets as assets_count'); - if ($request->has('status')) { + if ($request->filled('status')) { $assetmodels->onlyTrashed(); } - if ($request->has('search')) { + if ($request->filled('search')) { $assetmodels->TextSearch($request->input('search')); } @@ -114,7 +115,7 @@ class AssetModelsController extends Controller public function show($id) { $this->authorize('view', AssetModel::class); - $assetmodel = AssetModel::withCount('assets')->findOrFail($id); + $assetmodel = AssetModel::withCount('assets as assets_count')->findOrFail($id); return (new AssetModelsTransformer)->transformAssetModel($assetmodel); } @@ -177,7 +178,7 @@ class AssetModelsController extends Controller if ($assetmodel->image) { try { - unlink(public_path().'/uploads/models/'.$assetmodel->image); + Storage::disk('public')->delete('assetmodels/'.$assetmodel->image); } catch (\Exception $e) { \Log::error($e); } @@ -210,7 +211,7 @@ class AssetModelsController extends Controller $settings = \App\Models\Setting::getSettings(); - if ($request->has('search')) { + if ($request->filled('search')) { $assetmodels = $assetmodels->SearchByManufacturerOrCat($request->input('search')); } @@ -234,7 +235,7 @@ class AssetModelsController extends Controller $assetmodel->use_text .= ' (#'.e($assetmodel->model_number).')'; } - $assetmodel->use_image = ($settings->modellistCheckedValue('image') && ($assetmodel->image)) ? url('/').'/uploads/models/'.$assetmodel->image : null; + $assetmodel->use_image = ($settings->modellistCheckedValue('image') && ($assetmodel->image)) ? Storage::disk('public')->url('assetmodels/'.e($assetmodel->image)) : null; } return (new SelectlistTransformer)->transformSelectlist($assetmodels); diff --git a/app/Http/Controllers/Api/AssetsController.php b/app/Http/Controllers/Api/AssetsController.php index 6dfe6b9910..8cae0e3dbf 100644 --- a/app/Http/Controllers/Api/AssetsController.php +++ b/app/Http/Controllers/Api/AssetsController.php @@ -3,13 +3,14 @@ namespace App\Http\Controllers\Api; use App\Helpers\Helper; use App\Http\Controllers\Controller; -use App\Http\Requests\AssetRequest; use App\Http\Requests\AssetCheckoutRequest; use App\Http\Transformers\AssetsTransformer; +use App\Http\Transformers\LicensesTransformer; use App\Models\Asset; use App\Models\AssetModel; use App\Models\Company; use App\Models\CustomField; +use App\Models\License; use App\Models\Location; use App\Models\Setting; use App\Models\User; @@ -84,7 +85,7 @@ class AssetsController extends Controller $filter = array(); - if ($request->has('filter')) { + if ($request->filled('filter')) { $filter = json_decode($request->input('filter'), true); } @@ -101,7 +102,7 @@ class AssetsController extends Controller // These are used by the API to query against specific ID numbers. // They are also used by the individual searches on detail pages like // locations, etc. - if ($request->has('status_id')) { + if ($request->filled('status_id')) { $assets->where('assets.status_id', '=', $request->input('status_id')); } @@ -109,40 +110,40 @@ class AssetsController extends Controller $assets->where('assets.requestable', '=', '1'); } - if ($request->has('model_id')) { + if ($request->filled('model_id')) { $assets->InModelList([$request->input('model_id')]); } - if ($request->has('category_id')) { + if ($request->filled('category_id')) { $assets->InCategory($request->input('category_id')); } - if ($request->has('location_id')) { + if ($request->filled('location_id')) { $assets->where('assets.location_id', '=', $request->input('location_id')); } - if ($request->has('supplier_id')) { + if ($request->filled('supplier_id')) { $assets->where('assets.supplier_id', '=', $request->input('supplier_id')); } - if (($request->has('assigned_to')) && ($request->has('assigned_type'))) { + if (($request->filled('assigned_to')) && ($request->filled('assigned_type'))) { $assets->where('assets.assigned_to', '=', $request->input('assigned_to')) ->where('assets.assigned_type', '=', $request->input('assigned_type')); } - if ($request->has('company_id')) { + if ($request->filled('company_id')) { $assets->where('assets.company_id', '=', $request->input('company_id')); } - if ($request->has('manufacturer_id')) { + if ($request->filled('manufacturer_id')) { $assets->ByManufacturer($request->input('manufacturer_id')); } - if ($request->has('depreciation_id')) { + if ($request->filled('depreciation_id')) { $assets->ByDepreciationId($request->input('depreciation_id')); } - $request->has('order_number') ? $assets = $assets->where('assets.order_number', '=', e($request->get('order_number'))) : ''; + $request->filled('order_number') ? $assets = $assets->where('assets.order_number', '=', e($request->get('order_number'))) : ''; $offset = request('offset', 0); $limit = $request->input('limit', 50); @@ -155,7 +156,7 @@ class AssetsController extends Controller // I am sad. :( switch ($request->input('status')) { case 'Deleted': - $assets->withTrashed()->Deleted(); + $assets->onlyTrashed(); break; case 'Pending': $assets->join('status_labels AS status_alias',function ($join) { @@ -201,7 +202,7 @@ class AssetsController extends Controller break; default: - if ((!$request->has('status_id')) && ($settings->show_archived_in_list!='1')) { + if ((!$request->filled('status_id')) && ($settings->show_archived_in_list!='1')) { // terrible workaround for complex-query Laravel bug in fulltext $assets->join('status_labels AS status_alias',function ($join) { $join->on('status_alias.id', "=", "assets.status_id") @@ -220,7 +221,7 @@ class AssetsController extends Controller if ((!is_null($filter)) && (count($filter)) > 0) { $assets->ByFilter($filter); - } elseif ($request->has('search')) { + } elseif ($request->filled('search')) { $assets->TextSearch($request->input('search')); } @@ -270,9 +271,9 @@ class AssetsController extends Controller break; } - $total = $assets->count(); $assets = $assets->skip($offset)->take($limit)->get(); + // dd($assets); return (new AssetsTransformer)->transformAssets($assets, $total); } @@ -308,8 +309,7 @@ class AssetsController extends Controller $this->authorize('index', Asset::class); if ($assets = Asset::with('assetstatus')->with('assignedTo') ->withTrashed()->where('serial',$serial)->get()) { - - return (new AssetsTransformer)->transformAssets($assets, $assets->count()); + return (new AssetsTransformer)->transformAssets($assets, $assets->count()); } return response()->json(Helper::formatStandardApiResponse('error', null, 'Asset not found'), 200); @@ -326,14 +326,22 @@ class AssetsController extends Controller */ public function show($id) { - if ($asset = Asset::with('assetstatus')->with('assignedTo')->withTrashed()->withCount('checkins', 'checkouts', 'userRequests')->findOrFail($id)) { + if ($asset = Asset::with('assetstatus')->with('assignedTo')->withTrashed() + ->withCount('checkins as checkins_count', 'checkouts as checkouts_count', 'userRequests as user_requests_count')->findOrFail($id)) { $this->authorize('view', $asset); return (new AssetsTransformer)->transformAsset($asset); } } - + public function licenses($id) + { + $this->authorize('view', Asset::class); + $this->authorize('view', License::class); + $asset = Asset::where('id', $id)->withTrashed()->first(); + $licenses = $asset->licenses()->get(); + return (new LicensesTransformer())->transformLicenses($licenses, $licenses->count()); + } /** * Gets a paginated collection for the select2 menus @@ -354,13 +362,13 @@ class AssetsController extends Controller 'assets.assigned_to', 'assets.assigned_type', 'assets.status_id' - ])->with('model', 'assetstatus', 'assignedTo')->NotArchived(),'company_id', 'assets'); + ])->with('model', 'assetstatus', 'assignedTo')->NotArchived()); - if ($request->has('assetStatusType') && $request->input('assetStatusType') === 'RTD') { + if ($request->filled('assetStatusType') && $request->input('assetStatusType') === 'RTD') { $assets = $assets->RTD(); } - if ($request->has('search')) { + if ($request->filled('search')) { $assets = $assets->AssignedSearch($request->input('search')); } @@ -379,7 +387,7 @@ class AssetsController extends Controller $asset->use_text .= ' → '.$asset->assigned->getFullNameAttribute(); } - + if ($asset->assetstatus->getStatuslabelType()=='pending') { $asset->use_text .= '('.$asset->assetstatus->getStatuslabelType().')'; } @@ -400,7 +408,7 @@ class AssetsController extends Controller * @since [v4.0] * @return JsonResponse */ - public function store(AssetRequest $request) + public function store(Request $request) { $this->authorize('create', Asset::class); @@ -431,7 +439,7 @@ class AssetsController extends Controller // Update custom fields in the database. // Validation for these fields is handled through the AssetRequest form request $model = AssetModel::find($request->get('model_id')); - if ($model->fieldset) { + if (($model) && ($model->fieldset)) { foreach ($model->fieldset->fields as $field) { $asset->{$field->convertUnicodeDbSlug()} = e($request->input($field->convertUnicodeDbSlug(), null)); } @@ -468,21 +476,22 @@ class AssetsController extends Controller { $this->authorize('update', Asset::class); + $asset->fill($request->all()); + + if ($asset = Asset::find($id)) { - - $asset->fill($request->all()); - - ($request->has('model_id')) ? + ($request->filled('model_id')) ? $asset->model()->associate(AssetModel::find($request->get('model_id'))) : null; - ($request->has('company_id')) ? - $asset->company_id = Company::getIdForCurrentUser($request->get('company_id')) : null; - ($request->has('rtd_location_id')) ? - $asset->location_id = $request->get('rtd_location_id') : null; + ($request->filled('rtd_location_id')) ? + $asset->location_id = $request->get('rtd_location_id') : ''; + ($request->filled('company_id')) ? + $asset->company_id = Company::getIdForCurrentUser($request->get('company_id')) : ''; + // Update custom fields if (($model = AssetModel::find($asset->model_id)) && (isset($model->fieldset))) { foreach ($model->fieldset->fields as $field) { - if ($request->has($field->convertUnicodeDbSlug())) { + if ($request->filled($field->convertUnicodeDbSlug())) { $asset->{$field->convertUnicodeDbSlug()} = e($request->input($field->convertUnicodeDbSlug())); } } @@ -491,11 +500,11 @@ class AssetsController extends Controller if ($asset->save()) { - if (($request->has('assigned_user')) && ($target = User::find($request->get('assigned_user')))) { - $location = $target->location_id; - } elseif (($request->has('assigned_asset')) && ($target = Asset::find($request->get('assigned_asset')))) { - $location = $target->location_id; - } elseif (($request->has('assigned_location')) && ($target = Location::find($request->get('assigned_location')))) { + if (($request->filled('assigned_user')) && ($target = User::find($request->get('assigned_user')))) { + $location = $target->location_id; + } elseif (($request->filled('assigned_asset')) && ($target = Asset::find($request->get('assigned_asset')))) { + $location = $target->location_id; + } elseif (($request->filled('assigned_location')) && ($target = Location::find($request->get('assigned_location')))) { $location = $target->id; } @@ -650,7 +659,7 @@ class AssetsController extends Controller $asset->name = Input::get('name'); $asset->location_id = $asset->rtd_location_id; - if ($request->has('location_id')) { + if ($request->filled('location_id')) { $asset->location_id = $request->input('location_id'); } @@ -690,13 +699,27 @@ class AssetsController extends Controller return response()->json(Helper::formatStandardApiResponse('error', null, $validator->errors()->all())); } + $settings = Setting::getSettings(); + $dt = Carbon::now()->addMonths($settings->audit_interval)->toDateString(); + $asset = Asset::where('asset_tag','=', $request->input('asset_tag'))->first(); if ($asset) { // We don't want to log this as a normal update, so let's bypass that $asset->unsetEventDispatcher(); - $asset->next_audit_date = $request->input('next_audit_date'); + $asset->next_audit_date = $dt; + + if ($request->filled('next_audit_date')) { + $asset->next_audit_date = $request->input('next_audit_date'); + } + + // Check to see if they checked the box to update the physical location, + // not just note it in the audit notes + if ($request->input('update_location')=='1') { + $asset->location_id = $request->input('location_id'); + } + $asset->last_audit_date = date('Y-m-d h:i:s'); if ($asset->save()) { @@ -704,7 +727,7 @@ class AssetsController extends Controller return response()->json(Helper::formatStandardApiResponse('success', [ 'asset_tag'=> e($asset->asset_tag), 'note'=> e($request->input('note')), - 'next_audit_date' => Helper::getFormattedDateObject($log->calcNextAuditDate()) + 'next_audit_date' => Helper::getFormattedDateObject($asset->next_audit_date) ], trans('admin/hardware/message.audit.success'))); } } diff --git a/app/Http/Controllers/Api/CategoriesController.php b/app/Http/Controllers/Api/CategoriesController.php index 190b6f248a..1cee93110c 100644 --- a/app/Http/Controllers/Api/CategoriesController.php +++ b/app/Http/Controllers/Api/CategoriesController.php @@ -8,6 +8,7 @@ use App\Helpers\Helper; use App\Models\Category; use App\Http\Transformers\CategoriesTransformer; use App\Http\Transformers\SelectlistTransformer; +use Illuminate\Support\Facades\Storage; class CategoriesController extends Controller { @@ -24,9 +25,9 @@ class CategoriesController extends Controller $allowed_columns = ['id', 'name','category_type', 'category_type','use_default_eula','eula_text', 'require_acceptance','checkin_email', 'assets_count', 'accessories_count', 'consumables_count', 'components_count','licenses_count', 'image']; $categories = Category::select(['id', 'created_at', 'updated_at', 'name','category_type','use_default_eula','eula_text', 'require_acceptance','checkin_email','image']) - ->withCount('assets', 'accessories', 'consumables', 'components','licenses'); + ->withCount('assets as assets_count', 'accessories as accessories_count', 'consumables as consumables_count', 'components as components_count','licenses as licenses_count'); - if ($request->has('search')) { + if ($request->filled('search')) { $categories = $categories->TextSearch($request->input('search')); } @@ -114,15 +115,15 @@ class CategoriesController extends Controller public function destroy($id) { $this->authorize('delete', Category::class); - $category = Category::findOrFail($id); + $category = Category::withCount('models as models_count', 'accessories as accessories_count','consumables as consumables_count','components as components_count')->findOrFail($id); - if ($category->has_models() > 0) { + if ($category->models_count > 0) { return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/categories/message.assoc_items', ['asset_type'=>'model']))); - } elseif ($category->accessories()->count() > 0) { + } elseif ($category->accessories_count > 0) { return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/categories/message.assoc_items', ['asset_type'=>'accessory']))); - } elseif ($category->consumables()->count() > 0) { + } elseif ($category->consumables_count > 0) { return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/categories/message.assoc_items', ['asset_type'=>'consumable']))); - } elseif ($category->components()->count() > 0) { + } elseif ($category->components_count > 0) { return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/categories/message.assoc_items', ['asset_type'=>'component']))); } $category->delete(); @@ -148,7 +149,7 @@ class CategoriesController extends Controller 'image', ]); - if ($request->has('search')) { + if ($request->filled('search')) { $categories = $categories->where('name', 'LIKE', '%'.$request->get('search').'%'); } @@ -158,7 +159,7 @@ class CategoriesController extends Controller // This lets us have more flexibility in special cases like assets, where // they may not have a ->name value but we want to display something anyway foreach ($categories as $category) { - $category->use_image = ($category->image) ? url('/').'/uploads/categories/'.$category->image : null; + $category->use_image = ($category->image) ? Storage::disk('public')->url('categories/'.$category->image, $category->image) : null; } return (new SelectlistTransformer)->transformSelectlist($categories); diff --git a/app/Http/Controllers/Api/CompaniesController.php b/app/Http/Controllers/Api/CompaniesController.php index c960561b48..6b1c63f54b 100644 --- a/app/Http/Controllers/Api/CompaniesController.php +++ b/app/Http/Controllers/Api/CompaniesController.php @@ -35,9 +35,9 @@ class CompaniesController extends Controller 'components_count', ]; - $companies = Company::withCount('assets','licenses','accessories','consumables','components','users'); + $companies = Company::withCount('assets as assets_count','licenses as licenses_count','accessories as accessories_count','consumables as consumables_count','components as components_count','users as users_count'); - if ($request->has('search')) { + if ($request->filled('search')) { $companies->TextSearch($request->input('search')); } @@ -168,7 +168,7 @@ class CompaniesController extends Controller 'companies.image', ]); - if ($request->has('search')) { + if ($request->filled('search')) { $companies = $companies->where('companies.name', 'LIKE', '%'.$request->get('search').'%'); } @@ -178,7 +178,7 @@ class CompaniesController extends Controller // This lets us have more flexibility in special cases like assets, where // they may not have a ->name value but we want to display something anyway foreach ($companies as $company) { - $company->use_image = ($company->image) ? url('/').'/uploads/companies/'.$company->image : null; + $company->use_image = ($company->image) ? Storage::disk('public')->url('companies/'.$company->image, $company->image) : null; } return (new SelectlistTransformer)->transformSelectlist($companies); diff --git a/app/Http/Controllers/Api/ComponentsController.php b/app/Http/Controllers/Api/ComponentsController.php index 987d30da2e..068f7747f0 100644 --- a/app/Http/Controllers/Api/ComponentsController.php +++ b/app/Http/Controllers/Api/ComponentsController.php @@ -27,19 +27,19 @@ class ComponentsController extends Controller $components = Company::scopeCompanyables(Component::select('components.*') ->with('company', 'location', 'category')); - if ($request->has('search')) { + if ($request->filled('search')) { $components = $components->TextSearch($request->input('search')); } - if ($request->has('company_id')) { + if ($request->filled('company_id')) { $components->where('company_id','=',$request->input('company_id')); } - if ($request->has('category_id')) { + if ($request->filled('category_id')) { $components->where('category_id','=',$request->input('category_id')); } - if ($request->has('location_id')) { + if ($request->filled('location_id')) { $components->where('location_id','=',$request->input('location_id')); } diff --git a/app/Http/Controllers/Api/ConsumablesController.php b/app/Http/Controllers/Api/ConsumablesController.php index faf485f882..85b5201729 100644 --- a/app/Http/Controllers/Api/ConsumablesController.php +++ b/app/Http/Controllers/Api/ConsumablesController.php @@ -27,15 +27,15 @@ class ConsumablesController extends Controller ->with('company', 'location', 'category', 'users', 'manufacturer') ); - if ($request->has('search')) { + if ($request->filled('search')) { $consumables = $consumables->TextSearch(e($request->input('search'))); } - if ($request->has('company_id')) { + if ($request->filled('company_id')) { $consumables->where('company_id','=',$request->input('company_id')); } - if ($request->has('manufacturer_id')) { + if ($request->filled('manufacturer_id')) { $consumables->where('manufacturer_id','=',$request->input('manufacturer_id')); } @@ -152,7 +152,7 @@ class ConsumablesController extends Controller * Returns a JSON response containing details on the users associated with this consumable. * * @author [A. Gianotto] [] - * @see ConsumablesController::getView() method that returns the form. + * @see \App\Http\Controllers\Consumables\ConsumablesController::getView() method that returns the form. * @since [v1.0] * @param int $consumableId * @return array diff --git a/app/Http/Controllers/Api/CustomFieldsetsController.php b/app/Http/Controllers/Api/CustomFieldsetsController.php index 3946be433c..5ed9161522 100644 --- a/app/Http/Controllers/Api/CustomFieldsetsController.php +++ b/app/Http/Controllers/Api/CustomFieldsetsController.php @@ -16,7 +16,6 @@ use App\Http\Controllers\Controller; use App\Helpers\Helper; use App\Http\Transformers\CustomFieldsTransformer; use App\Http\Transformers\CustomFieldsetsTransformer; -use App\Http\Requests\AssetRequest; /** * This controller handles all actions related to Custom Asset Fieldsets for @@ -43,7 +42,7 @@ class CustomFieldsetsController extends Controller public function index() { $this->authorize('index', CustomFieldset::class); - $fieldsets = CustomFieldset::withCount(['fields', 'models'])->get(); + $fieldsets = CustomFieldset::withCount('fields as fields_count', 'models as models_count')->get(); return (new CustomFieldsetsTransformer)->transformCustomFieldsets($fieldsets, $fieldsets->count()); } diff --git a/app/Http/Controllers/Api/DepartmentsController.php b/app/Http/Controllers/Api/DepartmentsController.php index ab2132707d..338dc520b3 100644 --- a/app/Http/Controllers/Api/DepartmentsController.php +++ b/app/Http/Controllers/Api/DepartmentsController.php @@ -9,6 +9,7 @@ use App\Http\Transformers\DepartmentsTransformer; use App\Helpers\Helper; use Auth; use App\Http\Transformers\SelectlistTransformer; +use Illuminate\Support\Facades\Storage; class DepartmentsController extends Controller { @@ -33,9 +34,9 @@ class DepartmentsController extends Controller 'departments.created_at', 'departments.updated_at', 'departments.image' - ])->with('users')->with('location')->with('manager')->with('company')->withCount('users'); + ])->with('users')->with('location')->with('manager')->with('company')->withCount('users as users_count'); - if ($request->has('search')) { + if ($request->filled('search')) { $departments = $departments->TextSearch($request->input('search')); } @@ -76,7 +77,7 @@ class DepartmentsController extends Controller $department = new Department; $department->fill($request->all()); $department->user_id = Auth::user()->id; - $department->manager_id = ($request->has('manager_id' ) ? $request->input('manager_id') : null); + $department->manager_id = ($request->filled('manager_id' ) ? $request->input('manager_id') : null); if ($department->save()) { return response()->json(Helper::formatStandardApiResponse('success', $department, trans('admin/departments/message.create.success'))); @@ -100,14 +101,36 @@ class DepartmentsController extends Controller return (new DepartmentsTransformer)->transformDepartment($department); } + /** + * Update the specified resource in storage. + * + * @author [A. Gianotto] [] + * @since [v5.0] + * @param \Illuminate\Http\Request $request + * @param int $id + * @return \Illuminate\Http\Response + */ + public function update(Request $request, $id) + { + $this->authorize('update', Department::class); + $department = Department::findOrFail($id); + $department->fill($request->all()); + + if ($department->save()) { + return response()->json(Helper::formatStandardApiResponse('success', $department, trans('admin/departments/message.update.success'))); + } + + return response()->json(Helper::formatStandardApiResponse('error', null, $department->getErrors())); + } + /** - * Validates and deletes selected location. + * Validates and deletes selected department. * * @author [A. Gianotto] [] * @param int $locationId - * @since [v1.0] + * @since [v4.0] * @return \Illuminate\Http\RedirectResponse */ public function destroy($id) @@ -142,7 +165,7 @@ class DepartmentsController extends Controller 'image', ]); - if ($request->has('search')) { + if ($request->filled('search')) { $departments = $departments->where('name', 'LIKE', '%'.$request->get('search').'%'); } @@ -152,7 +175,7 @@ class DepartmentsController extends Controller // This lets us have more flexibility in special cases like assets, where // they may not have a ->name value but we want to display something anyway foreach ($departments as $department) { - $department->use_image = ($department->image) ? url('/').'/uploads/departments/'.$department->image : null; + $department->use_image = ($department->image) ? Storage::disk('public')->url('departments/'.$department->image, $department->image) : null; } return (new SelectlistTransformer)->transformSelectlist($departments); diff --git a/app/Http/Controllers/Api/DepreciationsController.php b/app/Http/Controllers/Api/DepreciationsController.php index 20e18baf43..e3f6edf2e8 100644 --- a/app/Http/Controllers/Api/DepreciationsController.php +++ b/app/Http/Controllers/Api/DepreciationsController.php @@ -24,7 +24,7 @@ class DepreciationsController extends Controller $depreciations = Depreciation::select('id','name','months','user_id','created_at','updated_at'); - if ($request->has('search')) { + if ($request->filled('search')) { $depreciations = $depreciations->TextSearch($request->input('search')); } @@ -110,10 +110,10 @@ class DepreciationsController extends Controller public function destroy($id) { $this->authorize('delete', Depreciation::class); - $depreciation = Depreciation::findOrFail($id); + $depreciation = Depreciation::withCount('models as models_count')->findOrFail($id); $this->authorize('delete', $depreciation); - if ($depreciation->has_models() > 0) { + if ($depreciation->models_count > 0) { return response()->json(Helper::formatStandardApiResponse('error', trans('admin/depreciations/message.assoc_users'))); } diff --git a/app/Http/Controllers/Api/GroupsController.php b/app/Http/Controllers/Api/GroupsController.php index e4839b27e4..4e779f9be6 100644 --- a/app/Http/Controllers/Api/GroupsController.php +++ b/app/Http/Controllers/Api/GroupsController.php @@ -22,9 +22,9 @@ class GroupsController extends Controller $this->authorize('view', Group::class); $allowed_columns = ['id','name','created_at', 'users_count']; - $groups = Group::select('id','name','permissions','created_at','updated_at')->withCount('users'); + $groups = Group::select('id','name','permissions','created_at','updated_at')->withCount('users as users_count'); - if ($request->has('search')) { + if ($request->filled('search')) { $groups = $groups->TextSearch($request->input('search')); } diff --git a/app/Http/Controllers/Api/ImportController.php b/app/Http/Controllers/Api/ImportController.php index d8d550501e..797df4d9ef 100644 --- a/app/Http/Controllers/Api/ImportController.php +++ b/app/Http/Controllers/Api/ImportController.php @@ -15,6 +15,7 @@ use League\Csv\Reader; use Symfony\Component\HttpFoundation\File\Exception\FileException; use Artisan; use App\Models\Asset; +use Illuminate\Support\Facades\Storage; class ImportController extends Controller { @@ -114,7 +115,7 @@ class ImportController extends Controller /** * Processes the specified Import. * - * @param \App\Import $import + * @param int $import_id * @return \Illuminate\Http\Response */ public function process(ItemImportRequest $request, $import_id) @@ -157,19 +158,26 @@ class ImportController extends Controller /** * Remove the specified resource from storage. * - * @param \App\Import $import + * @param int $import_id * @return \Illuminate\Http\Response */ public function destroy($import_id) { $this->authorize('create', Asset::class); - $import = Import::find($import_id); - try { - unlink(config('app.private_uploads').'/imports/'.$import->file_path); - $import->delete(); - return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/hardware/message.import.file_delete_success'))); - } catch (\Exception $e) { - return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/hardware/message.import.file_delete_error')), 500); + + if ($import = Import::find($import_id)) { + try { + // Try to delete the file + Storage::delete('imports/'.$import->file_path); + $import->delete(); + return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/hardware/message.import.file_delete_success'))); + + } catch (\Exception $e) { + // If the file delete didn't work, remove it from the database anyway and return a warning + $import->delete(); + return response()->json(Helper::formatStandardApiResponse('warning', null, trans('admin/hardware/message.import.file_not_deleted_warning'))); + } } + } } diff --git a/app/Http/Controllers/Api/LicensesController.php b/app/Http/Controllers/Api/LicensesController.php index af68208684..ee8f991136 100644 --- a/app/Http/Controllers/Api/LicensesController.php +++ b/app/Http/Controllers/Api/LicensesController.php @@ -25,59 +25,59 @@ class LicensesController extends Controller public function index(Request $request) { $this->authorize('view', License::class); - $licenses = Company::scopeCompanyables(License::with('company', 'manufacturer', 'freeSeats', 'supplier','category')->withCount('freeSeats')); + $licenses = Company::scopeCompanyables(License::with('company', 'manufacturer', 'freeSeats', 'supplier','category')->withCount('freeSeats as free_seats_count')); - if ($request->has('company_id')) { + if ($request->filled('company_id')) { $licenses->where('company_id','=',$request->input('company_id')); } - if ($request->has('name')) { + if ($request->filled('name')) { $licenses->where('licenses.name','=',$request->input('name')); } - if ($request->has('product_key')) { + if ($request->filled('product_key')) { $licenses->where('licenses.serial','=',$request->input('product_key')); } - if ($request->has('order_number')) { + if ($request->filled('order_number')) { $licenses->where('order_number','=',$request->input('order_number')); } - if ($request->has('purchase_order')) { + if ($request->filled('purchase_order')) { $licenses->where('purchase_order','=',$request->input('purchase_order')); } - if ($request->has('license_name')) { + if ($request->filled('license_name')) { $licenses->where('license_name','=',$request->input('license_name')); } - if ($request->has('license_email')) { + if ($request->filled('license_email')) { $licenses->where('license_email','=',$request->input('license_email')); } - if ($request->has('manufacturer_id')) { + if ($request->filled('manufacturer_id')) { $licenses->where('manufacturer_id','=',$request->input('manufacturer_id')); } - if ($request->has('supplier_id')) { + if ($request->filled('supplier_id')) { $licenses->where('supplier_id','=',$request->input('supplier_id')); } - if ($request->has('category_id')) { + if ($request->filled('category_id')) { $licenses->where('category_id','=',$request->input('category_id')); } - if ($request->has('depreciation_id')) { + if ($request->filled('depreciation_id')) { $licenses->where('depreciation_id','=',$request->input('depreciation_id')); } - if ($request->has('supplier_id')) { + if ($request->filled('supplier_id')) { $licenses->where('supplier_id','=',$request->input('supplier_id')); } - if ($request->has('search')) { + if ($request->filled('search')) { $licenses = $licenses->TextSearch($request->input('search')); } @@ -150,7 +150,7 @@ class LicensesController extends Controller public function show($id) { $this->authorize('view', License::class); - $license = License::findOrFail($id); + $license = License::withCount('freeSeats')->findOrFail($id); $license = $license->load('assignedusers', 'licenseSeats.user', 'licenseSeats.asset'); return (new LicensesTransformer)->transformLicense($license); } @@ -229,9 +229,18 @@ class LicensesController extends Controller $offset = request('offset', 0); $limit = request('limit', 50); - $order = $request->input('order') === 'asc' ? 'asc' : 'desc'; + if($seats->count() < $offset){ + $offset = 0; + } + + $order = $request->input('order') === 'asc' ? 'asc' : 'desc'; $total = $seats->count(); + + if($total < $offset){ + $offset = 0; + } + $seats = $seats->skip($offset)->take($limit)->get(); if ($seats) { diff --git a/app/Http/Controllers/Api/LocationsController.php b/app/Http/Controllers/Api/LocationsController.php index dd41330105..eaabc0ac30 100644 --- a/app/Http/Controllers/Api/LocationsController.php +++ b/app/Http/Controllers/Api/LocationsController.php @@ -8,6 +8,7 @@ use App\Helpers\Helper; use App\Models\Location; use App\Http\Transformers\LocationsTransformer; use App\Http\Transformers\SelectlistTransformer; +use Illuminate\Support\Facades\Storage; class LocationsController extends Controller { @@ -41,11 +42,11 @@ class LocationsController extends Controller 'locations.updated_at', 'locations.image', 'locations.currency' - ])->withCount('assignedAssets') - ->withCount('assets') - ->withCount('users'); + ])->withCount('assignedAssets as assigned_assets_count') + ->withCount('assets as assets_count') + ->withCount('users as users_count'); - if ($request->has('search')) { + if ($request->filled('search')) { $locations = $locations->TextSearch($request->input('search')); } @@ -192,7 +193,7 @@ class LocationsController extends Controller 'locations.image', ]); - if ($request->has('search')) { + if ($request->filled('search')) { $locations = $locations->where('locations.name', 'LIKE', '%'.$request->get('search').'%'); } @@ -203,7 +204,7 @@ class LocationsController extends Controller // they may not have a ->name value but we want to display something anyway foreach ($locations as $location) { $location->use_text = $location->name; - $location->use_image = ($location->image) ? url('/').'/uploads/locations/'.$location->image : null; + $location->use_image = ($location->image) ? Storage::disk('public')->url('locations/'.$location->image, $location->image): null; } return (new SelectlistTransformer)->transformSelectlist($locations); diff --git a/app/Http/Controllers/Api/ManufacturersController.php b/app/Http/Controllers/Api/ManufacturersController.php index 466c0858f9..2d30b3d5f2 100644 --- a/app/Http/Controllers/Api/ManufacturersController.php +++ b/app/Http/Controllers/Api/ManufacturersController.php @@ -9,6 +9,7 @@ use App\Models\Manufacturer; use App\Http\Transformers\DatatablesTransformer; use App\Http\Transformers\ManufacturersTransformer; use App\Http\Transformers\SelectlistTransformer; +use Illuminate\Support\Facades\Storage; class ManufacturersController extends Controller { @@ -26,13 +27,13 @@ class ManufacturersController extends Controller $manufacturers = Manufacturer::select( array('id','name','url','support_url','support_email','support_phone','created_at','updated_at','image', 'deleted_at') - )->withCount('assets')->withCount('licenses')->withCount('consumables')->withCount('accessories'); + )->withCount('assets as assets_count')->withCount('licenses as licenses_count')->withCount('consumables as consumables_count')->withCount('accessories as accessories_count'); if ($request->input('deleted')=='true') { $manufacturers->onlyTrashed(); } - if ($request->has('search')) { + if ($request->filled('search')) { $manufacturers = $manufacturers->TextSearch($request->input('search')); } @@ -83,7 +84,7 @@ class ManufacturersController extends Controller public function show($id) { $this->authorize('view', Manufacturer::class); - $manufacturer = Manufacturer::withCount('assets')->withCount('licenses')->withCount('consumables')->withCount('accessories')->findOrFail($id); + $manufacturer = Manufacturer::withCount('assets as assets_count', 'licenses as licenses_count', 'consumables as consumables_count', 'accessories as accessories_count', 'models as models_count' )->findOrFail($id); return (new ManufacturersTransformer)->transformManufacturer($manufacturer); } @@ -120,11 +121,21 @@ class ManufacturersController extends Controller */ public function destroy($id) { + $this->authorize('delete', Manufacturer::class); - $manufacturer = Manufacturer::findOrFail($id); + $manufacturer = Manufacturer::withCount('assets as assets_count', 'licenses as licenses_count', 'consumables as consumables_count', 'accessories as accessories_count', 'models as models_count' )->findOrFail($id); $this->authorize('delete', $manufacturer); - $manufacturer->delete(); - return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/manufacturers/message.delete.success'))); + + if (($manufacturer->assets_count == 0) && ($manufacturer->licenses_count==0) && ($manufacturer->consumables_count==0) && ($manufacturer->accessories_count==0) && ($manufacturer->models_count==0) && ($manufacturer->deleted_at=='')) { + $manufacturer->delete(); + return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/manufacturers/message.delete.success'))); + } + + return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/manufacturers/message.delete.error'))); + + + + } @@ -145,7 +156,7 @@ class ManufacturersController extends Controller 'image', ]); - if ($request->has('search')) { + if ($request->filled('search')) { $manufacturers = $manufacturers->where('name', 'LIKE', '%'.$request->get('search').'%'); } @@ -156,7 +167,7 @@ class ManufacturersController extends Controller // they may not have a ->name value but we want to display something anyway foreach ($manufacturers as $manufacturer) { $manufacturer->use_text = $manufacturer->name; - $manufacturer->use_image = ($manufacturer->image) ? url('/').'/uploads/manufacturers/'.$manufacturer->image : null; + $manufacturer->use_image = ($manufacturer->image) ? Storage::disk('public')->url('manufacturers/'.$manufacturer->image, $manufacturer->image) : null; } return (new SelectlistTransformer)->transformSelectlist($manufacturers); diff --git a/app/Http/Controllers/Api/ReportsController.php b/app/Http/Controllers/Api/ReportsController.php index 277aa8b765..e1b6ddd813 100644 --- a/app/Http/Controllers/Api/ReportsController.php +++ b/app/Http/Controllers/Api/ReportsController.php @@ -22,25 +22,25 @@ class ReportsController extends Controller $actionlogs = Actionlog::with('item', 'user', 'target','location'); - if ($request->has('search')) { + if ($request->filled('search')) { $actionlogs = $actionlogs->TextSearch(e($request->input('search'))); } - if (($request->has('target_type')) && ($request->has('target_id'))) { + if (($request->filled('target_type')) && ($request->filled('target_id'))) { $actionlogs = $actionlogs->where('target_id','=',$request->input('target_id')) ->where('target_type','=',"App\\Models\\".ucwords($request->input('target_type'))); } - if (($request->has('item_type')) && ($request->has('item_id'))) { + if (($request->filled('item_type')) && ($request->filled('item_id'))) { $actionlogs = $actionlogs->where('item_id','=',$request->input('item_id')) ->where('item_type','=',"App\\Models\\".ucwords($request->input('item_type'))); } - if ($request->has('action_type')) { + if ($request->filled('action_type')) { $actionlogs = $actionlogs->where('action_type','=',$request->input('action_type'))->orderBy('created_at', 'desc'); } - if ($request->has('uploads')) { + if ($request->filled('uploads')) { $actionlogs = $actionlogs->whereNotNull('filename')->orderBy('created_at', 'desc'); } diff --git a/app/Http/Controllers/Api/SettingsController.php b/app/Http/Controllers/Api/SettingsController.php index 2a4b757674..b08cb06412 100644 --- a/app/Http/Controllers/Api/SettingsController.php +++ b/app/Http/Controllers/Api/SettingsController.php @@ -2,104 +2,85 @@ namespace App\Http\Controllers\Api; -use Illuminate\Http\Request; -use App\Http\Controllers\Controller; -use App\Models\Ldap; -use Validator; +use App\Services\LdapAd; +use Illuminate\Support\Facades\DB; +use Illuminate\Support\Facades\Notification; use App\Models\Setting; -use Mail; -use App\Notifications\SlackTest; -use Notification; +use Illuminate\Http\Request; use App\Notifications\MailTest; +use App\Notifications\SlackTest; +use Illuminate\Http\JsonResponse; +use Illuminate\Support\Facades\Log; +use App\Http\Controllers\Controller; +use App\Http\Transformers\LoginAttemptsTransformer; class SettingsController extends Controller { - - public function ldaptest() + /** + * Test the ldap settings + * + * @author Wes Hulette + * + * @since 5.0.0 + * + * @param App\Models\LdapAd $ldap + * + * @return \Illuminate\Http\JsonResponse + */ + public function ldapAdSettingsTest(LdapAd $ldap): JsonResponse { - - if (Setting::getSettings()->ldap_enabled!='1') { - \Log::debug('LDAP is not enabled cannot test.'); + if(!$ldap->init()) { + Log::info('LDAP is not enabled cannot test.'); return response()->json(['message' => 'LDAP is not enabled, cannot test.'], 400); } - \Log::debug('Preparing to test LDAP connection'); + // The connect, bind and resulting users message + $message = []; + Log::info('Preparing to test LDAP user login'); + // Test user can connect to the LDAP server try { - $connection = Ldap::connectToLdap(); - try { - \Log::debug('attempting to bind to LDAP for LDAP test'); - Ldap::bindAdminToLdap($connection); - return response()->json(['message' => 'It worked!'], 200); - } catch (\Exception $e) { - \Log::debug('Bind failed'); - return response()->json(['message' => $e->getMessage()], 400); - //return response()->json(['message' => $e->getMessage()], 500); - } - } catch (\Exception $e) { - \Log::debug('Connection failed'); - return response()->json(['message' => $e->getMessage()], 600); + $ldap->testLdapAdUserConnection(); + $message['login'] = [ + 'message' => 'Successfully connected to LDAP server.' + ]; + } catch (\Exception $ex) { + return response()->json([ + 'message' => 'Error logging into LDAP server, error: ' . $ex->getMessage() . ' - Verify your that your username and password are correct' + ], 400); } - - } - - public function ldaptestlogin(Request $request) - { - - if (Setting::getSettings()->ldap_enabled!='1') { - \Log::debug('LDAP is not enabled. Cannot test.'); - return response()->json(['message' => 'LDAP is not enabled, cannot test.'], 400); - } - - - $rules = array( - 'ldaptest_user' => 'required', - 'ldaptest_password' => 'required' - ); - - $validator = Validator::make($request->all(), $rules); - if ($validator->fails()) { - \Log::debug('LDAP Validation test failed.'); - $validation_errors = implode(' ',$validator->errors()->all()); - return response()->json(['message' => $validator->errors()->all()], 400); - } - - - \Log::debug('Preparing to test LDAP login'); + Log::info('Preparing to test LDAP bind connection'); + // Test user can bind to the LDAP server try { - $connection = Ldap::connectToLdap(); - try { - Ldap::bindAdminToLdap($connection); - \Log::debug('Attempting to bind to LDAP for LDAP test'); - try { - $ldap_user = Ldap::findAndBindUserLdap($request->input('ldaptest_user'), $request->input('ldaptest_password')); - if ($ldap_user) { - \Log::debug('It worked! '. $request->input('ldaptest_user').' successfully binded to LDAP.'); - return response()->json(['message' => 'It worked! '. $request->input('ldaptest_user').' successfully binded to LDAP.'], 200); - } - return response()->json(['message' => 'Login Failed. '. $request->input('ldaptest_user').' did not successfully bind to LDAP.'], 400); - - } catch (\Exception $e) { - \Log::debug('LDAP login failed'); - return response()->json(['message' => $e->getMessage()], 400); - } - - } catch (\Exception $e) { - \Log::debug('Bind failed'); - return response()->json(['message' => $e->getMessage()], 400); - //return response()->json(['message' => $e->getMessage()], 500); - } - } catch (\Exception $e) { - \Log::debug('Connection failed'); - return response()->json(['message' => $e->getMessage()], 500); + $ldap->testLdapAdBindConnection(); + $message['bind'] = [ + 'message' => 'Successfully binded to LDAP server.' + ]; + } catch (\Exception $ex) { + return response()->json([ + 'message' => 'Error binding to LDAP server, error: ' . $ex->getMessage() + ], 400); } + Log::info('Preparing to get sample user set from LDAP directory'); + // Get a sample of 10 users so user can verify the data is correct + try { + $users = $ldap->testUserImportSync(); + $message['user_sync'] = [ + 'users' => $users + ]; + } catch (\Exception $ex) { + $message['user_sync'] = [ + 'message' => 'Error getting users from LDAP directory, error: ' . $ex->getMessage() + ]; + return response()->json($message, 400); + } + return response()->json($message, 200); } - public function slacktest() { @@ -143,6 +124,30 @@ class SettingsController extends Controller } + /** + * Get a list of login attempts + * + * @author [A. Gianotto] [] + * @since [v5.0.0] + * @param \Illuminate\Http\Request $request + * @return array + */ + public function showLoginAttempts(Request $request) + { + $allowed_columns = ['id', 'username', 'remote_ip', 'user_agent','successful','created_at']; + + $login_attempts = DB::table('login_attempts'); + $order = $request->input('order') === 'asc' ? 'asc' : 'desc'; + $sort = in_array($request->get('sort'), $allowed_columns) ? $request->get('sort') : 'created_at'; + + $total = $login_attempts->count(); + $login_attempts->orderBy($sort, $order); + $login_attempt_results = $login_attempts->skip(request('offset', 0))->take(request('limit', 20))->get(); + + return (new LoginAttemptsTransformer)->transformLoginAttempts($login_attempt_results, $total); + + } + } diff --git a/app/Http/Controllers/Api/StatuslabelsController.php b/app/Http/Controllers/Api/StatuslabelsController.php index dce204e025..6a7aa33d4b 100644 --- a/app/Http/Controllers/Api/StatuslabelsController.php +++ b/app/Http/Controllers/Api/StatuslabelsController.php @@ -24,9 +24,9 @@ class StatuslabelsController extends Controller $this->authorize('view', Statuslabel::class); $allowed_columns = ['id','name','created_at', 'assets_count','color','default_label']; - $statuslabels = Statuslabel::withCount('assets'); + $statuslabels = Statuslabel::withCount('assets as assets_count'); - if ($request->has('search')) { + if ($request->filled('search')) { $statuslabels = $statuslabels->TextSearch($request->input('search')); } @@ -55,7 +55,7 @@ class StatuslabelsController extends Controller $this->authorize('create', Statuslabel::class); $request->except('deployable', 'pending','archived'); - if (!$request->has('type')) { + if (!$request->filled('type')) { return response()->json(Helper::formatStandardApiResponse('error', null, ["type" => ["Status label type is required."]]),500); } @@ -106,7 +106,7 @@ class StatuslabelsController extends Controller $request->except('deployable', 'pending','archived'); - if (!$request->has('type')) { + if (!$request->filled('type')) { return response()->json(Helper::formatStandardApiResponse('error', null, 'Status label type is required.')); } @@ -162,7 +162,7 @@ class StatuslabelsController extends Controller { $this->authorize('view', Statuslabel::class); - $statuslabels = Statuslabel::with('assets')->groupBy('id')->withCount('assets')->get(); + $statuslabels = Statuslabel::with('assets')->groupBy('id')->withCount('assets as assets_count')->get(); $labels=[]; $points=[]; @@ -204,11 +204,11 @@ class StatuslabelsController extends Controller { $this->authorize('view', Statuslabel::class); $this->authorize('index', Asset::class); - $assets = Asset::where('status_id','=',$id); + $assets = Asset::where('status_id','=',$id)->with('assignedTo'); $allowed_columns = [ 'id', - 'name' + 'name', ]; $offset = request('offset', 0); @@ -238,8 +238,6 @@ class StatuslabelsController extends Controller */ public function checkIfDeployable($id) { $statuslabel = Statuslabel::findOrFail($id); - $this->authorize('view', Asset::class); - if ($statuslabel->getStatuslabelType()=='deployable') { return '1'; } diff --git a/app/Http/Controllers/Api/SuppliersController.php b/app/Http/Controllers/Api/SuppliersController.php index 27cee15216..d15492b1bb 100644 --- a/app/Http/Controllers/Api/SuppliersController.php +++ b/app/Http/Controllers/Api/SuppliersController.php @@ -8,6 +8,7 @@ use App\Helpers\Helper; use App\Models\Supplier; use App\Http\Transformers\SuppliersTransformer; use App\Http\Transformers\SelectlistTransformer; +use Illuminate\Support\Facades\Storage; class SuppliersController extends Controller @@ -22,14 +23,14 @@ class SuppliersController extends Controller public function index(Request $request) { $this->authorize('view', Supplier::class); - $allowed_columns = ['id','name','address','phone','contact','fax','email','image','assets_count','licenses_count', 'accessories_count']; + $allowed_columns = ['id','name','address','phone','contact','fax','email','image','assets_count','licenses_count', 'accessories_count','url']; $suppliers = Supplier::select( - array('id','name','address','address2','city','state','country','fax', 'phone','email','contact','created_at','updated_at','deleted_at','image','notes') - )->withCount('assets')->withCount('licenses')->withCount('accessories'); + array('id','name','address','address2','city','state','country','fax', 'phone','email','contact','created_at','updated_at','deleted_at','image','notes', 'url') + )->withCount('assets as assets_count')->withCount('licenses as licenses_count')->withCount('accessories as accessories_count'); - if ($request->has('search')) { + if ($request->filled('search')) { $suppliers = $suppliers->TextSearch($request->input('search')); } @@ -115,7 +116,7 @@ class SuppliersController extends Controller public function destroy($id) { $this->authorize('delete', Supplier::class); - $supplier = Supplier::with('asset_maintenances', 'assets', 'licenses')->withCount('asset_maintenances','assets', 'licenses')->findOrFail($id); + $supplier = Supplier::with('asset_maintenances', 'assets', 'licenses')->withCount('asset_maintenances as asset_maintenances_count','assets as assets_count', 'licenses as licenses_count')->findOrFail($id); $this->authorize('delete', $supplier); @@ -153,7 +154,7 @@ class SuppliersController extends Controller 'image', ]); - if ($request->has('search')) { + if ($request->filled('search')) { $suppliers = $suppliers->where('suppliers.name', 'LIKE', '%'.$request->get('search').'%'); } @@ -164,7 +165,7 @@ class SuppliersController extends Controller // they may not have a ->name value but we want to display something anyway foreach ($suppliers as $supplier) { $supplier->use_text = $supplier->name; - $supplier->use_image = ($supplier->image) ? url('/').'/uploads/suppliers/'.$supplier->image : null; + $supplier->use_image = ($supplier->image) ? Storage::disk('public')->url('suppliers/'.$supplier->image, $supplier->image) : null; } return (new SelectlistTransformer)->transformSelectlist($suppliers); diff --git a/app/Http/Controllers/Api/UsersController.php b/app/Http/Controllers/Api/UsersController.php index 5bd825d957..35676c584c 100644 --- a/app/Http/Controllers/Api/UsersController.php +++ b/app/Http/Controllers/Api/UsersController.php @@ -2,6 +2,8 @@ namespace App\Http\Controllers\Api; +use App\Http\Transformers\LicensesTransformer; +use App\Models\License; use Illuminate\Http\Request; use App\Http\Controllers\Controller; use App\Http\Transformers\UsersTransformer; @@ -56,31 +58,31 @@ class UsersController extends Controller 'users.zip', ])->with('manager', 'groups', 'userloc', 'company', 'department','assets','licenses','accessories','consumables') - ->withCount('assets','licenses','accessories','consumables'); + ->withCount('assets as assets_count','licenses as licneses_count','accessories as accessories_count','consumables as consumables_count'); $users = Company::scopeCompanyables($users); - if (($request->has('deleted')) && ($request->input('deleted')=='true')) { - $users = $users->GetDeleted(); + if (($request->filled('deleted')) && ($request->input('deleted')=='true')) { + $users = $users->onlyTrashed(); } - if ($request->has('company_id')) { + if ($request->filled('company_id')) { $users = $users->where('users.company_id', '=', $request->input('company_id')); } - if ($request->has('location_id')) { + if ($request->filled('location_id')) { $users = $users->where('users.location_id', '=', $request->input('location_id')); } - if ($request->has('group_id')) { + if ($request->filled('group_id')) { $users = $users->ByGroup($request->get('group_id')); } - if ($request->has('department_id')) { + if ($request->filled('department_id')) { $users = $users->where('users.department_id','=',$request->input('department_id')); } - if ($request->has('search')) { + if ($request->filled('search')) { $users = $users->TextSearch($request->input('search')); } @@ -146,7 +148,7 @@ class UsersController extends Controller $users = Company::scopeCompanyables($users); - if ($request->has('search')) { + if ($request->filled('search')) { $users = $users->where('first_name', 'LIKE', '%'.$request->get('search').'%') ->orWhere('last_name', 'LIKE', '%'.$request->get('search').'%') ->orWhere('username', 'LIKE', '%'.$request->get('search').'%') @@ -199,6 +201,7 @@ class UsersController extends Controller $tmp_pass = substr(str_shuffle("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"), 0, 20); $user->password = bcrypt($request->get('password', $tmp_pass)); + if ($user->save()) { if ($request->has('groups')) { $user->groups()->sync($request->input('groups')); @@ -240,13 +243,23 @@ class UsersController extends Controller $this->authorize('update', User::class); $user = User::findOrFail($id); + + // This is a janky hack to prevent people from changing admin demo user data on the public demo. + // The $ids 1 and 2 are special since they are seeded as superadmins in the demo seeder. + // Thanks, jerks. You are why we can't have nice things. - snipe + + if ((($id == 1) || ($id == 2)) && (config('app.lock_passwords'))) { + return response()->json(Helper::formatStandardApiResponse('error', null, 'Permission denied. You cannot update user information via API on the demo.')); + } + + $user->fill($request->all()); if ($user->id == $request->input('manager_id')) { return response()->json(Helper::formatStandardApiResponse('error', null, 'You cannot be your own manager')); } - if ($request->has('password')) { + if ($request->filled('password')) { $user->password = bcrypt($request->input('password')); } @@ -255,6 +268,9 @@ class UsersController extends Controller ->where('assigned_to', $user->id)->update(['location_id' => $request->input('location_id', null)]); if ($user->save()) { + if ($request->filled('groups')) { + $user->groups()->sync($request->input('groups')); + } return response()->json(Helper::formatStandardApiResponse('success', (new UsersTransformer)->transformUser($user), trans('admin/users/message.success.update'))); } @@ -280,6 +296,15 @@ class UsersController extends Controller return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/users/message.error.delete_has_assets'))); } + // Remove the user's avatar if they have one + if (Storage::disk('public')->exists('avatars/'.$user->avatar)) { + try { + Storage::disk('public')->delete('avatars/'.$user->avatar); + } catch (\Exception $e) { + \Log::debug($e); + } + } + if ($user->delete()) { return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/users/message.success.delete'))); } @@ -302,6 +327,23 @@ class UsersController extends Controller return (new AssetsTransformer)->transformAssets($assets, $assets->count()); } + /** + * Return JSON containing a list of licenses assigned to a user. + * + * @author [N. Mathar] [] + * @since [v5.0] + * @param $userId + * @return string JSON + */ + public function licenses($id) + { + $this->authorize('view', User::class); + $this->authorize('view', License::class); + $user = User::where('id', $id)->withTrashed()->first(); + $licenses = $user->licenses()->get(); + return (new LicensesTransformer())->transformLicenses($licenses, $licenses->count()); + } + /** * Reset the user's two-factor status * @@ -315,7 +357,7 @@ class UsersController extends Controller $this->authorize('update', User::class); - if ($request->has('id')) { + if ($request->filled('id')) { try { $user = User::find($request->get('id')); $user->two_factor_secret = null; diff --git a/app/Http/Controllers/AssetMaintenancesController.php b/app/Http/Controllers/AssetMaintenancesController.php index 9e58aada72..6e0100065a 100644 --- a/app/Http/Controllers/AssetMaintenancesController.php +++ b/app/Http/Controllers/AssetMaintenancesController.php @@ -165,6 +165,7 @@ class AssetMaintenancesController extends Controller } elseif (!$assetMaintenance->asset) { return redirect()->route('maintenances.index') ->with('error', 'The asset associated with this maintenance does not exist.'); + } elseif (!Company::isCurrentUserHasAccess($assetMaintenance->asset)) { return static::getInsufficientPermissionsRedirect(); } diff --git a/app/Http/Controllers/AssetModelsController.php b/app/Http/Controllers/AssetModelsController.php index 0ae3c59e88..790b8c9876 100755 --- a/app/Http/Controllers/AssetModelsController.php +++ b/app/Http/Controllers/AssetModelsController.php @@ -1,26 +1,15 @@ ] - * @since [v1.0] - * @return View - */ + * Returns a view that invokes the ajax tables which actually contains + * the content for the accessories listing, which is generated in getDatatable. + * + * @author [A. Gianotto] [] + * @since [v1.0] + * @return View + * @throws \Illuminate\Auth\Access\AuthorizationException + */ public function index() { $this->authorize('index', AssetModel::class); @@ -45,29 +35,31 @@ class AssetModelsController extends Controller } /** - * Returns a view containing the asset model creation form. - * - * @author [A. Gianotto] [] - * @since [v1.0] - * @return View - */ + * Returns a view containing the asset model creation form. + * + * @author [A. Gianotto] [] + * @since [v1.0] + * @return View + * @throws \Illuminate\Auth\Access\AuthorizationException + */ public function create() { $this->authorize('create', AssetModel::class); - $category_type = 'asset'; - return view('models/edit')->with('category_type',$category_type) - ->with('depreciation_list', Helper::depreciationList()) - ->with('item', new AssetModel); + return view('models/edit')->with('category_type', 'asset') + ->with('depreciation_list', Helper::depreciationList()) + ->with('item', new AssetModel); } /** - * Validate and process the new Asset Model data. - * - * @author [A. Gianotto] [] - * @since [v1.0] - * @return Redirect - */ + * Validate and process the new Asset Model data. + * + * @author [A. Gianotto] [] + * @since [v1.0] + * @param ImageUploadRequest $request + * @return Redirect + * @throws \Illuminate\Auth\Access\AuthorizationException + */ public function store(ImageUploadRequest $request) { @@ -90,23 +82,7 @@ class AssetModelsController extends Controller $model->fieldset_id = e($request->input('custom_fieldset')); } - if (Input::file('image')) { - - $image = Input::file('image'); - $file_name = str_slug($image->getClientOriginalName()) . "." . $image->getClientOriginalExtension(); - $path = app('models_upload_path'); - - if ($image->getClientOriginalExtension()!='svg') { - Image::make($image->getRealPath())->resize(500, null, function ($constraint) { - $constraint->aspectRatio(); - $constraint->upsize(); - })->save($path.'/'.$file_name); - } else { - $image->move($path, $file_name); - } - $model->image = $file_name; - - } + $model = $request->handleImages($model); // Was it created? if ($model->save()) { @@ -121,13 +97,14 @@ class AssetModelsController extends Controller } /** - * Returns a view containing the asset model edit form. - * - * @author [A. Gianotto] [] - * @since [v1.0] - * @param int $modelId - * @return View - */ + * Returns a view containing the asset model edit form. + * + * @author [A. Gianotto] [] + * @since [v1.0] + * @param int $modelId + * @return View + * @throws \Illuminate\Auth\Access\AuthorizationException + */ public function edit($modelId = null) { $this->authorize('update', AssetModel::class); @@ -144,14 +121,16 @@ class AssetModelsController extends Controller /** - * Validates and processes form data from the edit - * Asset Model form based on the model ID passed. - * - * @author [A. Gianotto] [] - * @since [v1.0] - * @param int $modelId - * @return Redirect - */ + * Validates and processes form data from the edit + * Asset Model form based on the model ID passed. + * + * @author [A. Gianotto] [] + * @since [v1.0] + * @param ImageUploadRequest $request + * @param int $modelId + * @return Redirect + * @throws \Illuminate\Auth\Access\AuthorizationException + */ public function update(ImageUploadRequest $request, $modelId = null) { $this->authorize('update', AssetModel::class); @@ -182,37 +161,7 @@ class AssetModelsController extends Controller } } - $old_image = $model->image; - - // Set the model's image property to null if the image is being deleted - if ($request->input('image_delete') == 1) { - $model->image = null; - } - - if ($request->file('image')) { - $image = $request->file('image'); - $file_name = $model->id.'-'.str_slug($image->getClientOriginalName()) . "." . $image->getClientOriginalExtension(); - - if ($image->getClientOriginalExtension()!='svg') { - Image::make($image->getRealPath())->resize(500, null, function ($constraint) { - $constraint->aspectRatio(); - $constraint->upsize(); - })->save(app('models_upload_path').$file_name); - } else { - $image->move(app('models_upload_path'), $file_name); - } - $model->image = $file_name; - - } - - if ((($request->file('image')) && (isset($old_image)) && ($old_image!='')) || ($request->input('image_delete') == 1)) { - try { - unlink(app('models_upload_path').$old_image); - } catch (\Exception $e) { - \Log::error($e); - } - } - + $model = $request->handleImages($model); if ($model->save()) { return redirect()->route("models.index")->with('success', trans('admin/models/message.update.success')); @@ -221,14 +170,15 @@ class AssetModelsController extends Controller } /** - * Validate and delete the given Asset Model. An Asset Model - * cannot be deleted if there are associated assets. - * - * @author [A. Gianotto] [] - * @since [v1.0] - * @param int $modelId - * @return Redirect - */ + * Validate and delete the given Asset Model. An Asset Model + * cannot be deleted if there are associated assets. + * + * @author [A. Gianotto] [] + * @since [v1.0] + * @param int $modelId + * @return Redirect + * @throws \Illuminate\Auth\Access\AuthorizationException + */ public function destroy($modelId) { $this->authorize('delete', AssetModel::class); @@ -244,7 +194,7 @@ class AssetModelsController extends Controller if ($model->image) { try { - unlink(public_path().'/uploads/models/'.$model->image); + Storage::disk('public')->delete('models/'.$model->image); } catch (\Exception $e) { \Log::error($e); } @@ -259,13 +209,14 @@ class AssetModelsController extends Controller /** - * Restore a given Asset Model (mark as un-deleted) - * - * @author [A. Gianotto] [] - * @since [v1.0] - * @param int $modelId - * @return Redirect - */ + * Restore a given Asset Model (mark as un-deleted) + * + * @author [A. Gianotto] [] + * @since [v1.0] + * @param int $modelId + * @return Redirect + * @throws \Illuminate\Auth\Access\AuthorizationException + */ public function getRestore($modelId = null) { $this->authorize('create', AssetModel::class); @@ -273,16 +224,8 @@ class AssetModelsController extends Controller $model = AssetModel::withTrashed()->find($modelId); if (isset($model->id)) { - - // Restore the model $model->restore(); - - // Prepare the success message - $success = trans('admin/models/message.restore.success'); - - // Redirect back - return redirect()->route('models.index')->with('success', $success); - + return redirect()->route('models.index')->with('success', trans('admin/models/message.restore.success')); } return redirect()->back()->with('error', trans('admin/models/message.not_found')); @@ -290,13 +233,14 @@ class AssetModelsController extends Controller /** - * Get the model information to present to the model view page - * - * @author [A. Gianotto] [] - * @since [v1.0] - * @param int $modelId - * @return View - */ + * Get the model information to present to the model view page + * + * @author [A. Gianotto] [] + * @since [v1.0] + * @param int $modelId + * @return View + * @throws \Illuminate\Auth\Access\AuthorizationException + */ public function show($modelId = null) { $this->authorize('view', AssetModel::class); @@ -305,11 +249,8 @@ class AssetModelsController extends Controller if (isset($model->id)) { return view('models/view', compact('model')); } - // Prepare the error message - $error = trans('admin/models/message.does_not_exist', compact('id')); - // Redirect to the user management page - return redirect()->route('models.index')->with('error', $error); + return redirect()->route('models.index')->with('error', trans('admin/models/message.does_not_exist')); } /** @@ -331,12 +272,10 @@ class AssetModelsController extends Controller $model->id = null; // Show the page - $view = View::make('models/edit'); - $view->with('depreciation_list', Helper::depreciationList()); - $view->with('item', $model); - $view->with('clone_model', $model_to_clone); - return $view; - + return view('models/edit') + ->with('depreciation_list', Helper::depreciationList()) + ->with('item', $model) + ->with('clone_model', $model_to_clone); } @@ -350,150 +289,10 @@ class AssetModelsController extends Controller */ public function getCustomFields($modelId) { - $model = AssetModel::find($modelId); - return view("models.custom_fields_form")->with("model", $model); + return view("models.custom_fields_form")->with("model", AssetModel::find($modelId)); } - - - /** - * Returns a view that allows the user to bulk edit model attrbutes - * - * @author [A. Gianotto] [] - * @since [v1.7] - * @return \Illuminate\Contracts\View\View - */ - public function postBulkEdit(Request $request) - { - - $models_raw_array = Input::get('ids'); - - // Make sure some IDs have been selected - if ((is_array($models_raw_array)) && (count($models_raw_array) > 0)) { - - - $models = AssetModel::whereIn('id', $models_raw_array)->withCount('assets')->orderBy('assets_count', 'ASC')->get(); - - // If deleting.... - if ($request->input('bulk_actions')=='delete') { - $valid_count = 0; - foreach ($models as $model) { - if ($model->assets_count == 0) { - $valid_count++; - } - } - return view('models/bulk-delete', compact('models'))->with('valid_count', $valid_count); - - // Otherwise display the bulk edit screen - } else { - - $nochange = ['NC' => 'No Change']; - $fieldset_list = $nochange + Helper::customFieldsetList(); - $depreciation_list = $nochange + Helper::depreciationList(); - - return view('models/bulk-edit', compact('models')) - ->with('fieldset_list', $fieldset_list) - ->with('depreciation_list', $depreciation_list); - } - - } - - return redirect()->route('models.index') - ->with('error', 'You must select at least one model to edit.'); - - } - - - - /** - * Returns a view that allows the user to bulk edit model attrbutes - * - * @author [A. Gianotto] [] - * @since [v1.7] - * @return \Illuminate\Contracts\View\View - */ - public function postBulkEditSave(Request $request) - { - - $models_raw_array = Input::get('ids'); - $update_array = array(); - - - if (($request->has('manufacturer_id') && ($request->input('manufacturer_id')!='NC'))) { - $update_array['manufacturer_id'] = $request->input('manufacturer_id'); - } - if (($request->has('category_id') && ($request->input('category_id')!='NC'))) { - $update_array['category_id'] = $request->input('category_id'); - } - if ($request->input('fieldset_id')!='NC') { - $update_array['fieldset_id'] = $request->input('fieldset_id'); - } - if ($request->input('depreciation_id')!='NC') { - $update_array['depreciation_id'] = $request->input('depreciation_id'); - } - - - - if (count($update_array) > 0) { - AssetModel::whereIn('id', $models_raw_array)->update($update_array); - return redirect()->route('models.index') - ->with('success', trans('admin/models/message.bulkedit.success')); - } - - return redirect()->route('models.index') - ->with('warning', trans('admin/models/message.bulkedit.error')); - - } - - /** - * Validate and delete the given Asset Models. An Asset Model - * cannot be deleted if there are associated assets. - * - * @author [A. Gianotto] [] - * @since [v1.0] - * @param int $modelId - * @return Redirect - */ - public function postBulkDelete(Request $request) - { - $models_raw_array = Input::get('ids'); - - if ((is_array($models_raw_array)) && (count($models_raw_array) > 0)) { - - $models = AssetModel::whereIn('id', $models_raw_array)->withCount('assets')->get(); - - $del_error_count = 0; - $del_count = 0; - - foreach ($models as $model) { - \Log::debug($model->id); - - if ($model->assets_count > 0) { - $del_error_count++; - } else { - $model->delete(); - $del_count++; - } - } - - \Log::debug($del_count); - \Log::debug($del_error_count); - - if ($del_error_count == 0) { - return redirect()->route('models.index') - ->with('success', trans('admin/models/message.bulkdelete.success',['success_count'=> $del_count] )); - } - - return redirect()->route('models.index') - ->with('warning', trans('admin/models/message.bulkdelete.success_partial', ['fail_count'=>$del_error_count, 'success_count'=> $del_count])); - } - - return redirect()->route('models.index') - ->with('error', trans('admin/models/message.bulkdelete.error')); - - } - /** * Returns true if a fieldset is set, 'add default values' is ticked and if * any default values were entered into the form. diff --git a/app/Http/Controllers/AssetCheckinController.php b/app/Http/Controllers/Assets/AssetCheckinController.php similarity index 70% rename from app/Http/Controllers/AssetCheckinController.php rename to app/Http/Controllers/Assets/AssetCheckinController.php index e03ea8b529..e87a1df23c 100644 --- a/app/Http/Controllers/AssetCheckinController.php +++ b/app/Http/Controllers/Assets/AssetCheckinController.php @@ -1,25 +1,29 @@ ] - * @param int $assetId - * @param string $backto - * @since [v1.0] - * @return View - */ + * Returns a view that presents a form to check an asset back into inventory. + * + * @author [A. Gianotto] [] + * @param int $assetId + * @param string $backto + * @return View + * @throws \Illuminate\Auth\Access\AuthorizationException + * @since [v1.0] + */ public function create($assetId, $backto = null) { // Check if the asset exists @@ -40,6 +44,7 @@ class AssetCheckinController extends Controller * @param int $assetId * @param null $backto * @return Redirect + * @throws \Illuminate\Auth\Access\AuthorizationException * @since [v1.0] */ public function store(AssetCheckinRequest $request, $assetId = null, $backto = null) @@ -67,31 +72,20 @@ class AssetCheckinController extends Controller $asset->accepted = null; $asset->name = e($request->get('name')); - if ($request->has('status_id')) { + if ($request->filled('status_id')) { $asset->status_id = e($request->get('status_id')); } $asset->location_id = $asset->rtd_location_id; - if ($request->has('location_id')) { + if ($request->filled('location_id')) { $asset->location_id = e($request->get('location_id')); } // Was the asset updated? if ($asset->save()) { - $logaction = $asset->logCheckin($target, e(request('note'))); - - $data['log_id'] = $logaction->id; - $data['first_name'] = get_class($target) == User::class ? $target->first_name : ''; - $data['last_name'] = get_class($target) == User::class ? $target->last_name : ''; - $data['item_name'] = $asset->present()->name(); - $data['checkin_date'] = $logaction->created_at; - $data['item_tag'] = $asset->asset_tag; - $data['item_serial'] = $asset->serial; - $data['note'] = $logaction->note; - $data['manufacturer_name'] = $asset->model->manufacturer->name; - $data['model_name'] = $asset->model->name; - $data['model_number'] = $asset->model->model_number; + + event(new CheckoutableCheckedIn($asset, $target, Auth::user(), $request->input('note'))); if ($backto=='user') { return redirect()->route("users.show", $user->id)->with('success', trans('admin/hardware/message.checkin.success')); diff --git a/app/Http/Controllers/AssetCheckoutController.php b/app/Http/Controllers/Assets/AssetCheckoutController.php similarity index 93% rename from app/Http/Controllers/AssetCheckoutController.php rename to app/Http/Controllers/Assets/AssetCheckoutController.php index 7220c35fa5..746376df4b 100644 --- a/app/Http/Controllers/AssetCheckoutController.php +++ b/app/Http/Controllers/Assets/AssetCheckoutController.php @@ -1,9 +1,11 @@ updateAssetLocation($asset, $target); $checkout_at = date("Y-m-d H:i:s"); - if (($request->has('checkout_at')) && ($request->get('checkout_at')!= date("Y-m-d"))) { + if (($request->filled('checkout_at')) && ($request->get('checkout_at')!= date("Y-m-d"))) { $checkout_at = $request->get('checkout_at'); } $expected_checkin = ''; - if ($request->has('expected_checkin')) { + if ($request->filled('expected_checkin')) { $expected_checkin = $request->get('expected_checkin'); } diff --git a/app/Http/Controllers/AssetFilesController.php b/app/Http/Controllers/Assets/AssetFilesController.php similarity index 58% rename from app/Http/Controllers/AssetFilesController.php rename to app/Http/Controllers/Assets/AssetFilesController.php index aca7429415..bc7f808135 100644 --- a/app/Http/Controllers/AssetFilesController.php +++ b/app/Http/Controllers/Assets/AssetFilesController.php @@ -1,13 +1,14 @@ authorize('update', $asset); - $destinationPath = config('app.private_uploads').'/assets'; - if ($request->hasFile('file')) { + + if (!Storage::exists('private_uploads/assets')) Storage::makeDirectory('private_uploads/assets', 775); + foreach ($request->file('file') as $file) { $extension = $file->getClientOriginalExtension(); - $filename = 'hardware-'.$asset->id.'-'.str_random(8); - $filename .= '-'.str_slug(basename($file->getClientOriginalName(), '.'.$extension)).'.'.$extension; - $file->move($destinationPath, $filename); - $asset->logUpload($filename, e($request->get('notes'))); + $file_name = 'hardware-'.$asset->id.'-'.str_random(8).'-'.str_slug(basename($file->getClientOriginalName(), '.'.$extension)).'.'.$extension; + Storage::put('private_uploads/assets/'.$file_name, $file); + $asset->logUpload($file_name, e($request->get('notes'))); } return redirect()->back()->with('success', trans('admin/hardware/message.upload.success')); } @@ -45,14 +47,15 @@ class AssetFilesController extends Controller } /** - * Check for permissions and display the file. - * - * @author [A. Gianotto] [] - * @param int $assetId - * @param int $fileId - * @since [v1.0] - * @return View - */ + * Check for permissions and display the file. + * + * @author [A. Gianotto] [] + * @param int $assetId + * @param int $fileId + * @since [v1.0] + * @return View + * @throws \Illuminate\Auth\Access\AuthorizationException + */ public function show($assetId = null, $fileId = null, $download = true) { $asset = Asset::find($assetId); @@ -65,24 +68,25 @@ class AssetFilesController extends Controller ->header('Content-Type', 'text/plain'); } - $file = $log->get_src('assets'); + $file = 'private_uploads/assets/'.$log->filename; + \Log::debug('Checking for '.$file); if ($log->action_type =='audit') { - $file = $log->get_src('audits'); + $file = 'private_uploads/audits/'.$log->filename; } - if (!file_exists($file)) { + if (!Storage::exists($file)) { return response('File '.$file.' not found on server', 404) ->header('Content-Type', 'text/plain'); } if ($download != 'true') { - if ($contents = file_get_contents($file)) { - return Response::make($contents)->header('Content-Type', mime_content_type($file)); + if ($contents = file_get_contents(Storage::url($file))) { + return Response::make(Storage::url($file)->header('Content-Type', mime_content_type($file))); } return JsonResponse::create(["error" => "Failed validation: "], 500); } - return Response::download($file); + return Storage::download($file); } // Prepare the error message $error = trans('admin/hardware/message.does_not_exist', ['id' => $fileId]); @@ -92,31 +96,31 @@ class AssetFilesController extends Controller } /** - * Delete the associated file - * - * @author [A. Gianotto] [] - * @param int $assetId - * @param int $fileId - * @since [v1.0] - * @return View - */ + * Delete the associated file + * + * @author [A. Gianotto] [] + * @param int $assetId + * @param int $fileId + * @since [v1.0] + * @return View + * @throws \Illuminate\Auth\Access\AuthorizationException + */ public function destroy($assetId = null, $fileId = null) { $asset = Asset::find($assetId); $this->authorize('update', $asset); - $destinationPath = config('app.private_uploads').'/imports/assets'; + $rel_path = 'storage/private_uploads/assets'; // the asset is valid if (isset($asset->id)) { $this->authorize('update', $asset); - $log = Actionlog::find($fileId); - $full_filename = $destinationPath.'/'.$log->filename; - if (file_exists($full_filename)) { - unlink($destinationPath.'/'.$log->filename); + if (file_exists(base_path().'/'.$rel_path.'/'.$log->filename)) { + Storage::disk('public')->delete($rel_path.'/'.$log->filename); } $log->delete(); - return redirect()->back()->with('success', trans('admin/hardware/message.deletefile.success')); + return redirect()->back() + ->with('success', trans('admin/hardware/message.deletefile.success')); } // Redirect to the hardware management page diff --git a/app/Http/Controllers/AssetsController.php b/app/Http/Controllers/Assets/AssetsController.php similarity index 55% rename from app/Http/Controllers/AssetsController.php rename to app/Http/Controllers/Assets/AssetsController.php index e143a8a184..acf2596034 100755 --- a/app/Http/Controllers/AssetsController.php +++ b/app/Http/Controllers/Assets/AssetsController.php @@ -1,18 +1,13 @@ ] * @see AssetController::getDatatable() method that generates the JSON response * @since [v1.0] + * @param Request $request * @return View + * @throws \Illuminate\Auth\Access\AuthorizationException */ public function index(Request $request) { $this->authorize('index', Asset::class); - if ($request->has('company_id')) { + if ($request->filled('company_id')) { $company = Company::find($request->input('company_id')); } else { $company = null; @@ -96,7 +95,7 @@ class AssetsController extends Controller ->with('item', new Asset) ->with('statuslabel_types', Helper::statusTypeList()); - if ($request->has('model_id')) { + if ($request->filled('model_id')) { $selected_model = AssetModel::find($request->input('model_id')); $view->with('selected_model', $selected_model); } @@ -110,116 +109,106 @@ class AssetsController extends Controller * @since [v1.0] * @return Redirect */ - public function store(AssetRequest $request) + public function store(ImageUploadRequest $request) { $this->authorize(Asset::class); + // Handle asset tags - there could be one, or potentially many. + // This is only necessary on create, not update, since bulk editing is handled + // differently + $asset_tags = $request->input('asset_tags'); - $asset = new Asset(); - $asset->model()->associate(AssetModel::find($request->input('model_id'))); + $success = false; + $serials = $request->input('serials'); - $asset->name = $request->input('name'); - $asset->serial = $request->input('serial'); - $asset->company_id = Company::getIdForCurrentUser($request->input('company_id')); - $asset->model_id = $request->input('model_id'); - $asset->order_number = $request->input('order_number'); - $asset->notes = $request->input('notes'); - $asset->asset_tag = $request->input('asset_tag'); - $asset->user_id = Auth::id(); - $asset->archived = '0'; - $asset->physical = '1'; - $asset->depreciate = '0'; - $asset->status_id = request('status_id', 0); - $asset->warranty_months = request('warranty_months', null); - $asset->purchase_cost = Helper::ParseFloat($request->get('purchase_cost')); - $asset->purchase_date = request('purchase_date', null); - $asset->assigned_to = request('assigned_to', null); - $asset->supplier_id = request('supplier_id', 0); - $asset->requestable = request('requestable', 0); - $asset->rtd_location_id = request('rtd_location_id', null); + for ($a = 1; $a <= count($asset_tags); $a++) { - if ($asset->assigned_to=='') { - $asset->location_id = $request->input('rtd_location_id', null); - } + $asset = new Asset(); + $asset->model()->associate(AssetModel::find($request->input('model_id'))); + $asset->name = $request->input('name'); + // Check for a corresponding serial + if (($serials) && (array_key_exists($a, $serials))) { + $asset->serial = $serials[$a]; + } + $asset->company_id = Company::getIdForCurrentUser($request->input('company_id')); + $asset->model_id = $request->input('model_id'); + $asset->order_number = $request->input('order_number'); + $asset->notes = $request->input('notes'); + $asset->user_id = Auth::id(); + $asset->archived = '0'; + $asset->physical = '1'; + $asset->depreciate = '0'; + $asset->status_id = request('status_id', 0); + $asset->warranty_months = request('warranty_months', null); + $asset->purchase_cost = Helper::ParseFloat($request->get('purchase_cost')); + $asset->purchase_date = request('purchase_date', null); + $asset->assigned_to = request('assigned_to', null); + $asset->supplier_id = request('supplier_id', 0); + $asset->requestable = request('requestable', 0); + $asset->rtd_location_id = request('rtd_location_id', null); + + if ($asset->assigned_to=='') { + $asset->location_id = $request->input('rtd_location_id', null); + } // Create the image (if one was chosen.) - if ($request->has('image')) { + if ($request->hasFile('image')) { $image = $request->input('image'); - // After modification, the image is prefixed by mime info like the following: - // data:image/jpeg;base64,; This causes the image library to be unhappy, so we need to remove it. - $header = explode(';', $image, 2)[0]; - // Grab the image type from the header while we're at it. - $extension = substr($header, strpos($header, '/')+1); - // Start reading the image after the first comma, postceding the base64. - $image = substr($image, strpos($image, ',')+1); - $file_name = str_random(25).".".$extension; - - $directory= public_path('uploads/assets/'); - // Check if the uploads directory exists. If not, try to create it. - if (!file_exists($directory)) { - mkdir($directory, 0755, true); - } - $path = public_path('uploads/assets/'.$file_name); - try { - Image::make($image)->resize(500, 500, function ($constraint) { - $constraint->aspectRatio(); - $constraint->upsize(); - })->save($path); - $asset->image = $file_name; - } catch (\Exception $e) { - \Input::flash(); - $messageBag = new \Illuminate\Support\MessageBag(); - $messageBag->add('image', $e->getMessage()); - \Session()->flash('errors', \Session::get('errors', new \Illuminate\Support\ViewErrorBag) - ->put('default', $messageBag)); - return response()->json(['image' => $e->getMessage()], 422); - } - } + $asset->asset_tag = $asset_tags[$a]; + $asset = $request->handleImages($asset); - // Update custom fields in the database. - // Validation for these fields is handled through the AssetRequest form request - $model = AssetModel::find($request->get('model_id')); + // Update custom fields in the database. + // Validation for these fields is handled through the AssetRequest form request + $model = AssetModel::find($request->get('model_id')); - if ($model->fieldset) { - foreach ($model->fieldset->fields as $field) { - if ($field->field_encrypted=='1') { - if (Gate::allows('admin')) { - $asset->{$field->convertUnicodeDbSlug()} = \Crypt::encrypt($request->input($field->convertUnicodeDbSlug())); + if (($model) && ($model->fieldset)) { + foreach ($model->fieldset->fields as $field) { + if ($field->field_encrypted=='1') { + if (Gate::allows('admin')) { + $asset->{$field->convertUnicodeDbSlug()} = \Crypt::encrypt($request->input($field->convertUnicodeDbSlug())); + } + } else { + $asset->{$field->convertUnicodeDbSlug()} = $request->input($field->convertUnicodeDbSlug()); } - } else { - $asset->{$field->convertUnicodeDbSlug()} = $request->input($field->convertUnicodeDbSlug()); } } + + // Validate the asset before saving + if ($asset->isValid() && $asset->save()) { + + if (request('assigned_user')) { + $target = User::find(request('assigned_user')); + $location = $target->location_id; + } elseif (request('assigned_asset')) { + $target = Asset::find(request('assigned_asset')); + $location = $target->location_id; + } elseif (request('assigned_location')) { + $target = Location::find(request('assigned_location')); + $location = $target->id; + } + + if (isset($target)) { + $asset->checkOut($target, Auth::user(), date('Y-m-d H:i:s'), '', 'Checked out on asset creation', e($request->get('name')), $location); + } + + $success = true; + + + } + } - // Was the asset created? - if ($asset->save()) { - - - if (request('assigned_user')) { - $target = User::find(request('assigned_user')); - $location = $target->location_id; - } elseif (request('assigned_asset')) { - $target = Asset::find(request('assigned_asset')); - $location = $target->location_id; - } elseif (request('assigned_location')) { - $target = Location::find(request('assigned_location')); - $location = $target->id; - } - - if (isset($target)) { - $asset->checkOut($target, Auth::user(), date('Y-m-d H:i:s'), '', 'Checked out on asset creation', e($request->get('name')), $location); - } + if ($success) { // Redirect to the asset listing page - \Session::flash('success', trans('admin/hardware/message.create.success')); - return response()->json(['redirect_url' => route('hardware.index')]); + return redirect()->route('hardware.index') + ->with('success', trans('admin/hardware/message.create.success')); } - \Input::flash(); - \Session::flash('errors', $asset->getErrors()); - return response()->json(['errors' => $asset->getErrors()], 500); + + return redirect()->back()->withInput()->withErrors($asset->getErrors()); + } /** @@ -297,7 +286,7 @@ class AssetsController extends Controller * @return Redirect */ - public function update(AssetRequest $request, $assetId = null) + public function update(ImageUploadRequest $request, $assetId = null) { // Check if the asset exists if (!$asset = Asset::find($assetId)) { @@ -313,7 +302,7 @@ class AssetsController extends Controller $asset->supplier_id = $request->input('supplier_id', null); // If the box isn't checked, it's not in the request at all. - $asset->requestable = $request->has('requestable'); + $asset->requestable = $request->filled('requestable'); $asset->rtd_location_id = $request->input('rtd_location_id', null); if ($asset->assigned_to=='') { @@ -321,7 +310,7 @@ class AssetsController extends Controller } - if ($request->has('image_delete')) { + if ($request->filled('image_delete')) { try { unlink(public_path().'/uploads/assets/'.$asset->image); $asset->image = ''; @@ -333,47 +322,18 @@ class AssetsController extends Controller // Update the asset data + $asset_tag = $request->input('asset_tags'); + $serial = $request->input('serials'); $asset->name = $request->input('name'); - $asset->serial = $request->input('serial'); + $asset->serial = $serial[1]; $asset->company_id = Company::getIdForCurrentUser($request->input('company_id')); $asset->model_id = $request->input('model_id'); $asset->order_number = $request->input('order_number'); - $asset->asset_tag = $request->input('asset_tag'); + $asset->asset_tag = $asset_tag[1]; $asset->notes = $request->input('notes'); $asset->physical = '1'; - // Update the image - if ($request->has('image')) { - $image = $request->input('image'); - // See postCreate for more explaination of the following. - $header = explode(';', $image, 2)[0]; - $extension = substr($header, strpos($header, '/')+1); - $image = substr($image, strpos($image, ',')+1); - - $directory= public_path('uploads/assets/'); - // Check if the uploads directory exists. If not, try to create it. - if (!file_exists($directory)) { - mkdir($directory, 0755, true); - } - - $file_name = str_random(25).".".$extension; - $path = public_path('uploads/assets/'.$file_name); - try { - Image::make($image)->resize(500, 500, function ($constraint) { - $constraint->aspectRatio(); - $constraint->upsize(); - })->save($path); - $asset->image = $file_name; - } catch (\Exception $e) { - \Input::flash(); - $messageBag = new \Illuminate\Support\MessageBag(); - $messageBag->add('image', $e->getMessage()); - \Session()->flash('errors', \Session::get('errors', new \Illuminate\Support\ViewErrorBag) - ->put('default', $messageBag)); - return response()->json(['image' => $e->getMessage()], 422); - } - $asset->image = $file_name; - } + $asset = $request->handleImages($asset); // Update custom fields in the database. // Validation for these fields is handlded through the AssetRequest form request @@ -394,13 +354,12 @@ class AssetsController extends Controller if ($asset->save()) { - // Redirect to the new asset page - \Session::flash('success', trans('admin/hardware/message.update.success')); - return response()->json(['redirect_url' => route("hardware.show", $assetId)]); + return redirect()->route("hardware.show", $assetId) + ->with('success', trans('admin/hardware/message.update.success')); } - \Input::flash(); - \Session::flash('errors', $asset->getErrors()); - return response()->json(['errors' => $asset->getErrors()], 500); + + return redirect()->back()->withInput()->withErrors()->with('error', trans('admin/hardware/message.does_not_exist')); + } /** @@ -425,6 +384,14 @@ class AssetsController extends Controller ->where('id', $asset->id) ->update(array('assigned_to' => null)); + if ($asset->image) { + try { + Storage::disk('public')->delete('assets'.'/'.$asset->image); + } catch (\Exception $e) { + \Log::debug($e); + } + } + $asset->delete(); return redirect()->route('hardware.index')->with('success', trans('admin/hardware/message.delete.success')); @@ -554,7 +521,7 @@ class AssetsController extends Controller */ public function getImportHistory() { - $this->authorize('checkout', Asset::class); + $this->authorize('admin'); return view('hardware/history'); } @@ -564,8 +531,8 @@ class AssetsController extends Controller * This needs a LOT of love. It's done very inelegantly right now, and there are * a ton of optimizations that could (and should) be done. * - * @author [A. Gianotto] [] - * @since [v3.3] + * @author [herroworrd] + * @since [v5.0] * @return View */ public function postImportHistory(Request $request) @@ -574,129 +541,103 @@ class AssetsController extends Controller ini_set("auto_detect_line_endings", '1'); } - $csv = Reader::createFromPath(Input::file('user_import_csv')); - $csv->setNewline("\r\n"); - //get the first row, usually the CSV header - //$headers = $csv->fetchOne(); + $requiredcolumns = ['Asset Tag', 'Checkout Date', 'Checkin Date', 'Full Name']; + + $csv = Reader::createFromPath(Input::file('user_import_csv')); + + $csv->setHeaderOffset(0); + + //Stop here if we don't have the columns we need + if(count(array_intersect($requiredcolumns, $csv->getHeader())) != count($requiredcolumns)) { + $status['error'][]['csv'][]['msg'] = 'Headers do not match'; + return view('hardware/history')->with('status', $status); + } + $statement = (new Statement()) + ->orderBy(\Closure::fromCallable([$this, 'sortByName'])); + + $results = $statement->process($csv); - $results = $csv->fetchAssoc(); - $item = array(); $status = array(); $status['error'] = array(); $status['success'] = array(); + $base_username = null; + $cachetime = Carbon::now()->addSeconds(120); + foreach ($results as $record) { - foreach ($results as $row) { - if (is_array($row)) { - $row = array_change_key_case($row, CASE_LOWER); - $asset_tag = Helper::array_smart_fetch($row, "asset tag"); - if (!array_key_exists($asset_tag, $item)) { - $item[$asset_tag] = array(); - } - $batch_counter = count($item[$asset_tag]); + $asset_tag = $record['Asset Tag']; - $item[$asset_tag][$batch_counter]['checkout_date'] = Carbon::parse(Helper::array_smart_fetch($row, "date"))->format('Y-m-d H:i:s'); - - $item[$asset_tag][$batch_counter]['asset_tag'] = Helper::array_smart_fetch($row, "asset tag"); - $item[$asset_tag][$batch_counter]['name'] = Helper::array_smart_fetch($row, "name"); - $item[$asset_tag][$batch_counter]['email'] = Helper::array_smart_fetch($row, "email"); - - if ($asset = Asset::where('asset_tag', '=', $asset_tag)->first()) { - $item[$asset_tag][$batch_counter]['asset_id'] = $asset->id; - - $base_username = User::generateFormattedNameFromFullName(Setting::getSettings()->username_format, $item[$asset_tag][$batch_counter]['name']); - $user = User::where('username', '=', $base_username['username']); - $user_query = ' on username '.$base_username['username']; - - if ($request->input('match_firstnamelastname')=='1') { - $firstnamedotlastname = User::generateFormattedNameFromFullName('firstname.lastname', $item[$asset_tag][$batch_counter]['name']); - $item[$asset_tag][$batch_counter]['username'][] = $firstnamedotlastname['username']; - $user->orWhere('username', '=', $firstnamedotlastname['username']); - $user_query .= ', or on username '.$firstnamedotlastname['username']; - } - - if ($request->input('match_flastname')=='1') { - $flastname = User::generateFormattedNameFromFullName('filastname', $item[$asset_tag][$batch_counter]['name']); - $item[$asset_tag][$batch_counter]['username'][] = $flastname['username']; - $user->orWhere('username', '=', $flastname['username']); - $user_query .= ', or on username '.$flastname['username']; - } - if ($request->input('match_firstname')=='1') { - $firstname = User::generateFormattedNameFromFullName('firstname', $item[$asset_tag][$batch_counter]['name']); - $item[$asset_tag][$batch_counter]['username'][] = $firstname['username']; - $user->orWhere('username', '=', $firstname['username']); - $user_query .= ', or on username '.$firstname['username']; - } - if ($request->input('match_email')=='1') { - if ($item[$asset_tag][$batch_counter]['email']=='') { - $item[$asset_tag][$batch_counter]['username'][] = $user_email = User::generateEmailFromFullName($item[$asset_tag][$batch_counter]['name']); - $user->orWhere('username', '=', $user_email); - $user_query .= ', or on username '.$user_email; - } - } - - // A matching user was found - if ($user = $user->first()) { - $item[$asset_tag][$batch_counter]['checkedout_to'] = $user->id; - $item[$asset_tag][$batch_counter]['user_id'] = $user->id; - - Actionlog::firstOrCreate(array( - 'item_id' => $asset->id, - 'item_type' => Asset::class, - 'user_id' => Auth::user()->id, - 'note' => 'Checkout imported by '.Auth::user()->present()->fullName().' from history importer', - 'target_id' => $item[$asset_tag][$batch_counter]['user_id'], - 'target_type' => User::class, - 'created_at' => $item[$asset_tag][$batch_counter]['checkout_date'], - 'action_type' => 'checkout', - )); - - $asset->assigned_to = $user->id; - - if ($asset->save()) { - $status['success'][]['asset'][$asset_tag]['msg'] = 'Asset successfully matched for '.Helper::array_smart_fetch($row, "name").$user_query.' on '.$item[$asset_tag][$batch_counter]['checkout_date']; - } else { - $status['error'][]['asset'][$asset_tag]['msg'] = 'Asset and user was matched but could not be saved.'; - } - } else { - $item[$asset_tag][$batch_counter]['checkedout_to'] = null; - $status['error'][]['user'][Helper::array_smart_fetch($row, "name")]['msg'] = 'User does not exist so no checkin log was created.'; - } - } else { - $item[$asset_tag][$batch_counter]['asset_id'] = null; - $status['error'][]['asset'][$asset_tag]['msg'] = 'Asset does not exist so no match was attempted.'; - } + try { + $checkoutdate = Carbon::parse($record['Checkout Date'])->format('Y-m-d H:i:s'); + $checkindate = Carbon::parse($record['Checkin Date'])->format('Y-m-d H:i:s'); + } + catch (\Exception $err) { + $status['error'][]['asset'][$asset_tag]['msg'] = 'Your dates are screwed up. Format needs to be Y-m-d H:i:s'; + continue; } - } - // Loop through and backfill the checkins - foreach ($item as $key => $asset_batch) { - $total_in_batch = count($asset_batch); - for ($x = 0; $x < $total_in_batch; $x++) { - $next = $x + 1; + if($asset = Cache::remember('asset:' . $asset_tag, $cachetime, function () use( &$asset_tag) { + $tocache = Asset::where('asset_tag', '=', $asset_tag)->value('id'); + return is_null($tocache) ? false : $tocache;})) + { + //we've found our asset, now lets look for a user + if($base_username != User::generateFormattedNameFromFullName($record['Full Name'], Setting::getSettings()->username_format)) { - // Only do this if a matching user was found - if ((array_key_exists('checkedout_to', $asset_batch[$x])) && ($asset_batch[$x]['checkedout_to']!='')) { - if (($total_in_batch > 1) && ($x < $total_in_batch) && (array_key_exists($next, $asset_batch))) { - $checkin_date = Carbon::parse($asset_batch[$next]['checkout_date'])->subDay(1)->format('Y-m-d H:i:s'); - $asset_batch[$x]['real_checkin'] = $checkin_date; + $base_username = User::generateFormattedNameFromFullName($record['Full Name'], Setting::getSettings()->username_format); + + if(!$user = Cache::remember('user:' . $base_username['username'], $cachetime, function () use( &$base_username) { + $tocache = User::where('username', '=', $base_username['username'])->value('id'); + return is_null($tocache) ? false : $tocache;})) + { + $status['error'][]['asset'][$asset_tag]['msg'] = 'Asset was found but user (' . $record['Full Name'] . ') not matched'; + $base_username = null; + continue; + } + } + + if($checkoutdate < $checkindate) { Actionlog::firstOrCreate(array( - 'item_id' => $asset_batch[$x]['asset_id'], + 'item_id' => $asset, 'item_type' => Asset::class, 'user_id' => Auth::user()->id, - 'note' => 'Checkin imported by ' . Auth::user()->present()->fullName() . ' from history importer', - 'target_id' => null, - 'created_at' => $checkin_date, + 'note' => 'Historical record added by ' . Auth::user()->present()->fullName(), + 'target_id' => $user, + 'target_type' => User::class, + 'created_at' => $checkoutdate, + 'action_type' => 'checkout', + )); + + Actionlog::firstOrCreate(array( + 'item_id' => $asset, + 'item_type' => Asset::class, + 'user_id' => Auth::user()->id, + 'note' => 'Historical record added by ' . Auth::user()->present()->fullName(), + 'target_id' => $user, + 'target_type' => User::class, + 'created_at' => $checkindate, 'action_type' => 'checkin' )); - } + + $status['success'][]['asset'][$asset_tag]['msg'] = 'Asset successfully matched for ' . $record['Full Name'] . ' on ' . $checkoutdate; + } + else { + $status['error'][]['asset'][$asset_tag]['msg'] = 'Checkin date needs to be after checkout date.'; } } + else { + $status['error'][]['asset'][$asset_tag]['msg'] = 'Asset not found in Snipe'; + } } + return view('hardware/history')->with('status', $status); } + protected function sortByName(array $recordA, array $recordB): int + { + return strcmp($recordB['Full Name'], $recordA['Full Name']); + } + /** * Retore a deleted asset. * @@ -745,7 +686,7 @@ class AssetsController extends Controller } - public function auditStore(AssetFileRequest $request, $id) + public function auditStore(Request $request, $id) { $this->authorize('audit', Asset::class); @@ -768,24 +709,28 @@ class AssetsController extends Controller $asset->next_audit_date = $request->input('next_audit_date'); $asset->last_audit_date = date('Y-m-d h:i:s'); + // Check to see if they checked the box to update the physical location, + // not just note it in the audit notes + if ($request->input('update_location')=='1') { + \Log::debug('update location in audit'); + $asset->location_id = $request->input('location_id'); + } + + if ($asset->save()) { - - - $filename = ''; - + $file_name = ''; + // Upload an image, if attached if ($request->hasFile('image')) { - $file = $request->file('image'); - try { - $destinationPath = config('app.private_uploads').'/audits'; - $extension = $file->getClientOriginalExtension(); - $filename = 'audit-'.$asset->id.'-'.str_slug(basename($file->getClientOriginalName(), '.'.$extension)).'.'.$extension; - $file->move($destinationPath, $filename); - } catch (\Exception $e) { - \Log::error($e); - } + $path = 'private_uploads/audits'; + if (!Storage::exists($path)) Storage::makeDirectory($path, 775); + $upload = $image = $request->file('image'); + $ext = $image->getClientOriginalExtension(); + $file_name = 'audit-'.str_random(18).'.'.$ext; + Storage::putFileAs($path, $upload, $file_name); } - $asset->logAudit($request->input('note'), $request->input('location_id'), $filename); + + $asset->logAudit($request->input('note'), $request->input('location_id'), $file_name); return redirect()->to("hardware")->with('success', trans('admin/hardware/message.audit.success')); } } diff --git a/app/Http/Controllers/BulkAssetsController.php b/app/Http/Controllers/Assets/BulkAssetsController.php similarity index 84% rename from app/Http/Controllers/BulkAssetsController.php rename to app/Http/Controllers/Assets/BulkAssetsController.php index cec9adf7f8..9fd91b0366 100644 --- a/app/Http/Controllers/BulkAssetsController.php +++ b/app/Http/Controllers/Assets/BulkAssetsController.php @@ -1,9 +1,10 @@ authorize('update', Asset::class); - if (!$request->has('ids')) { + if (!$request->filled('ids')) { return redirect()->back()->with('error', 'No assets selected'); } $asset_ids = array_keys($request->input('ids')); - if ($request->has('bulk_actions')) { + if ($request->filled('bulk_actions')) { switch($request->input('bulk_actions')) { case 'labels': return view('hardware/labels') @@ -68,22 +71,22 @@ class BulkAssetsController extends Controller \Log::debug($request->input('ids')); - if(!$request->has('ids') || count($request->input('ids')) <= 0) { + if(!$request->filled('ids') || count($request->input('ids')) <= 0) { return redirect()->route("hardware.index")->with('warning', trans('No assets selected, so nothing was updated.')); } $assets = array_keys($request->input('ids')); - if (($request->has('purchase_date')) - || ($request->has('purchase_cost')) - || ($request->has('supplier_id')) - || ($request->has('order_number')) - || ($request->has('warranty_months')) - || ($request->has('rtd_location_id')) - || ($request->has('requestable')) - || ($request->has('company_id')) - || ($request->has('status_id')) - || ($request->has('model_id')) + if (($request->filled('purchase_date')) + || ($request->filled('purchase_cost')) + || ($request->filled('supplier_id')) + || ($request->filled('order_number')) + || ($request->filled('warranty_months')) + || ($request->filled('rtd_location_id')) + || ($request->filled('requestable')) + || ($request->filled('company_id')) + || ($request->filled('status_id')) + || ($request->filled('model_id')) ) { foreach ($assets as $assetId) { $this->update_array = []; @@ -96,20 +99,20 @@ class BulkAssetsController extends Controller ->conditionallyAddItem('supplier_id') ->conditionallyAddItem('warranty_months'); - if ($request->has('purchase_cost')) { + if ($request->filled('purchase_cost')) { $this->update_array['purchase_cost'] = Helper::ParseFloat($request->input('purchase_cost')); } - if ($request->has('company_id')) { + if ($request->filled('company_id')) { $this->update_array['company_id'] = $request->input('company_id'); if ($request->input('company_id')=="clear") { $this->update_array['company_id'] = null; } } - if ($request->has('rtd_location_id')) { + if ($request->filled('rtd_location_id')) { $this->update_array['rtd_location_id'] = $request->input('rtd_location_id'); - if (($request->has('update_real_loc')) && (($request->input('update_real_loc')) == '1')) { + if (($request->filled('update_real_loc')) && (($request->input('update_real_loc')) == '1')) { $this->update_array['location_id'] = $request->input('rtd_location_id'); } } @@ -130,14 +133,15 @@ class BulkAssetsController extends Controller * @var Array */ private $update_array; + /** * Adds parameter to update array for an item if it exists in request - * @param String $field field name - * @return this Model for Chaining + * @param String $field field name + * @return BulkAssetsController Model for Chaining */ protected function conditionallyAddItem($field) { - if(request()->has($field)) { + if(request()->filled($field)) { $this->update_array[$field] = request()->input($field); } return $this; @@ -147,7 +151,9 @@ class BulkAssetsController extends Controller * Save bulk deleted. * * @author [A. Gianotto] [] + * @param Request $request * @return View + * @throws \Illuminate\Auth\Access\AuthorizationException * @internal param array $assets * @since [v2.0] */ @@ -155,7 +161,7 @@ class BulkAssetsController extends Controller { $this->authorize('delete', Asset::class); - if ($request->has('ids')) { + if ($request->filled('ids')) { $assets = Asset::find($request->get('ids')); foreach ($assets as $asset) { $update_array['deleted_at'] = date('Y-m-d H:i:s'); @@ -206,13 +212,13 @@ class BulkAssetsController extends Controller } } $checkout_at = date("Y-m-d H:i:s"); - if (($request->has('checkout_at')) && ($request->get('checkout_at')!= date("Y-m-d"))) { + if (($request->filled('checkout_at')) && ($request->get('checkout_at')!= date("Y-m-d"))) { $checkout_at = e($request->get('checkout_at')); } $expected_checkin = ''; - if ($request->has('expected_checkin')) { + if ($request->filled('expected_checkin')) { $expected_checkin = e($request->get('expected_checkin')); } diff --git a/app/Http/Controllers/Auth/ForgotPasswordController.php b/app/Http/Controllers/Auth/ForgotPasswordController.php index c64710ac38..ef085c6e7e 100644 --- a/app/Http/Controllers/Auth/ForgotPasswordController.php +++ b/app/Http/Controllers/Auth/ForgotPasswordController.php @@ -5,6 +5,7 @@ namespace App\Http\Controllers\Auth; use App\Http\Controllers\Controller; use Illuminate\Foundation\Auth\SendsPasswordResetEmails; use Illuminate\Http\Request; +use App\Models\User; class ForgotPasswordController extends Controller { @@ -49,27 +50,28 @@ class ForgotPasswordController extends Controller */ public function sendResetLinkEmail(Request $request) { - $this->validate($request, ['email' => 'required|email']); + $this->validate($request, ['username' => 'required'], ['username.required' => 'Please enter your username.']); - // We will send the password reset link to this user. Once we have attempted - // to send the link, we will examine the response then see the message we - // need to show to the user. Finally, we'll send out a proper response. + + // Make sure the user is active, and their password is not controlled via LDAP $response = $this->broker()->sendResetLink( array_merge( - $request->only('email'), - ['activated' => '1'] + $request->only('username'), + ['activated' => '1'], + ['ldap_import' => '0'] ) ); if ($response === \Password::RESET_LINK_SENT) { - return redirect()->route('login')->with('status', trans($response)); + \Log::info('Password reset attempt: User '.$request->input('username').' found, password reset sent'); + } else { + \Log::info('Password reset attempt: User '.$request->input('username').' not found or user is inactive'); } - // If an error was returned by the password broker, we will get this message - // translated so we can notify a user of the problem. We'll redirect back - // to where the users came from so they can attempt this process again. - return back()->withErrors( - ['email' => trans($response)] - ); + + + // Regardless of response, we do not want to disclose the status of a user account, + // so we give them a generic "If this exists, we're TOTALLY gonna email you" response + return redirect()->route('login')->with('success',trans('passwords.sent')); } } diff --git a/app/Http/Controllers/Auth/LoginController.php b/app/Http/Controllers/Auth/LoginController.php index cfd9549d4e..23b2fca093 100644 --- a/app/Http/Controllers/Auth/LoginController.php +++ b/app/Http/Controllers/Auth/LoginController.php @@ -2,20 +2,19 @@ namespace App\Http\Controllers\Auth; -use Validator; +use App\Services\LdapAd; +use Illuminate\Support\Carbon; +use Illuminate\Support\Facades\Session; +use Illuminate\Support\Facades\Validator; use App\Http\Controllers\Controller; use Illuminate\Foundation\Auth\ThrottlesLogins; use App\Models\Setting; -use App\Models\Ldap; use App\Models\User; -use Auth; -use Config; +use Illuminate\Support\Facades\Auth; use Illuminate\Http\Request; -use Input; +use Illuminate\Support\Facades\Input; use Redirect; -use Log; -use View; -use PragmaRX\Google2FA\Google2FA; +use Illuminate\Support\Facades\Log; /** * This controller handles authentication for the user, including local @@ -39,15 +38,24 @@ class LoginController extends Controller */ protected $redirectTo = '/'; + /** + * @var LdapAd + */ + protected $ldap; + /** * Create a new authentication controller instance. * + * @param LdapAd $ldap + * * @return void */ - public function __construct() + public function __construct(LdapAd $ldap) { + parent::__construct(); $this->middleware('guest', ['except' => ['logout','postTwoFactorAuth','getTwoFactorAuth','getTwoFactorEnroll']]); - \Session::put('backUrl', \URL::previous()); + Session::put('backUrl', \URL::previous()); + $this->ldap = $ldap; } function showLoginForm(Request $request) @@ -64,6 +72,29 @@ class LoginController extends Controller return view('auth.login'); } + /** + * Log in a user by LDAP + * + * @author Wes Hulette + * + * @since 5.0.0 + * + * @param Request $request + * + * @return User + * + * @throws \Exception + */ + private function loginViaLdap(Request $request): User + { + try { + return $this->ldap->ldapLogin($request->input('username'), $request->input('password')); + } catch (\Exception $ex) { + LOG::debug("LDAP user login: " . $ex->getMessage()); + throw new \Exception($ex->getMessage()); + } + } + private function loginViaRemoteUser(Request $request) { $remote_user = $request->server('REMOTE_USER'); @@ -85,53 +116,6 @@ class LoginController extends Controller } } - private function loginViaLdap(Request $request) - { - Log::debug("Binding user to LDAP."); - $ldap_user = Ldap::findAndBindUserLdap($request->input('username'), $request->input('password')); - if (!$ldap_user) { - Log::debug("LDAP user ".$request->input('username')." not found in LDAP or could not bind"); - throw new \Exception("Could not find user in LDAP directory"); - } else { - Log::debug("LDAP user ".$request->input('username')." successfully bound to LDAP"); - } - - // Check if the user already exists in the database and was imported via LDAP - $user = User::where('username', '=', Input::get('username'))->whereNull('deleted_at')->where('ldap_import', '=', 1)->where('activated', '=', '1')->first(); - Log::debug("Local auth lookup complete"); - - // The user does not exist in the database. Try to get them from LDAP. - // If user does not exist and authenticates successfully with LDAP we - // will create it on the fly and sign in with default permissions - if (!$user) { - Log::debug("Local user ".Input::get('username')." does not exist"); - Log::debug("Creating local user ".Input::get('username')); - - if ($user = Ldap::createUserFromLdap($ldap_user)) { //this handles passwords on its own - Log::debug("Local user created."); - } else { - Log::debug("Could not create local user."); - throw new \Exception("Could not create local user"); - } - // If the user exists and they were imported from LDAP already - } else { - Log::debug("Local user ".$request->input('username')." exists in database. Updating existing user against LDAP."); - - $ldap_attr = Ldap::parseAndMapLdapAttributes($ldap_user); - - if (Setting::getSettings()->ldap_pw_sync=='1') { - $user->password = bcrypt($request->input('password')); - } - - $user->email = $ldap_attr['email']; - $user->first_name = $ldap_attr['firstname']; - $user->last_name = $ldap_attr['lastname']; - $user->save(); - } // End if(!user) - return $user; - } - - /** * Account sign in form processing. * @@ -160,9 +144,10 @@ class LoginController extends Controller $user = null; // Should we even check for LDAP users? - if (Setting::getSettings()->ldap_enabled=='1') { - Log::debug("LDAP is enabled."); + if ($this->ldap->init()) { + LOG::debug("LDAP is enabled."); try { + LOG::debug("Attempting to log user in by LDAP authentication."); $user = $this->loginViaLdap($request); Auth::login($user, true); @@ -192,8 +177,8 @@ class LoginController extends Controller } if ($user = Auth::user()) { - $user->last_login = \Carbon::now(); - \Log::debug('Last login:'.$user->last_login); + $user->last_login = Carbon::now(); + Log::debug('Last login:'.$user->last_login); $user->save(); } // Redirect to the users page @@ -214,7 +199,7 @@ class LoginController extends Controller } $user = Auth::user(); - $google2fa = app()->make('PragmaRX\Google2FA\Contracts\Google2FA'); + $google2fa = app()->make('pragmarx.google2fa'); if ($user->two_factor_secret=='') { $user->two_factor_secret = $google2fa->generateSecretKey(32); @@ -222,7 +207,7 @@ class LoginController extends Controller } - $google2fa_url = $google2fa->getQRCodeGoogleUrl( + $google2fa_url = $google2fa->getQRCodeInline( urlencode(Setting::getSettings()->site_name), urlencode($user->username), $user->two_factor_secret @@ -246,6 +231,8 @@ class LoginController extends Controller /** * Two factor code submission * + * @param Request $request + * * @return Redirect */ public function postTwoFactorAuth(Request $request) @@ -257,7 +244,7 @@ class LoginController extends Controller $user = Auth::user(); $secret = $request->get('two_factor_secret'); - $google2fa = app()->make('PragmaRX\Google2FA\Contracts\Google2FA'); + $google2fa = app()->make('pragmarx.google2fa'); $valid = $google2fa->verifyKey($user->two_factor_secret, $secret); if ($valid) { @@ -276,6 +263,8 @@ class LoginController extends Controller /** * Logout page. * + * @param Request $request + * * @return Redirect */ public function logout(Request $request) @@ -340,7 +329,7 @@ class LoginController extends Controller * Override the lockout time and duration * * @param \Illuminate\Http\Request $request - * @return \Illuminate\Http\RedirectResponse + * @return bool */ protected function hasTooManyLoginAttempts(Request $request) { diff --git a/app/Http/Controllers/Auth/ResetPasswordController.php b/app/Http/Controllers/Auth/ResetPasswordController.php index ac31e273cb..fe1eb6d1e0 100644 --- a/app/Http/Controllers/Auth/ResetPasswordController.php +++ b/app/Http/Controllers/Auth/ResetPasswordController.php @@ -4,9 +4,9 @@ namespace App\Http\Controllers\Auth; use App\Http\Controllers\Controller; use Illuminate\Foundation\Auth\ResetsPasswords; -use App\Models\User; use Illuminate\Http\Request; + class ResetPasswordController extends Controller { /* @@ -39,7 +39,36 @@ class ResetPasswordController extends Controller $this->middleware('guest'); } - + protected function rules() + { + return [ + 'token' => 'required', + 'username' => 'required', + 'password' => 'required|confirmed|min:6', + ]; + } + protected function credentials(Request $request) + { + return $request->only( + 'username', 'password', 'password_confirmation', 'token' + ); + } + + + public function showResetForm(Request $request, $token = null) + { + return view('auth.passwords.reset')->with( + ['token' => $token, 'username' => $request->input('username')] + ); + } + + protected function sendResetFailedResponse(Request $request, $response) + { + return redirect()->back() + ->withInput(['username'=>$request->input('username')]) + ->withErrors(['username' => trans($response)]); + } + } diff --git a/app/Http/Controllers/BulkAssetModelsController.php b/app/Http/Controllers/BulkAssetModelsController.php new file mode 100644 index 0000000000..f8c15d1ebd --- /dev/null +++ b/app/Http/Controllers/BulkAssetModelsController.php @@ -0,0 +1,138 @@ +] + * @since [v1.7] + * @param Request $request + * @return \Illuminate\Contracts\View\View + */ + public function edit(Request $request) + { + $models_raw_array = Input::get('ids'); + + // Make sure some IDs have been selected + if ((is_array($models_raw_array)) && (count($models_raw_array) > 0)) { + + $models = AssetModel::whereIn('id', $models_raw_array) + ->withCount('assets as assets_count') + ->orderBy('assets_count', 'ASC') + ->get(); + + // If deleting.... + if ($request->input('bulk_actions')=='delete') { + $valid_count = 0; + foreach ($models as $model) { + if ($model->assets_count == 0) { + $valid_count++; + } + } + return view('models/bulk-delete', compact('models'))->with('valid_count', $valid_count); + + // Otherwise display the bulk edit screen + } + + $nochange = ['NC' => 'No Change']; + return view('models/bulk-edit', compact('models')) + ->with('fieldset_list', $nochange + Helper::customFieldsetList()) + ->with('depreciation_list', $nochange + Helper::depreciationList()); + } + + return redirect()->route('models.index') + ->with('error', 'You must select at least one model to edit.'); + } + + /** + * Returns a view that allows the user to bulk edit model attrbutes + * + * @author [A. Gianotto] [] + * @since [v1.7] + * @param Request $request + * @return \Illuminate\Contracts\View\View + */ + public function update(Request $request) + { + + $models_raw_array = Input::get('ids'); + $update_array = array(); + + if (($request->filled('manufacturer_id') && ($request->input('manufacturer_id')!='NC'))) { + $update_array['manufacturer_id'] = $request->input('manufacturer_id'); + } + if (($request->filled('category_id') && ($request->input('category_id')!='NC'))) { + $update_array['category_id'] = $request->input('category_id'); + } + if ($request->input('fieldset_id')!='NC') { + $update_array['fieldset_id'] = $request->input('fieldset_id'); + } + if ($request->input('depreciation_id')!='NC') { + $update_array['depreciation_id'] = $request->input('depreciation_id'); + } + + + + if (count($update_array) > 0) { + AssetModel::whereIn('id', $models_raw_array)->update($update_array); + return redirect()->route('models.index') + ->with('success', trans('admin/models/message.bulkedit.success')); + } + + return redirect()->route('models.index') + ->with('warning', trans('admin/models/message.bulkedit.error')); + + } + + /** + * Validate and delete the given Asset Models. An Asset Model + * cannot be deleted if there are associated assets. + * + * @author [A. Gianotto] [] + * @since [v1.0] + * @return Redirect + */ + public function destroy() + { + $models_raw_array = Input::get('ids'); + + if ((is_array($models_raw_array)) && (count($models_raw_array) > 0)) { + + $models = AssetModel::whereIn('id', $models_raw_array)->withCount('assets as assets_count')->get(); + + $del_error_count = 0; + $del_count = 0; + + foreach ($models as $model) { + if ($model->assets_count > 0) { + $del_error_count++; + } else { + $model->delete(); + $del_count++; + } + } + + if ($del_error_count == 0) { + return redirect()->route('models.index') + ->with('success', trans('admin/models/message.bulkdelete.success',['success_count'=> $del_count] )); + } + + return redirect()->route('models.index') + ->with('warning', trans('admin/models/message.bulkdelete.success_partial', ['fail_count'=>$del_error_count, 'success_count'=> $del_count])); + } + + return redirect()->route('models.index') + ->with('error', trans('admin/models/message.bulkdelete.error')); + + } + +} diff --git a/app/Http/Controllers/CategoriesController.php b/app/Http/Controllers/CategoriesController.php index 74b83acac3..bc643841e9 100755 --- a/app/Http/Controllers/CategoriesController.php +++ b/app/Http/Controllers/CategoriesController.php @@ -17,6 +17,7 @@ use Str; use View; use Image; use App\Http\Requests\ImageUploadRequest; +use Illuminate\Support\Facades\Storage; /** * This class controls all actions related to Categories for @@ -29,13 +30,14 @@ class CategoriesController extends Controller { /** - * Returns a view that invokes the ajax tables which actually contains - * the content for the categories listing, which is generated in getDatatable. - * - * @author [A. Gianotto] [] - * @see CategoriesController::getDatatable() method that generates the JSON response - * @since [v1.0] - * @return \Illuminate\Contracts\View\View + * Returns a view that invokes the ajax tables which actually contains + * the content for the categories listing, which is generated in getDatatable. + * + * @author [A. Gianotto] [] + * @see CategoriesController::getDatatable() method that generates the JSON response + * @since [v1.0] + * @return \Illuminate\Contracts\View\View + * @throws \Illuminate\Auth\Access\AuthorizationException */ public function index() { @@ -46,30 +48,32 @@ class CategoriesController extends Controller /** - * Returns a form view to create a new category. - * - * @author [A. Gianotto] [] - * @see CategoriesController::store() method that stores the data - * @since [v1.0] - * @return \Illuminate\Contracts\View\View + * Returns a form view to create a new category. + * + * @author [A. Gianotto] [] + * @see CategoriesController::store() method that stores the data + * @since [v1.0] + * @return \Illuminate\Contracts\View\View + * @throws \Illuminate\Auth\Access\AuthorizationException */ public function create() { // Show the page $this->authorize('create', Category::class); - $category_types= Helper::categoryTypeList(); return view('categories/edit')->with('item', new Category) - ->with('category_types', $category_types); + ->with('category_types', Helper::categoryTypeList()); } /** - * Validates and stores the new category data. - * - * @author [A. Gianotto] [] - * @see CategoriesController::create() method that makes the form. - * @since [v1.0] - * @return \Illuminate\Http\RedirectResponse + * Validates and stores the new category data. + * + * @author [A. Gianotto] [] + * @see CategoriesController::create() method that makes the form. + * @since [v1.0] + * @param ImageUploadRequest $request + * @return \Illuminate\Http\RedirectResponse + * @throws \Illuminate\Auth\Access\AuthorizationException */ public function store(ImageUploadRequest $request) { @@ -83,17 +87,7 @@ class CategoriesController extends Controller $category->checkin_email = $request->input('checkin_email', '0'); $category->user_id = Auth::id(); - if ($request->file('image')) { - $image = $request->file('image'); - $file_name = str_random(25).".".$image->getClientOriginalExtension(); - $path = public_path('uploads/categories/'.$file_name); - Image::make($image->getRealPath())->resize(200, null, function ($constraint) { - $constraint->aspectRatio(); - $constraint->upsize(); - })->save($path); - $category->image = $file_name; - } - + $category = $request->handleImages($category); if ($category->save()) { return redirect()->route('categories.index')->with('success', trans('admin/categories/message.create.success')); @@ -103,13 +97,14 @@ class CategoriesController extends Controller } /** - * Returns a view that makes a form to update a category. - * - * @author [A. Gianotto] [] - * @see CategoriesController::postEdit() method saves the data - * @param int $categoryId - * @since [v1.0] - * @return \Illuminate\Contracts\View\View + * Returns a view that makes a form to update a category. + * + * @author [A. Gianotto] [] + * @see CategoriesController::postEdit() method saves the data + * @param int $categoryId + * @since [v1.0] + * @return \Illuminate\Contracts\View\View + * @throws \Illuminate\Auth\Access\AuthorizationException */ public function edit($categoryId = null) { @@ -117,10 +112,8 @@ class CategoriesController extends Controller if (is_null($item = Category::find($categoryId))) { return redirect()->route('categories.index')->with('error', trans('admin/categories/message.does_not_exist')); } - $category_types= Helper::categoryTypeList(); - return view('categories/edit', compact('item')) - ->with('category_types', $category_types); + ->with('category_types', Helper::categoryTypeList()); } @@ -129,9 +122,10 @@ class CategoriesController extends Controller * * @author [A. Gianotto] [] * @see CategoriesController::getEdit() method that makes the form. - * @param Request $request + * @param ImageUploadRequest $request * @param int $categoryId * @return \Illuminate\Http\RedirectResponse + * @throws \Illuminate\Auth\Access\AuthorizationException * @since [v1.0] */ public function update(ImageUploadRequest $request, $categoryId = null) @@ -152,37 +146,7 @@ class CategoriesController extends Controller $category->require_acceptance = $request->input('require_acceptance', '0'); $category->checkin_email = $request->input('checkin_email', '0'); - $old_image = $category->image; - - // Set the model's image property to null if the image is being deleted - if ($request->input('image_delete') == 1) { - $category->image = null; - } - - if ($request->file('image')) { - $image = $request->file('image'); - $file_name = $category->id.'-'.str_slug($image->getClientOriginalName()) . "." . $image->getClientOriginalExtension(); - - if ($image->getClientOriginalExtension()!='svg') { - Image::make($image->getRealPath())->resize(500, null, function ($constraint) { - $constraint->aspectRatio(); - $constraint->upsize(); - })->save(app('categories_upload_path').$file_name); - } else { - $image->move(app('categories_upload_path'), $file_name); - } - $category->image = $file_name; - - } - - if ((($request->file('image')) && (isset($old_image)) && ($old_image!='')) || ($request->input('image_delete') == 1)) { - try { - unlink(app('categories_upload_path').$old_image); - } catch (\Exception $e) { - \Log::error($e); - } - } - + $category = $request->handleImages($category); if ($category->save()) { // Redirect to the new category page @@ -193,31 +157,33 @@ class CategoriesController extends Controller } /** - * Validates and marks a category as deleted. - * - * @author [A. Gianotto] [] - * @since [v1.0] - * @param int $categoryId - * @return \Illuminate\Http\RedirectResponse + * Validates and marks a category as deleted. + * + * @author [A. Gianotto] [] + * @since [v1.0] + * @param int $categoryId + * @return \Illuminate\Http\RedirectResponse + * @throws \Illuminate\Auth\Access\AuthorizationException */ public function destroy($categoryId) { $this->authorize('delete', Category::class); // Check if the category exists - if (is_null($category = Category::find($categoryId))) { + if (is_null($category = Category::withCount('models as models_count', 'accessories as accessories_count','consumables as consumables_count','components as components_count')->findOrFail($categoryId))) { return redirect()->route('categories.index')->with('error', trans('admin/categories/message.not_found')); } - if ($category->has_models() > 0) { + if ($category->models_count > 0) { return redirect()->route('categories.index')->with('error', trans('admin/categories/message.assoc_items', ['asset_type'=>'model'])); - } elseif ($category->accessories()->count() > 0) { - return redirect()->route('categories.index')->with('error', trans('admin/categories/message.assoc_items', ['asset_type'=>'accessory'])); - } elseif ($category->consumables()->count() > 0) { - return redirect()->route('categories.index')->with('error', trans('admin/categories/message.assoc_items', ['asset_type'=>'consumable'])); - } elseif ($category->components()->count() > 0) { - return redirect()->route('categories.index')->with('error', trans('admin/categories/message.assoc_items', ['asset_type'=>'component'])); + } elseif ($category->accessories_count > 0) { + return redirect()->route('categories.index')->with('error', trans('admin/categories/message.assoc_items', ['asset_type'=>'accessory'])); + } elseif ($category->consumables_count > 0) { + return redirect()->route('categories.index')->with('error', trans('admin/categories/message.assoc_items', ['asset_type'=>'consumable'])); + } elseif ($category->components_count > 0) { + return redirect()->route('categories.index')->with('error', trans('admin/categories/message.assoc_items', ['asset_type'=>'component'])); } + Storage::disk('public')->delete('categories'.'/'.$category->image); $category->delete(); // Redirect to the locations management page return redirect()->route('categories.index')->with('success', trans('admin/categories/message.delete.success')); @@ -225,14 +191,15 @@ class CategoriesController extends Controller /** - * Returns a view that invokes the ajax tables which actually contains - * the content for the categories detail view, which is generated in getDataView. - * - * @author [A. Gianotto] [] - * @see CategoriesController::getDataView() method that generates the JSON response - * @param int $categoryId - * @since [v1.8] - * @return \Illuminate\Contracts\View\View + * Returns a view that invokes the ajax tables which actually contains + * the content for the categories detail view, which is generated in getDataView. + * + * @author [A. Gianotto] [] + * @see CategoriesController::getDataView() method that generates the JSON response + * @param $id + * @return \Illuminate\Contracts\View\View + * @throws \Illuminate\Auth\Access\AuthorizationException + * @since [v1.8] */ public function show($id) { @@ -255,10 +222,8 @@ class CategoriesController extends Controller } // Prepare the error message - $error = trans('admin/categories/message.does_not_exist', compact('id')); // Redirect to the user management page - return redirect()->route('categories.index')->with('error', $error); + return redirect()->route('categories.index') + ->with('error', trans('admin/categories/message.does_not_exist')); } - - } diff --git a/app/Http/Controllers/CheckInOutRequest.php b/app/Http/Controllers/CheckInOutRequest.php index f88d6acda7..484b6e49db 100644 --- a/app/Http/Controllers/CheckInOutRequest.php +++ b/app/Http/Controllers/CheckInOutRequest.php @@ -4,6 +4,7 @@ namespace App\Http\Controllers; use App\Exceptions\CheckoutNotAllowed; use App\Models\Asset; use App\Models\Location; +use App\Models\SnipeModel; use App\Models\User; trait CheckInOutRequest diff --git a/app/Http/Controllers/CompaniesController.php b/app/Http/Controllers/CompaniesController.php index 8d1a854720..fa6df0b1f6 100644 --- a/app/Http/Controllers/CompaniesController.php +++ b/app/Http/Controllers/CompaniesController.php @@ -2,13 +2,10 @@ namespace App\Http\Controllers; use App\Models\Company; -use Input; -use Lang; -use Redirect; -use View; use Illuminate\Http\Request; use Image; use App\Http\Requests\ImageUploadRequest; +use Illuminate\Support\Facades\Storage; /** * This controller handles all actions related to Companies for @@ -21,11 +18,12 @@ final class CompaniesController extends Controller { /** - * Returns view to display listing of companies. - * - * @author [Abdullah Alansari] [] - * @since [v1.8] - * @return \Illuminate\Contracts\View\View + * Returns view to display listing of companies. + * + * @author [Abdullah Alansari] [] + * @since [v1.8] + * @return \Illuminate\Contracts\View\View + * @throws \Illuminate\Auth\Access\AuthorizationException */ public function index() { @@ -35,11 +33,12 @@ final class CompaniesController extends Controller } /** - * Returns view to create a new company. - * - * @author [Abdullah Alansari] [] - * @since [v1.8] - * @return \Illuminate\Contracts\View\View + * Returns view to create a new company. + * + * @author [Abdullah Alansari] [] + * @since [v1.8] + * @return \Illuminate\Contracts\View\View + * @throws \Illuminate\Auth\Access\AuthorizationException */ public function create() { @@ -55,6 +54,7 @@ final class CompaniesController extends Controller * @since [v1.8] * @param Request $request * @return \Illuminate\Http\RedirectResponse + * @throws \Illuminate\Auth\Access\AuthorizationException */ public function store(ImageUploadRequest $request) { @@ -63,16 +63,7 @@ final class CompaniesController extends Controller $company = new Company; $company->name = $request->input('name'); - if ($request->file('image')) { - $image = $request->file('image'); - $file_name = str_random(25).".".$image->getClientOriginalExtension(); - $path = public_path('uploads/companies/'.$file_name); - Image::make($image->getRealPath())->resize(200, null, function ($constraint) { - $constraint->aspectRatio(); - $constraint->upsize(); - })->save($path); - $company->image = $file_name; - } + $company = $request->handleImages($company); if ($company->save()) { return redirect()->route('companies.index') @@ -83,12 +74,13 @@ final class CompaniesController extends Controller /** - * Return form to edit existing company. - * - * @author [Abdullah Alansari] [] - * @since [v1.8] - * @param int $companyId - * @return \Illuminate\Contracts\View\View + * Return form to edit existing company. + * + * @author [Abdullah Alansari] [] + * @since [v1.8] + * @param int $companyId + * @return \Illuminate\Contracts\View\View + * @throws \Illuminate\Auth\Access\AuthorizationException */ public function edit($companyId) { @@ -107,9 +99,10 @@ final class CompaniesController extends Controller * * @author [Abdullah Alansari] [] * @since [v1.8] - * @param Request $request + * @param ImageUploadRequest $request * @param int $companyId * @return \Illuminate\Http\RedirectResponse + * @throws \Illuminate\Auth\Access\AuthorizationException */ public function update(ImageUploadRequest $request, $companyId) { @@ -121,37 +114,7 @@ final class CompaniesController extends Controller $company->name = $request->input('name'); - $old_image = $company->image; - - // Set the model's image property to null if the image is being deleted - if ($request->input('image_delete') == 1) { - $company->image = null; - } - - if ($request->file('image')) { - $image = $request->file('image'); - $file_name = $company->id.'-'.str_slug($image->getClientOriginalName()) . "." . $image->getClientOriginalExtension(); - - if ($image->getClientOriginalExtension()!='svg') { - Image::make($image->getRealPath())->resize(500, null, function ($constraint) { - $constraint->aspectRatio(); - $constraint->upsize(); - })->save(app('companies_upload_path').$file_name); - } else { - $image->move(app('companies_upload_path'), $file_name); - } - $company->image = $file_name; - - } - - if ((($request->file('image')) && (isset($old_image)) && ($old_image!='')) || ($request->input('image_delete') == 1)) { - try { - unlink(app('companies_upload_path').$old_image); - } catch (\Exception $e) { - \Log::error($e); - } - } - + $company = $request->handleImages($company); if ($company->save()) { return redirect()->route('companies.index') @@ -162,38 +125,47 @@ final class CompaniesController extends Controller } /** - * Delete company - * - * @author [Abdullah Alansari] [] - * @since [v1.8] - * @param int $companyId - * @return \Illuminate\Http\RedirectResponse + * Delete company + * + * @author [Abdullah Alansari] [] + * @since [v1.8] + * @param int $companyId + * @return \Illuminate\Http\RedirectResponse + * @throws \Illuminate\Auth\Access\AuthorizationException */ public function destroy($companyId) { + $this->authorize('delete', $company); + if (is_null($company = Company::find($companyId))) { return redirect()->route('companies.index') ->with('error', trans('admin/companies/message.not_found')); - } else { + } - $this->authorize('delete', $company); + try { - try { - $company->delete(); - return redirect()->route('companies.index') - ->with('success', trans('admin/companies/message.delete.success')); - } catch (\Illuminate\Database\QueryException $exception) { - /* - * NOTE: This happens when there's a foreign key constraint violation - * For example when rows in other tables are referencing this company - */ - if ($exception->getCode() == 23000) { - return redirect()->route('companies.index') - ->with('error', trans('admin/companies/message.assoc_users')); - } else { - throw $exception; + if ($company->image) { + try { + Storage::disk('public')->delete('companies'.'/'.$company->image); + } catch (\Exception $e) { + \Log::debug($e); } } + + $company->delete(); + return redirect()->route('companies.index') + ->with('success', trans('admin/companies/message.delete.success')); + } catch (\Illuminate\Database\QueryException $exception) { + /* + * NOTE: This happens when there's a foreign key constraint violation + * For example when rows in other tables are referencing this company + */ + if ($exception->getCode() == 23000) { + return redirect()->route('companies.index') + ->with('error', trans('admin/companies/message.assoc_users')); + } + + throw $exception; } } @@ -203,9 +175,8 @@ final class CompaniesController extends Controller if (is_null($company = Company::find($id))) { return redirect()->route('companies.index') ->with('error', trans('admin/companies/message.not_found')); - } else { - return view('companies/view')->with('company',$company); } + return view('companies/view')->with('company',$company); } } diff --git a/app/Http/Controllers/Components/ComponentCheckinController.php b/app/Http/Controllers/Components/ComponentCheckinController.php new file mode 100644 index 0000000000..dfba1dcf84 --- /dev/null +++ b/app/Http/Controllers/Components/ComponentCheckinController.php @@ -0,0 +1,108 @@ +] + * @see ComponentCheckinController::store() method that stores the data. + * @since [v4.1.4] + * @param $component_asset_id + * @return \Illuminate\Contracts\View\View + * @throws \Illuminate\Auth\Access\AuthorizationException + */ + public function create($component_asset_id) + { + + // This could probably be done more cleanly but I am very tired. - @snipe + if ($component_assets = DB::table('components_assets')->find($component_asset_id)) { + if (is_null($component = Component::find($component_assets->component_id))) { + return redirect()->route('components.index')->with('error', trans('admin/components/messages.not_found')); + } + if (is_null($asset = Asset::find($component_assets->asset_id))) { + return redirect()->route('components.index')->with('error', + trans('admin/components/message.not_found')); + } + $this->authorize('checkin', $component); + return view('components/checkin', compact('component_assets','component','asset')); + } + + return redirect()->route('components.index')->with('error', trans('admin/components/messages.not_found')); + + } + + + /** + * Validate and store checkin data. + * + * @author [A. Gianotto] [] + * @see ComponentCheckinController::create() method that returns the form. + * @since [v4.1.4] + * @param Request $request + * @param $component_asset_id + * @return \Illuminate\Http\RedirectResponse + * @throws \Illuminate\Auth\Access\AuthorizationException + */ + public function store(Request $request, $component_asset_id) + { + if ($component_assets = DB::table('components_assets')->find($component_asset_id)) { + if (is_null($component = Component::find($component_assets->component_id))) { + return redirect()->route('components.index')->with('error', + trans('admin/components/message.not_found')); + } + + + $this->authorize('checkin', $component); + + $max_to_checkin = $component_assets->assigned_qty; + $validator = Validator::make($request->all(), [ + "checkin_qty" => "required|numeric|between:1,$max_to_checkin" + ]); + + if ($validator->fails()) { + return redirect()->back() + ->withErrors($validator) + ->withInput(); + } + + // Validation passed, so let's figure out what we have to do here. + $qty_remaining_in_checkout = ($component_assets->assigned_qty - (int)$request->input('checkin_qty')); + + // We have to modify the record to reflect the new qty that's + // actually checked out. + $component_assets->assigned_qty = $qty_remaining_in_checkout; + DB::table('components_assets')->where('id', + $component_asset_id)->update(['assigned_qty' => $qty_remaining_in_checkout]); + + // If the checked-in qty is exactly the same as the assigned_qty, + // we can simply delete the associated components_assets record + if ($qty_remaining_in_checkout == 0) { + DB::table('components_assets')->where('id', '=', $component_asset_id)->delete(); + } + + $asset = Asset::find($component_assets->asset_id); + + event(new CheckoutableCheckedIn($component, $asset, Auth::user(), $request->input('note'))); + + return redirect()->route('components.index')->with('success', + trans('admin/components/message.checkout.success')); + } + return redirect()->route('components.index')->with('error', trans('admin/components/message.not_found')); + } + +} diff --git a/app/Http/Controllers/Components/ComponentCheckoutController.php b/app/Http/Controllers/Components/ComponentCheckoutController.php new file mode 100644 index 0000000000..bfa9e8967b --- /dev/null +++ b/app/Http/Controllers/Components/ComponentCheckoutController.php @@ -0,0 +1,95 @@ +] + * @see ComponentCheckoutController::store() method that stores the data. + * @since [v3.0] + * @param int $componentId + * @return \Illuminate\Contracts\View\View + * @throws \Illuminate\Auth\Access\AuthorizationException + */ + public function create($componentId) + { + // Check if the component exists + if (is_null($component = Component::find($componentId))) { + // Redirect to the component management page with error + return redirect()->route('components.index')->with('error', trans('admin/components/message.not_found')); + } + $this->authorize('checkout', $component); + return view('components/checkout', compact('component')); + } + + /** + * Validate and store checkout data. + * + * @author [A. Gianotto] [] + * @see ComponentCheckoutController::create() method that returns the form. + * @since [v3.0] + * @param Request $request + * @param int $componentId + * @return \Illuminate\Http\RedirectResponse + * @throws \Illuminate\Auth\Access\AuthorizationException + */ + public function store(Request $request, $componentId) + { + // Check if the component exists + if (is_null($component = Component::find($componentId))) { + // Redirect to the component management page with error + return redirect()->route('components.index')->with('error', trans('admin/components/message.not_found')); + } + + $this->authorize('checkout', $component); + + $max_to_checkout = $component->numRemaining(); + $validator = Validator::make($request->all(), [ + "asset_id" => "required", + "assigned_qty" => "required|numeric|between:1,$max_to_checkout" + ]); + + if ($validator->fails()) { + return redirect()->back() + ->withErrors($validator) + ->withInput(); + } + + $admin_user = Auth::user(); + $asset_id = e(Input::get('asset_id')); + + // Check if the user exists + if (is_null($asset = Asset::find($asset_id))) { + // Redirect to the component management page with error + return redirect()->route('components.index')->with('error', trans('admin/components/message.asset_does_not_exist')); + } + + // Update the component data + $component->asset_id = $asset_id; + + $component->assets()->attach($component->id, [ + 'component_id' => $component->id, + 'user_id' => $admin_user->id, + 'created_at' => date('Y-m-d H:i:s'), + 'assigned_qty' => Input::get('assigned_qty'), + 'asset_id' => $asset_id + ]); + + event(new CheckoutableCheckedOut($component, $asset, Auth::user(), $request->input('note'))); + + return redirect()->route('components.index')->with('success', trans('admin/components/message.checkout.success')); + } +} diff --git a/app/Http/Controllers/Components/ComponentsController.php b/app/Http/Controllers/Components/ComponentsController.php new file mode 100644 index 0000000000..6839e1604d --- /dev/null +++ b/app/Http/Controllers/Components/ComponentsController.php @@ -0,0 +1,199 @@ +] + * @see ComponentsController::getDatatable() method that generates the JSON response + * @since [v3.0] + * @return \Illuminate\Contracts\View\View + * @throws \Illuminate\Auth\Access\AuthorizationException + */ + public function index() + { + $this->authorize('view', Component::class); + return view('components/index'); + } + + + /** + * Returns a form to create a new component. + * + * @author [A. Gianotto] [] + * @see ComponentsController::postCreate() method that stores the data + * @since [v3.0] + * @return \Illuminate\Contracts\View\View + * @throws \Illuminate\Auth\Access\AuthorizationException + */ + public function create() + { + $this->authorize('create', Component::class); + return view('components/edit')->with('category_type', 'component') + ->with('item', new Component); + } + + + /** + * Validate and store data for new component. + * + * @author [A. Gianotto] [] + * @see ComponentsController::getCreate() method that generates the view + * @since [v3.0] + * @param ImageUploadRequest $request + * @return \Illuminate\Http\RedirectResponse + * @throws \Illuminate\Auth\Access\AuthorizationException + */ + public function store(ImageUploadRequest $request) + { + $this->authorize('create', Component::class); + $component = new Component(); + $component->name = $request->input('name'); + $component->category_id = $request->input('category_id'); + $component->location_id = $request->input('location_id'); + $component->company_id = Company::getIdForCurrentUser($request->input('company_id')); + $component->order_number = $request->input('order_number', null); + $component->min_amt = $request->input('min_amt', null); + $component->serial = $request->input('serial', null); + $component->purchase_date = $request->input('purchase_date', null); + $component->purchase_cost = $request->input('purchase_cost', null); + $component->qty = $request->input('qty'); + $component->user_id = Auth::id(); + + $component = $request->handleImages($component); + + if ($component->save()) { + return redirect()->route('components.index')->with('success', trans('admin/components/message.create.success')); + } + return redirect()->back()->withInput()->withErrors($component->getErrors()); + } + + /** + * Return a view to edit a component. + * + * @author [A. Gianotto] [] + * @see ComponentsController::postEdit() method that stores the data. + * @since [v3.0] + * @param int $componentId + * @return \Illuminate\Contracts\View\View + * @throws \Illuminate\Auth\Access\AuthorizationException + */ + public function edit($componentId = null) + { + if ($item = Component::find($componentId)) { + $this->authorize('update', $item); + return view('components/edit', compact('item'))->with('category_type', 'component'); + } + return redirect()->route('components.index')->with('error', trans('admin/components/message.does_not_exist')); + } + + + /** + * Return a view to edit a component. + * + * @author [A. Gianotto] [] + * @see ComponentsController::getEdit() method presents the form. + * @param ImageUploadRequest $request + * @param int $componentId + * @return \Illuminate\Http\RedirectResponse + * @throws \Illuminate\Auth\Access\AuthorizationException + * @since [v3.0] + */ + public function update(ImageUploadRequest $request, $componentId = null) + { + if (is_null($component = Component::find($componentId))) { + return redirect()->route('components.index')->with('error', trans('admin/components/message.does_not_exist')); + } + + $this->authorize('update', $component); + + // Update the component data + $component->name = Input::get('name'); + $component->category_id = Input::get('category_id'); + $component->location_id = Input::get('location_id'); + $component->company_id = Company::getIdForCurrentUser(Input::get('company_id')); + $component->order_number = Input::get('order_number'); + $component->min_amt = Input::get('min_amt'); + $component->serial = Input::get('serial'); + $component->purchase_date = Input::get('purchase_date'); + $component->purchase_cost = request('purchase_cost'); + $component->qty = Input::get('qty'); + + $component = $request->handleImages($component); + + if ($component->save()) { + return redirect()->route('components.index')->with('success', trans('admin/components/message.update.success')); + } + return redirect()->back()->withInput()->withErrors($component->getErrors()); + } + + /** + * Delete a component. + * + * @author [A. Gianotto] [] + * @since [v3.0] + * @param int $componentId + * @return \Illuminate\Http\RedirectResponse + * @throws \Illuminate\Auth\Access\AuthorizationException + */ + public function destroy($componentId) + { + if (is_null($component = Component::find($componentId))) { + return redirect()->route('components.index')->with('error', trans('admin/components/message.does_not_exist')); + } + + $this->authorize('delete', $component); + + // Remove the image if one exists + if (Storage::disk('public')->exists('components/'.$component->image)) { + try { + Storage::disk('public')->delete('components/'.$component->image); + } catch (\Exception $e) { + \Log::debug($e); + } + } + + $component->delete(); + return redirect()->route('components.index')->with('success', trans('admin/components/message.delete.success')); + } + + /** + * Return a view to display component information. + * + * @author [A. Gianotto] [] + * @see ComponentsController::getDataView() method that generates the JSON response + * @since [v3.0] + * @param int $componentId + * @return \Illuminate\Contracts\View\View + * @throws \Illuminate\Auth\Access\AuthorizationException + */ + public function show($componentId = null) + { + $component = Component::find($componentId); + + if (isset($component->id)) { + $this->authorize('view', $component); + return view('components/view', compact('component')); + } + // Redirect to the user management page + return redirect()->route('components.index') + ->with('error', trans('admin/components/message.does_not_exist')); + } +} diff --git a/app/Http/Controllers/ComponentsController.php b/app/Http/Controllers/ComponentsController.php deleted file mode 100644 index a73a951363..0000000000 --- a/app/Http/Controllers/ComponentsController.php +++ /dev/null @@ -1,397 +0,0 @@ -] - * @see ComponentsController::getDatatable() method that generates the JSON response - * @since [v3.0] - * @return \Illuminate\Contracts\View\View - */ - public function index() - { - $this->authorize('view', Component::class); - return view('components/index'); - } - - - /** - * Returns a form to create a new component. - * - * @author [A. Gianotto] [] - * @see ComponentsController::postCreate() method that stores the data - * @since [v3.0] - * @return \Illuminate\Contracts\View\View - */ - public function create() - { - $this->authorize('create', Component::class); - $category_type = 'component'; - return view('components/edit')->with('category_type',$category_type) - ->with('item', new Component); - } - - - /** - * Validate and store data for new component. - * - * @author [A. Gianotto] [] - * @see ComponentsController::getCreate() method that generates the view - * @since [v3.0] - * @return \Illuminate\Http\RedirectResponse - */ - public function store(ImageUploadRequest $request) - { - $this->authorize('create', Component::class); - $component = new Component(); - $component->name = $request->input('name'); - $component->category_id = $request->input('category_id'); - $component->location_id = $request->input('location_id'); - $component->company_id = Company::getIdForCurrentUser($request->input('company_id')); - $component->order_number = $request->input('order_number', null); - $component->min_amt = $request->input('min_amt', null); - $component->serial = $request->input('serial', null); - $component->purchase_date = $request->input('purchase_date', null); - $component->purchase_cost = $request->input('purchase_cost', null); - $component->qty = $request->input('qty'); - $component->user_id = Auth::id(); - - - if ($request->file('image')) { - $image = $request->file('image'); - $file_name = str_random(25).".".$image->getClientOriginalExtension(); - $path = public_path('uploads/components/'.$file_name); - Image::make($image->getRealPath())->resize(200, null, function ($constraint) { - $constraint->aspectRatio(); - $constraint->upsize(); - })->save($path); - $component->image = $file_name; - } - - if ($component->save()) { - return redirect()->route('components.index')->with('success', trans('admin/components/message.create.success')); - } - return redirect()->back()->withInput()->withErrors($component->getErrors()); - } - - /** - * Return a view to edit a component. - * - * @author [A. Gianotto] [] - * @see ComponentsController::postEdit() method that stores the data. - * @since [v3.0] - * @param int $componentId - * @return \Illuminate\Contracts\View\View - */ - public function edit($componentId = null) - { - - - if ($item = Component::find($componentId)) { - $this->authorize('update', $item); - $category_type = 'component'; - return view('components/edit', compact('item'))->with('category_type', $category_type); - } - return redirect()->route('components.index')->with('error', trans('admin/components/message.does_not_exist')); - - - - - } - - - /** - * Return a view to edit a component. - * - * @author [A. Gianotto] [] - * @see ComponentsController::getEdit() method presents the form. - * @param int $componentId - * @since [v3.0] - * @return \Illuminate\Http\RedirectResponse - */ - public function update(ImageUploadRequest $request, $componentId = null) - { - if (is_null($component = Component::find($componentId))) { - return redirect()->route('components.index')->with('error', trans('admin/components/message.does_not_exist')); - } - - $this->authorize('update', $component); - - - // Update the component data - $component->name = Input::get('name'); - $component->category_id = Input::get('category_id'); - $component->location_id = Input::get('location_id'); - $component->company_id = Company::getIdForCurrentUser(Input::get('company_id')); - $component->order_number = Input::get('order_number'); - $component->min_amt = Input::get('min_amt'); - $component->serial = Input::get('serial'); - $component->purchase_date = Input::get('purchase_date'); - $component->purchase_cost = request('purchase_cost'); - $component->qty = Input::get('qty'); - - if ($request->file('image')) { - $image = $request->file('image'); - $file_name = str_random(25).".".$image->getClientOriginalExtension(); - $path = public_path('uploads/components/'.$file_name); - Image::make($image->getRealPath())->resize(200, null, function ($constraint) { - $constraint->aspectRatio(); - $constraint->upsize(); - })->save($path); - $component->image = $file_name; - } elseif ($request->input('image_delete')=='1') { - $component->image = null; - } - - if ($component->save()) { - return redirect()->route('components.index')->with('success', trans('admin/components/message.update.success')); - } - return redirect()->back()->withInput()->withErrors($component->getErrors()); - } - - /** - * Delete a component. - * - * @author [A. Gianotto] [] - * @since [v3.0] - * @param int $componentId - * @return \Illuminate\Http\RedirectResponse - */ - public function destroy($componentId) - { - if (is_null($component = Component::find($componentId))) { - return redirect()->route('components.index')->with('error', trans('admin/components/message.does_not_exist')); - } - - $this->authorize('delete', $component); - $component->delete(); - return redirect()->route('components.index')->with('success', trans('admin/components/message.delete.success')); - } - - /** - * Return a view to display component information. - * - * @author [A. Gianotto] [] - * @see ComponentsController::getDataView() method that generates the JSON response - * @since [v3.0] - * @param int $componentId - * @return \Illuminate\Contracts\View\View - */ - public function show($componentId = null) - { - $component = Component::find($componentId); - - if (isset($component->id)) { - $this->authorize('view', $component); - return view('components/view', compact('component')); - } - // Prepare the error message - $error = trans('admin/components/message.does_not_exist', compact('id')); - // Redirect to the user management page - return redirect()->route('components.index')->with('error', $error); - } - - /** - * Returns a view that allows the checkout of a component to an asset. - * - * @author [A. Gianotto] [] - * @see ComponentsController::postCheckout() method that stores the data. - * @since [v3.0] - * @param int $componentId - * @return \Illuminate\Contracts\View\View - */ - public function getCheckout($componentId) - { - // Check if the component exists - if (is_null($component = Component::find($componentId))) { - // Redirect to the component management page with error - return redirect()->route('components.index')->with('error', trans('admin/components/message.not_found')); - } - $this->authorize('checkout', $component); - return view('components/checkout', compact('component')); - } - - /** - * Validate and store checkout data. - * - * @author [A. Gianotto] [] - * @see ComponentsController::getCheckout() method that returns the form. - * @since [v3.0] - * @param Request $request - * @param int $componentId - * @return \Illuminate\Http\RedirectResponse - */ - public function postCheckout(Request $request, $componentId) - { - // Check if the component exists - if (is_null($component = Component::find($componentId))) { - // Redirect to the component management page with error - return redirect()->route('components.index')->with('error', trans('admin/components/message.not_found')); - } - - $this->authorize('checkout', $component); - - $max_to_checkout = $component->numRemaining(); - $validator = Validator::make($request->all(), [ - "asset_id" => "required", - "assigned_qty" => "required|numeric|between:1,$max_to_checkout" - ]); - - if ($validator->fails()) { - return redirect()->back() - ->withErrors($validator) - ->withInput(); - } - - $admin_user = Auth::user(); - $asset_id = e(Input::get('asset_id')); - - // Check if the user exists - if (is_null($asset = Asset::find($asset_id))) { - // Redirect to the component management page with error - return redirect()->route('components.index')->with('error', trans('admin/components/message.asset_does_not_exist')); - } - - // Update the component data - $component->asset_id = $asset_id; - - $component->assets()->attach($component->id, [ - 'component_id' => $component->id, - 'user_id' => $admin_user->id, - 'created_at' => date('Y-m-d H:i:s'), - 'assigned_qty' => Input::get('assigned_qty'), - 'asset_id' => $asset_id - ]); - - $component->logCheckout(e(Input::get('note')), $asset); - return redirect()->route('components.index')->with('success', trans('admin/components/message.checkout.success')); - } - - /** - * Returns a view that allows the checkin of a component from an asset. - * - * @author [A. Gianotto] [] - * @see ComponentsController::postCheckout() method that stores the data. - * @since [v4.1.4] - * @param int $componentId - * @return \Illuminate\Contracts\View\View - */ - public function getCheckin($component_asset_id) - { - - // This could probably be done more cleanly but I am very tired. - @snipe - if ($component_assets = DB::table('components_assets')->find($component_asset_id)) { - if (is_null($component = Component::find($component_assets->component_id))) { - return redirect()->route('components.index')->with('error', trans('admin/components/messages.not_found')); - } - if (is_null($asset = Asset::find($component_assets->asset_id))) { - return redirect()->route('components.index')->with('error', - trans('admin/components/message.not_found')); - } - $this->authorize('checkin', $component); - return view('components/checkin', compact('component_assets','component','asset')); - } - - return redirect()->route('components.index')->with('error', trans('admin/components/messages.not_found')); - - } - - /** - * Validate and store checkin data. - * - * @author [A. Gianotto] [] - * @see ComponentsController::getCheckout() method that returns the form. - * @since [v4.1.4] - * @param Request $request - * @param int $componentId - * @return \Illuminate\Http\RedirectResponse - */ - public function postCheckin(Request $request, $component_asset_id) - { - if ($component_assets = DB::table('components_assets')->find($component_asset_id)) { - if (is_null($component = Component::find($component_assets->component_id))) { - return redirect()->route('components.index')->with('error', - trans('admin/components/message.not_found')); - } - - - $this->authorize('checkin', $component); - - $max_to_checkin = $component_assets->assigned_qty; - $validator = Validator::make($request->all(), [ - "checkin_qty" => "required|numeric|between:1,$max_to_checkin" - ]); - - if ($validator->fails()) { - return redirect()->back() - ->withErrors($validator) - ->withInput(); - } - - // Validation passed, so let's figure out what we have to do here. - $qty_remaining_in_checkout = ($component_assets->assigned_qty - (int)$request->input('checkin_qty')); - - // We have to modify the record to reflect the new qty that's - // actually checked out. - $component_assets->assigned_qty = $qty_remaining_in_checkout; - DB::table('components_assets')->where('id', - $component_asset_id)->update(['assigned_qty' => $qty_remaining_in_checkout]); - - $log = new Actionlog(); - $log->user_id = Auth::user()->id; - $log->action_type = 'checkin from'; - $log->target_type = Asset::class; - $log->target_id = $component_assets->asset_id; - $log->item_id = $component_assets->component_id; - $log->item_type = Component::class; - $log->note = $request->input('note'); - $log->save(); - - // If the checked-in qty is exactly the same as the assigned_qty, - // we can simply delete the associated components_assets record - if ($qty_remaining_in_checkout == 0) { - DB::table('components_assets')->where('id', '=', $component_asset_id)->delete(); - } - - return redirect()->route('components.index')->with('success', - trans('admin/components/message.checkout.success')); - } - return redirect()->route('components.index')->with('error', trans('admin/components/message.not_found')); - } - - -} diff --git a/app/Http/Controllers/Consumables/ConsumableCheckoutController.php b/app/Http/Controllers/Consumables/ConsumableCheckoutController.php new file mode 100644 index 0000000000..e3e3e11b03 --- /dev/null +++ b/app/Http/Controllers/Consumables/ConsumableCheckoutController.php @@ -0,0 +1,77 @@ +] + * @see ConsumableCheckoutController::store() method that stores the data. + * @since [v1.0] + * @param int $consumableId + * @return \Illuminate\Contracts\View\View + * @throws \Illuminate\Auth\Access\AuthorizationException + */ + public function create($consumableId) + { + if (is_null($consumable = Consumable::find($consumableId))) { + return redirect()->route('consumables.index')->with('error', trans('admin/consumables/message.does_not_exist')); + } + $this->authorize('checkout', $consumable); + return view('consumables/checkout', compact('consumable')); + } + + /** + * Saves the checkout information + * + * @author [A. Gianotto] [] + * @see ConsumableCheckoutController::create() method that returns the form. + * @since [v1.0] + * @param int $consumableId + * @return \Illuminate\Http\RedirectResponse + * @throws \Illuminate\Auth\Access\AuthorizationException + */ + public function store(Request $request, $consumableId) + { + if (is_null($consumable = Consumable::find($consumableId))) { + return redirect()->route('consumables.index')->with('error', trans('admin/consumables/message.not_found')); + } + + $this->authorize('checkout', $consumable); + + $admin_user = Auth::user(); + $assigned_to = e(Input::get('assigned_to')); + + // Check if the user exists + if (is_null($user = User::find($assigned_to))) { + // Redirect to the consumable management page with error + return redirect()->route('checkout/consumable', $consumable)->with('error', trans('admin/consumables/message.checkout.user_does_not_exist')); + } + + // Update the consumable data + $consumable->assigned_to = e(Input::get('assigned_to')); + + $consumable->users()->attach($consumable->id, [ + 'consumable_id' => $consumable->id, + 'user_id' => $admin_user->id, + 'assigned_to' => e(Input::get('assigned_to')) + ]); + + event(new CheckoutableCheckedOut($consumable, $user, Auth::user(), $request->input('note'))); + + // Redirect to the new consumable page + return redirect()->route('consumables.index')->with('success', trans('admin/consumables/message.checkout.success')); + + } +} diff --git a/app/Http/Controllers/Consumables/ConsumablesController.php b/app/Http/Controllers/Consumables/ConsumablesController.php new file mode 100644 index 0000000000..9bb9318ca4 --- /dev/null +++ b/app/Http/Controllers/Consumables/ConsumablesController.php @@ -0,0 +1,197 @@ +] + * @see ConsumablesController::getDatatable() method that generates the JSON response + * @since [v1.0] + * @return \Illuminate\Contracts\View\View + * @throws \Illuminate\Auth\Access\AuthorizationException + */ + public function index() + { + $this->authorize('index', Consumable::class); + return view('consumables/index'); + } + + + /** + * Return a view to display the form view to create a new consumable + * + * @author [A. Gianotto] [] + * @see ConsumablesController::postCreate() method that stores the form data + * @since [v1.0] + * @return \Illuminate\Contracts\View\View + * @throws \Illuminate\Auth\Access\AuthorizationException + */ + public function create() + { + $this->authorize('create', Consumable::class); + return view('consumables/edit')->with('category_type', 'consumable') + ->with('item', new Consumable); + } + + + /** + * Validate and store new consumable data. + * + * @author [A. Gianotto] [] + * @see ConsumablesController::getCreate() method that returns the form view + * @since [v1.0] + * @param ImageUploadRequest $request + * @return \Illuminate\Http\RedirectResponse + * @throws \Illuminate\Auth\Access\AuthorizationException + */ + public function store(ImageUploadRequest $request) + { + $this->authorize('create', Consumable::class); + $consumable = new Consumable(); + $consumable->name = $request->input('name'); + $consumable->category_id = $request->input('category_id'); + $consumable->location_id = $request->input('location_id'); + $consumable->company_id = Company::getIdForCurrentUser($request->input('company_id')); + $consumable->order_number = $request->input('order_number'); + $consumable->min_amt = $request->input('min_amt'); + $consumable->manufacturer_id = $request->input('manufacturer_id'); + $consumable->model_number = $request->input('model_number'); + $consumable->item_no = $request->input('item_no'); + $consumable->purchase_date = $request->input('purchase_date'); + $consumable->purchase_cost = Helper::ParseFloat($request->input('purchase_cost')); + $consumable->qty = $request->input('qty'); + $consumable->user_id = Auth::id(); + + + $consumable = $request->handleImages($consumable); + + if ($consumable->save()) { + return redirect()->route('consumables.index')->with('success', trans('admin/consumables/message.create.success')); + } + + return redirect()->back()->withInput()->withErrors($consumable->getErrors()); + + } + + /** + * Returns a form view to edit a consumable. + * + * @author [A. Gianotto] [] + * @param int $consumableId + * @see ConsumablesController::postEdit() method that stores the form data. + * @since [v1.0] + * @return \Illuminate\Contracts\View\View + * @throws \Illuminate\Auth\Access\AuthorizationException + */ + public function edit($consumableId = null) + { + if ($item = Consumable::find($consumableId)) { + $this->authorize($item); + return view('consumables/edit', compact('item'))->with('category_type', 'consumable'); + } + + return redirect()->route('consumables.index')->with('error', trans('admin/consumables/message.does_not_exist')); + + } + + + /** + * Returns a form view to edit a consumable. + * + * @author [A. Gianotto] [] + * @param ImageUploadRequest $request + * @param int $consumableId + * @return \Illuminate\Http\RedirectResponse + * @throws \Illuminate\Auth\Access\AuthorizationException + * @see ConsumablesController::getEdit() method that stores the form data. + * @since [v1.0] + */ + public function update(ImageUploadRequest $request, $consumableId = null) + { + if (is_null($consumable = Consumable::find($consumableId))) { + return redirect()->route('consumables.index')->with('error', trans('admin/consumables/message.does_not_exist')); + } + + $this->authorize($consumable); + + $consumable->name = $request->input('name'); + $consumable->category_id = $request->input('category_id'); + $consumable->location_id = $request->input('location_id'); + $consumable->company_id = Company::getIdForCurrentUser($request->input('company_id')); + $consumable->order_number = $request->input('order_number'); + $consumable->min_amt = $request->input('min_amt'); + $consumable->manufacturer_id = $request->input('manufacturer_id'); + $consumable->model_number = $request->input('model_number'); + $consumable->item_no = $request->input('item_no'); + $consumable->purchase_date = $request->input('purchase_date'); + $consumable->purchase_cost = Helper::ParseFloat(Input::get('purchase_cost')); + $consumable->qty = Helper::ParseFloat(Input::get('qty')); + + $consumable = $request->handleImages($consumable); + + if ($consumable->save()) { + return redirect()->route('consumables.index')->with('success', trans('admin/consumables/message.update.success')); + } + return redirect()->back()->withInput()->withErrors($consumable->getErrors()); + } + + /** + * Delete a consumable. + * + * @author [A. Gianotto] [] + * @param int $consumableId + * @since [v1.0] + * @return \Illuminate\Http\RedirectResponse + * @throws \Illuminate\Auth\Access\AuthorizationException + */ + public function destroy($consumableId) + { + if (is_null($consumable = Consumable::find($consumableId))) { + return redirect()->route('consumables.index')->with('error', trans('admin/consumables/message.not_found')); + } + $this->authorize($consumable); + $consumable->delete(); + // Redirect to the locations management page + return redirect()->route('consumables.index')->with('success', trans('admin/consumables/message.delete.success')); + } + + /** + * Return a view to display component information. + * + * @author [A. Gianotto] [] + * @see ConsumablesController::getDataView() method that generates the JSON response + * @since [v1.0] + * @param int $consumableId + * @return \Illuminate\Contracts\View\View + * @throws \Illuminate\Auth\Access\AuthorizationException + */ + public function show($consumableId = null) + { + $consumable = Consumable::find($consumableId); + $this->authorize($consumable); + if (isset($consumable->id)) { + return view('consumables/view', compact('consumable')); + } + return redirect()->route('consumables.index') + ->with('error', trans('admin/consumables/message.does_not_exist')); + } + +} diff --git a/app/Http/Controllers/ConsumablesController.php b/app/Http/Controllers/ConsumablesController.php deleted file mode 100644 index 92f3752968..0000000000 --- a/app/Http/Controllers/ConsumablesController.php +++ /dev/null @@ -1,286 +0,0 @@ -] - * @see ConsumablesController::getDatatable() method that generates the JSON response - * @since [v1.0] - * @return \Illuminate\Contracts\View\View - */ - public function index() - { - $this->authorize('index', Consumable::class); - return view('consumables/index'); - } - - - /** - * Return a view to display the form view to create a new consumable - * - * @author [A. Gianotto] [] - * @see ConsumablesController::postCreate() method that stores the form data - * @since [v1.0] - * @return \Illuminate\Contracts\View\View - */ - public function create() - { - $this->authorize('create', Consumable::class); - $category_type = 'consumable'; - return view('consumables/edit')->with('category_type', $category_type) - ->with('item', new Consumable); - } - - - /** - * Validate and store new consumable data. - * - * @author [A. Gianotto] [] - * @see ConsumablesController::getCreate() method that returns the form view - * @since [v1.0] - * @return \Illuminate\Http\RedirectResponse - */ - public function store(ImageUploadRequest $request) - { - $this->authorize('create', Consumable::class); - $consumable = new Consumable(); - $consumable->name = $request->input('name'); - $consumable->category_id = $request->input('category_id'); - $consumable->location_id = $request->input('location_id'); - $consumable->company_id = Company::getIdForCurrentUser($request->input('company_id')); - $consumable->order_number = $request->input('order_number'); - $consumable->min_amt = $request->input('min_amt'); - $consumable->manufacturer_id = $request->input('manufacturer_id'); - $consumable->model_number = $request->input('model_number'); - $consumable->item_no = $request->input('item_no'); - $consumable->purchase_date = $request->input('purchase_date'); - $consumable->purchase_cost = Helper::ParseFloat($request->input('purchase_cost')); - $consumable->qty = $request->input('qty'); - $consumable->user_id = Auth::id(); - - - if ($request->file('image')) { - $image = $request->file('image'); - $file_name = str_random(25).".".$image->getClientOriginalExtension(); - $path = public_path('uploads/consumables/'.$file_name); - Image::make($image->getRealPath())->resize(200, null, function ($constraint) { - $constraint->aspectRatio(); - $constraint->upsize(); - })->save($path); - $consumable->image = $file_name; - } - - if ($consumable->save()) { - return redirect()->route('consumables.index')->with('success', trans('admin/consumables/message.create.success')); - } - - return redirect()->back()->withInput()->withErrors($consumable->getErrors()); - - } - - /** - * Returns a form view to edit a consumable. - * - * @author [A. Gianotto] [] - * @param int $consumableId - * @see ConsumablesController::postEdit() method that stores the form data. - * @since [v1.0] - * @return \Illuminate\Contracts\View\View - */ - public function edit($consumableId = null) - { - if ($item = Consumable::find($consumableId)) { - $this->authorize($item); - $category_type = 'consumable'; - return view('consumables/edit', compact('item'))->with('category_type', $category_type); - } - - return redirect()->route('consumables.index')->with('error', trans('admin/consumables/message.does_not_exist')); - - } - - - /** - * Returns a form view to edit a consumable. - * - * @author [A. Gianotto] [] - * @param int $consumableId - * @see ConsumablesController::getEdit() method that stores the form data. - * @since [v1.0] - * @return \Illuminate\Http\RedirectResponse - */ - public function update(ImageUploadRequest $request, $consumableId = null) - { - if (is_null($consumable = Consumable::find($consumableId))) { - return redirect()->route('consumables.index')->with('error', trans('admin/consumables/message.does_not_exist')); - } - - $this->authorize($consumable); - - $consumable->name = $request->input('name'); - $consumable->category_id = $request->input('category_id'); - $consumable->location_id = $request->input('location_id'); - $consumable->company_id = Company::getIdForCurrentUser($request->input('company_id')); - $consumable->order_number = $request->input('order_number'); - $consumable->min_amt = $request->input('min_amt'); - $consumable->manufacturer_id = $request->input('manufacturer_id'); - $consumable->model_number = $request->input('model_number'); - $consumable->item_no = $request->input('item_no'); - $consumable->purchase_date = $request->input('purchase_date'); - $consumable->purchase_cost = Helper::ParseFloat(Input::get('purchase_cost')); - $consumable->qty = Helper::ParseFloat(Input::get('qty')); - - if ($request->file('image')) { - $image = $request->file('image'); - $file_name = str_random(25).".".$image->getClientOriginalExtension(); - $path = public_path('uploads/consumables/'.$file_name); - Image::make($image->getRealPath())->resize(200, null, function ($constraint) { - $constraint->aspectRatio(); - $constraint->upsize(); - })->save($path); - $consumable->image = $file_name; - } elseif ($request->input('image_delete')=='1') { - $consumable->image = null; - } - - if ($consumable->save()) { - return redirect()->route('consumables.index')->with('success', trans('admin/consumables/message.update.success')); - } - return redirect()->back()->withInput()->withErrors($consumable->getErrors()); - } - - /** - * Delete a consumable. - * - * @author [A. Gianotto] [] - * @param int $consumableId - * @since [v1.0] - * @return \Illuminate\Http\RedirectResponse - */ - public function destroy($consumableId) - { - if (is_null($consumable = Consumable::find($consumableId))) { - return redirect()->route('consumables.index')->with('error', trans('admin/consumables/message.not_found')); - } - $this->authorize($consumable); - $consumable->delete(); - // Redirect to the locations management page - return redirect()->route('consumables.index')->with('success', trans('admin/consumables/message.delete.success')); - } - - /** - * Return a view to display component information. - * - * @author [A. Gianotto] [] - * @see ConsumablesController::getDataView() method that generates the JSON response - * @since [v1.0] - * @param int $consumableId - * @return \Illuminate\Contracts\View\View - */ - public function show($consumableId = null) - { - $consumable = Consumable::find($consumableId); - $this->authorize($consumable); - if (isset($consumable->id)) { - return view('consumables/view', compact('consumable')); - } - return redirect()->route('consumables.index')->with('error', trans('admin/consumables/message.does_not_exist', compact('id'))); - } - - /** - * Return a view to checkout a consumable to a user. - * - * @author [A. Gianotto] [] - * @see ConsumablesController::postCheckout() method that stores the data. - * @since [v1.0] - * @param int $consumableId - * @return \Illuminate\Contracts\View\View - */ - public function getCheckout($consumableId) - { - if (is_null($consumable = Consumable::find($consumableId))) { - return redirect()->route('consumables.index')->with('error', trans('admin/consumables/message.does_not_exist')); - } - $this->authorize('checkout', $consumable); - return view('consumables/checkout', compact('consumable')); - } - - /** - * Saves the checkout information - * - * @author [A. Gianotto] [] - * @see ConsumablesController::getCheckout() method that returns the form. - * @since [v1.0] - * @param int $consumableId - * @return \Illuminate\Http\RedirectResponse - */ - public function postCheckout($consumableId) - { - if (is_null($consumable = Consumable::find($consumableId))) { - return redirect()->route('consumables.index')->with('error', trans('admin/consumables/message.not_found')); - } - - $this->authorize('checkout', $consumable); - - $admin_user = Auth::user(); - $assigned_to = e(Input::get('assigned_to')); - - // Check if the user exists - if (is_null($user = User::find($assigned_to))) { - // Redirect to the consumable management page with error - return redirect()->route('checkout/consumable', $consumable)->with('error', trans('admin/consumables/message.checkout.user_does_not_exist')); - } - - // Update the consumable data - $consumable->assigned_to = e(Input::get('assigned_to')); - - $consumable->users()->attach($consumable->id, [ - 'consumable_id' => $consumable->id, - 'user_id' => $admin_user->id, - 'assigned_to' => e(Input::get('assigned_to')) - ]); - - $logaction = $consumable->logCheckout(e(Input::get('note')), $user); - $data['log_id'] = $logaction->id; - $data['eula'] = $consumable->getEula(); - $data['first_name'] = $user->first_name; - $data['item_name'] = $consumable->name; - $data['checkout_date'] = $logaction->created_at; - $data['note'] = $logaction->note; - $data['require_acceptance'] = $consumable->requireAcceptance(); - - - // Redirect to the new consumable page - return redirect()->route('consumables.index')->with('success', trans('admin/consumables/message.checkout.success')); - - } - -} diff --git a/app/Http/Controllers/CustomFieldsController.php b/app/Http/Controllers/CustomFieldsController.php index 62f2cf32f7..0e0b95b090 100644 --- a/app/Http/Controllers/CustomFieldsController.php +++ b/app/Http/Controllers/CustomFieldsController.php @@ -1,19 +1,14 @@ ] - * @since [v1.8] - * @return View - */ + * Returns a view with a listing of custom fields. + * + * @author [Brady Wetherington] [] + * @since [v1.8] + * @return \Illuminate\Support\Facades\View + * @throws \Illuminate\Auth\Access\AuthorizationException + */ public function index() { $this->authorize('view', CustomField::class); $fieldsets = CustomFieldset::with("fields", "models")->get(); $fields = CustomField::with("fieldset")->get(); + return view("custom_fields.index")->with("custom_fieldsets", $fieldsets)->with("custom_fields", $fields); } - - - /** - * Returns a view with a form to create a new custom field. - * - * @see CustomFieldsController::storeField() - * @author [Brady Wetherington] [] - * @since [v1.8] - * @return View - */ + * Returns a view with a form to create a new custom field. + * + * @see CustomFieldsController::storeField() + * @author [Brady Wetherington] [] + * @since [v1.8] + * @return \Illuminate\Support\Facades\View + * @throws \Illuminate\Auth\Access\AuthorizationException + */ public function create() { $this->authorize('create', CustomField::class); - return view("custom_fields.fields.edit")->with('field', new CustomField()); + return view("custom_fields.fields.edit",[ + 'predefinedFormats' => Helper::predefined_formats(), + 'customFormat' => '' + ])->with('field', new CustomField()); } /** - * Validates and stores a new custom field. - * - * @see CustomFieldsController::createField() - * @author [Brady Wetherington] [] - * @since [v1.8] - * @return Redirect - */ + * Validates and stores a new custom field. + * + * @see CustomFieldsController::createField() + * @author [Brady Wetherington] [] + * @since [v1.8] + * @return Redirect + * @throws \Illuminate\Auth\Access\AuthorizationException + */ public function store(CustomFieldRequest $request) { $this->authorize('create', CustomField::class); @@ -83,22 +82,24 @@ class CustomFieldsController extends Controller "field_values" => $request->get("field_values"), "field_encrypted" => $request->get("field_encrypted", 0), "show_in_email" => $request->get("show_in_email", 0), - "user_id" => Auth::user()->id + "user_id" => Auth::id() ]); - if ($request->has("custom_format")) { + if ($request->filled("custom_format")) { $field->format = e($request->get("custom_format")); } else { $field->format = e($request->get("format")); } if ($field->save()) { + return redirect()->route("fields.index")->with("success", trans('admin/custom_fields/message.field.create.success')); - } else { - return redirect()->back()->withInput()->with('error', trans('admin/custom_fields/message.field.create.error')); } + return redirect()->back()->withInput() + ->with('error', trans('admin/custom_fields/message.field.create.error')); + } @@ -108,6 +109,7 @@ class CustomFieldsController extends Controller * @author [A. Gianotto] [] * @since [v3.0] * @return Redirect + * @throws \Illuminate\Auth\Access\AuthorizationException */ public function deleteFieldFromFieldset($field_id, $fieldset_id) { @@ -116,19 +118,21 @@ class CustomFieldsController extends Controller $this->authorize('update', $field); if ($field->fieldset()->detach($fieldset_id)) { - return redirect()->route('fieldsets.show', ['fieldset' => $fieldset_id])->with("success", trans('admin/custom_fields/message.field.delete.success')); + return redirect()->route('fieldsets.show', ['fieldset' => $fieldset_id]) + ->with("success", trans('admin/custom_fields/message.field.delete.success')); } return redirect()->back()->withErrors(['message' => "Field is in-use"]); } /** - * Delete a custom field. - * - * @author [Brady Wetherington] [] - * @since [v1.8] - * @return Redirect - */ + * Delete a custom field. + * + * @author [Brady Wetherington] [] + * @since [v1.8] + * @return Redirect + * @throws \Illuminate\Auth\Access\AuthorizationException + */ public function destroy($field_id) { $field = CustomField::find($field_id); @@ -137,56 +141,66 @@ class CustomFieldsController extends Controller if ($field->fieldset->count()>0) { return redirect()->back()->withErrors(['message' => "Field is in-use"]); - } else { - $field->delete(); - return redirect()->route("fields.index")->with("success", trans('admin/custom_fields/message.field.delete.success')); } + $field->delete(); + return redirect()->route("fields.index") + ->with("success", trans('admin/custom_fields/message.field.delete.success')); } - /** - * Return a view to edit a custom field - * - * @author [A. Gianotto] [] - * @param int $id - * @since [v4.0] - * @return View - */ + * Return a view to edit a custom field + * + * @author [A. Gianotto] [] + * @param int $id + * @since [v4.0] + * @return \Illuminate\Support\Facades\View + * @throws \Illuminate\Auth\Access\AuthorizationException + */ public function edit($id) { $field = CustomField::find($id); $this->authorize('update', $field); - return view("custom_fields.fields.edit")->with('field', $field); + $customFormat = ''; + if((stripos($field->format, 'regex') === 0) && ($field->format !== CustomField::PREDEFINED_FORMATS['MAC'])) { + $customFormat = $field->format; + } + + return view("custom_fields.fields.edit",[ + 'field' => $field, + 'customFormat' => $customFormat, + 'predefinedFormats' => Helper::predefined_formats() + ]); } /** - * Store the updated field - * - * @todo Allow encrypting/decrypting if encryption status changes - * - * @author [A. Gianotto] [] - * @param int $id - * @since [v4.0] - * @return Redirect - */ + * Store the updated field + * + * @todo Allow encrypting/decrypting if encryption status changes + * + * @author [A. Gianotto] [] + * @param int $id + * @since [v4.0] + * @return Redirect + * @throws \Illuminate\Auth\Access\AuthorizationException + */ public function update(CustomFieldRequest $request, $id) { $field = CustomField::find($id); - + $this->authorize('update', $field); - $field->name = e($request->get("name")); - $field->element = e($request->get("element")); - $field->field_values = e($request->get("field_values")); - $field->user_id = Auth::user()->id; - $field->help_text = $request->get("help_text"); + $field->name = e($request->get("name")); + $field->element = e($request->get("element")); + $field->field_values = e($request->get("field_values")); + $field->user_id = Auth::id(); + $field->help_text = $request->get("help_text"); $field->show_in_email = $request->get("show_in_email", 0); - if (!in_array(Input::get('format'), array_keys(CustomField::$PredefinedFormats))) { + if ($request->get('format') == 'CUSTOM REGEX') { $field->format = e($request->get("custom_format")); } else { $field->format = e($request->get("format")); diff --git a/app/Http/Controllers/CustomFieldsetsController.php b/app/Http/Controllers/CustomFieldsetsController.php index fa46263487..fae646e9d1 100644 --- a/app/Http/Controllers/CustomFieldsetsController.php +++ b/app/Http/Controllers/CustomFieldsetsController.php @@ -1,17 +1,14 @@ ] - * @param int $id - * @since [v1.8] - * @return View - */ + /** + * Validates and stores a new custom field. + * + * @author [Brady Wetherington] [] + * @param int $id + * @return \Illuminate\Support\Facades\View + * @throws \Illuminate\Auth\Access\AuthorizationException + * @since [v1.8] + */ public function show($id) { - $cfset = CustomFieldset::with('fields')->where('id', '=', $id)->orderBy('id', 'ASC')->first(); + $cfset = CustomFieldset::with('fields') + ->where('id', '=', $id)->orderBy('id', 'ASC')->first(); $this->authorize('view', $cfset); if ($cfset) { $custom_fields_list = ["" => "Add New Field to Fieldset"] + CustomField::pluck("name", "id")->toArray(); + $maxid = 0; foreach ($cfset->fields() as $field) { - if ($field->pivot->order > $maxid) { - $maxid=$field->pivot->order; - } - if (isset($custom_fields_list[$field->id])) { - unset($custom_fields_list[$field->id]); + + if ($field) { + if ($field->pivot->order > $maxid) { + $maxid=$field->pivot->order; + } + if (isset($custom_fields_list[$field->id])) { + unset($custom_fields_list[$field->id]); + } } + } - return view("custom_fields.fieldsets.view")->with("custom_fieldset", $cfset)->with("maxid", $maxid+1)->with("custom_fields_list", $custom_fields_list); + return view("custom_fields.fieldsets.view") + ->with("custom_fieldset", $cfset) + ->with("maxid", $maxid+1) + ->with("custom_fields_list", $custom_fields_list); } - return redirect()->route("fields.index")->with("error", trans('admin/custom_fields/message.fieldset.does_not_exist')); + return redirect()->route("fields.index") + ->with("error", trans('admin/custom_fields/message.fieldset.does_not_exist')); } /** - * Returns a view with a form for creating a new custom fieldset. - * - * @author [Brady Wetherington] [] - * @since [v1.8] - * @return View - */ + * Returns a view with a form for creating a new custom fieldset. + * + * @author [Brady Wetherington] [] + * @since [v1.8] + * @return \Illuminate\Support\Facades\View + * @throws \Illuminate\Auth\Access\AuthorizationException + */ public function create() { $this->authorize('create', CustomFieldset::class); @@ -77,29 +86,30 @@ class CustomFieldsetsController extends Controller /** - * Validates and stores a new custom fieldset. - * - * @author [Brady Wetherington] [] - * @since [v1.8] - * @return Redirect - */ + * Validates and stores a new custom fieldset. + * + * @author [Brady Wetherington] [] + * @since [v1.8] + * @param Request $request + * @return Redirect + * @throws \Illuminate\Auth\Access\AuthorizationException + */ public function store(Request $request) { $this->authorize('create', CustomFieldset::class); - $cfset = new CustomFieldset( - [ + $cfset = new CustomFieldset([ "name" => e($request->get("name")), - "user_id" => Auth::user()->id] - ); + "user_id" => Auth::user()->id + ]); $validator = Validator::make(Input::all(), $cfset->rules); if ($validator->passes()) { $cfset->save(); - return redirect()->route("fieldsets.show", [$cfset->id])->with('success', trans('admin/custom_fields/message.fieldset.create.success')); - } else { - return redirect()->back()->withInput()->withErrors($validator); + return redirect()->route("fieldsets.show", [$cfset->id]) + ->with('success', trans('admin/custom_fields/message.fieldset.create.success')); } + return redirect()->back()->withInput()->withErrors($validator); } @@ -136,13 +146,14 @@ class CustomFieldsetsController extends Controller /** - * Validates a custom fieldset and then deletes if it has no models associated. - * - * @author [Brady Wetherington] [] - * @param int $id - * @since [v1.8] - * @return View - */ + * Validates a custom fieldset and then deletes if it has no models associated. + * + * @author [Brady Wetherington] [] + * @param int $id + * @since [v1.8] + * @return View + * @throws \Illuminate\Auth\Access\AuthorizationException + */ public function destroy($id) { $fieldset = CustomFieldset::find($id); @@ -154,9 +165,8 @@ class CustomFieldsetsController extends Controller if ($models->count() == 0) { $fieldset->delete(); return redirect()->route("fields.index")->with("success", trans('admin/custom_fields/message.fieldset.delete.success')); - } else { - return redirect()->route("fields.index")->with("error", trans('admin/custom_fields/message.fieldset.delete.in_use')); } + return redirect()->route("fields.index")->with("error", trans('admin/custom_fields/message.fieldset.delete.in_use')); } return redirect()->route("fields.index")->with("error", trans('admin/custom_fields/message.fieldset.does_not_exist')); @@ -166,12 +176,13 @@ class CustomFieldsetsController extends Controller /** - * Associate the custom field with a custom fieldset. - * - * @author [Brady Wetherington] [] - * @since [v1.8] - * @return View - */ + * Associate the custom field with a custom fieldset. + * + * @author [Brady Wetherington] [] + * @since [v1.8] + * @return View + * @throws \Illuminate\Auth\Access\AuthorizationException + */ public function associate($id) { diff --git a/app/Http/Controllers/DepartmentsController.php b/app/Http/Controllers/DepartmentsController.php index 49375d8cdb..4afcd2a5a9 100644 --- a/app/Http/Controllers/DepartmentsController.php +++ b/app/Http/Controllers/DepartmentsController.php @@ -4,10 +4,10 @@ namespace App\Http\Controllers; use Illuminate\Http\Request; use App\Models\Department; -use App\Helpers\Helper; -use Auth; +use Illuminate\Support\Facades\Auth; use Image; use App\Http\Requests\ImageUploadRequest; +use Illuminate\Support\Facades\Storage; class DepartmentsController extends Controller { @@ -24,13 +24,15 @@ class DepartmentsController extends Controller * @author [A. Gianotto] [] * @see AssetController::getDatatable() method that generates the JSON response * @since [v4.0] - * @return View + * @param Request $request + * @return \Illuminate\Support\Facades\View + * @throws \Illuminate\Auth\Access\AuthorizationException */ public function index(Request $request) { $this->authorize('index', Department::class); $company = null; - if ($request->has('company_id')) { + if ($request->filled('company_id')) { $company = Company::find($request->input('company_id')); } return view('departments/index')->with('company', $company); @@ -42,27 +44,19 @@ class DepartmentsController extends Controller * * @author [A. Gianotto] [] * @since [v4.0] - * @param \Illuminate\Http\Request $request + * @param ImageUploadRequest $request * @return \Illuminate\Http\Response + * @throws \Illuminate\Auth\Access\AuthorizationException */ public function store(ImageUploadRequest $request) { $this->authorize('create', Department::class); $department = new Department; $department->fill($request->all()); - $department->user_id = Auth::user()->id; - $department->manager_id = ($request->has('manager_id' ) ? $request->input('manager_id') : null); + $department->user_id = Auth::id(); + $department->manager_id = $request->input('manager_id', null); - if ($request->file('image')) { - $image = $request->file('image'); - $file_name = str_random(25).".".$image->getClientOriginalExtension(); - $path = public_path('uploads/departments/'.$file_name); - Image::make($image->getRealPath())->resize(200, null, function ($constraint) { - $constraint->aspectRatio(); - $constraint->upsize(); - })->save($path); - $department->image = $file_name; - } + $department = $request->handleImages($department); if ($department->save()) { return redirect()->route("departments.index")->with('success', trans('admin/departments/message.create.success')); @@ -78,6 +72,7 @@ class DepartmentsController extends Controller * @param int $id * @since [v4.0] * @return \Illuminate\Contracts\View\View + * @throws \Illuminate\Auth\Access\AuthorizationException */ public function show($id) { @@ -88,7 +83,7 @@ class DepartmentsController extends Controller if (isset($department->id)) { return view('departments/view', compact('department')); } - return redirect()->route('departments.index')->with('error', trans('admin/departments/message.does_not_exist', compact('id'))); + return redirect()->route('departments.index')->with('error', trans('admin/departments/message.does_not_exist')); } @@ -99,6 +94,7 @@ class DepartmentsController extends Controller * @see DepartmentsController::postCreate() method that validates and stores the data * @since [v4.0] * @return \Illuminate\Contracts\View\View + * @throws \Illuminate\Auth\Access\AuthorizationException */ public function create() { @@ -115,6 +111,7 @@ class DepartmentsController extends Controller * @param int $locationId * @since [v4.0] * @return \Illuminate\Http\RedirectResponse + * @throws \Illuminate\Auth\Access\AuthorizationException */ public function destroy($id) { @@ -128,23 +125,32 @@ class DepartmentsController extends Controller return redirect()->to(route('departments.index'))->with('error', trans('admin/departments/message.assoc_users')); } + if ($department->image) { + try { + Storage::disk('public')->delete('departments'.'/'.$department->image); + } catch (\Exception $e) { + \Log::debug($e); + } + } $department->delete(); + return redirect()->back()->with('success', trans('admin/departments/message.delete.success')); } /** - * Makes a form view to edit location information. + * Makes a form view to edit Department information. * * @author [A. Gianotto] [] * @see LocationsController::postCreate() method that validates and stores - * @param int $locationId + * @param int $departmentId * @since [v1.0] * @return \Illuminate\Contracts\View\View + * @throws \Illuminate\Auth\Access\AuthorizationException */ - public function edit($id = null) + public function edit($departmentId = null) { - if (is_null($item = Department::find($id))) { + if (is_null($item = Department::find($departmentId))) { return redirect()->back()->with('error', trans('admin/locations/message.does_not_exist')); } @@ -162,38 +168,9 @@ class DepartmentsController extends Controller $this->authorize('update', $department); $department->fill($request->all()); - $department->manager_id = ($request->has('manager_id' ) ? $request->input('manager_id') : null); + $department->manager_id = ($request->filled('manager_id' ) ? $request->input('manager_id') : null); - $old_image = $department->image; - - // Set the model's image property to null if the image is being deleted - if ($request->input('image_delete') == 1) { - $department->image = null; - } - - if ($request->file('image')) { - $image = $request->file('image'); - $file_name = $department->id.'-'.str_slug($image->getClientOriginalName()) . "." . $image->getClientOriginalExtension(); - - if ($image->getClientOriginalExtension()!='svg') { - Image::make($image->getRealPath())->resize(500, null, function ($constraint) { - $constraint->aspectRatio(); - $constraint->upsize(); - })->save(app('departments_upload_path').$file_name); - } else { - $image->move(app('departments_upload_path'), $file_name); - } - $department->image = $file_name; - - } - - if ((($request->file('image')) && (isset($old_image)) && ($old_image!='')) || ($request->input('image_delete') == 1)) { - try { - unlink(app('departments_upload_path').$old_image); - } catch (\Exception $e) { - \Log::error($e); - } - } + $department = $request->handleImages($department); if ($department->save()) { return redirect()->route("departments.index")->with('success', trans('admin/departments/message.update.success')); diff --git a/app/Http/Controllers/DepreciationsController.php b/app/Http/Controllers/DepreciationsController.php index d9f84415ee..c2b205ecb2 100755 --- a/app/Http/Controllers/DepreciationsController.php +++ b/app/Http/Controllers/DepreciationsController.php @@ -1,15 +1,8 @@ find($depreciationId))) { return redirect()->route('depreciations.index')->with('error', trans('admin/depreciations/message.not_found')); } $this->authorize('delete', $depreciation); - if ($depreciation->has_models() > 0) { + if ($depreciation->models_count > 0) { // Redirect to the asset management page return redirect()->route('depreciations.index')->with('error', trans('admin/depreciations/message.assoc_users')); } @@ -175,6 +174,7 @@ class DepreciationsController extends Controller * @param int $depreciationId * @since [v1.0] * @return \Illuminate\Contracts\View\View + * @throws \Illuminate\Auth\Access\AuthorizationException */ public function show($id) { diff --git a/app/Http/Controllers/GroupsController.php b/app/Http/Controllers/GroupsController.php index e03847cd2e..abeb8c2a8e 100755 --- a/app/Http/Controllers/GroupsController.php +++ b/app/Http/Controllers/GroupsController.php @@ -1,13 +1,7 @@ route('groups.index')->with('error', trans('admin/groups/message.group_not_found', compact('id'))); } @@ -126,13 +119,14 @@ class GroupsController extends Controller } /** - * Validates and deletes the User Group. - * - * @author [A. Gianotto] [] - * @param int $locationId - * @since [v4.0.11] + * @param $id * @return \Illuminate\Contracts\View\View + * @since [v4.0.11] */ public function show($id) { diff --git a/app/Http/Controllers/ImportsController.php b/app/Http/Controllers/ImportsController.php index 1331b7dd86..30f397ca08 100644 --- a/app/Http/Controllers/ImportsController.php +++ b/app/Http/Controllers/ImportsController.php @@ -4,17 +4,19 @@ namespace App\Http\Controllers; use App\Http\Transformers\ImportsTransformer; use App\Models\Import; -use Illuminate\Http\Request; use App\Models\Asset; class ImportsController extends Controller { + /** + * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View + * @throws \Illuminate\Auth\Access\AuthorizationException + */ public function index() { $this->authorize('create', Asset::class); - $imports = Import::latest()->get(); - $imports = (new ImportsTransformer)->transformImports($imports); + $imports = (new ImportsTransformer)->transformImports(Import::latest()->get()); return view('importer/import')->with('imports', $imports); } } diff --git a/app/Http/Controllers/Licenses/LicenseCheckinController.php b/app/Http/Controllers/Licenses/LicenseCheckinController.php new file mode 100644 index 0000000000..14df85a080 --- /dev/null +++ b/app/Http/Controllers/Licenses/LicenseCheckinController.php @@ -0,0 +1,106 @@ +] + * @since [v1.0] + * @param int $seatId + * @param string $backTo + * @return \Illuminate\Contracts\View\View + * @throws \Illuminate\Auth\Access\AuthorizationException + */ + public function create($seatId = null, $backTo = null) + { + // Check if the asset exists + if (is_null($licenseSeat = LicenseSeat::find($seatId)) || is_null($license = License::find($licenseSeat->license_id))) { + // Redirect to the asset management page with error + return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.not_found')); + } + + $this->authorize('checkout', $license); + return view('licenses/checkin', compact('licenseSeat'))->with('backto', $backTo); + } + + + /** + * Validates and stores the license checkin action. + * + * @author [A. Gianotto] [] + * @see LicenseCheckinController::create() method that provides the form view + * @since [v1.0] + * @param int $seatId + * @param string $backTo + * @return \Illuminate\Http\RedirectResponse + * @throws \Illuminate\Auth\Access\AuthorizationException + */ + public function store(Request $request, $seatId = null, $backTo = null) + { + // Check if the asset exists + if (is_null($licenseSeat = LicenseSeat::find($seatId))) { + // Redirect to the asset management page with error + return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.not_found')); + } + + $license = License::find($licenseSeat->license_id); + $this->authorize('checkout', $license); + + if (!$license->reassignable) { + // Not allowed to checkin + Session::flash('error', 'License not reassignable.'); + return redirect()->back()->withInput(); + } + + // Declare the rules for the form validation + $rules = [ + 'note' => 'string', + 'notes' => 'string', + ]; + + // Create a new validator instance from our validation rules + $validator = Validator::make(Input::all(), $rules); + + // If validation fails, we'll exit the operation now. + if ($validator->fails()) { + // Ooops.. something went wrong + return redirect()->back()->withInput()->withErrors($validator); + } + $return_to = User::find($licenseSeat->assigned_to); + + // Update the asset data + $licenseSeat->assigned_to = null; + $licenseSeat->asset_id = null; + + // Was the asset updated? + if ($licenseSeat->save()) { + + event(new CheckoutableCheckedIn($licenseSeat, $return_to, Auth::user(), $request->input('note'))); + + if ($backTo=='user') { + return redirect()->route("users.show", $return_to->id)->with('success', trans('admin/licenses/message.checkin.success')); + } + return redirect()->route("licenses.show", $licenseSeat->license_id)->with('success', trans('admin/licenses/message.checkin.success')); + } + + // Redirect to the license page with error + return redirect()->route("licenses.index")->with('error', trans('admin/licenses/message.checkin.error')); + } + +} diff --git a/app/Http/Controllers/Licenses/LicenseCheckoutController.php b/app/Http/Controllers/Licenses/LicenseCheckoutController.php new file mode 100644 index 0000000000..5d878a1506 --- /dev/null +++ b/app/Http/Controllers/Licenses/LicenseCheckoutController.php @@ -0,0 +1,131 @@ +] + * @since [v1.0] + * @param $licenseId + * @return \Illuminate\Contracts\View\View + * @throws \Illuminate\Auth\Access\AuthorizationException + */ + public function create($licenseId) + { + // Check that the license is valid + if ($license = License::find($licenseId)) { + + // If the license is valid, check that there is an available seat + if ($license->avail_seats_count < 1) { + return redirect()->route('licenses.index')->with('error', 'There are no available seats for this license'); + } + } + + $this->authorize('checkout', $license); + return view('licenses/checkout', compact('license')); + } + + + /** + * Validates and stores the license checkout action. + * + * @author [A. Gianotto] [] + * @since [v1.0] + * @param LicenseCheckoutRequest $request + * @param $licenseId + * @return \Illuminate\Http\RedirectResponse + * @throws \Illuminate\Auth\Access\AuthorizationException + */ + + public function store(LicenseCheckoutRequest $request, $licenseId, $seatId = null) + { + if (!$license = License::find($licenseId)) { + return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.not_found')); + } + + $this->authorize('checkout', $license); + + $licenseSeat = $this->findLicenseSeatToCheckout($license, $seatId); + $licenseSeat->user_id = Auth::id(); + + $checkoutMethod = 'checkoutTo'.ucwords(request('checkout_to_type')); + if ($this->$checkoutMethod($licenseSeat)) { + return redirect()->route("licenses.index")->with('success', trans('admin/licenses/message.checkout.success')); + } + + return redirect()->route("licenses.index")->with('error', trans('Something went wrong handling this checkout.')); + } + + protected function findLicenseSeatToCheckout($license, $seatId) + { + $licenseSeat = LicenseSeat::find($seatId) ?? $license->freeSeat(); + + if (!$licenseSeat) { + if ($seatId) { + return redirect()->route('licenses.index')->with('error', 'This Seat is not available for checkout.'); + } + return redirect()->route('licenses.index')->with('error', 'There are no available seats for this license'); + } + + if(!$licenseSeat->license->is($license)) { + return redirect()->route('licenses.index')->with('error', 'The license seat provided does not match the license.'); + } + + return $licenseSeat; + } + + protected function checkoutToAsset($licenseSeat) + { + if (is_null($target = Asset::find(request('asset_id')))) { + return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.asset_does_not_exist')); + } + $licenseSeat->asset_id = request('asset_id'); + + // Override asset's assigned user if available + if ($target->checkedOutToUser()) { + $licenseSeat->assigned_to = $target->assigned_to; + } + if ($licenseSeat->save()) { + + event(new CheckoutableCheckedOut($licenseSeat, $target, Auth::user(), request('note'))); + + return true; + } + return false; + } + + protected function checkoutToUser($licenseSeat) + { + // Fetch the target and set the license user + if (is_null($target = User::find(request('assigned_to')))) { + return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.user_does_not_exist')); + } + $licenseSeat->assigned_to = request('assigned_to'); + + if ($licenseSeat->save()) { + + event(new CheckoutableCheckedOut($licenseSeat, $target, Auth::user(), request('note'))); + + return true; + } + return false; + } +} diff --git a/app/Http/Controllers/Licenses/LicenseFilesController.php b/app/Http/Controllers/Licenses/LicenseFilesController.php new file mode 100644 index 0000000000..4ff388335b --- /dev/null +++ b/app/Http/Controllers/Licenses/LicenseFilesController.php @@ -0,0 +1,154 @@ +] + * @since [v1.0] + * @param AssetFileRequest $request + * @param int $licenseId + * @return \Illuminate\Http\RedirectResponse + * @throws \Illuminate\Auth\Access\AuthorizationException + */ + public function store(AssetFileRequest $request, $licenseId = null) + { + $license = License::find($licenseId); + // the license is valid + $destinationPath = config('app.private_uploads').'/licenses'; + + if (isset($license->id)) { + $this->authorize('update', $license); + + if (Input::hasFile('file')) { + + if (!Storage::exists('private_uploads/licenses')) Storage::makeDirectory('private_uploads/licenses', 775); + + $upload_success = false; + foreach (Input::file('file') as $file) { + $extension = $file->getClientOriginalExtension(); + $file_name = 'license-'.$license->id.'-'.str_random(8).'-'.str_slug(basename($file->getClientOriginalName(), '.'.$extension)).'.'.$extension; + + $upload_success = Storage::put('private_uploads/licenses/'.$file_name, $file); + + //Log the upload to the log + $license->logUpload($file_name, e($request->input('notes'))); + } + + // This being called from a modal seems to confuse redirect()->back() + // It thinks we should go to the dashboard. As this is only used + // from the modal at present, hardcode the redirect. Longterm + // maybe we evaluate something else. + if ($upload_success) { + return redirect()->route('licenses.show', $license->id)->with('success', trans('admin/licenses/message.upload.success')); + } + return redirect()->route('licenses.show', $license->id)->with('error', trans('admin/licenses/message.upload.error')); + } + return redirect()->route('licenses.show', $license->id)->with('error', trans('admin/licenses/message.upload.nofiles')); + } + // Prepare the error message + return redirect()->route('licenses.index') + ->with('error', trans('admin/licenses/message.does_not_exist')); + } + + + /** + * Deletes the selected license file. + * + * @author [A. Gianotto] [] + * @since [v1.0] + * @param int $licenseId + * @param int $fileId + * @return \Illuminate\Http\RedirectResponse + * @throws \Illuminate\Auth\Access\AuthorizationException + */ + public function destroy($licenseId = null, $fileId = null) + { + $license = License::find($licenseId); + + // the asset is valid + if (isset($license->id)) { + $this->authorize('update', $license); + $log = Actionlog::find($fileId); + + // Remove the file if one exists + if (Storage::exists('licenses/'.$log->filename)) { + try { + Storage::delete('licenses/'.$log->filename); + } catch (\Exception $e) { + \Log::debug($e); + } + } + + $log->delete(); + return redirect()->back() + ->with('success', trans('admin/hardware/message.deletefile.success')); + } + + // Redirect to the licence management page + return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.does_not_exist')); + } + + + + /** + * Allows the selected file to be viewed. + * + * @author [A. Gianotto] [] + * @since [v1.4] + * @param int $licenseId + * @param int $fileId + * @return \Symfony\Component\HttpFoundation\Response + * @throws \Illuminate\Auth\Access\AuthorizationException + */ + public function show($licenseId = null, $fileId = null, $download = true) + { + + $license = License::find($licenseId); + + // the license is valid + if (isset($license->id)) { + $this->authorize('view', $license); + + if (!$log = Actionlog::find($fileId)) { + return response('No matching record for that asset/file', 500) + ->header('Content-Type', 'text/plain'); + } + + $file = 'private_uploads/licenses/'.$log->filename; + \Log::debug('Checking for '.$file); + + if (!Storage::exists($file)) { + return response('File '.$file.' not found on server', 404) + ->header('Content-Type', 'text/plain'); + } + + if ($download != 'true') { + if ($contents = file_get_contents(Storage::url($file))) { + return Response::make(Storage::url($file)->header('Content-Type', mime_content_type($file))); + } + return JsonResponse::create(["error" => "Failed validation: "], 500); + } + return Storage::download($file); + } + return redirect()->route('hardware.index')->with('error', trans('admin/licenses/message.does_not_exist', ['id' => $fileId])); + + } + + + +} diff --git a/app/Http/Controllers/Licenses/LicensesController.php b/app/Http/Controllers/Licenses/LicensesController.php new file mode 100755 index 0000000000..1e6f926c1b --- /dev/null +++ b/app/Http/Controllers/Licenses/LicensesController.php @@ -0,0 +1,273 @@ +] + * @see LicensesController::getDatatable() method that generates the JSON response + * @since [v1.0] + * @return \Illuminate\Contracts\View\View + * @throws \Illuminate\Auth\Access\AuthorizationException + */ + public function index() + { + $this->authorize('view', License::class); + return view('licenses/index'); + } + + + /** + * Returns a form view that allows an admin to create a new licence. + * + * @author [A. Gianotto] [] + * @see AccessoriesController::getDatatable() method that generates the JSON response + * @since [v1.0] + * @return \Illuminate\Contracts\View\View + * @throws \Illuminate\Auth\Access\AuthorizationException + */ + public function create() + { + $this->authorize('create', License::class); + $maintained_list = [ + '' => 'Maintained', + '1' => 'Yes', + '0' => 'No' + ]; + + return view('licenses/edit') + ->with('depreciation_list', Helper::depreciationList()) + ->with('maintained_list', $maintained_list) + ->with('item', new License); + + } + + + /** + * Validates and stores the license form data submitted from the new + * license form. + * + * @author [A. Gianotto] [] + * @see LicensesController::getCreate() method that provides the form view + * @since [v1.0] + * @param Request $request + * @return \Illuminate\Http\RedirectResponse + * @throws \Illuminate\Auth\Access\AuthorizationException + */ + public function store(Request $request) + { + $this->authorize('create', License::class); + // create a new model instance + $license = new License(); + // Save the license data + $license->company_id = Company::getIdForCurrentUser($request->input('company_id')); + $license->depreciation_id = $request->input('depreciation_id'); + $license->expiration_date = $request->input('expiration_date'); + $license->license_email = $request->input('license_email'); + $license->license_name = $request->input('license_name'); + $license->maintained = $request->input('maintained', 0); + $license->manufacturer_id = $request->input('manufacturer_id'); + $license->name = $request->input('name'); + $license->notes = $request->input('notes'); + $license->order_number = $request->input('order_number'); + $license->purchase_cost = $request->input('purchase_cost'); + $license->purchase_date = $request->input('purchase_date'); + $license->purchase_order = $request->input('purchase_order'); + $license->purchase_order = $request->input('purchase_order'); + $license->reassignable = $request->input('reassignable', 0); + $license->seats = $request->input('seats'); + $license->serial = $request->input('serial'); + $license->supplier_id = $request->input('supplier_id'); + $license->category_id = $request->input('category_id'); + $license->termination_date = $request->input('termination_date'); + $license->user_id = Auth::id(); + + if ($license->save()) { + return redirect()->route("licenses.index")->with('success', trans('admin/licenses/message.create.success')); + } + return redirect()->back()->withInput()->withErrors($license->getErrors()); + } + + /** + * Returns a form with existing license data to allow an admin to + * update license information. + * + * @author [A. Gianotto] [] + * @since [v1.0] + * @param int $licenseId + * @return \Illuminate\Contracts\View\View + * @throws \Illuminate\Auth\Access\AuthorizationException + */ + public function edit($licenseId = null) + { + if (is_null($item = License::find($licenseId))) { + return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.does_not_exist')); + } + + $this->authorize('update', $item); + + $maintained_list = [ + '' => 'Maintained', + '1' => 'Yes', + '0' => 'No' + ]; + + return view('licenses/edit', compact('item')) + ->with('depreciation_list', Helper::depreciationList()) + ->with('maintained_list', $maintained_list); + } + + + /** + * Validates and stores the license form data submitted from the edit + * license form. + * + * @author [A. Gianotto] [] + * @see LicensesController::getEdit() method that provides the form view + * @since [v1.0] + * @param Request $request + * @param int $licenseId + * @return \Illuminate\Http\RedirectResponse + * @throws \Illuminate\Auth\Access\AuthorizationException + */ + public function update(Request $request, $licenseId = null) + { + if (is_null($license = License::find($licenseId))) { + return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.does_not_exist')); + } + + $this->authorize('update', $license); + + $license->company_id = Company::getIdForCurrentUser($request->input('company_id')); + $license->depreciation_id = $request->input('depreciation_id'); + $license->expiration_date = $request->input('expiration_date'); + $license->license_email = $request->input('license_email'); + $license->license_name = $request->input('license_name'); + $license->maintained = $request->input('maintained',0); + $license->name = $request->input('name'); + $license->notes = $request->input('notes'); + $license->order_number = $request->input('order_number'); + $license->purchase_cost = $request->input('purchase_cost'); + $license->purchase_date = $request->input('purchase_date'); + $license->purchase_order = $request->input('purchase_order'); + $license->reassignable = $request->input('reassignable', 0); + $license->serial = $request->input('serial'); + $license->termination_date = $request->input('termination_date'); + $license->seats = e($request->input('seats')); + $license->manufacturer_id = $request->input('manufacturer_id'); + $license->supplier_id = $request->input('supplier_id'); + $license->category_id = $request->input('category_id'); + + if ($license->save()) { + return redirect()->route('licenses.show', ['license' => $licenseId])->with('success', trans('admin/licenses/message.update.success')); + } + // If we can't adjust the number of seats, the error is flashed to the session by the event handler in License.php + return redirect()->back()->withInput()->withErrors($license->getErrors()); + } + + /** + * Checks to see whether the selected license can be deleted, and + * if it can, marks it as deleted. + * + * @author [A. Gianotto] [] + * @since [v1.0] + * @param int $licenseId + * @return \Illuminate\Http\RedirectResponse + * @throws \Illuminate\Auth\Access\AuthorizationException + */ + public function destroy($licenseId) + { + // Check if the license exists + if (is_null($license = License::find($licenseId))) { + // Redirect to the license management page + return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.not_found')); + } + + $this->authorize('delete', $license); + + if ($license->assigned_seats_count == 0) { + // Delete the license and the associated license seats + DB::table('license_seats') + ->where('id', $license->id) + ->update(array('assigned_to' => null,'asset_id' => null)); + + $licenseSeats = $license->licenseseats(); + $licenseSeats->delete(); + $license->delete(); + + // Redirect to the licenses management page + return redirect()->route('licenses.index')->with('success', trans('admin/licenses/message.delete.success')); + // Redirect to the license management page + } + // There are still licenses in use. + return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.assoc_users')); + + } + + + /** + * Makes the license detail page. + * + * @author [A. Gianotto] [] + * @since [v1.0] + * @param int $licenseId + * @return \Illuminate\Contracts\View\View + * @throws \Illuminate\Auth\Access\AuthorizationException + */ + public function show($licenseId = null) + { + + $license = License::with('assignedusers', 'licenseSeats.user', 'licenseSeats.asset')->find($licenseId); + + if ($license) { + $this->authorize('view', $license); + return view('licenses/view', compact('license')); + } + return redirect()->route('licenses.index') + ->with('error', trans('admin/licenses/message.does_not_exist')); + } + + + public function getClone($licenseId = null) + { + if (is_null($license_to_clone = License::find($licenseId))) { + return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.does_not_exist')); + } + + $this->authorize('create', License::class); + + $maintained_list = [ + '' => 'Maintained', + '1' => 'Yes', + '0' => 'No' + ]; + //clone the orig + $license = clone $license_to_clone; + $license->id = null; + $license->serial = null; + + // Show the page + return view('licenses/edit') + ->with('depreciation_list', Helper::depreciationList()) + ->with('item', $license) + ->with('maintained_list', $maintained_list); + } +} diff --git a/app/Http/Controllers/LicensesController.php b/app/Http/Controllers/LicensesController.php deleted file mode 100755 index 98a946197c..0000000000 --- a/app/Http/Controllers/LicensesController.php +++ /dev/null @@ -1,649 +0,0 @@ -] - * @see LicensesController::getDatatable() method that generates the JSON response - * @since [v1.0] - * @return \Illuminate\Contracts\View\View - */ - public function index() - { - $this->authorize('view', License::class); - return view('licenses/index'); - } - - - /** - * Returns a form view that allows an admin to create a new licence. - * - * @author [A. Gianotto] [] - * @see AccessoriesController::getDatatable() method that generates the JSON response - * @since [v1.0] - * @return \Illuminate\Contracts\View\View - */ - public function create() - { - $this->authorize('create', License::class); - $maintained_list = [ - '' => 'Maintained', - '1' => 'Yes', - '0' => 'No' - ]; - - return view('licenses/edit') - //->with('license_options',$license_options) - ->with('depreciation_list', Helper::depreciationList()) - ->with('maintained_list', $maintained_list) - ->with('item', new License); - - } - - - /** - * Validates and stores the license form data submitted from the new - * license form. - * - * @author [A. Gianotto] [] - * @see LicensesController::getCreate() method that provides the form view - * @since [v1.0] - * @param Request $request - * @return \Illuminate\Http\RedirectResponse - */ - public function store(Request $request) - { - $this->authorize('create', License::class); - // create a new model instance - $license = new License(); - // Save the license data - $license->company_id = Company::getIdForCurrentUser($request->input('company_id')); - $license->depreciation_id = $request->input('depreciation_id'); - $license->expiration_date = $request->input('expiration_date'); - $license->license_email = $request->input('license_email'); - $license->license_name = $request->input('license_name'); - $license->maintained = $request->input('maintained', 0); - $license->manufacturer_id = $request->input('manufacturer_id'); - $license->name = $request->input('name'); - $license->notes = $request->input('notes'); - $license->order_number = $request->input('order_number'); - $license->purchase_cost = $request->input('purchase_cost'); - $license->purchase_date = $request->input('purchase_date'); - $license->purchase_order = $request->input('purchase_order'); - $license->purchase_order = $request->input('purchase_order'); - $license->reassignable = $request->input('reassignable', 0); - $license->seats = $request->input('seats'); - $license->serial = $request->input('serial'); - $license->supplier_id = $request->input('supplier_id'); - $license->category_id = $request->input('category_id'); - $license->termination_date = $request->input('termination_date'); - $license->user_id = Auth::id(); - - if ($license->save()) { - return redirect()->route("licenses.index")->with('success', trans('admin/licenses/message.create.success')); - } - return redirect()->back()->withInput()->withErrors($license->getErrors()); - } - - /** - * Returns a form with existing license data to allow an admin to - * update license information. - * - * @author [A. Gianotto] [] - * @since [v1.0] - * @param int $licenseId - * @return \Illuminate\Contracts\View\View - */ - public function edit($licenseId = null) - { - if (is_null($item = License::find($licenseId))) { - return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.does_not_exist')); - } - - $this->authorize('update', $item); - - $maintained_list = [ - '' => 'Maintained', - '1' => 'Yes', - '0' => 'No' - ]; - - return view('licenses/edit', compact('item')) - ->with('depreciation_list', Helper::depreciationList()) - ->with('maintained_list', $maintained_list); - } - - - /** - * Validates and stores the license form data submitted from the edit - * license form. - * - * @author [A. Gianotto] [] - * @see LicensesController::getEdit() method that provides the form view - * @since [v1.0] - * @param Request $request - * @param int $licenseId - * @return \Illuminate\Http\RedirectResponse - */ - public function update(Request $request, $licenseId = null) - { - if (is_null($license = License::find($licenseId))) { - return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.does_not_exist')); - } - - $this->authorize('update', $license); - - $license->company_id = Company::getIdForCurrentUser($request->input('company_id')); - $license->depreciation_id = $request->input('depreciation_id'); - $license->expiration_date = $request->input('expiration_date'); - $license->license_email = $request->input('license_email'); - $license->license_name = $request->input('license_name'); - $license->maintained = $request->input('maintained',0); - $license->name = $request->input('name'); - $license->notes = $request->input('notes'); - $license->order_number = $request->input('order_number'); - $license->purchase_cost = $request->input('purchase_cost'); - $license->purchase_date = $request->input('purchase_date'); - $license->purchase_order = $request->input('purchase_order'); - $license->reassignable = $request->input('reassignable', 0); - $license->serial = $request->input('serial'); - $license->termination_date = $request->input('termination_date'); - $license->seats = e($request->input('seats')); - $license->manufacturer_id = $request->input('manufacturer_id'); - $license->supplier_id = $request->input('supplier_id'); - $license->category_id = $request->input('category_id'); - - if ($license->save()) { - return redirect()->route('licenses.show', ['license' => $licenseId])->with('success', trans('admin/licenses/message.update.success')); - } - // If we can't adjust the number of seats, the error is flashed to the session by the event handler in License.php - return redirect()->back()->withInput()->withErrors($license->getErrors()); - } - - /** - * Checks to see whether the selected license can be deleted, and - * if it can, marks it as deleted. - * - * @author [A. Gianotto] [] - * @since [v1.0] - * @param int $licenseId - * @return \Illuminate\Http\RedirectResponse - */ - public function destroy($licenseId) - { - // Check if the license exists - if (is_null($license = License::find($licenseId))) { - // Redirect to the license management page - return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.not_found')); - } - - $this->authorize('delete', $license); - - if ($license->assigned_seats_count == 0) { - // Delete the license and the associated license seats - DB::table('license_seats') - ->where('id', $license->id) - ->update(array('assigned_to' => null,'asset_id' => null)); - - $licenseSeats = $license->licenseseats(); - $licenseSeats->delete(); - $license->delete(); - - // Redirect to the licenses management page - return redirect()->route('licenses.index')->with('success', trans('admin/licenses/message.delete.success')); - // Redirect to the license management page - } - // There are still licenses in use. - return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.assoc_users')); - - } - - /** - * Provides the form view for checking out a license to a user. - * Here we pass the license seat ID instead of the license ID, - * because licenses themselves are never checked out to anyone, - * only the seats associated with them. - * - * @author [A. Gianotto] [] - * @since [v1.0] - * @param int $seatId - * @return \Illuminate\Contracts\View\View - */ - public function getCheckout($licenceId) - { - // Check that the license is valid - if ($license = License::where('id',$licenceId)->first()) { - - // If the license is valid, check that there is an available seat - if ($license->getAvailSeatsCountAttribute() < 1) { - return redirect()->route('licenses.index')->with('error', 'There are no available seats for this license'); - } - } - - $this->authorize('checkout', $license); - return view('licenses/checkout', compact('license')); - } - - - /** - * Validates and stores the license checkout action. - * - * @todo Switch to using a FormRequest for validation here. - * @author [A. Gianotto] [] - * @since [v1.0] - * @param Request $request - * @param int $licenseId - * @param int $seatId - * @return \Illuminate\Http\RedirectResponse - */ - public function postCheckout(Request $request, $licenseId, $seatId = null) - { - - // Check that the license is valid - if ($license = License::where('id', $licenseId)->first()) { - - // If the license is valid, check that there is an available seat - if ($license->getAvailSeatsCountAttribute() < 1) { - return redirect()->route('licenses.index')->with('error', 'There are no available seats for this license'); - } - if (!$seatId) { - // Get the next available seat for this license - $next = $license->freeSeat(); - if (!$next) { - return redirect()->route('licenses.index')->with('error', 'There are no available seats for this license'); - } - if (!$licenseSeat = LicenseSeat::where('id', '=', $next->id)->first()) { - return redirect()->route('licenses.index')->with('error', 'There are no available seats for this license'); - } - } else { - $licenseSeat = LicenseSeat::where('id', '=', $seatId)->first(); - if (!$licenseSeat) { - return redirect()->route('licenses.index')->with('error', 'License seat is not available for checkout'); - } - } - - - - - - - $this->authorize('checkout', $license); - - // Declare the rules for the form validation - $rules = [ - 'note' => 'string|nullable', - 'asset_id' => 'required_without:assigned_to', - ]; - - // Create a new validator instance from our validation rules - $validator = Validator::make(Input::all(), $rules); - - // If validation fails, we'll exit the operation now. - if ($validator->fails()) { - // Ooops.. something went wrong - return redirect()->back()->withInput()->withErrors($validator); - } - $target = null; - - - // This item is checked out to a an asset - if (request('checkout_to_type')=='asset') { - if (is_null($target = Asset::find(request('asset_id')))) { - return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.asset_does_not_exist')); - } - $licenseSeat->asset_id = $request->input('asset_id'); - - // Override asset's assigned user if available - if ($target->checkedOutToUser()) { - $licenseSeat->assigned_to = $target->assigned_to; - } - - } else { - - // Fetch the target and set the license user - if (is_null($target = User::find(request('assigned_to')))) { - return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.user_does_not_exist')); - } - $licenseSeat->assigned_to = request('assigned_to'); - } - - $licenseSeat->user_id = Auth::user()->id; - - - if ($licenseSeat->save()) { - $licenseSeat->logCheckout($request->input('note'), $target); - return redirect()->route("licenses.index")->with('success', trans('admin/licenses/message.checkout.success')); - } - - } - return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.not_found')); - - - - - return redirect()->route("licenses.index")->with('error', trans('admin/licenses/message.checkout.error')); - } - - - /** - * Makes the form view to check a license seat back into inventory. - * - * @author [A. Gianotto] [] - * @since [v1.0] - * @param int $seatId - * @param string $backTo - * @return \Illuminate\Contracts\View\View - */ - public function getCheckin($seatId = null, $backTo = null) - { - // Check if the asset exists - if (is_null($licenseSeat = LicenseSeat::find($seatId))) { - // Redirect to the asset management page with error - return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.not_found')); - } - - if (is_null($license = License::find($licenseSeat->license_id))) { - // Redirect to the asset management page with error - return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.not_found')); - } - - - $this->authorize('checkout', $license); - return view('licenses/checkin', compact('licenseSeat'))->with('backto', $backTo); - } - - - /** - * Validates and stores the license checkin action. - * - * @author [A. Gianotto] [] - * @see LicensesController::getCheckin() method that provides the form view - * @since [v1.0] - * @param int $seatId - * @param string $backTo - * @return \Illuminate\Http\RedirectResponse - */ - public function postCheckin($seatId = null, $backTo = null) - { - // Check if the asset exists - if (is_null($licenseSeat = LicenseSeat::find($seatId))) { - // Redirect to the asset management page with error - return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.not_found')); - } - - $license = License::find($licenseSeat->license_id); - $this->authorize('checkout', $license); - - if (!$license->reassignable) { - // Not allowed to checkin - Session::flash('error', 'License not reassignable.'); - return redirect()->back()->withInput(); - } - - // Declare the rules for the form validation - $rules = array( - 'note' => 'string', - 'notes' => 'string', - ); - - // Create a new validator instance from our validation rules - $validator = Validator::make(Input::all(), $rules); - - // If validation fails, we'll exit the operation now. - if ($validator->fails()) { - // Ooops.. something went wrong - return redirect()->back()->withInput()->withErrors($validator); - } - $return_to = User::find($licenseSeat->assigned_to); - if (!$return_to) { - $return_to = Asset::find($licenseSeat->asset_id); - } - - // Update the asset data - $licenseSeat->assigned_to = null; - $licenseSeat->asset_id = null; - - // Was the asset updated? - if ($licenseSeat->save()) { - $licenseSeat->logCheckin($return_to, e(request('note'))); - if ($backTo=='user') { - return redirect()->route("users.show", $return_to->id)->with('success', trans('admin/licenses/message.checkin.success')); - } - return redirect()->route("licenses.show", $licenseSeat->license_id)->with('success', trans('admin/licenses/message.checkin.success')); - } - - // Redirect to the license page with error - return redirect()->route("licenses.index")->with('error', trans('admin/licenses/message.checkin.error')); - } - - /** - * Makes the license detail page. - * - * @author [A. Gianotto] [] - * @since [v1.0] - * @param int $licenseId - * @return \Illuminate\Contracts\View\View - */ - public function show($licenseId = null) - { - - $license = License::with('assignedusers', 'licenseSeats.user', 'licenseSeats.asset')->find($licenseId); - - if ($license) { - $this->authorize('view', $license); - return view('licenses/view', compact('license')); - } - return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.does_not_exist', compact('id'))); - } - - - public function getClone($licenseId = null) - { - if (is_null($license_to_clone = License::find($licenseId))) { - return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.does_not_exist')); - } - - $this->authorize('create', License::class); - - $maintained_list = [ - '' => 'Maintained', - '1' => 'Yes', - '0' => 'No' - ]; - //clone the orig - $license = clone $license_to_clone; - $license->id = null; - $license->serial = null; - - // Show the page - return view('licenses/edit') - ->with('depreciation_list', Helper::depreciationList()) - ->with('item', $license) - ->with('maintained_list', $maintained_list); - } - - - /** - * Validates and stores files associated with a license. - * - * @todo Switch to using the AssetFileRequest form request validator. - * @author [A. Gianotto] [] - * @since [v1.0] - * @param int $licenseId - * @return \Illuminate\Http\RedirectResponse - */ - public function postUpload(AssetFileRequest $request, $licenseId = null) - { - $license = License::find($licenseId); - // the license is valid - $destinationPath = config('app.private_uploads').'/licenses'; - - if (isset($license->id)) { - $this->authorize('update', $license); - - if (Input::hasFile('file')) { - - foreach (Input::file('file') as $file) { - $extension = $file->getClientOriginalExtension(); - $filename = 'license-'.$license->id.'-'.str_random(8).'-'.str_slug(basename($file->getClientOriginalName(), '.'.$extension)).'.'.$extension; - $upload_success = $file->move($destinationPath, $filename); - - //Log the upload to the log - $license->logUpload($filename, e($request->input('notes'))); - } - // This being called from a modal seems to confuse redirect()->back() - // It thinks we should go to the dashboard. As this is only used - // from the modal at present, hardcode the redirect. Longterm - // maybe we evaluate something else. - if ($upload_success) { - return redirect()->route('licenses.show', $license->id)->with('success', trans('admin/licenses/message.upload.success')); - } - return redirect()->route('licenses.show', $license->id)->with('error', trans('admin/licenses/message.upload.error')); - } - return redirect()->route('licenses.show', $license->id)->with('error', trans('admin/licenses/message.upload.nofiles')); - } - // Prepare the error message - $error = trans('admin/licenses/message.does_not_exist', compact('id')); - return redirect()->route('licenses.index')->with('error', $error); - } - - - /** - * Deletes the selected license file. - * - * @author [A. Gianotto] [] - * @since [v1.0] - * @param int $licenseId - * @param int $fileId - * @return \Illuminate\Http\RedirectResponse - */ - public function getDeleteFile($licenseId = null, $fileId = null) - { - $license = License::find($licenseId); - $destinationPath = config('app.private_uploads').'/licenses'; - - // the license is valid - if (isset($license->id)) { - $this->authorize('edit', $license); - $log = Actionlog::find($fileId); - $full_filename = $destinationPath.'/'.$log->filename; - if (file_exists($full_filename)) { - unlink($destinationPath.'/'.$log->filename); - } - $log->delete(); - return redirect()->back()->with('success', trans('admin/licenses/message.deletefile.success')); - } - // Prepare the error message - $error = trans('admin/licenses/message.does_not_exist', compact('id')); - - // Redirect to the licence management page - return redirect()->route('licenses.index')->with('error', $error); - } - - - - /** - * Allows the selected file to be viewed. - * - * @author [A. Gianotto] [] - * @since [v1.4] - * @param int $licenseId - * @param int $fileId - * @return \Symfony\Component\HttpFoundation\BinaryFileResponse - */ - public function displayFile($licenseId = null, $fileId = null, $download = true) - { - - $license = License::find($licenseId); - - // the license is valid - if (isset($license->id)) { - $this->authorize('view', $license); - $log = Actionlog::find($fileId); - $file = $log->get_src('licenses'); - - - if ($file =='') { - return response('File not found on server', 404) - ->header('Content-Type', 'text/plain'); - } - - $mimetype = \File::mimeType($file); - - - if (!file_exists($file)) { - return response('File '.$file.' not found on server', 404) - ->header('Content-Type', 'text/plain'); - } - - if ($download != 'true') { - if ($contents = file_get_contents($file)) { - return Response::make($contents)->header('Content-Type', $mimetype); - } - return JsonResponse::create(["error" => "Failed validation: "], 500); - } - return Response::download($file); - } - - - return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.does_not_exist', compact('id'))); - } - - - - /** - * Generates the next free seat ID for checkout. - * - * @todo This is a dumb way to solve this problem. - * Author should refactor. And go hide in a hole and - * think about what she's done. And perhaps find a new - * line of work. And get in the sea. - * - * @author [A. Gianotto] [] - * @since [v1.0] - * @param int $licenseId - * @return \Illuminate\Http\RedirectResponse - */ - public function getFreeLicense($licenseId) - { - $this->authorize('checkout', License::class); - if (is_null($license = License::find($licenseId))) { - return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.not_found')); - } - $seatId = $license->freeSeat($licenseId); - return redirect()->route('licenses.checkout', $seatId); - } -} diff --git a/app/Http/Controllers/LocationsController.php b/app/Http/Controllers/LocationsController.php index b67843b836..8d826d6b04 100755 --- a/app/Http/Controllers/LocationsController.php +++ b/app/Http/Controllers/LocationsController.php @@ -1,23 +1,12 @@ ] - * @see LocationsController::getDatatable() method that generates the JSON response - * @since [v1.0] - * @return \Illuminate\Contracts\View\View + * Returns a view that invokes the ajax tables which actually contains + * the content for the locations listing, which is generated in getDatatable. + * + * @author [A. Gianotto] [] + * @see LocationsController::getDatatable() method that generates the JSON response + * @since [v1.0] + * @return \Illuminate\Contracts\View\View + * @throws \Illuminate\Auth\Access\AuthorizationException */ public function index() { // Grab all the locations $this->authorize('view', Location::class); - $locations = Location::orderBy('created_at', 'DESC')->with('parent', 'assets', 'assignedassets')->get(); - // Show the page return view('locations/index'); } /** - * Returns a form view used to create a new location. - * - * @author [A. Gianotto] [] - * @see LocationsController::postCreate() method that validates and stores the data - * @since [v1.0] - * @return \Illuminate\Contracts\View\View + * Returns a form view used to create a new location. + * + * @author [A. Gianotto] [] + * @see LocationsController::postCreate() method that validates and stores the data + * @since [v1.0] + * @return \Illuminate\Contracts\View\View + * @throws \Illuminate\Auth\Access\AuthorizationException */ public function create() { @@ -72,13 +61,15 @@ class LocationsController extends Controller /** - * Validates and stores a new location. - * - * @todo Check if a Form Request would work better here. - * @author [A. Gianotto] [] - * @see LocationsController::getCreate() method that makes the form - * @since [v1.0] - * @return \Illuminate\Http\RedirectResponse + * Validates and stores a new location. + * + * @todo Check if a Form Request would work better here. + * @author [A. Gianotto] [] + * @see LocationsController::getCreate() method that makes the form + * @since [v1.0] + * @param ImageUploadRequest $request + * @return \Illuminate\Http\RedirectResponse + * @throws \Illuminate\Auth\Access\AuthorizationException */ public function store(ImageUploadRequest $request) { @@ -97,16 +88,7 @@ class LocationsController extends Controller $location->manager_id = $request->input('manager_id'); $location->user_id = Auth::id(); - if ($request->file('image')) { - $image = $request->file('image'); - $file_name = str_random(25).".".$image->getClientOriginalExtension(); - $path = public_path('uploads/locations/'.$file_name); - Image::make($image->getRealPath())->resize(600, null, function ($constraint) { - $constraint->aspectRatio(); - $constraint->upsize(); - })->save($path); - $location->image = $file_name; - } + $location = $request->handleImages($location, 'public/uploads/locations'); if ($location->save()) { return redirect()->route("locations.index")->with('success', trans('admin/locations/message.create.success')); @@ -116,13 +98,14 @@ class LocationsController extends Controller /** - * Makes a form view to edit location information. - * - * @author [A. Gianotto] [] - * @see LocationsController::postCreate() method that validates and stores - * @param int $locationId - * @since [v1.0] - * @return \Illuminate\Contracts\View\View + * Makes a form view to edit location information. + * + * @author [A. Gianotto] [] + * @see LocationsController::postCreate() method that validates and stores + * @param int $locationId + * @since [v1.0] + * @return \Illuminate\Contracts\View\View + * @throws \Illuminate\Auth\Access\AuthorizationException */ public function edit($locationId = null) { @@ -144,13 +127,15 @@ class LocationsController extends Controller /** - * Validates and stores updated location data from edit form. - * - * @author [A. Gianotto] [] - * @see LocationsController::getEdit() method that makes the form view - * @param int $locationId - * @since [v1.0] - * @return \Illuminate\Http\RedirectResponse + * Validates and stores updated location data from edit form. + * + * @author [A. Gianotto] [] + * @see LocationsController::getEdit() method that makes the form view + * @param ImageUploadRequest $request + * @param int $locationId + * @return \Illuminate\Http\RedirectResponse + * @throws \Illuminate\Auth\Access\AuthorizationException + * @since [v1.0] */ public function update(ImageUploadRequest $request, $locationId = null) { @@ -173,36 +158,7 @@ class LocationsController extends Controller $location->ldap_ou = $request->input('ldap_ou'); $location->manager_id = $request->input('manager_id'); - $old_image = $location->image; - - // Set the model's image property to null if the image is being deleted - if ($request->input('image_delete') == 1) { - $location->image = null; - } - - if ($request->file('image')) { - $image = $request->file('image'); - $file_name = $location->id.'-'.str_slug($image->getClientOriginalName()) . "." . $image->getClientOriginalExtension(); - - if ($image->getClientOriginalExtension()!='svg') { - Image::make($image->getRealPath())->resize(600, null, function ($constraint) { - $constraint->aspectRatio(); - $constraint->upsize(); - })->save(app('locations_upload_path').$file_name); - } else { - $image->move(app('locations_upload_path'), $file_name); - } - $location->image = $file_name; - - } - - if ((($request->file('image')) && (isset($old_image)) && ($old_image!='')) || ($request->input('image_delete') == 1)) { - try { - unlink(app('locations_upload_path').$old_image); - } catch (\Exception $e) { - \Log::error($e); - } - } + $location = $request->handleImages($location, 'public/uploads/locations'); if ($location->save()) { @@ -212,12 +168,13 @@ class LocationsController extends Controller } /** - * Validates and deletes selected location. - * - * @author [A. Gianotto] [] - * @param int $locationId - * @since [v1.0] - * @return \Illuminate\Http\RedirectResponse + * Validates and deletes selected location. + * + * @author [A. Gianotto] [] + * @param int $locationId + * @since [v1.0] + * @return \Illuminate\Http\RedirectResponse + * @throws \Illuminate\Auth\Access\AuthorizationException */ public function destroy($locationId) { @@ -226,22 +183,29 @@ class LocationsController extends Controller return redirect()->to(route('locations.index'))->with('error', trans('admin/locations/message.not_found')); } - if ($location->users->count() > 0) { + if ($location->users()->count() > 0) { return redirect()->to(route('locations.index'))->with('error', trans('admin/locations/message.assoc_users')); - } elseif ($location->childLocations->count() > 0) { + } elseif ($location->childLocations()->count() > 0) { return redirect()->to(route('locations.index'))->with('error', trans('admin/locations/message.assoc_child_loc')); - } elseif ($location->assets->count() > 0) { + } elseif ($location->assets()->count() > 0) { return redirect()->to(route('locations.index'))->with('error', trans('admin/locations/message.assoc_assets')); - } elseif ($location->assignedassets->count() > 0) { + } elseif ($location->assignedassets()->count() > 0) { return redirect()->to(route('locations.index'))->with('error', trans('admin/locations/message.assoc_assets')); - } else { - $location->delete(); - return redirect()->to(route('locations.index'))->with('success', trans('admin/locations/message.delete.success')); } + + if ($location->image) { + try { + Storage::disk('public')->delete('locations/'.$location->image); + } catch (\Exception $e) { + \Log::error($e); + } + } + $location->delete(); + return redirect()->to(route('locations.index'))->with('success', trans('admin/locations/message.delete.success')); } @@ -250,19 +214,19 @@ class LocationsController extends Controller * the content for the locations detail page. * * @author [A. Gianotto] [] - * @param int $locationId + * @param int $id * @since [v1.0] * @return \Illuminate\Contracts\View\View */ - public function show($locationId = null) + public function show($id = null) { - $location = Location::find($locationId); + $location = Location::find($id); if (isset($location->id)) { return view('locations/view', compact('location')); } - return redirect()->route('locations.index')->with('error', trans('admin/locations/message.does_not_exist', compact('id'))); + return redirect()->route('locations.index')->with('error', trans('admin/locations/message.does_not_exist')); } } diff --git a/app/Http/Controllers/ManufacturersController.php b/app/Http/Controllers/ManufacturersController.php index 686a2081fa..928f89fb66 100755 --- a/app/Http/Controllers/ManufacturersController.php +++ b/app/Http/Controllers/ManufacturersController.php @@ -1,20 +1,13 @@ ] - * @see Api\ManufacturersController::index() method that generates the JSON response - * @since [v1.0] - * @return \Illuminate\Contracts\View\View + * Returns a view that invokes the ajax tables which actually contains + * the content for the manufacturers listing, which is generated in getDatatable. + * + * @author [A. Gianotto] [] + * @see Api\ManufacturersController::index() method that generates the JSON response + * @since [v1.0] + * @return \Illuminate\Contracts\View\View + * @throws \Illuminate\Auth\Access\AuthorizationException */ public function index() { @@ -41,12 +35,13 @@ class ManufacturersController extends Controller /** - * Returns a view that displays a form to create a new manufacturer. - * - * @author [A. Gianotto] [] - * @see ManufacturersController::store() - * @since [v1.0] - * @return \Illuminate\Contracts\View\View + * Returns a view that displays a form to create a new manufacturer. + * + * @author [A. Gianotto] [] + * @see ManufacturersController::store() + * @since [v1.0] + * @return \Illuminate\Contracts\View\View + * @throws \Illuminate\Auth\Access\AuthorizationException */ public function create() { @@ -61,32 +56,24 @@ class ManufacturersController extends Controller * @author [A. Gianotto] [] * @see ManufacturersController::create() * @since [v1.0] - * @param Request $request + * @param ImageUploadRequest $request * @return \Illuminate\Http\RedirectResponse + * @throws \Illuminate\Auth\Access\AuthorizationException */ public function store(ImageUploadRequest $request) { $this->authorize('create', Manufacturer::class); $manufacturer = new Manufacturer; - $manufacturer->name = $request->input('name'); - $manufacturer->user_id = Auth::user()->id; - $manufacturer->url = $request->input('url'); - $manufacturer->support_url = $request->input('support_url'); + $manufacturer->name = $request->input('name'); + $manufacturer->user_id = Auth::id(); + $manufacturer->url = $request->input('url'); + $manufacturer->support_url = $request->input('support_url'); $manufacturer->support_phone = $request->input('support_phone'); $manufacturer->support_email = $request->input('support_email'); - if ($request->file('image')) { - $image = $request->file('image'); - $file_name = str_slug($image->getClientOriginalName()).".".$image->getClientOriginalExtension(); - $path = public_path('uploads/manufacturers/'.$file_name); - Image::make($image->getRealPath())->resize(200, null, function ($constraint) { - $constraint->aspectRatio(); - $constraint->upsize(); - })->save($path); - $manufacturer->image = $file_name; - } + $manufacturer = $request->handleImages($manufacturer,'manufacturers'); @@ -97,19 +84,20 @@ class ManufacturersController extends Controller } /** - * Returns a view that displays a form to edit a manufacturer. - * - * @author [A. Gianotto] [] - * @see ManufacturersController::update() - * @param int $manufacturerId - * @since [v1.0] - * @return \Illuminate\Contracts\View\View + * Returns a view that displays a form to edit a manufacturer. + * + * @author [A. Gianotto] [] + * @see ManufacturersController::update() + * @param int $manufacturerId + * @since [v1.0] + * @return \Illuminate\Contracts\View\View + * @throws \Illuminate\Auth\Access\AuthorizationException */ - public function edit($id = null) + public function edit($manufacturerId = null) { $this->authorize('edit', Manufacturer::class); // Check if the manufacturer exists - if (is_null($item = Manufacturer::find($id))) { + if (is_null($item = Manufacturer::find($manufacturerId))) { return redirect()->route('manufacturers.index')->with('error', trans('admin/manufacturers/message.does_not_exist')); } // Show the page @@ -126,6 +114,7 @@ class ManufacturersController extends Controller * @param int $manufacturerId * @return \Illuminate\Http\RedirectResponse * @since [v1.0] + * @throws \Illuminate\Auth\Access\AuthorizationException */ public function update(ImageUploadRequest $request, $manufacturerId = null) { @@ -137,42 +126,13 @@ class ManufacturersController extends Controller } // Save the data - $manufacturer->name = $request->input('name'); - $manufacturer->url = $request->input('url'); - $manufacturer->support_url = $request->input('support_url'); + $manufacturer->name = $request->input('name'); + $manufacturer->url = $request->input('url'); + $manufacturer->support_url = $request->input('support_url'); $manufacturer->support_phone = $request->input('support_phone'); $manufacturer->support_email = $request->input('support_email'); - $old_image = $manufacturer->image; - - // Set the model's image property to null if the image is being deleted - if ($request->input('image_delete') == 1) { - $manufacturer->image = null; - } - - if ($request->file('image')) { - $image = $request->file('image'); - $file_name = $manufacturer->id.'-'.str_slug($image->getClientOriginalName()) . "." . $image->getClientOriginalExtension(); - - if ($image->getClientOriginalExtension()!='svg') { - Image::make($image->getRealPath())->resize(500, null, function ($constraint) { - $constraint->aspectRatio(); - $constraint->upsize(); - })->save(app('manufacturers_upload_path').$file_name); - } else { - $image->move(app('manufacturers_upload_path'), $file_name); - } - $manufacturer->image = $file_name; - - } - - if ((($request->file('image')) && (isset($old_image)) && ($old_image!='')) || ($request->input('image_delete') == 1)) { - try { - unlink(app('manufacturers_upload_path').$old_image); - } catch (\Exception $e) { - \Log::error($e); - } - } + $manufacturer = $request->handleImages($manufacturer); if ($manufacturer->save()) { @@ -182,30 +142,28 @@ class ManufacturersController extends Controller } /** - * Deletes a manufacturer. - * - * @author [A. Gianotto] [] - * @param int $manufacturerId - * @since [v1.0] - * @return \Illuminate\Http\RedirectResponse + * Deletes a manufacturer. + * + * @author [A. Gianotto] [] + * @param int $manufacturerId + * @since [v1.0] + * @return \Illuminate\Http\RedirectResponse + * @throws \Illuminate\Auth\Access\AuthorizationException */ public function destroy($manufacturerId) { $this->authorize('delete', Manufacturer::class); - // Check if the manufacturer exists - if (is_null($manufacturer = Manufacturer::find($manufacturerId))) { - // Redirect to the manufacturers page + if (is_null($manufacturer = Manufacturer::withCount('models as models_count')->find($manufacturerId))) { return redirect()->route('manufacturers.index')->with('error', trans('admin/manufacturers/message.not_found')); } - if ($manufacturer->has_models() > 0) { - // Redirect to the asset management page + if ($manufacturer->models_count > 0) { return redirect()->route('manufacturers.index')->with('error', trans('admin/manufacturers/message.assoc_users')); } if ($manufacturer->image) { try { - unlink(public_path().'/uploads/manufacturers/'.$manufacturer->image); + Storage::disk('public')->delete('manufacturers/'.$manufacturer->image); } catch (\Exception $e) { \Log::error($e); } @@ -219,14 +177,15 @@ class ManufacturersController extends Controller } /** - * Returns a view that invokes the ajax tables which actually contains - * the content for the manufacturers detail listing, which is generated via API. - * This data contains a listing of all assets that belong to that manufacturer. - * - * @author [A. Gianotto] [] - * @param int $manufacturerId - * @since [v1.0] - * @return \Illuminate\Contracts\View\View + * Returns a view that invokes the ajax tables which actually contains + * the content for the manufacturers detail listing, which is generated via API. + * This data contains a listing of all assets that belong to that manufacturer. + * + * @author [A. Gianotto] [] + * @param int $manufacturerId + * @since [v1.0] + * @return \Illuminate\Contracts\View\View + * @throws \Illuminate\Auth\Access\AuthorizationException */ public function show($manufacturerId = null) { @@ -249,6 +208,7 @@ class ManufacturersController extends Controller * @since [v4.1.15] * @param int $manufacturers_id * @return Redirect + * @throws \Illuminate\Auth\Access\AuthorizationException */ public function restore($manufacturers_id) { diff --git a/app/Http/Controllers/ProfileController.php b/app/Http/Controllers/ProfileController.php index 492b65db0b..5b0a06ede3 100755 --- a/app/Http/Controllers/ProfileController.php +++ b/app/Http/Controllers/ProfileController.php @@ -12,6 +12,7 @@ use Gate; use Illuminate\Http\Request; use Illuminate\Support\Facades\Hash; use App\Http\Requests\ImageUploadRequest; +use Illuminate\Support\Facades\Storage; /** * This controller handles all actions related to User Profiles for @@ -61,18 +62,38 @@ class ProfileController extends Controller if (Gate::allows('self.edit_location') && (!config('app.lock_passwords'))) { $user->location_id = $request->input('location_id'); } - - if (Input::file('avatar')) { - $image = Input::file('avatar'); - $file_name = str_slug($user->first_name."-".$user->last_name).".".$image->getClientOriginalExtension(); - $path = public_path('uploads/avatars/'.$file_name); - Image::make($image->getRealPath())->resize(84, 84)->save($path); + + + if ($request->input('avatar_delete') == 1) { + $user->avatar = null; + } + + + if ($request->hasFile('avatar')) { + $path = 'avatars'; + + if(!Storage::disk('public')->exists($path)) Storage::disk('public')->makeDirectory($path, 775); + + $upload = $image = $request->file('avatar'); + $ext = $image->getClientOriginalExtension(); + $file_name = 'avatar-'.str_random(18).'.'.$ext; + + if ($image->getClientOriginalExtension()!='svg') { + $upload = Image::make($image->getRealPath())->resize(84, 84); + } + + // This requires a string instead of an object, so we use ($string) + Storage::disk('public')->put($path.'/'.$file_name, (string)$upload->encode()); + + // Remove Current image if exists + if (($user->avatar) && (Storage::disk('public')->exists($path.'/'.$user->avatar))) { + Storage::disk('public')->delete($path.'/'.$user->avatar); + } + $user->avatar = $file_name; } - if (Input::get('avatar_delete') == 1 && Input::file('avatar') == "") { - $user->avatar = null; - } + if ($user->save()) { return redirect()->route('profile')->with('success', 'Account successfully updated'); diff --git a/app/Http/Controllers/ReportsController.php b/app/Http/Controllers/ReportsController.php index 6692e60840..23ffd7a6c6 100644 --- a/app/Http/Controllers/ReportsController.php +++ b/app/Http/Controllers/ReportsController.php @@ -7,6 +7,7 @@ use App\Models\Actionlog; use App\Models\Asset; use App\Models\AssetMaintenance; use App\Models\CustomField; +use App\Models\CheckoutAcceptance; use App\Models\Depreciation; use App\Models\License; use App\Models\Setting; @@ -31,8 +32,6 @@ class ReportsController extends Controller */ public function __construct() { parent::__construct(); - - $this->authorize('reports.view'); } /** @@ -44,6 +43,7 @@ class ReportsController extends Controller */ public function getAccessoryReport() { + $this->authorize('reports.view'); $accessories = Accessory::orderBy('created_at', 'DESC')->with('company')->get(); return view('reports/accessories', compact('accessories')); } @@ -59,6 +59,7 @@ class ReportsController extends Controller */ public function exportAccessoryReport() { + $this->authorize('reports.view'); $accessories = Accessory::orderBy('created_at', 'DESC')->get(); $rows = array(); @@ -99,7 +100,7 @@ class ReportsController extends Controller */ public function getDeprecationReport() { - + $this->authorize('reports.view'); $depreciations = Depreciation::get(); // Grab all the assets $assets = Asset::with( 'assignedTo', 'assetstatus', 'defaultLoc', 'location', 'assetlog', 'company', 'model.category', 'model.depreciation') @@ -118,7 +119,7 @@ class ReportsController extends Controller */ public function exportDeprecationReport() { - + $this->authorize('reports.view'); // Grab all the assets $assets = Asset::with('model', 'assignedTo', 'assetstatus', 'defaultLoc', 'assetlog') ->orderBy('created_at', 'DESC')->get(); @@ -172,7 +173,7 @@ class ReportsController extends Controller if ($asset->location) { $currency = e($asset->location->currency); } else { - $currency = e(Setting::first()->default_currency); + $currency = e(Setting::getSettings()->default_currency); } $row[] = $asset->purchase_date; @@ -197,6 +198,7 @@ class ReportsController extends Controller */ public function audit() { + $this->authorize('reports.view'); return view('reports/audit'); } @@ -210,7 +212,7 @@ class ReportsController extends Controller */ public function getActivityReport() { - + $this->authorize('reports.view'); return view('reports/activity'); } @@ -224,7 +226,7 @@ class ReportsController extends Controller */ public function getLicenseReport() { - + $this->authorize('reports.view'); $licenses = License::with('depreciation')->orderBy('created_at', 'DESC') ->with('company') ->get(); @@ -242,6 +244,7 @@ class ReportsController extends Controller */ public function exportLicenseReport() { + $this->authorize('reports.view'); $licenses = License::orderBy('created_at', 'DESC')->get(); $rows = [ ]; @@ -292,6 +295,7 @@ class ReportsController extends Controller */ public function getCustomReport() { + $this->authorize('reports.view'); $customfields = CustomField::get(); return view('reports/custom')->with('customfields', $customfields); } @@ -306,7 +310,7 @@ class ReportsController extends Controller */ public function postCustom(Request $request) { - + $this->authorize('reports.view'); \Debugbar::disable(); $customfields = CustomField::get(); $response = new StreamedResponse(function () use ($customfields, $request) { @@ -314,65 +318,65 @@ class ReportsController extends Controller // Open output stream $handle = fopen('php://output', 'w'); - if ($request->has('use_bom')) { + if ($request->filled('use_bom')) { fprintf($handle, chr(0xEF) . chr(0xBB) . chr(0xBF)); } $header = []; - if ($request->has('company')) { + if ($request->filled('company')) { $header[] = trans('general.company'); } - if ($request->has('asset_name')) { + if ($request->filled('asset_name')) { $header[] = trans('admin/hardware/form.name'); } - if ($request->has('asset_tag')) { + if ($request->filled('asset_tag')) { $header[] = trans('admin/hardware/table.asset_tag'); } - if ($request->has('model')) { + if ($request->filled('model')) { $header[] = trans('admin/hardware/form.model'); $header[] = trans('general.model_no'); } - if ($request->has('category')) { + if ($request->filled('category')) { $header[] = trans('general.category'); } - if ($request->has('manufacturer')) { + if ($request->filled('manufacturer')) { $header[] = trans('admin/hardware/form.manufacturer'); } - if ($request->has('serial')) { + if ($request->filled('serial')) { $header[] = trans('admin/hardware/table.serial'); } - if ($request->has('purchase_date')) { + if ($request->filled('purchase_date')) { $header[] = trans('admin/hardware/table.purchase_date'); } - if (($request->has('purchase_cost')) || ($request->has('depreciation'))) { + if (($request->filled('purchase_cost')) || ($request->filled('depreciation'))) { $header[] = trans('admin/hardware/table.purchase_cost'); } - if ($request->has('eol')) { + if ($request->filled('eol')) { $header[] = trans('admin/hardware/table.eol'); } - if ($request->has('order')) { + if ($request->filled('order')) { $header[] = trans('admin/hardware/form.order'); } - if ($request->has('supplier')) { + if ($request->filled('supplier')) { $header[] = trans('general.supplier'); } - if ($request->has('location')) { + if ($request->filled('location')) { $header[] = trans('admin/hardware/table.location'); } - if ($request->has('location_address')) { + if ($request->filled('location_address')) { $header[] = trans('general.address'); $header[] = trans('general.address'); $header[] = trans('general.city'); @@ -381,11 +385,11 @@ class ReportsController extends Controller $header[] = trans('general.zip'); } - if ($request->has('rtd_location')) { + if ($request->filled('rtd_location')) { $header[] = trans('admin/hardware/form.default_location'); } - if ($request->has('rtd_location_address')) { + if ($request->filled('rtd_location_address')) { $header[] = trans('general.address'); $header[] = trans('general.address'); $header[] = trans('general.city'); @@ -395,65 +399,66 @@ class ReportsController extends Controller } - if ($request->has('assigned_to')) { + if ($request->filled('assigned_to')) { $header[] = trans('admin/hardware/table.checkoutto'); $header[] = trans('general.type'); } - if ($request->has('username')) { + if ($request->filled('username')) { $header[] = 'Username'; } - if ($request->has('employee_num')) { + if ($request->filled('employee_num')) { $header[] = 'Employee No.'; } - if ($request->has('manager')) { + if ($request->filled('manager')) { $header[] = trans('admin/users/table.manager'); } - if ($request->has('department')) { + if ($request->filled('department')) { $header[] = trans('general.department'); } - if ($request->has('status')) { + if ($request->filled('status')) { $header[] = trans('general.status'); } - if ($request->has('warranty')) { + if ($request->filled('warranty')) { $header[] = 'Warranty'; $header[] = 'Warranty Expires'; } - if ($request->has('depreciation')) { + if ($request->filled('depreciation')) { $header[] = 'Value'; $header[] = 'Diff'; + $header[] = 'Fully Depreciated'; } - if ($request->has('checkout_date')) { + if ($request->filled('checkout_date')) { $header[] = trans('admin/hardware/table.checkout_date'); } - if ($request->has('expected_checkin')) { + if ($request->filled('expected_checkin')) { $header[] = trans('admin/hardware/form.expected_checkin'); } - if ($request->has('created_at')) { + if ($request->filled('created_at')) { $header[] = trans('general.created_at'); } - if ($request->has('updated_at')) { + if ($request->filled('updated_at')) { $header[] = trans('general.updated_at'); } - if ($request->has('last_audit_date')) { + if ($request->filled('last_audit_date')) { $header[] = trans('general.last_audit'); } - if ($request->has('next_audit_date')) { + if ($request->filled('next_audit_date')) { $header[] = trans('general.next_audit_date'); } - if ($request->has('notes')) { + if ($request->filled('notes')) { $header[] = trans('general.notes'); } @@ -471,52 +476,57 @@ class ReportsController extends Controller 'location', 'assetstatus', 'assetlog', 'company', 'defaultLoc','assignedTo', 'model.category', 'model.manufacturer','supplier'); - if ($request->has('by_location_id')) { + if ($request->filled('by_location_id')) { $assets->where('assets.location_id', $request->input('by_location_id')); } - if ($request->has('by_rtd_location_id')) { + if ($request->filled('by_rtd_location_id')) { \Log::debug('RTD location should match: '.$request->input('by_rtd_location_id')); $assets->where('assets.rtd_location_id', $request->input('by_rtd_location_id')); } - if ($request->has('by_supplier_id')) { + if ($request->filled('by_supplier_id')) { $assets->where('assets.supplier_id', $request->input('by_supplier_id')); } - if ($request->has('by_company_id')) { + if ($request->filled('by_company_id')) { $assets->where('assets.company_id', $request->input('by_company_id')); } - if ($request->has('by_model_id')) { + if ($request->filled('by_model_id')) { $assets->where('assets.model_id', $request->input('by_model_id')); } - if ($request->has('by_category_id')) { + if ($request->filled('by_category_id')) { $assets->InCategory($request->input('by_category_id')); } - if ($request->has('by_manufacturer_id')) { + if ($request->filled('by_dept_id')) { + \Log::debug('Only users in dept '.$request->input('by_dept_id')); + $assets->CheckedOutToTargetInDepartment($request->input('by_dept_id')); + } + + if ($request->filled('by_manufacturer_id')) { $assets->ByManufacturer($request->input('by_manufacturer_id')); } - if ($request->has('by_order_number')) { + if ($request->filled('by_order_number')) { $assets->where('assets.order_number', $request->input('by_order_number')); } - if ($request->has('by_status_id')) { + if ($request->filled('by_status_id')) { $assets->where('assets.status_id', $request->input('by_status_id')); } - if (($request->has('purchase_start')) && ($request->has('purchase_end'))) { + if (($request->filled('purchase_start')) && ($request->filled('purchase_end'))) { $assets->whereBetween('assets.purchase_date', [$request->input('purchase_start'), $request->input('purchase_end')]); } - if (($request->has('created_start')) && ($request->has('created_end'))) { + if (($request->filled('created_start')) && ($request->filled('created_end'))) { $assets->whereBetween('assets.created_at', [$request->input('created_start'), $request->input('created_end')]); } - if (($request->has('expected_checkin_start')) && ($request->has('expected_checkin_end'))) { + if (($request->filled('expected_checkin_start')) && ($request->filled('expected_checkin_end'))) { $assets->whereBetween('assets.expected_checkin', [$request->input('expected_checkin_start'), $request->input('expected_checkin_end')]); } @@ -525,61 +535,61 @@ class ReportsController extends Controller foreach ($assets as $asset) { $row = []; - if ($request->has('company')) { + if ($request->filled('company')) { $row[] = ($asset->company) ? $asset->company->name : ''; } - if ($request->has('asset_name')) { + if ($request->filled('asset_name')) { $row[] = ($asset->name) ? $asset->name : ''; } - if ($request->has('asset_tag')) { + if ($request->filled('asset_tag')) { $row[] = ($asset->asset_tag) ? $asset->asset_tag : ''; } - if ($request->has('model')) { + if ($request->filled('model')) { $row[] = ($asset->model) ? $asset->model->name : ''; $row[] = ($asset->model) ? $asset->model->model_number : ''; } - if ($request->has('category')) { + if ($request->filled('category')) { $row[] = (($asset->model) && ($asset->model->category)) ? $asset->model->category->name : ''; } - if ($request->has('manufacturer')) { + if ($request->filled('manufacturer')) { $row[] = ($asset->model && $asset->model->manufacturer) ? $asset->model->manufacturer->name : ''; } - if ($request->has('serial')) { + if ($request->filled('serial')) { $row[] = ($asset->serial) ? $asset->serial : ''; } - if ($request->has('purchase_date')) { + if ($request->filled('purchase_date')) { $row[] = ($asset->purchase_date) ? $asset->purchase_date : ''; } - if ($request->has('purchase_cost')) { + if ($request->filled('purchase_cost')) { $row[] = ($asset->purchase_cost) ? Helper::formatCurrencyOutput($asset->purchase_cost) : ''; } - if ($request->has('eol')) { + if ($request->filled('eol')) { $row[] = ($asset->purchase_date!='') ? $asset->present()->eol_date() : ''; } - if ($request->has('order')) { + if ($request->filled('order')) { $row[] = ($asset->order_number) ? $asset->order_number : ''; } - if ($request->has('supplier')) { + if ($request->filled('supplier')) { $row[] = ($asset->supplier) ? $asset->supplier->name : ''; } - if ($request->has('location')) { + if ($request->filled('location')) { $row[] = ($asset->location) ? $asset->location->present()->name() : ''; } - if ($request->has('location_address')) { + if ($request->filled('location_address')) { $row[] = ($asset->location) ? $asset->location->address : ''; $row[] = ($asset->location) ? $asset->location->address2 : ''; $row[] = ($asset->location) ? $asset->location->city : ''; @@ -588,11 +598,11 @@ class ReportsController extends Controller $row[] = ($asset->location) ? $asset->location->zip : ''; } - if ($request->has('rtd_location')) { + if ($request->filled('rtd_location')) { $row[] = ($asset->defaultLoc) ? $asset->defaultLoc->present()->name() : ''; } - if ($request->has('rtd_location_address')) { + if ($request->filled('rtd_location_address')) { $row[] = ($asset->defaultLoc) ? $asset->defaultLoc->address : ''; $row[] = ($asset->defaultLoc) ? $asset->defaultLoc->address2 : ''; $row[] = ($asset->defaultLoc) ? $asset->defaultLoc->city : ''; @@ -602,12 +612,12 @@ class ReportsController extends Controller } - if ($request->has('assigned_to')) { + if ($request->filled('assigned_to')) { $row[] = ($asset->checkedOutToUser() && $asset->assigned) ? $asset->assigned->getFullNameAttribute() : ($asset->assigned ? $asset->assigned->display_name : ''); $row[] = ($asset->checkedOutToUser() && $asset->assigned) ? 'user' : $asset->assignedType(); } - if ($request->has('username')) { + if ($request->filled('username')) { // Only works if we're checked out to a user, not anything else. if ($asset->checkedOutToUser()) { $row[] = ($asset->assignedto) ? $asset->assignedto->username : ''; @@ -616,7 +626,7 @@ class ReportsController extends Controller } } - if ($request->has('employee_num')) { + if ($request->filled('employee_num')) { // Only works if we're checked out to a user, not anything else. if ($asset->checkedOutToUser()) { $row[] = ($asset->assignedto) ? $asset->assignedto->employee_num : ''; @@ -625,7 +635,7 @@ class ReportsController extends Controller } } - if ($request->has('manager')) { + if ($request->filled('manager')) { if ($asset->checkedOutToUser()) { $row[] = (($asset->assignedto) && ($asset->assignedto->manager)) ? $asset->assignedto->manager->present()->fullName : ''; } else { @@ -634,7 +644,7 @@ class ReportsController extends Controller } - if ($request->has('department')) { + if ($request->filled('department')) { if ($asset->checkedOutToUser()) { $row[] = (($asset->assignedto) && ($asset->assignedto->department)) ? $asset->assignedto->department->name : ''; } else { @@ -642,55 +652,56 @@ class ReportsController extends Controller } } - if ($request->has('status')) { + if ($request->filled('status')) { $row[] = ($asset->assetstatus) ? $asset->assetstatus->name.' ('.$asset->present()->statusMeta.')' : ''; } - if ($request->has('warranty')) { + if ($request->filled('warranty')) { $row[] = ($asset->warranty_months) ? $asset->warranty_months : ''; $row[] = $asset->present()->warrantee_expires(); } - if ($request->has('depreciation')) { + if ($request->filled('depreciation')) { $depreciation = $asset->getDepreciatedValue(); $diff = ($asset->purchase_cost - $depreciation); $row[] = Helper::formatCurrencyOutput($depreciation); $row[] = Helper::formatCurrencyOutput($diff); + $row[] = ($asset->depreciated_date()!='') ? $asset->depreciated_date()->format('Y-m-d') : ''; } - if ($request->has('checkout_date')) { + if ($request->filled('checkout_date')) { $row[] = ($asset->last_checkout) ? $asset->last_checkout : ''; } - if ($request->has('expected_checkin')) { + if ($request->filled('expected_checkin')) { $row[] = ($asset->expected_checkin) ? $asset->expected_checkin : ''; } - if ($request->has('created_at')) { + if ($request->filled('created_at')) { $row[] = ($asset->created_at) ? $asset->created_at : ''; } - if ($request->has('updated_at')) { + if ($request->filled('updated_at')) { $row[] = ($asset->updated_at) ? $asset->updated_at : ''; } - if ($request->has('last_audit_date')) { + if ($request->filled('last_audit_date')) { $row[] = ($asset->last_audit_date) ? $asset->last_audit_date : ''; } - if ($request->has('next_audit_date')) { + if ($request->filled('next_audit_date')) { $row[] = ($asset->next_audit_date) ? $asset->next_audit_date : ''; } - if ($request->has('notes')) { + if ($request->filled('notes')) { $row[] = ($asset->notes) ? $asset->notes : ''; } foreach ($customfields as $customfield) { $column_name = $customfield->db_column_name(); - if ($request->has($customfield->db_column_name())) { + if ($request->filled($customfield->db_column_name())) { $row[] = $asset->$column_name; } } @@ -721,6 +732,7 @@ class ReportsController extends Controller */ public function getAssetMaintenancesReport() { + $this->authorize('reports.view'); // Grab all the improvements $assetMaintenances = AssetMaintenance::with('asset', 'supplier', 'asset.company') ->orderBy('created_at', 'DESC') @@ -739,6 +751,7 @@ class ReportsController extends Controller */ public function exportAssetMaintenancesReport() { + $this->authorize('reports.view'); // Grab all the improvements $assetMaintenances = AssetMaintenance::with('asset', 'supplier') ->orderBy('created_at', 'DESC') @@ -799,7 +812,21 @@ class ReportsController extends Controller */ public function getAssetAcceptanceReport() { - $assetsForReport = Asset::notYetAccepted()->with('company')->get(); + $this->authorize('reports.view'); + + /** + * Get all assets with pending checkout acceptances + */ + + $acceptances = CheckoutAcceptance::pending()->get(); + + $assetsForReport = $acceptances + ->filter(function($acceptance) { + return $acceptance->checkoutable_type == 'App\Models\Asset'; + }) + ->map(function($acceptance) { + return $acceptance->checkoutable; + }); return view('reports/unaccepted_assets', compact('assetsForReport')); } @@ -813,7 +840,7 @@ class ReportsController extends Controller */ public function exportAssetAcceptanceReport() { - + $this->authorize('reports.view'); // Grab all the improvements $assetsForReport = Actionlog::whereIn('id', $this->getAssetsNotAcceptedYet()) ->get(); @@ -862,6 +889,7 @@ class ReportsController extends Controller */ protected function getCheckedOutAssetsRequiringAcceptance($modelsInCategoriesThatRequireAcceptance) { + $this->authorize('reports.view'); $assets = Asset::deployed() ->inModelList($modelsInCategoriesThatRequireAcceptance) ->select('id') @@ -881,7 +909,7 @@ class ReportsController extends Controller */ protected function getModelsInCategoriesThatRequireAcceptance($assetCategoriesRequiringAcceptance) { - + $this->authorize('reports.view'); return array_pluck(Model::inCategory($assetCategoriesRequiringAcceptance) ->select('id') ->get() @@ -897,7 +925,7 @@ class ReportsController extends Controller */ protected function getCategoriesThatRequireAcceptance() { - + $this->authorize('reports.view'); return array_pluck(Category::requiresAcceptance() ->select('id') ->get() @@ -913,7 +941,7 @@ class ReportsController extends Controller */ protected function getAssetsCheckedOutRequiringAcceptance() { - + $this->authorize('reports.view'); return $this->getCheckedOutAssetsRequiringAcceptance( $this->getModelsInCategoriesThatRequireAcceptance($this->getCategoriesThatRequireAcceptance()) ); @@ -928,6 +956,7 @@ class ReportsController extends Controller */ protected function getAssetsNotAcceptedYet() { + $this->authorize('reports.view'); return Asset::unaccepted(); } } diff --git a/app/Http/Controllers/SettingsController.php b/app/Http/Controllers/SettingsController.php index 1859d8e4a5..f96f4dc0bd 100755 --- a/app/Http/Controllers/SettingsController.php +++ b/app/Http/Controllers/SettingsController.php @@ -1,28 +1,25 @@ ] - * @since [v3.0] - * @return View - */ + * Checks to see whether or not the database has a migrations table + * and a user, otherwise display the setup view. + * + * @author [A. Gianotto] [] + * + * @since [v3.0] + * + * @return View + */ public function getSetupIndex() { + $start_settings['php_version_min'] = false; + if (version_compare(PHP_VERSION, config('app.min_php'), '<')) { + return response('

This software requires PHP version ' . config('app.min_php') . ' or greater. This server is running ' . PHP_VERSION . '.

Please upgrade PHP on this server and try again.

', 500); + } try { - $conn = DB::select('select 2 + 2'); - $start_settings['db_conn'] = true; - $start_settings['db_name'] = DB::connection()->getDatabaseName(); + $conn = DB::select('select 2 + 2'); + $start_settings['db_conn'] = true; + $start_settings['db_name'] = DB::connection()->getDatabaseName(); $start_settings['db_error'] = null; } catch (\PDOException $e) { - $start_settings['db_conn'] = false; - $start_settings['db_name'] = config('database.connections.mysql.database'); + $start_settings['db_conn'] = false; + $start_settings['db_name'] = config('database.connections.mysql.database'); $start_settings['db_error'] = $e->getMessage(); } - $protocol = array_key_exists('HTTPS', $_SERVER) && ( $_SERVER['HTTPS'] == "on") ? 'https://' : 'http://'; + $protocol = array_key_exists('HTTPS', $_SERVER) && ('on' == $_SERVER['HTTPS']) ? 'https://' : 'http://'; $host = array_key_exists('SERVER_NAME', $_SERVER) ? $_SERVER['SERVER_NAME'] : null; $port = array_key_exists('SERVER_PORT', $_SERVER) ? $_SERVER['SERVER_PORT'] : null; - if (($protocol === 'http://' && $port != '80') || ($protocol === 'https://' && $port != '443')) { + if (('http://' === $protocol && '80' != $port) || ('https://' === $protocol && '443' != $port)) { $host .= ':' . $port; } $pageURL = $protocol . $host . $_SERVER['REQUEST_URI']; - $start_settings['url_valid'] = (url('/').'/setup' === $pageURL); + $start_settings['url_valid'] = (url('/') . '/setup' === $pageURL); - $start_settings['url_config'] = url('/'); - $start_settings['real_url'] = $pageURL; + $start_settings['url_config'] = url('/'); + $start_settings['real_url'] = $pageURL; + $start_settings['php_version_min'] = true; // Curl the .env file to make sure it's not accessible via a browser - $ch = curl_init($protocol . $host.'/.env'); + $ch = curl_init($protocol . $host . '/.env'); curl_setopt($ch, CURLOPT_HEADER, true); // we want headers curl_setopt($ch, CURLOPT_NOBODY, true); // we don't need body curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_TIMEOUT, 10); - $output = curl_exec($ch); + $output = curl_exec($ch); $httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); - if ($httpcode == 404 || $httpcode == 403) { + if (404 == $httpcode || 403 == $httpcode || 0 == $httpcode) { $start_settings['env_exposed'] = false; } else { $start_settings['env_exposed'] = true; } - - if (\App::Environment('production') && (config('app.debug')==true)) { + if (\App::Environment('production') && (true == config('app.debug'))) { $start_settings['debug_exposed'] = true; } else { $start_settings['debug_exposed'] = false; } $environment = app()->environment(); - if ($environment!='production') { - $start_settings['env'] = $environment; + if ('production' != $environment) { + $start_settings['env'] = $environment; $start_settings['prod'] = false; } else { - $start_settings['env'] = $environment; + $start_settings['env'] = $environment; $start_settings['prod'] = true; - } if (function_exists('posix_getpwuid')) { // Probably Linux - $owner = posix_getpwuid(fileowner($_SERVER["SCRIPT_FILENAME"])); + $owner = posix_getpwuid(fileowner($_SERVER['SCRIPT_FILENAME'])); $start_settings['owner'] = $owner['name']; } else { // Windows // TODO: Is there a way of knowing if a windows user has elevated permissions @@ -113,110 +114,100 @@ class SettingsController extends Controller $start_settings['owner'] = ''; } - if (($start_settings['owner']==='root') || ($start_settings['owner']==='0')) { + if (('root' === $start_settings['owner']) || ('0' === $start_settings['owner'])) { $start_settings['owner_is_admin'] = true; } else { $start_settings['owner_is_admin'] = false; } if ((is_writable(storage_path())) - && (is_writable(storage_path().'/framework')) - && (is_writable(storage_path().'/framework/cache')) - && (is_writable(storage_path().'/framework/sessions')) - && (is_writable(storage_path().'/framework/views')) - && (is_writable(storage_path().'/logs')) + && (is_writable(storage_path() . '/framework')) + && (is_writable(storage_path() . '/framework/cache')) + && (is_writable(storage_path() . '/framework/sessions')) + && (is_writable(storage_path() . '/framework/views')) + && (is_writable(storage_path() . '/logs')) ) { $start_settings['writable'] = true; } else { $start_settings['writable'] = false; } - $start_settings['gd'] = extension_loaded('gd'); + return view('setup/index') ->with('step', 1) ->with('start_settings', $start_settings) ->with('section', 'Pre-Flight Check'); } - /** - * Save the first admin user from Setup. - * - * @author [A. Gianotto] [] - * @since [v3.0] - * @return Redirect - */ + * Save the first admin user from Setup. + * + * @author [A. Gianotto] [] + * + * @since [v3.0] + * + * @return Redirect + */ public function postSaveFirstAdmin(SetupUserRequest $request) { - - - $user = new User; - $user->first_name = $data['first_name']= $request->input('first_name'); - $user->last_name = $request->input('last_name'); - $user->email = $data['email'] = $request->input('email'); - $user->activated = 1; - $permissions = array('superuser' => 1); + $user = new User(); + $user->first_name = $data['first_name'] = $request->input('first_name'); + $user->last_name = $request->input('last_name'); + $user->email = $data['email'] = $request->input('email'); + $user->activated = 1; + $permissions = ['superuser' => 1]; $user->permissions = json_encode($permissions); - $user->username = $data['username'] = $request->input('username'); - $user->password = bcrypt($request->input('password')); - $data['password'] = $request->input('password'); + $user->username = $data['username'] = $request->input('username'); + $user->password = bcrypt($request->input('password')); + $data['password'] = $request->input('password'); - $settings = new Setting; + $settings = new Setting(); $settings->full_multiple_companies_support = $request->input('full_multiple_companies_support', 0); - $settings->site_name = $request->input('site_name'); - $settings->alert_email = $request->input('email'); - $settings->alerts_enabled = 1; - $settings->pwd_secure_min = 10; - $settings->brand = 1; - $settings->locale = $request->input('locale', 'en'); - $settings->default_currency = $request->input('default_currency', "USD"); - $settings->user_id = 1; - $settings->email_domain = $request->input('email_domain'); - $settings->email_format = $request->input('email_format'); - $settings->next_auto_tag_base = 1; - $settings->auto_increment_assets = $request->input('auto_increment_assets', 0); - $settings->auto_increment_prefix = $request->input('auto_increment_prefix'); + $settings->site_name = $request->input('site_name'); + $settings->alert_email = $request->input('email'); + $settings->alerts_enabled = 1; + $settings->pwd_secure_min = 10; + $settings->brand = 1; + $settings->locale = $request->input('locale', 'en'); + $settings->default_currency = $request->input('default_currency', 'USD'); + $settings->user_id = 1; + $settings->email_domain = $request->input('email_domain'); + $settings->email_format = $request->input('email_format'); + $settings->next_auto_tag_base = 1; + $settings->auto_increment_assets = $request->input('auto_increment_assets', 0); + $settings->auto_increment_prefix = $request->input('auto_increment_prefix'); - - if ((!$user->isValid()) || (!$settings->isValid())) { + if ((! $user->isValid()) || (! $settings->isValid())) { return redirect()->back()->withInput()->withErrors($user->getErrors())->withErrors($settings->getErrors()); } else { $user->save(); Auth::login($user, true); $settings->save(); - if (Input::get('email_creds')=='1') { - $data = array(); - $data['email'] = $user->email; - $data['username'] = $user->username; + if ('1' == Input::get('email_creds')) { + $data = []; + $data['email'] = $user->email; + $data['username'] = $user->username; $data['first_name'] = $user->first_name; - $data['last_name'] = $user->last_name; - $data['password'] = $request->input('password'); + $data['last_name'] = $user->last_name; + $data['password'] = $request->input('password'); $user->notify(new FirstAdminNotification($data)); - - /*Mail::send(['text' => 'emails.firstadmin'], $data, function ($m) use ($data) { - $m->to($data['email'], $data['first_name']); - $m->replyTo(config('mail.reply_to.address'), config('mail.reply_to.name')); - $m->subject(trans('mail.your_credentials')); - });*/ } - - return redirect()->route('setup.done'); } - - } /** - * Return the admin user creation form in Setup. - * - * @author [A. Gianotto] [] - * @since [v3.0] - * @return View - */ + * Return the admin user creation form in Setup. + * + * @author [A. Gianotto] [] + * + * @since [v3.0] + * + * @return View + */ public function getSetupUser() { return view('setup/user') @@ -225,132 +216,135 @@ class SettingsController extends Controller } /** - * Return the view that tells the user that the Setup is done. - * - * @author [A. Gianotto] [] - * @since [v3.0] - * @return View - */ + * Return the view that tells the user that the Setup is done. + * + * @author [A. Gianotto] [] + * + * @since [v3.0] + * + * @return View + */ public function getSetupDone() { - return view('setup/done') ->with('step', 4) ->with('section', 'Done!'); } /** - * Migrate the database tables, and return the output - * to a view for Setup - * - * @author [A. Gianotto] [] - * @since [v3.0] - * @return View - */ + * Migrate the database tables, and return the output + * to a view for Setup. + * + * @author [A. Gianotto] [] + * + * @since [v3.0] + * + * @return View + */ public function getSetupMigrate() { - Artisan::call('migrate', ['--force' => true]); - $output = Artisan::output(); - - if ((!file_exists(storage_path().'/oauth-private.key')) || (!file_exists(storage_path().'/oauth-public.key'))) { - Artisan::call('migrate', ['--force' => true]); + if ((! file_exists(storage_path() . '/oauth-private.key')) || (! file_exists(storage_path() . '/oauth-public.key'))) { + Artisan::call('migrate', ['--path' => 'vendor/laravel/passport/database/migrations', '--force' => true]); Artisan::call('passport:install'); } - return view('setup/migrate') - ->with('output', $output) + ->with('output', 'Databases installed!') ->with('step', 2) ->with('section', 'Create Database Tables'); - } - /** - * Return a view that shows some of the key settings. - * - * @author [A. Gianotto] [] - * @since [v1.0] - * @return View - */ + * Return a view that shows some of the key settings. + * + * @author [A. Gianotto] [] + * + * @since [v1.0] + * + * @return View + */ public function index() { - $settings = Setting::all(); + $settings = Setting::getSettings(); + return view('settings/index', compact('settings')); } - /** - * Return the admin settings page - * - * @author [A. Gianotto] [] - * @since [v1.0] - * @return View - */ + * Return the admin settings page. + * + * @author [A. Gianotto] [] + * + * @since [v1.0] + * + * @return View + */ public function getEdit() { - $setting = Setting::first(); + $setting = Setting::getSettings(); + return view('settings/general', compact('setting')); } - /** * Return a form to allow a super admin to update settings. * * @author [A. Gianotto] [] + * * @since [v1.0] + * * @return View */ public function getSettings() { - $setting = Setting::first(); + $setting = Setting::getSettings(); + return view('settings/general', compact('setting')); } - /** * Return a form to allow a super admin to update settings. * * @author [A. Gianotto] [] + * * @since [v1.0] + * * @return View */ public function postSettings(Request $request) { - - if (is_null($setting = Setting::first())) { + if (is_null($setting = Setting::getSettings())) { return redirect()->to('admin')->with('error', trans('admin/settings/message.update.error')); } $setting->modellist_displays = ''; - if (($request->has('show_in_model_list')) && (count($request->input('show_in_model_list')) > 0)) - { + if (($request->filled('show_in_model_list')) && (count($request->input('show_in_model_list')) > 0)) { $setting->modellist_displays = implode(',', $request->input('show_in_model_list')); } - $setting->full_multiple_companies_support = $request->input('full_multiple_companies_support', '0'); - $setting->load_remote = $request->input('load_remote', '0'); - $setting->unique_serial = $request->input('unique_serial', '0'); - $setting->show_images_in_email = $request->input('show_images_in_email', '0'); - $setting->show_archived_in_list = $request->input('show_archived_in_list', '0'); - $setting->dashboard_message = $request->input('dashboard_message'); - $setting->email_domain = $request->input('email_domain'); - $setting->email_format = $request->input('email_format'); - $setting->username_format = $request->input('username_format'); - $setting->require_accept_signature = $request->input('require_accept_signature'); - if (!config('app.lock_passwords')) { + $setting->unique_serial = $request->input('unique_serial', '0'); + $setting->show_images_in_email = $request->input('show_images_in_email', '0'); + $setting->show_archived_in_list = $request->input('show_archived_in_list', '0'); + $setting->dashboard_message = $request->input('dashboard_message'); + $setting->email_domain = $request->input('email_domain'); + $setting->email_format = $request->input('email_format'); + $setting->username_format = $request->input('username_format'); + $setting->require_accept_signature = $request->input('require_accept_signature'); + if (! config('app.lock_passwords')) { $setting->login_note = $request->input('login_note'); } - $setting->default_eula_text = $request->input('default_eula_text'); - $setting->thumbnail_max_h = $request->input('thumbnail_max_h'); + $setting->default_eula_text = $request->input('default_eula_text'); + $setting->thumbnail_max_h = $request->input('thumbnail_max_h'); $setting->privacy_policy_link = $request->input('privacy_policy_link'); - if (Input::get('per_page')!='') { + $setting->depreciation_method = $request->input('depreciation_method'); + + if ('' != Input::get('per_page')) { $setting->per_page = $request->input('per_page'); } else { $setting->per_page = 200; @@ -360,80 +354,146 @@ class SettingsController extends Controller return redirect()->route('settings.index') ->with('success', trans('admin/settings/message.update.success')); } + return redirect()->back()->withInput()->withErrors($setting->getErrors()); - } - - /** * Return a form to allow a super admin to update settings. * * @author [A. Gianotto] [] + * * @since [v1.0] + * * @return View */ public function getBranding() { - $setting = Setting::first(); + $setting = Setting::getSettings(); + return view('settings.branding', compact('setting')); } - /** * Return a form to allow a super admin to update settings. * * @author [A. Gianotto] [] + * * @since [v1.0] + * * @return View */ public function postBranding(ImageUploadRequest $request) { - - if (is_null($setting = Setting::first())) { + if (is_null($setting = Setting::getSettings())) { return redirect()->to('admin')->with('error', trans('admin/settings/message.update.error')); } - $setting->brand = $request->input('brand', '1'); - $setting->header_color = $request->input('header_color'); - $setting->support_footer = $request->input('support_footer'); - $setting->version_footer = $request->input('version_footer'); - $setting->footer_text = $request->input('footer_text'); - $setting->skin = $request->input('skin'); + $setting->brand = $request->input('brand', '1'); + $setting->header_color = $request->input('header_color'); + $setting->support_footer = $request->input('support_footer'); + $setting->version_footer = $request->input('version_footer'); + $setting->footer_text = $request->input('footer_text'); + $setting->skin = $request->input('skin'); $setting->show_url_in_emails = $request->input('show_url_in_emails', '0'); - $setting->logo_print_assets = $request->input('logo_print_assets', '0'); - - + $setting->logo_print_assets = $request->input('logo_print_assets', '0'); // Only allow the site name and CSS to be changed if lock_passwords is false // Because public demos make people act like dicks - if (!config('app.lock_passwords')) { - $setting->site_name = $request->input('site_name'); + if (! config('app.lock_passwords')) { + $setting->site_name = $request->input('site_name'); $setting->custom_css = $request->input('custom_css'); } - // If the user wants to clear the logo, reset the brand type - if ($request->input('clear_logo')=='1') { - $setting->logo = null; + if ('1' == $request->input('clear_logo')) { + Storage::disk('public')->delete($setting->logo); + $setting->logo = null; $setting->brand = 1; // If they are uploading an image, validate it and upload it } elseif ($request->hasFile('image')) { + $image = $request->file('image'); + $ext = $image->getClientOriginalExtension(); + $setting->logo = $file_name = 'logo.' . $ext; - if (!config('app.lock_passwords')) { - $image = $request->file('image'); - $file_name = "logo.".$image->getClientOriginalExtension(); - $path = public_path('uploads'); - if ($image->getClientOriginalExtension()!='svg') { - Image::make($image->getRealPath())->resize(null, 150, function ($constraint) { - $constraint->aspectRatio(); - $constraint->upsize(); - })->save($path.'/'.$file_name); - } else { - $image->move($path, $file_name); - } - $setting->logo = $file_name; + if ('svg' != $image->getClientOriginalExtension()) { + $upload = Image::make($image->getRealPath())->resize(null, 150, function($constraint) { + $constraint->aspectRatio(); + $constraint->upsize(); + }); + } + + // This requires a string instead of an object, so we use ($string) + Storage::disk('public')->put($file_name, (string) $upload->encode()); + + // Remove Current image if exists + if (($setting->logo) && (file_exists($file_name))) { + Storage::disk('public')->delete($file_name); + } + } + + // If the user wants to clear the email logo... + if ('1' == $request->input('clear_email_logo')) { + Storage::disk('public')->delete($setting->email_logo); + $setting->email_logo = null; + + // If they are uploading an image, validate it and upload it + } elseif ($request->hasFile('email_logo')) { + $email_image = $email_upload = $request->file('email_logo'); + $email_ext = $email_image->getClientOriginalExtension(); + $setting->email_logo = $email_file_name = 'email_logo.' . $email_ext; + + if ('svg' != $email_image->getClientOriginalExtension()) { + $email_upload = Image::make($email_image->getRealPath())->resize(null, 100, function($constraint) { + $constraint->aspectRatio(); + $constraint->upsize(); + }); + } + + // This requires a string instead of an object, so we use ($string) + Storage::disk('public')->put($email_file_name, (string) $email_upload->encode()); + + // Remove Current image if exists + if (($setting->email_logo) && (file_exists($email_file_name))) { + Storage::disk('public')->delete($email_file_name); + } + } + + + // If the user wants to clear the favicon... + if ('1' == $request->input('clear_favicon')) { + Storage::disk('public')->delete($setting->clear_favicon); + $setting->favicon = null; + + // If they are uploading an image, validate it and upload it + } elseif ($request->hasFile('favicon')) { + + $favicon_image = $favicon_upload = $request->file('favicon'); + $favicon_ext = $favicon_image->getClientOriginalExtension(); + $setting->favicon = $favicon_file_name = 'favicon-uploaded.' . $favicon_ext; + + if (('ico' != $favicon_image->getClientOriginalExtension()) && ('svg' != $favicon_image->getClientOriginalExtension())) { + $favicon_upload = Image::make($favicon_image->getRealPath())->resize(null, 36, function($constraint) { + $constraint->aspectRatio(); + $constraint->upsize(); + }); + + // This requires a string instead of an object, so we use ($string) + Storage::disk('public')->put($favicon_file_name, (string) $favicon_upload->encode()); + } else { + Storage::disk('public')->put($favicon_file_name, file_get_contents($request->file('favicon'))); + } + + + + + + + + // Remove Current image if exists + if (($setting->favicon) && (file_exists($favicon_file_name))) { + Storage::disk('public')->delete($favicon_file_name); } } @@ -441,107 +501,105 @@ class SettingsController extends Controller return redirect()->route('settings.index') ->with('success', trans('admin/settings/message.update.success')); } + return redirect()->back()->withInput()->withErrors($setting->getErrors()); - } - - /** * Return a form to allow a super admin to update settings. * * @author [A. Gianotto] [] + * * @since [v1.0] + * * @return View */ public function getSecurity() { - $setting = Setting::first(); + $setting = Setting::getSettings(); + return view('settings.security', compact('setting')); } - /** * Return a form to allow a super admin to update settings. * * @author [A. Gianotto] [] + * * @since [v1.0] + * * @return View */ public function postSecurity(Request $request) { - - if (is_null($setting = Setting::first())) { + if (is_null($setting = Setting::getSettings())) { return redirect()->to('admin')->with('error', trans('admin/settings/message.update.error')); } - - if (!config('app.lock_passwords')) { - - if ($request->input('two_factor_enabled')=='') { + if (! config('app.lock_passwords')) { + if ('' == $request->input('two_factor_enabled')) { $setting->two_factor_enabled = null; } else { $setting->two_factor_enabled = $request->input('two_factor_enabled'); } - # remote user login - $setting->login_remote_user_enabled = (int)$request->input('login_remote_user_enabled'); - $setting->login_common_disabled = (int)$request->input('login_common_disabled'); + // remote user login + $setting->login_remote_user_enabled = (int) $request->input('login_remote_user_enabled'); + $setting->login_common_disabled = (int) $request->input('login_common_disabled'); $setting->login_remote_user_custom_logout_url = $request->input('login_remote_user_custom_logout_url'); } - $setting->pwd_secure_uncommon = (int) $request->input('pwd_secure_uncommon'); - $setting->pwd_secure_min = (int) $request->input('pwd_secure_min'); + $setting->pwd_secure_uncommon = (int) $request->input('pwd_secure_uncommon'); + $setting->pwd_secure_min = (int) $request->input('pwd_secure_min'); $setting->pwd_secure_complexity = ''; - - if ($request->has('pwd_secure_complexity')) { - $setting->pwd_secure_complexity = implode('|', $request->input('pwd_secure_complexity')); + if ($request->filled('pwd_secure_complexity')) { + $setting->pwd_secure_complexity = implode('|', $request->input('pwd_secure_complexity')); } - - if ($setting->save()) { return redirect()->route('settings.index') ->with('success', trans('admin/settings/message.update.success')); } + return redirect()->back()->withInput()->withErrors($setting->getErrors()); - } - /** * Return a form to allow a super admin to update settings. * * @author [A. Gianotto] [] + * * @since [v1.0] + * * @return View */ public function getLocalization() { - $setting = Setting::first(); + $setting = Setting::getSettings(); + return view('settings.localization', compact('setting')); } - /** * Return a form to allow a super admin to update settings. * * @author [A. Gianotto] [] + * * @since [v1.0] + * * @return View */ public function postLocalization(Request $request) { - - if (is_null($setting = Setting::first())) { + if (is_null($setting = Setting::getSettings())) { return redirect()->to('admin')->with('error', trans('admin/settings/message.update.error')); } - if (!config('app.lock_passwords')) { + if (! config('app.lock_passwords')) { $setting->locale = $request->input('locale', 'en'); } - $setting->default_currency = $request->input('default_currency', '$'); + $setting->default_currency = $request->input('default_currency', '$'); $setting->date_display_format = $request->input('date_display_format'); $setting->time_display_format = $request->input('time_display_format'); @@ -549,276 +607,284 @@ class SettingsController extends Controller return redirect()->route('settings.index') ->with('success', trans('admin/settings/message.update.success')); } + return redirect()->back()->withInput()->withErrors($setting->getErrors()); - } - /** * Return a form to allow a super admin to update settings. * * @author [A. Gianotto] [] + * * @since [v1.0] + * * @return View */ public function getAlerts() { - $setting = Setting::first(); + $setting = Setting::getSettings(); + return view('settings.alerts', compact('setting')); } - /** * Return a form to allow a super admin to update settings. * * @author [A. Gianotto] [] + * * @since [v1.0] + * * @return View */ public function postAlerts(Request $request) { - - if (is_null($setting = Setting::first())) { + if (is_null($setting = Setting::getSettings())) { return redirect()->to('admin')->with('error', trans('admin/settings/message.update.error')); } - $alert_email = rtrim($request->input('alert_email'), ','); - $alert_email = trim($alert_email); + $alert_email = rtrim($request->input('alert_email'), ','); + $alert_email = trim($alert_email); $admin_cc_email = rtrim($request->input('admin_cc_email'), ','); $admin_cc_email = trim($admin_cc_email); - $setting->alert_email = $alert_email; - $setting->admin_cc_email = $admin_cc_email; - $setting->alerts_enabled = $request->input('alerts_enabled', '0'); - $setting->alert_interval = $request->input('alert_interval'); - $setting->alert_threshold = $request->input('alert_threshold'); - $setting->audit_interval = $request->input('audit_interval'); - $setting->audit_warning_days = $request->input('audit_warning_days'); + $setting->alert_email = $alert_email; + $setting->admin_cc_email = $admin_cc_email; + $setting->alerts_enabled = $request->input('alerts_enabled', '0'); + $setting->alert_interval = $request->input('alert_interval'); + $setting->alert_threshold = $request->input('alert_threshold'); + $setting->audit_interval = $request->input('audit_interval'); + $setting->audit_warning_days = $request->input('audit_warning_days'); $setting->show_alerts_in_menu = $request->input('show_alerts_in_menu', '0'); if ($setting->save()) { return redirect()->route('settings.index') ->with('success', trans('admin/settings/message.update.success')); } + return redirect()->back()->withInput()->withErrors($setting->getErrors()); - } - /** * Return a form to allow a super admin to update settings. * * @author [A. Gianotto] [] + * * @since [v1.0] + * * @return View */ public function getSlack() { - $setting = Setting::first(); + $setting = Setting::getSettings(); + return view('settings.slack', compact('setting')); } - /** * Return a form to allow a super admin to update settings. * * @author [A. Gianotto] [] + * * @since [v1.0] + * * @return View */ public function postSlack(Request $request) { - - if (is_null($setting = Setting::first())) { + if (is_null($setting = Setting::getSettings())) { return redirect()->to('admin')->with('error', trans('admin/settings/message.update.error')); } $setting->slack_endpoint = $request->input('slack_endpoint'); - $setting->slack_channel = $request->input('slack_channel'); - $setting->slack_botname = $request->input('slack_botname'); + $setting->slack_channel = $request->input('slack_channel'); + $setting->slack_botname = $request->input('slack_botname'); if ($setting->save()) { return redirect()->route('settings.index') ->with('success', trans('admin/settings/message.update.success')); } + return redirect()->back()->withInput()->withErrors($setting->getErrors()); - } - /** * Return a form to allow a super admin to update settings. * * @author [A. Gianotto] [] + * * @since [v1.0] + * * @return View */ public function getAssetTags() { - $setting = Setting::first(); + $setting = Setting::getSettings(); + return view('settings.asset_tags', compact('setting')); } - /** - * Saves settings from form + * Saves settings from form. * * @author [A. Gianotto] [] + * * @since [v1.0] + * * @return View */ public function postAssetTags(Request $request) { - - if (is_null($setting = Setting::first())) { + if (is_null($setting = Setting::getSettings())) { return redirect()->to('admin')->with('error', trans('admin/settings/message.update.error')); } $setting->auto_increment_prefix = $request->input('auto_increment_prefix'); $setting->auto_increment_assets = $request->input('auto_increment_assets', '0'); - $setting->zerofill_count = $request->input('zerofill_count'); - $setting->next_auto_tag_base = $request->input('next_auto_tag_base'); + $setting->zerofill_count = $request->input('zerofill_count'); + $setting->next_auto_tag_base = $request->input('next_auto_tag_base'); if ($setting->save()) { return redirect()->route('settings.index') ->with('success', trans('admin/settings/message.update.success')); } + return redirect()->back()->withInput()->withErrors($setting->getErrors()); - } - /** * Return a form to allow a super admin to update settings. * * @author [A. Gianotto] [] + * * @since [v1.0] + * * @return View */ public function getBarcodes() { - $setting = Setting::first(); + $setting = Setting::getSettings(); $is_gd_installed = extension_loaded('gd'); - return view('settings.barcodes', compact('setting'))->with('is_gd_installed',$is_gd_installed); + return view('settings.barcodes', compact('setting'))->with('is_gd_installed', $is_gd_installed); } - /** - * Saves settings from form + * Saves settings from form. * * @author [A. Gianotto] [] + * * @since [v1.0] + * * @return View */ public function postBarcodes(Request $request) { - - if (is_null($setting = Setting::first())) { + if (is_null($setting = Setting::getSettings())) { return redirect()->to('admin')->with('error', trans('admin/settings/message.update.error')); } - $setting->qr_code = $request->input('qr_code', '0'); - $setting->alt_barcode = $request->input('alt_barcode'); + $setting->qr_code = $request->input('qr_code', '0'); + $setting->alt_barcode = $request->input('alt_barcode'); $setting->alt_barcode_enabled = $request->input('alt_barcode_enabled', '0'); - $setting->barcode_type = $request->input('barcode_type'); - $setting->qr_text = $request->input('qr_text'); - + $setting->barcode_type = $request->input('barcode_type'); + $setting->qr_text = $request->input('qr_text'); if ($setting->save()) { return redirect()->route('settings.index') ->with('success', trans('admin/settings/message.update.success')); } + return redirect()->back()->withInput()->withErrors($setting->getErrors()); - } - /** * Return a form to allow a super admin to update settings. * * @author [A. Gianotto] [] + * * @since [v4.0] + * * @return View */ public function getPhpInfo() { - if (config('app.debug')=== true) { + if (true === config('app.debug')) { return view('settings.phpinfo'); } + return redirect()->route('settings.index') ->with('error', 'PHP syetem debugging information is only available when debug is enabled in your .env file.'); } - /** * Return a form to allow a super admin to update settings. * * @author [A. Gianotto] [] + * * @since [v4.0] + * * @return View */ public function getLabels() { - $setting = Setting::first(); + $setting = Setting::getSettings(); + return view('settings.labels', compact('setting')); } - /** - * Saves settings from form + * Saves settings from form. * * @author [A. Gianotto] [] + * * @since [v4.0] + * * @return View */ public function postLabels(Request $request) { - - if (is_null($setting = Setting::first())) { + if (is_null($setting = Setting::getSettings())) { return redirect()->to('admin')->with('error', trans('admin/settings/message.update.error')); } - $setting->labels_per_page = $request->input('labels_per_page'); - $setting->labels_width = $request->input('labels_width'); - $setting->labels_height = $request->input('labels_height'); - $setting->labels_pmargin_left = $request->input('labels_pmargin_left'); - $setting->labels_pmargin_right = $request->input('labels_pmargin_right'); - $setting->labels_pmargin_top = $request->input('labels_pmargin_top'); - $setting->labels_pmargin_bottom = $request->input('labels_pmargin_bottom'); - $setting->labels_display_bgutter = $request->input('labels_display_bgutter'); - $setting->labels_display_sgutter = $request->input('labels_display_sgutter'); - $setting->labels_fontsize = $request->input('labels_fontsize'); - $setting->labels_pagewidth = $request->input('labels_pagewidth'); - $setting->labels_pageheight = $request->input('labels_pageheight'); + $setting->labels_per_page = $request->input('labels_per_page'); + $setting->labels_width = $request->input('labels_width'); + $setting->labels_height = $request->input('labels_height'); + $setting->labels_pmargin_left = $request->input('labels_pmargin_left'); + $setting->labels_pmargin_right = $request->input('labels_pmargin_right'); + $setting->labels_pmargin_top = $request->input('labels_pmargin_top'); + $setting->labels_pmargin_bottom = $request->input('labels_pmargin_bottom'); + $setting->labels_display_bgutter = $request->input('labels_display_bgutter'); + $setting->labels_display_sgutter = $request->input('labels_display_sgutter'); + $setting->labels_fontsize = $request->input('labels_fontsize'); + $setting->labels_pagewidth = $request->input('labels_pagewidth'); + $setting->labels_pageheight = $request->input('labels_pageheight'); $setting->labels_display_company_name = $request->input('labels_display_company_name', '0'); - - - if ($request->has('labels_display_name')) { + if ($request->filled('labels_display_name')) { $setting->labels_display_name = 1; } else { $setting->labels_display_name = 0; } - if ($request->has('labels_display_serial')) { + if ($request->filled('labels_display_serial')) { $setting->labels_display_serial = 1; } else { $setting->labels_display_serial = 0; } - if ($request->has('labels_display_tag')) { + if ($request->filled('labels_display_tag')) { $setting->labels_display_tag = 1; } else { $setting->labels_display_tag = 0; - } + } - if ($request->has('labels_display_tag')) { - $setting->labels_display_tag = 1; - } else { - $setting->labels_display_tag = 0; - } + if ($request->filled('labels_display_tag')) { + $setting->labels_display_tag = 1; + } else { + $setting->labels_display_tag = 0; + } - if ($request->has('labels_display_model')) { + if ($request->filled('labels_display_model')) { $setting->labels_display_model = 1; } else { $setting->labels_display_model = 0; @@ -828,167 +894,151 @@ class SettingsController extends Controller return redirect()->route('settings.index') ->with('success', trans('admin/settings/message.update.success')); } + return redirect()->back()->withInput()->withErrors($setting->getErrors()); - } - /** * Return a form to allow a super admin to update settings. * * @author [A. Gianotto] [] + * * @since [v4.0] + * * @return View */ public function getLdapSettings() { - $setting = Setting::first(); + $setting = Setting::getSettings(); + return view('settings.ldap', compact('setting')); } - /** - * Saves settings from form + * Saves settings from form. * * @author [A. Gianotto] [] + * * @since [v4.0] + * * @return View */ public function postLdapSettings(Request $request) { - - if (is_null($setting = Setting::first())) { + if (is_null($setting = Setting::getSettings())) { return redirect()->to('admin')->with('error', trans('admin/settings/message.update.error')); } - $setting->ldap_enabled = $request->input('ldap_enabled', '0'); - $setting->ldap_server = $request->input('ldap_server'); + $setting->ldap_enabled = $request->input('ldap_enabled', '0'); + $setting->ldap_server = $request->input('ldap_server'); $setting->ldap_server_cert_ignore = $request->input('ldap_server_cert_ignore', false); - $setting->ldap_uname = $request->input('ldap_uname'); - if (Input::has('ldap_pword')) { + $setting->ldap_uname = $request->input('ldap_uname'); + if ($request->input('ldap_pword') !== '') { $setting->ldap_pword = Crypt::encrypt($request->input('ldap_pword')); } - $setting->ldap_basedn = $request->input('ldap_basedn'); - $setting->ldap_filter = $request->input('ldap_filter'); - $setting->ldap_username_field = $request->input('ldap_username_field'); - $setting->ldap_lname_field = $request->input('ldap_lname_field'); - $setting->ldap_fname_field = $request->input('ldap_fname_field'); + $setting->ldap_basedn = $request->input('ldap_basedn'); + $setting->ldap_filter = $request->input('ldap_filter'); + $setting->ldap_username_field = $request->input('ldap_username_field'); + $setting->ldap_lname_field = $request->input('ldap_lname_field'); + $setting->ldap_fname_field = $request->input('ldap_fname_field'); $setting->ldap_auth_filter_query = $request->input('ldap_auth_filter_query'); - $setting->ldap_version = $request->input('ldap_version'); - $setting->ldap_active_flag = $request->input('ldap_active_flag'); - $setting->ldap_emp_num = $request->input('ldap_emp_num'); - $setting->ldap_email = $request->input('ldap_email'); - $setting->ad_domain = $request->input('ad_domain'); - $setting->is_ad = $request->input('is_ad', '0'); - $setting->ldap_tls = $request->input('ldap_tls', '0'); - $setting->ldap_pw_sync = $request->input('ldap_pw_sync', '0'); + $setting->ldap_version = $request->input('ldap_version'); + $setting->ldap_active_flag = $request->input('ldap_active_flag'); + $setting->ldap_emp_num = $request->input('ldap_emp_num'); + $setting->ldap_email = $request->input('ldap_email'); + $setting->ad_domain = $request->input('ad_domain'); + $setting->is_ad = $request->input('is_ad', '0'); + $setting->ldap_tls = $request->input('ldap_tls', '0'); + $setting->ldap_pw_sync = $request->input('ldap_pw_sync', '0'); $setting->custom_forgot_pass_url = $request->input('custom_forgot_pass_url'); if ($setting->save()) { - return redirect()->route('settings.index') + return redirect()->route('settings.ldap.index') ->with('success', trans('admin/settings/message.update.success')); } - return redirect()->back()->withInput()->withErrors($setting->getErrors()); + return redirect()->back()->withInput()->withErrors($setting->getErrors()); } - - - - - /** - * Show the listing of backups - * - * @author [A. Gianotto] [] - * @since [v1.8] - * @return View - */ + * Show the listing of backups. + * + * @author [A. Gianotto] [] + * + * @since [v1.8] + * + * @return View + */ public function getBackups() { + $path = storage_path() . '/app/' . config('backup.backup.name'); - $path = storage_path().'/app/'.config('laravel-backup.backup.name'); - - $files = array(); - - if ($handle = opendir($path)) { - - /* This is the correct way to loop over the directory. */ - while (false !== ($entry = readdir($handle))) { - clearstatcache(); - if (substr(strrchr($entry, '.'), 1)=='zip') { - $files[] = array( - 'filename' => $entry, - 'filesize' => Setting::fileSizeConvert(filesize($path.'/'.$entry)), - 'modified' => filemtime($path.'/'.$entry) - ); - } + $path = 'backups'; + $backup_files = Storage::files($path); + $files = []; + if (count($backup_files) > 0) { + for ($f = 0; $f < count($backup_files); ++$f) { + $files[] = [ + 'filename' => basename($backup_files[$f]), + 'filesize' => Setting::fileSizeConvert(Storage::size($backup_files[$f])), + 'modified' => Storage::lastModified($backup_files[$f]), + ]; } - closedir($handle); - rsort($files); } - return view('settings/backups', compact('path', 'files')); } - /** - * Process the backup. - * - * @author [A. Gianotto] [] - * @since [v1.8] - * @return Redirect - */ - + * Process the backup. + * + * @author [A. Gianotto] [] + * + * @since [v1.8] + * + * @return Redirect + */ public function postBackups() { - - if (!config('app.lock_passwords')) { + if (! config('app.lock_passwords')) { Artisan::call('backup:run'); $output = Artisan::output(); // Backup completed - if (!preg_match('/failed/', $output)) { + if (! preg_match('/failed/', $output)) { return redirect()->route('settings.backups.index') ->with('success', trans('admin/settings/message.backup.generated')); } - $formatted_output = str_replace('Backup completed!', '', $output); - $output_split = explode('...', $formatted_output); + $output_split = explode('...', $formatted_output); if (array_key_exists(2, $output_split)) { - return redirect()->route("settings.backups.index")->with('error', $output_split[2]); + return redirect()->route('settings.backups.index')->with('error', $output_split[2]); } - return redirect()->route("settings.backups.index")->with('error', $formatted_output); - - } - return redirect()->route("settings.backups.index")->with('error', trans('general.feature_disabled')); - - + return redirect()->route('settings.backups.index')->with('error', $formatted_output); + } + return redirect()->route('settings.backups.index')->with('error', trans('general.feature_disabled')); } - /** - * Download the backup file - * - * @author [A. Gianotto] [] - * @since [v1.8] - * @return Redirect - */ + * Download the backup file. + * + * @author [A. Gianotto] [] + * + * @since [v1.8] + * + * @return Redirect + */ public function downloadFile($filename = null) { - if (!config('app.lock_passwords')) { - $path = storage_path().'/app/'.config('laravel-backup.backup.name'); - $file = $path.'/'.$filename; - if (file_exists($file)) { - return Response::download($file); + if (! config('app.lock_passwords')) { + if (Storage::exists($filename)) { + return Response::download(Storage::url('') . e($filename)); } else { - // Redirect to the backup page return redirect()->route('settings.backups.index')->with('error', trans('admin/settings/message.backup.file_not_found')); } @@ -996,42 +1046,45 @@ class SettingsController extends Controller // Redirect to the backup page return redirect()->route('settings.backups.index')->with('error', trans('general.feature_disabled')); } - - } /** - * Delete the backup file - * - * @author [A. Gianotto] [] - * @since [v1.8] - * @return View - */ + * Delete the backup file. + * + * @author [A. Gianotto] [] + * + * @since [v1.8] + * + * @return View + */ public function deleteFile($filename = null) { + if (! config('app.lock_passwords')) { + $path = 'backups'; - if (!config('app.lock_passwords')) { + if (Storage::exists($path . '/' . $filename)) { + try { + Storage::delete($path . '/' . $filename); - $path = storage_path().'/app/'.config('laravel-backup.backup.name'); - $file = $path.'/'.$filename; - if (file_exists($file)) { - unlink($file); - return redirect()->route('settings.backups.index')->with('success', trans('admin/settings/message.backup.file_deleted')); + return redirect()->route('settings.backups.index')->with('success', trans('admin/settings/message.backup.file_deleted')); + } catch (\Exception $e) { + \Log::debug($e); + } } else { return redirect()->route('settings.backups.index')->with('error', trans('admin/settings/message.backup.file_not_found')); } } else { return redirect()->route('settings.backups.index')->with('error', trans('general.feature_disabled')); } - } - /** * Return a form to allow a super admin to update settings. * * @author [A. Gianotto] [] + * * @since [v4.0] + * * @return View */ public function getPurge() @@ -1040,26 +1093,28 @@ class SettingsController extends Controller } /** - * Purges soft-deletes - * - * @author [A. Gianotto] [] - * @since [v3.0] - * @return View - */ + * Purges soft-deletes. + * + * @author [A. Gianotto] [] + * + * @since [v3.0] + * + * @return View + */ public function postPurge() { - if (!config('app.lock_passwords')) { - if (Input::get('confirm_purge')=='DELETE') { + if (! config('app.lock_passwords')) { + if ('DELETE' == Input::get('confirm_purge')) { // Run a backup immediately before processing Artisan::call('backup:run'); - Artisan::call('snipeit:purge', ['--force'=>'true','--no-interaction'=>true]); + Artisan::call('snipeit:purge', ['--force' => 'true', '--no-interaction' => true]); $output = Artisan::output(); + return view('settings/purge') ->with('output', $output)->with('success', trans('admin/settings/message.purge.success')); } else { return redirect()->back()->with('error', trans('admin/settings/message.purge.validation_failed')); } - } else { return redirect()->back()->with('error', trans('general.feature_disabled')); } @@ -1072,34 +1127,41 @@ class SettingsController extends Controller * in the routes file if you want to be able to cache the routes. * * @author [A. Gianotto] [] + * * @since [v4.0] + * * @return View */ - public function api() { + public function api() + { return view('settings.api'); } - - /** - * Test the email configuration + * Test the email configuration. * * @author [A. Gianotto] [] + * * @since [v3.0] + * * @return Redirect */ public function ajaxTestEmail() { try { - Mail::send('emails.test', [], function ($m) { - $m->to(config('mail.from.address'), config('mail.from.name')); - $m->replyTo(config('mail.reply_to.address'), config('mail.reply_to.name')); - $m->subject(trans('mail.test_email')); - }); + (new User())->forceFill([ + 'name' => config('mail.from.name'), + 'email' => config('mail.from.address'), + ])->notify(new MailTest()); + return response()->json(Helper::formatStandardApiResponse('success', null, 'Maiol sent!')); } catch (Exception $e) { return response()->json(Helper::formatStandardApiResponse('success', null, $e->getMessage())); } + } + public function getLoginAttempts() + { + return view('settings.logins'); } } diff --git a/app/Http/Controllers/StatuslabelsController.php b/app/Http/Controllers/StatuslabelsController.php index cb096ea35d..7908d8865b 100755 --- a/app/Http/Controllers/StatuslabelsController.php +++ b/app/Http/Controllers/StatuslabelsController.php @@ -1,21 +1,12 @@ with('statuslabel', $statuslabel); } - return redirect()->route('statuslabels.index')->with('error', trans('admin/statuslabels/message.does_not_exist', compact('id'))); + return redirect()->route('statuslabels.index')->with('error', trans('admin/statuslabels/message.does_not_exist')); } - /** * Statuslabel create. * * @return \Illuminate\Contracts\View\View + * @throws \Illuminate\Auth\Access\AuthorizationException */ public function create() { // Show the page $this->authorize('create', Statuslabel::class); - $item = new Statuslabel; - $use_statuslabel_type = $item->getStatuslabelType(); - $statuslabel_types = Helper::statusTypeList(); - return view('statuslabels/edit', compact('statuslabel_types', 'item'))->with('use_statuslabel_type', $use_statuslabel_type); + return view('statuslabels/edit') + ->with('item', new Statuslabel) + ->with('statuslabel_types', Helper::statusTypeList()) + ->with('use_statuslabel_type', (new Statuslabel)->getStatuslabelType()); } @@ -70,6 +62,7 @@ class StatuslabelsController extends Controller * * @param Request $request * @return \Illuminate\Http\RedirectResponse + * @throws \Illuminate\Auth\Access\AuthorizationException */ public function store(Request $request) { @@ -78,7 +71,7 @@ class StatuslabelsController extends Controller // create a new model instance $statusLabel = new Statuslabel(); - if (!$request->has('statuslabel_types')) { + if (!$request->filled('statuslabel_types')) { return redirect()->back()->withInput()->withErrors(['statuslabel_types' => trans('validation.statuslabel_type')]); } @@ -106,8 +99,9 @@ class StatuslabelsController extends Controller /** * Statuslabel update. * - * @param int $statuslabelId + * @param int $statuslabelId * @return \Illuminate\Contracts\View\View + * @throws \Illuminate\Auth\Access\AuthorizationException */ public function edit($statuslabelId = null) { @@ -129,8 +123,9 @@ class StatuslabelsController extends Controller /** * Statuslabel update form processing page. * - * @param int $statuslabelId + * @param int $statuslabelId * @return \Illuminate\Http\RedirectResponse + * @throws \Illuminate\Auth\Access\AuthorizationException */ public function update(Request $request, $statuslabelId = null) { @@ -141,7 +136,7 @@ class StatuslabelsController extends Controller return redirect()->route('statuslabels.index')->with('error', trans('admin/statuslabels/message.does_not_exist')); } - if (!$request->has('statuslabel_types')) { + if (!$request->filled('statuslabel_types')) { return redirect()->back()->withInput()->withErrors(['statuslabel_types' => trans('validation.statuslabel_type')]); } @@ -169,8 +164,9 @@ class StatuslabelsController extends Controller /** * Delete the given Statuslabel. * - * @param int $statuslabelId + * @param int $statuslabelId * @return \Illuminate\Http\RedirectResponse + * @throws \Illuminate\Auth\Access\AuthorizationException */ public function destroy($statuslabelId) { diff --git a/app/Http/Controllers/SuppliersController.php b/app/Http/Controllers/SuppliersController.php index 7666ebff4f..89d53772c0 100755 --- a/app/Http/Controllers/SuppliersController.php +++ b/app/Http/Controllers/SuppliersController.php @@ -1,21 +1,12 @@ url = $supplier->addhttp(request('url')); $supplier->user_id = Auth::id(); - if ($request->file('image')) { - $image = $request->file('image'); - $file_name = str_random(25).".".$image->getClientOriginalExtension(); - $path = public_path('uploads/suppliers/'.$file_name); - Image::make($image->getRealPath())->resize(200, null, function ($constraint) { - $constraint->aspectRatio(); - $constraint->upsize(); - })->save($path); - $supplier->image = $file_name; - } + $supplier = $request->handleImages($supplier); if ($supplier->save()) { return redirect()->route('suppliers.index')->with('success', trans('admin/suppliers/message.create.success')); @@ -99,8 +84,9 @@ class SuppliersController extends Controller /** * Supplier update. * - * @param int $supplierId + * @param int $supplierId * @return \Illuminate\Contracts\View\View + * @throws \Illuminate\Auth\Access\AuthorizationException */ public function edit($supplierId = null) { @@ -119,8 +105,9 @@ class SuppliersController extends Controller /** * Supplier update form processing page. * - * @param int $supplierId + * @param int $supplierId * @return \Illuminate\Http\RedirectResponse + * @throws \Illuminate\Auth\Access\AuthorizationException */ public function update($supplierId = null, ImageUploadRequest $request) { @@ -146,37 +133,7 @@ class SuppliersController extends Controller $supplier->url = $supplier->addhttp(request('url')); $supplier->notes = request('notes'); - - $old_image = $supplier->image; - - // Set the model's image property to null if the image is being deleted - if ($request->input('image_delete') == 1) { - $supplier->image = null; - } - - if ($request->file('image')) { - $image = $request->file('image'); - $file_name = $supplier->id.'-'.str_slug($image->getClientOriginalName()) . "." . $image->getClientOriginalExtension(); - - if ($image->getClientOriginalExtension()!='svg') { - Image::make($image->getRealPath())->resize(500, null, function ($constraint) { - $constraint->aspectRatio(); - $constraint->upsize(); - })->save(app('suppliers_upload_path').$file_name); - } else { - $image->move(app('suppliers_upload_path'), $file_name); - } - $supplier->image = $file_name; - - } - - if ((($request->file('image')) && (isset($old_image)) && ($old_image!='')) || ($request->input('image_delete') == 1)) { - try { - unlink(app('suppliers_upload_path').$old_image); - } catch (\Exception $e) { - \Log::error($e); - } - } + $supplier = $request->handleImages($supplier); if ($supplier->save()) { @@ -190,13 +147,14 @@ class SuppliersController extends Controller /** * Delete the given supplier. * - * @param int $supplierId + * @param int $supplierId * @return \Illuminate\Http\RedirectResponse + * @throws \Illuminate\Auth\Access\AuthorizationException */ public function destroy($supplierId) { $this->authorize('delete', Supplier::class); - if (is_null($supplier = Supplier::with('asset_maintenances', 'assets', 'licenses')->withCount('asset_maintenances','assets','licenses')->find($supplierId))) { + if (is_null($supplier = Supplier::with('asset_maintenances', 'assets', 'licenses')->withCount('asset_maintenances as asset_maintenances_count','assets as assets_count','licenses as licenses_count')->find($supplierId))) { return redirect()->route('suppliers.index')->with('error', trans('admin/suppliers/message.not_found')); } @@ -236,11 +194,8 @@ class SuppliersController extends Controller if (isset($supplier->id)) { return view('suppliers/view', compact('supplier')); } - // Prepare the error message - $error = trans('admin/suppliers/message.does_not_exist', compact('id')); - // Redirect to the user management page - return redirect()->route('suppliers.index')->with('error', $error); + return redirect()->route('suppliers.index')->with('error', trans('admin/suppliers/message.does_not_exist')); } } diff --git a/app/Http/Controllers/Users/BulkUsersController.php b/app/Http/Controllers/Users/BulkUsersController.php new file mode 100644 index 0000000000..ea150f4b84 --- /dev/null +++ b/app/Http/Controllers/Users/BulkUsersController.php @@ -0,0 +1,229 @@ +] + * @since [v1.7] + * @param Request $request + * @return \Illuminate\Contracts\View\View + * @throws \Illuminate\Auth\Access\AuthorizationException + */ + public function edit(Request $request) + { + $this->authorize('update', User::class); + + // Make sure there were users selected + if (($request->filled('ids')) && (count($request->input('ids')) > 0)) { + + $statuslabel_list = Helper::statusLabelList(); + + // Get the list of affected users + $users = User::whereIn('id', array_keys(request('ids'))) + ->with('groups', 'assets', 'licenses', 'accessories')->get(); + + if ($request->input('bulk_actions') == 'edit') { + return view('users/bulk-edit', compact('users')) + ->with('groups', Group::pluck('name', 'id')); + + } elseif ($request->input('bulk_actions') == 'delete') { + return view('users/confirm-bulk-delete', compact('users', 'statuslabel_list')); + + } elseif ($request->input('bulk_actions') == 'bulkpasswordreset') { + if ($users) { + foreach ($users as $user) { + if (($user->activated=='1') && ($user->email!='')) { + $credentials = ['email' => $user->email]; + Password::sendResetLink($credentials, function (Message $message) { + $message->subject($this->getEmailSubject()); + }); + } + } + } + return redirect()->back()->with('success', trans('admin/users/message.password_resets_sent')); + + } + + } + + return redirect()->back()->with('error', 'No users selected'); + } + + + /** + * Save bulk-edited users + * + * @author [A. Gianotto] [] + * @since [v1.0] + * @param Request $request + * @return \Illuminate\Http\RedirectResponse + * @throws \Illuminate\Auth\Access\AuthorizationException + */ + public function update(Request $request) + { + $this->authorize('update', User::class); + + if((!$request->filled('ids')) || $request->input('ids') <= 0) { + return redirect()->back()->with('error', 'No users selected'); + } + $user_raw_array = $request->input('ids'); + + // Remove the user from any updates. + $user_raw_array = array_diff($user_raw_array, [Auth::id()]); + $manager_conflict = false; + $users = User::whereIn('id', $user_raw_array)->where('id', '!=', Auth::user()->id)->get(); + + $return_array = [ + 'success' => trans('admin/users/message.success.update_bulk') + ]; + + + $this->conditionallyAddItem('location_id') + ->conditionallyAddItem('department_id') + ->conditionallyAddItem('company_id') + ->conditionallyAddItem('locale') + ->conditionallyAddItem('activated') +; + // If the manager_id is one of the users being updated, generate a warning. + if (array_search($request->input('manager_id'), $user_raw_array)) { + $manager_conflict = true; + $return_array = [ + 'warning' => trans('admin/users/message.bulk_manager_warn') + ]; + } + if (!$manager_conflict) { + $this->conditionallyAddItem('manager_id'); + } + + + // Save the updated info + User::whereIn('id', $user_raw_array) + ->where('id', '!=', Auth::id())->update($this->update_array); + + // Only sync groups if groups were selected + if ($request->filled('groups')) { + foreach ($users as $user) { + $user->groups()->sync($request->input('groups')); + } + } + + return redirect()->route('users.index') + ->with($return_array); + } + + /** + * Array to store update data per item + * @var Array + */ + private $update_array = []; + + /** + * Adds parameter to update array for an item if it exists in request + * @param String $field field name + * @return BulkUsersController Model for Chaining + */ + protected function conditionallyAddItem($field) + { + if(request()->filled($field)) { + $this->update_array[$field] = request()->input($field); + } + return $this; + } + + /** + * Soft-delete bulk users + * + * @author [A. Gianotto] [] + * @since [v1.0] + * @param Request $request + * @return \Illuminate\Http\RedirectResponse + * @throws \Illuminate\Auth\Access\AuthorizationException + */ + public function destroy(Request $request) + { + $this->authorize('update', User::class); + + if ((!$request->filled('ids')) || (count($request->input('ids')) == 0)) { + return redirect()->back()->with('error', 'No users selected'); + } + if ((!$request->filled('status_id')) || ($request->input('status_id')=='')) { + return redirect()->route('users.index')->with('error', 'No status selected'); + } + + if (config('app.lock_passwords')) { + return redirect()->route('users.index')->with('error', 'Bulk delete is not enabled in this installation'); + } + $user_raw_array = request('ids'); + + if (($key = array_search(Auth::id(), $user_raw_array)) !== false) { + unset($user_raw_array[$key]); + } + + $users = User::whereIn('id', $user_raw_array)->get(); + $assets = Asset::whereIn('assigned_to', $user_raw_array)->get(); + $accessories = DB::table('accessories_users')->whereIn('assigned_to', $user_raw_array)->get(); + $licenses = DB::table('license_seats')->whereIn('assigned_to', $user_raw_array)->get(); + + + $this->logItemCheckinAndDelete($assets, Asset::class); + $this->logItemCheckinAndDelete($accessories, Accessory::class); + $this->logItemCheckinAndDelete($licenses, LicenseSeat::class); + + Asset::whereIn('id', $assets->pluck('id'))->update([ + 'status_id' => e(request('status_id')), + 'assigned_to' => null, + 'assigned_type' => null, + ]); + + + LicenseSeat::whereIn('id', $licenses->pluck('id'))->update(['assigned_to' => null]); + + foreach ($users as $user) { + $user->accessories()->sync([]); + $user->delete(); + } + + return redirect()->route('users.index')->with('success', 'Your selected users have been deleted and their assets have been updated.'); + } + + /** + * Generate an action log entry for each of a group of items. + * @param $items + * @param $itemType string name of items being passed. + */ + protected function logItemCheckinAndDelete($items, $itemType) { + + foreach($items as $item) { + $logAction = new Actionlog(); + $logAction->item_id = $item->id; + // We can't rely on get_class here because the licenses/accessories fetched above are not eloquent models, but simply arrays. + $logAction->item_type = $itemType; + $logAction->target_id = $item->assigned_to; + $logAction->target_type = User::class; + $logAction->user_id = Auth::id(); + $logAction->note = 'Bulk checkin items and delete user'; + $logAction->logaction('checkin from'); + } + } + + + +} diff --git a/app/Http/Controllers/Users/LDAPImportController.php b/app/Http/Controllers/Users/LDAPImportController.php new file mode 100644 index 0000000000..3abd1d1c0e --- /dev/null +++ b/app/Http/Controllers/Users/LDAPImportController.php @@ -0,0 +1,85 @@ +ldap = $ldap; + $this->ldap->init(); + } + + /** + * Return view for LDAP import. + * + * @author Aladin Alaily + * @author Wes Hulette + * + * @since 5.0.0 + * + * @return \Illuminate\Contracts\View\View + * + * @throws \Illuminate\Auth\Access\AuthorizationException + */ + public function create() + { + $this->authorize('update', User::class); + try { + $this->ldap->testLdapAdUserConnection(); + } catch (\Exception $e) { + return redirect()->route('users.index')->with('error', $e->getMessage()); + } + + return view('users/ldap'); + } + + /** + * LDAP form processing. + * + * @author Aladin Alaily + * @author Wes Hulette + * + * @since 5.0.0 + * + * @return \Illuminate\Http\RedirectResponse + */ + public function store(Request $request) + { + // Call Artisan LDAP import command. + $location_id = $request->input('location_id'); + Artisan::call('snipeit:ldap-sync', ['--location_id' => $location_id, '--json_summary' => true]); + + // Collect and parse JSON summary. + $ldap_results_json = Artisan::output(); + $ldap_results = json_decode($ldap_results_json, true); + + // Direct user to appropriate status page. + if ($ldap_results['error']) { + return redirect()->back()->withInput()->with('error', $ldap_results['error_message']); + } + + return redirect()->route('ldap/user') + ->with('success', 'LDAP Import successful.') + ->with('summary', $ldap_results['summary']); + } +} diff --git a/app/Http/Controllers/Users/UserFilesController.php b/app/Http/Controllers/Users/UserFilesController.php new file mode 100644 index 0000000000..db812e1072 --- /dev/null +++ b/app/Http/Controllers/Users/UserFilesController.php @@ -0,0 +1,130 @@ +] + * @since [v1.6] + * @param AssetFileRequest $request + * @param int $userId + * @return string JSON + * @throws \Illuminate\Auth\Access\AuthorizationException + */ + public function store(AssetFileRequest $request, $userId = null) + { + $user = User::find($userId); + $destinationPath = config('app.private_uploads') . '/users'; + + if (isset($user->id)) { + $this->authorize('update', $user); + + $logActions = []; + $files = $request->file('file'); + foreach($files as $file) { + $extension = $file->getClientOriginalExtension(); + $filename = 'user-' . $user->id . '-' . str_random(8); + $filename .= '-' . str_slug($file->getClientOriginalName()) . '.' . $extension; + if (!$file->move($destinationPath, $filename)) { + return JsonResponse::create(["error" => "Unabled to move file"], 500); + } + //Log the uploaded file to the log + $logAction = new Actionlog(); + $logAction->item_id = $user->id; + $logAction->item_type = User::class; + $logAction->user_id = Auth::id(); + $logAction->note = e(Input::get('notes')); + $logAction->target_id = null; + $logAction->created_at = date("Y-m-d H:i:s"); + $logAction->filename = $filename; + $logAction->action_type = 'uploaded'; + + if (!$logAction->save()) { + return JsonResponse::create(["error" => "Failed validation: " . print_r($logAction->getErrors(), true)], 500); + + } + $logActions[] = $logAction; + } +// dd($logActions); + return JsonResponse::create($logActions); + } + return JsonResponse::create(["error" => "No User associated with this request"], 500); + + } + + + /** + * Delete file + * + * @author [A. Gianotto] [] + * @since [v1.6] + * @param int $userId + * @param int $fileId + * @return \Illuminate\Http\RedirectResponse + * @throws \Illuminate\Auth\Access\AuthorizationException + */ + public function destroy($userId = null, $fileId = null) + { + $user = User::find($userId); + $destinationPath = config('app.private_uploads').'/users'; + + if (isset($user->id)) { + $this->authorize('update', $user); + $log = Actionlog::find($fileId); + $full_filename = $destinationPath . '/' . $log->filename; + if (file_exists($full_filename)) { + unlink($destinationPath . '/' . $log->filename); + } + $log->delete(); + return redirect()->back()->with('success', trans('admin/users/message.deletefile.success')); + } + // Prepare the error message + $error = trans('admin/users/message.user_not_found', ['id' => $userId]); + // Redirect to the licence management page + return redirect()->route('users.index')->with('error', $error); + + } + + /** + * Display/download the uploaded file + * + * @author [A. Gianotto] [] + * @since [v1.6] + * @param int $userId + * @param int $fileId + * @return mixed + * @throws \Illuminate\Auth\Access\AuthorizationException + */ + public function show($userId = null, $fileId = null) + { + $user = User::find($userId); + + // the license is valid + if (isset($user->id)) { + $this->authorize('view', $user); + + $log = Actionlog::find($fileId); + $file = $log->get_src('users'); + return Response::download($file); + } + // Prepare the error message + $error = trans('admin/users/message.user_not_found', ['id' => $userId]); + + // Redirect to the licence management page + return redirect()->route('users.index')->with('error', $error); + } + +} diff --git a/app/Http/Controllers/Users/UsersController.php b/app/Http/Controllers/Users/UsersController.php new file mode 100755 index 0000000000..0e938e42b3 --- /dev/null +++ b/app/Http/Controllers/Users/UsersController.php @@ -0,0 +1,629 @@ +] + * @see UsersController::getDatatable() method that generates the JSON response + * @since [v1.0] + * @return \Illuminate\Contracts\View\View + * @throws \Illuminate\Auth\Access\AuthorizationException + */ + public function index() + { + $this->authorize('index', User::class); + return view('users/index'); + } + + /** + * Returns a view that displays the user creation form. + * + * @author [A. Gianotto] [] + * @since [v1.0] + * @return \Illuminate\Contracts\View\View + * @throws \Illuminate\Auth\Access\AuthorizationException + */ + public function create() + { + $this->authorize('create', User::class); + $groups = Group::pluck('name', 'id'); + + $userGroups = collect(); + + if (Input::old('groups')) { + $userGroups = Group::whereIn('id', Input::old('groups'))->pluck('name', 'id'); + } + + $permissions = config('permissions'); + $userPermissions = Helper::selectedPermissionsArray($permissions, Input::old('permissions', array())); + $permissions = $this->filterDisplayable($permissions); + + $user = new User; + $user->activated = 1; + + return view('users/edit', compact('groups', 'userGroups', 'permissions', 'userPermissions')) + ->with('user', $user); + } + + /** + * Validate and store the new user data, or return an error. + * + * @author [A. Gianotto] [] + * @since [v1.0] + * @param SaveUserRequest $request + * @return \Illuminate\Http\RedirectResponse + * @throws \Illuminate\Auth\Access\AuthorizationException + */ + public function store(SaveUserRequest $request) + { + $this->authorize('create', User::class); + $user = new User; + //Username, email, and password need to be handled specially because the need to respect config values on an edit. + $user->email = e($request->input('email')); + $user->username = e($request->input('username')); + if ($request->filled('password')) { + $user->password = bcrypt($request->input('password')); + } + $user->first_name = $request->input('first_name'); + $user->last_name = $request->input('last_name'); + $user->locale = $request->input('locale'); + $user->employee_num = $request->input('employee_num'); + $user->activated = $request->input('activated', 0); + $user->jobtitle = $request->input('jobtitle'); + $user->phone = $request->input('phone'); + $user->location_id = $request->input('location_id', null); + $user->department_id = $request->input('department_id', null); + $user->company_id = Company::getIdForUser($request->input('company_id', null)); + $user->manager_id = $request->input('manager_id', null); + $user->notes = $request->input('notes'); + $user->address = $request->input('address', null); + $user->city = $request->input('city', null); + $user->state = $request->input('state', null); + $user->country = $request->input('country', null); + $user->zip = $request->input('zip', null); + + // Strip out the superuser permission if the user isn't a superadmin + $permissions_array = $request->input('permission'); + + if (!Auth::user()->isSuperUser()) { + unset($permissions_array['superuser']); + } + $user->permissions = json_encode($permissions_array); + + if ($user->save()) { + if ($request->filled('groups')) { + $user->groups()->sync($request->input('groups')); + } else { + $user->groups()->sync(array()); + } + + if (($request->input('email_user') == 1) && ($request->filled('email'))) { + // Send the credentials through email + $data = array(); + $data['email'] = e($request->input('email')); + $data['username'] = e($request->input('username')); + $data['first_name'] = e($request->input('first_name')); + $data['last_name'] = e($request->input('last_name')); + $data['password'] = e($request->input('password')); + + $user->notify(new WelcomeNotification($data)); + } + return redirect::route('users.index')->with('success', trans('admin/users/message.success.create')); + } + return redirect()->back()->withInput()->withErrors($user->getErrors()); + } + + + + private function filterDisplayable($permissions) + { + $output = null; + foreach ($permissions as $key => $permission) { + $output[$key] = array_filter($permission, function ($p) { + return $p['display'] === true; + }); + } + return $output; + } + + /** + * Returns a view that displays the edit user form + * + * @author [A. Gianotto] [] + * @since [v1.0] + * @param $permissions + * @return View + * @internal param int $id + * @throws \Illuminate\Auth\Access\AuthorizationException + */ + public function edit($id) + { + if ($user = User::find($id)) { + $this->authorize('update', $user); + $permissions = config('permissions'); + + $groups = Group::pluck('name', 'id'); + + $userGroups = $user->groups()->pluck('name', 'id'); + $user->permissions = $user->decodePermissions(); + $userPermissions = Helper::selectedPermissionsArray($permissions, $user->permissions); + $permissions = $this->filterDisplayable($permissions); + + return view('users/edit', compact('user', 'groups', 'userGroups', 'permissions', 'userPermissions'))->with('item', $user); + } + + $error = trans('admin/users/message.user_not_found', compact('id')); + return redirect()->route('users.index')->with('error', $error); + } + + /** + * Validate and save edited user data from edit form. + * + * @author [A. Gianotto] [] + * @since [v1.0] + * @param SaveUserRequest $request + * @param int $id + * @return \Illuminate\Http\RedirectResponse + * @throws \Illuminate\Auth\Access\AuthorizationException + */ + public function update(SaveUserRequest $request, $id = null) + { + // We need to reverse the UI specific logic for our + // permissions here before we update the user. + $permissions = $request->input('permissions', array()); + app('request')->request->set('permissions', $permissions); + + // This is a janky hack to prevent people from changing admin demo user data on the public demo. + // The $ids 1 and 2 are special since they are seeded as superadmins in the demo seeder. + // Thanks, jerks. You are why we can't have nice things. - snipe + + if ((($id == 1) || ($id == 2)) && (config('app.lock_passwords'))) { + return redirect()->route('users.index')->with('error', 'Permission denied. You cannot update user information for superadmins on the demo.'); + } + + try { + $user = User::findOrFail($id); + + if ($user->id == $request->input('manager_id')) { + return redirect()->back()->withInput()->with('error', 'You cannot be your own manager.'); + } + $this->authorize('update', $user); + // Figure out of this user was an admin before this edit + $orig_permissions_array = $user->decodePermissions(); + $orig_superuser = '0'; + if (is_array($orig_permissions_array)) { + if (array_key_exists('superuser', $orig_permissions_array)) { + $orig_superuser = $orig_permissions_array['superuser']; + } + } + } catch (ModelNotFoundException $e) { + return redirect()->route('users.index') + ->with('error', trans('admin/users/message.user_not_found', compact('id'))); + } + + + // Only save groups if the user is a super user + if (Auth::user()->isSuperUser()) { + $user->groups()->sync($request->input('groups')); + } + + + if ($request->filled('username')) { + $user->username = $request->input('username'); + } + $user->email = $request->input('email'); + + + // Update the user + $user->first_name = $request->input('first_name'); + $user->last_name = $request->input('last_name'); + $user->two_factor_optin = $request->input('two_factor_optin') ?: 0; + $user->locale = $request->input('locale'); + $user->employee_num = $request->input('employee_num'); + $user->activated = $request->input('activated', 0); + $user->jobtitle = $request->input('jobtitle', null); + $user->phone = $request->input('phone'); + $user->location_id = $request->input('location_id', null); + $user->company_id = Company::getIdForUser($request->input('company_id', null)); + $user->manager_id = $request->input('manager_id', null); + $user->notes = $request->input('notes'); + $user->department_id = $request->input('department_id', null); + $user->address = $request->input('address', null); + $user->city = $request->input('city', null); + $user->state = $request->input('state', null); + $user->country = $request->input('country', null); + $user->activated = $request->input('activated', 0); + $user->zip = $request->input('zip', null); + + + // Update the location of any assets checked out to this user + Asset::where('assigned_type', User::class) + ->where('assigned_to', $user->id) + ->update(['location_id' => $request->input('location_id', null)]); + + // Do we want to update the user password? + if ($request->filled('password')) { + $user->password = bcrypt($request->input('password')); + } + + $permissions_array = $request->input('permission'); + + // Strip out the superuser permission if the user isn't a superadmin + if (!Auth::user()->isSuperUser()) { + unset($permissions_array['superuser']); + $permissions_array['superuser'] = $orig_superuser; + } + + $user->permissions = json_encode($permissions_array); + + // Was the user updated? + if ($user->save()) { + // Redirect to the user page + return redirect()->route('users.index') + ->with('success', trans('admin/users/message.success.update')); + } + return redirect()->back()->withInput()->withErrors($user->getErrors()); + } + + /** + * Delete a user + * + * @author [A. Gianotto] [] + * @since [v1.0] + * @param int $id + * @return \Illuminate\Http\RedirectResponse + * @throws \Illuminate\Auth\Access\AuthorizationException + */ + public function destroy($id = null) + { + try { + // Get user information + $user = User::findOrFail($id); + // Authorize takes care of many of our logic checks now. + $this->authorize('delete', User::class); + + // Check if we are not trying to delete ourselves + if ($user->id === Auth::id()) { + // Redirect to the user management page + return redirect()->route('users.index') + ->with('error', 'We would feel really bad if you deleted yourself, please reconsider.'); + } + + if (($assetsCount = $user->assets()->count()) > 0) { + // Redirect to the user management page + return redirect()->route('users.index') + ->with('error', 'This user still has ' . $assetsCount . ' assets associated with them.'); + } + + if (($licensesCount = $user->licenses()->count()) > 0) { + // Redirect to the user management page + return redirect()->route('users.index') + ->with('error', 'This user still has ' . $licensesCount . ' licenses associated with them.'); + } + + if (($accessoriesCount = $user->accessories()->count()) > 0) { + // Redirect to the user management page + return redirect()->route('users.index') + ->with('error', 'This user still has ' . $accessoriesCount . ' accessories associated with them.'); + } + + if (($managedLocationsCount = $user->managedLocations()->count()) > 0) { + // Redirect to the user management page + return redirect()->route('users.index') + ->with('error', 'This user still has ' . $managedLocationsCount . ' locations that they manage.'); + } + + // Delete the user + $user->delete(); + + // Prepare the success message + // Redirect to the user management page + return redirect()->route('users.index')->with('success', trans('admin/users/message.success.delete')); + } catch (ModelNotFoundException $e) { + // Prepare the error message + // Redirect to the user management page + return redirect()->route('users.index') + ->with('error', trans('admin/users/message.user_not_found', compact('id'))); + } + } + + /** + * Restore a deleted user + * + * @author [A. Gianotto] [] + * @since [v1.0] + * @param int $id + * @return \Illuminate\Http\RedirectResponse + * @throws \Illuminate\Auth\Access\AuthorizationException + */ + public function getRestore($id = null) + { + $this->authorize('edit', User::class); + // Get user information + if (!$user = User::onlyTrashed()->find($id)) { + return redirect()->route('users.index')->with('error', trans('admin/users/messages.user_not_found')); + } + + // Restore the user + if (User::withTrashed()->where('id', $id)->restore()) { + return redirect()->route('users.index')->with('success', trans('admin/users/message.success.restored')); + } + return redirect()->route('users.index')->with('error', 'User could not be restored.'); + } + + + /** + * Return a view with user detail + * + * @author [A. Gianotto] [] + * @since [v1.0] + * @param int $userId + * @return \Illuminate\Contracts\View\View + * @throws \Illuminate\Auth\Access\AuthorizationException + */ + public function show($userId = null) + { + if (!$user = User::with('assets', 'assets.model', 'consumables', 'accessories', 'licenses', 'userloc')->withTrashed()->find($userId)) { + // Redirect to the user management page + return redirect()->route('users.index') + ->with('error', trans('admin/users/message.user_not_found', ['id' => $userId])); + } + + $userlog = $user->userlog->load('item'); + + $this->authorize('view', $user); + return view('users/view', compact('user', 'userlog')); + } + + /** + * Unsuspend a user. + * + * @author [A. Gianotto] [] + * @since [v1.0] + * @param int $id + * @return Redirect + * @throws \Illuminate\Auth\Access\AuthorizationException + */ + public function getUnsuspend($id = null) + { + try { + // Get user information + $user = User::findOrFail($id); + $this->authorize('edit', $user); + + // Check if we are not trying to unsuspend ourselves + if ($user->id === Auth::id()) { + // Prepare the error message + $error = trans('admin/users/message.error.unsuspend'); + // Redirect to the user management page + return redirect()->route('users.index')->with('error', $error); + } + + // Do we have permission to unsuspend this user? + if ($user->isSuperUser() && !Auth::user()->isSuperUser()) { + // Redirect to the user management page + return redirect()->route('users.index')->with('error', 'Insufficient permissions!'); + } + + // Redirect to the user management page + return redirect()->route('users.index')->with('success', trans('admin/users/message.success.unsuspend')); + } catch (ModelNotFoundException $e) { + // Redirect to the user management page + return redirect()->route('users.index') + ->with('error', trans('admin/users/message.user_not_found', compact('id'))); + } + } + + + /** + * Return a view containing a pre-populated new user form, + * populated with some fields from an existing user. + * + * @author [A. Gianotto] [] + * @since [v1.0] + * @param int $id + * @return \Illuminate\Contracts\View\View + * @throws \Illuminate\Auth\Access\AuthorizationException + */ + public function getClone($id = null) + { + $this->authorize('create', User::class); + // We need to reverse the UI specific logic for our + // permissions here before we update the user. + $permissions = Input::get('permissions', array()); + app('request')->request->set('permissions', $permissions); + + + try { + // Get the user information + $user_to_clone = User::withTrashed()->find($id); + $user = clone $user_to_clone; + $user->first_name = ''; + $user->last_name = ''; + $user->email = substr($user->email, ($pos = strpos($user->email, '@')) !== false ? $pos : 0); + + $user->id = null; + + // Get this user groups + $userGroups = $user_to_clone->groups()->pluck('name', 'id'); + // Get all the available permissions + $permissions = config('permissions'); + $clonedPermissions = $user_to_clone->decodePermissions(); + + $userPermissions = Helper::selectedPermissionsArray($permissions, $clonedPermissions); + + // Show the page + return view('users/edit', compact('permissions', 'userPermissions')) + ->with('user', $user) + ->with('groups', Group::pluck('name', 'id')) + ->with('userGroups', $userGroups) + ->with('clone_user', $user_to_clone); + } catch (ModelNotFoundException $e) { + // Prepare the error message + // Redirect to the user management page + return redirect()->route('users.index') + ->with('error', trans('admin/users/message.user_not_found', compact('id'))); + } + } + + + /** + * Exports users to CSV + * + * @author [A. Gianotto] [] + * @since [v3.5] + * @return StreamedResponse + * @throws \Illuminate\Auth\Access\AuthorizationException + */ + public function getExportUserCsv() + { + $this->authorize('view', User::class); + \Debugbar::disable(); + + $response = new StreamedResponse(function () { + // Open output stream + $handle = fopen('php://output', 'w'); + + User::with('assets', 'accessories', 'consumables', 'department', 'licenses', 'manager', 'groups', 'userloc', 'company') + ->orderBy('created_at', 'DESC') + ->chunk(500, function ($users) use ($handle) { + $headers=[ + // strtolower to prevent Excel from trying to open it as a SYLK file + strtolower(trans('general.id')), + trans('admin/companies/table.title'), + trans('admin/users/table.title'), + trans('admin/users/table.employee_num'), + trans('admin/users/table.name'), + trans('admin/users/table.username'), + trans('admin/users/table.email'), + trans('admin/users/table.manager'), + trans('admin/users/table.location'), + trans('general.department'), + trans('general.assets'), + trans('general.licenses'), + trans('general.accessories'), + trans('general.consumables'), + trans('admin/users/table.groups'), + trans('general.notes'), + trans('admin/users/table.activated'), + trans('general.created_at') + ]; + + fputcsv($handle, $headers); + + foreach ($users as $user) { + $user_groups = ''; + + foreach ($user->groups as $user_group) { + $user_groups .= $user_group->name.', '; + } + + // Add a new row with data + $values = [ + $user->id, + ($user->company) ? $user->company->name : '', + $user->jobtitle, + $user->employee_num, + $user->present()->fullName(), + $user->username, + $user->email, + ($user->manager) ? $user->manager->present()->fullName() : '', + ($user->userloc) ? $user->userloc->name : '', + ($user->department) ? $user->department->name : '', + $user->assets->count(), + $user->licenses->count(), + $user->accessories->count(), + $user->consumables->count(), + $user_groups, + $user->notes, + ($user->activated=='1') ? trans('general.yes') : trans('general.no'), + $user->created_at, + ]; + + fputcsv($handle, $values); + } + }); + + // Close the output stream + fclose($handle); + }, 200, [ + 'Content-Type' => 'text/csv; charset=UTF-8', + 'Content-Disposition' => 'attachment; filename="users-'.date('Y-m-d-his').'.csv"', + ]); + + return $response; + } + + /** + * LDAP form processing. + * + * @author Aladin Alaily + * @since [v1.8] + * @return \Illuminate\Http\RedirectResponse + */ + public function printInventory($id) + { + $this->authorize('view', User::class); + $show_user = User::where('id', $id)->withTrashed()->first(); + $assets = Asset::where('assigned_to', $id)->where('assigned_type', User::class)->with('model', 'model.category')->get(); + $accessories = $show_user->accessories()->get(); + $consumables = $show_user->consumables()->get(); + return view('users/print')->with('assets', $assets) + ->with('licenses', $show_user->licenses()->get()) + ->with('accessories', $accessories) + ->with('consumables', $consumables) + ->with('show_user', $show_user); + } +} diff --git a/app/Http/Controllers/UsersController.php b/app/Http/Controllers/UsersController.php deleted file mode 100755 index 88e2911f59..0000000000 --- a/app/Http/Controllers/UsersController.php +++ /dev/null @@ -1,995 +0,0 @@ -] - * @see UsersController::getDatatable() method that generates the JSON response - * @since [v1.0] - * @return \Illuminate\Contracts\View\View - */ - public function index() - { - $this->authorize('index', User::class); - return view('users/index'); - } - - /** - * Returns a view that displays the user creation form. - * - * @author [A. Gianotto] [] - * @since [v1.0] - * @return \Illuminate\Contracts\View\View - */ - public function create() - { - $this->authorize('create', User::class); - $groups = Group::pluck('name', 'id'); - - if (Input::old('groups')) { - $userGroups = Group::whereIn('id', Input::old('groups'))->pluck('name', 'id'); - } else { - $userGroups = collect(); - } - - $permissions = config('permissions'); - $userPermissions = Helper::selectedPermissionsArray($permissions, Input::old('permissions', array())); - $permissions = $this->filterDisplayable($permissions); - - $user = new User; - $user->activated = 1; - - return view('users/edit', compact('groups', 'userGroups', 'permissions', 'userPermissions')) - ->with('user', $user); - } - - /** - * Validate and store the new user data, or return an error. - * - * @author [A. Gianotto] [] - * @since [v1.0] - * @return \Illuminate\Http\RedirectResponse - */ - public function store(SaveUserRequest $request) - { - $this->authorize('create', User::class); - $user = new User; - //Username, email, and password need to be handled specially because the need to respect config values on an edit. - $user->email = $data['email'] = e($request->input('email')); - $user->username = $data['username'] = e($request->input('username')); - if ($request->has('password')) { - $user->password = bcrypt($request->input('password')); - $data['password'] = $request->input('password'); - } - $user->first_name = $request->input('first_name'); - $user->last_name = $request->input('last_name'); - $user->locale = $request->input('locale'); - $user->employee_num = $request->input('employee_num'); - $user->activated = $request->input('activated', 0); - $user->jobtitle = $request->input('jobtitle'); - $user->phone = $request->input('phone'); - $user->location_id = $request->input('location_id', null); - $user->department_id = $request->input('department_id', null); - $user->company_id = Company::getIdForUser($request->input('company_id', null)); - $user->manager_id = $request->input('manager_id', null); - $user->notes = $request->input('notes'); - $user->address = $request->input('address', null); - $user->city = $request->input('city', null); - $user->state = $request->input('state', null); - $user->country = $request->input('country', null); - $user->zip = $request->input('zip', null); - - // Strip out the superuser permission if the user isn't a superadmin - $permissions_array = $request->input('permission'); - - if (!Auth::user()->isSuperUser()) { - unset($permissions_array['superuser']); - } - $user->permissions = json_encode($permissions_array); - - if ($user->save()) { - - if ($request->has('groups')) { - $user->groups()->sync($request->input('groups')); - } else { - $user->groups()->sync(array()); - } - - if (($request->input('email_user') == 1) && ($request->has('email'))) { - // Send the credentials through email - $data = array(); - $data['email'] = e($request->input('email')); - $data['username'] = e($request->input('username')); - $data['first_name'] = e($request->input('first_name')); - $data['last_name'] = e($request->input('last_name')); - $data['password'] = e($request->input('password')); - - $user->notify(new WelcomeNotification($data)); - -/* Mail::send('emails.send-login', $data, function ($m) use ($user) { - $m->to($user->email, $user->first_name . ' ' . $user->last_name); - $m->replyTo(config('mail.reply_to.address'), config('mail.reply_to.name')); - $m->subject(trans('mail.welcome', ['name' => $user->first_name])); - });*/ - } - return redirect::route('users.index')->with('success', trans('admin/users/message.success.create')); - } - return redirect()->back()->withInput()->withErrors($user->getErrors()); - } - - - - private function filterDisplayable($permissions) - { - $output = null; - foreach ($permissions as $key => $permission) { - $output[$key] = array_filter($permission, function ($p) { - return $p['display'] === true; - }); - } - return $output; - } - - /** - * Returns a view that displays the edit user form - * - * @author [A. Gianotto] [] - * @since [v1.0] - * @param $permissions - * @return View - * @internal param int $id - */ - public function edit($id) - { - - if ($user = User::find($id)) { - - $this->authorize('update', $user); - $permissions = config('permissions'); - - $groups = Group::pluck('name', 'id'); - - $userGroups = $user->groups()->pluck('name', 'id'); - $user->permissions = $user->decodePermissions(); - $userPermissions = Helper::selectedPermissionsArray($permissions, $user->permissions); - $permissions = $this->filterDisplayable($permissions); - - return view('users/edit', compact('user', 'groups', 'userGroups', 'permissions', 'userPermissions'))->with('item', $user); - } - - $error = trans('admin/users/message.user_not_found', compact('id')); - return redirect()->route('users.index')->with('error', $error); - - - } - - /** - * Validate and save edited user data from edit form. - * - * @author [A. Gianotto] [] - * @since [v1.0] - * @param UpdateUserRequest $request - * @param int $id - * @return \Illuminate\Http\RedirectResponse - */ - public function update(SaveUserRequest $request, $id = null) - { - // We need to reverse the UI specific logic for our - // permissions here before we update the user. - $permissions = $request->input('permissions', array()); - app('request')->request->set('permissions', $permissions); - // Only update the email address if locking is set to false - if (config('app.lock_passwords')) { - return redirect()->route('users.index')->with('error', 'Denied! You cannot update user information on the demo.'); - } - - try { - - $user = User::find($id); - - if ($user->id == $request->input('manager_id')) { - return redirect()->back()->withInput()->with('error', 'You cannot be your own manager.'); - } - $this->authorize('update', $user); - // Figure out of this user was an admin before this edit - $orig_permissions_array = $user->decodePermissions(); - $orig_superuser = '0'; - if (is_array($orig_permissions_array)) { - if (array_key_exists('superuser', $orig_permissions_array)) { - $orig_superuser = $orig_permissions_array['superuser']; - } - } - - - } catch (ModelNotFoundException $e) { - return redirect()->route('users.index') - ->with('error', trans('admin/users/message.user_not_found', compact('id'))); - } - - - // Only save groups if the user is a super user - if (Auth::user()->isSuperUser()) { - $user->groups()->sync($request->input('groups')); - } - - - if ($request->has('username')) { - $user->username = $request->input('username'); - } - $user->email = $request->input('email'); - - - // Update the user - $user->first_name = $request->input('first_name'); - $user->last_name = $request->input('last_name'); - $user->two_factor_optin = $request->input('two_factor_optin') ?: 0; - $user->locale = $request->input('locale'); - $user->employee_num = $request->input('employee_num'); - $user->activated = $request->input('activated', 0); - $user->jobtitle = $request->input('jobtitle', null); - $user->phone = $request->input('phone'); - $user->location_id = $request->input('location_id', null); - $user->company_id = Company::getIdForUser($request->input('company_id', null)); - $user->manager_id = $request->input('manager_id', null); - $user->notes = $request->input('notes'); - $user->department_id = $request->input('department_id', null); - $user->address = $request->input('address', null); - $user->city = $request->input('city', null); - $user->state = $request->input('state', null); - $user->country = $request->input('country', null); - $user->activated = $request->input('activated', 0); - $user->zip = $request->input('zip', null); - - - // Update the location of any assets checked out to this user - Asset::where('assigned_type', User::class) - ->where('assigned_to', $user->id)->update(['location_id' => $request->input('location_id', null)]); - - // Do we want to update the user password? - if ($request->has('password')) { - $user->password = bcrypt($request->input('password')); - } - - // Strip out the superuser permission if the user isn't a superadmin - $permissions_array = $request->input('permission'); - - if (!Auth::user()->isSuperUser()) { - unset($permissions_array['superuser']); - $permissions_array['superuser'] = $orig_superuser; - } - - $user->permissions = json_encode($permissions_array); - - // Was the user updated? - if ($user->save()) { - // Prepare the success message - $success = trans('admin/users/message.success.update'); - // Redirect to the user page - return redirect()->route('users.index')->with('success', $success); - } - return redirect()->back()->withInput()->withErrors($user->getErrors()); - } - - /** - * Delete a user - * - * @author [A. Gianotto] [] - * @since [v1.0] - * @param int $id - * @return \Illuminate\Http\RedirectResponse - */ - public function destroy($id = null) - { - try { - // Get user information - $user = User::findOrFail($id); - // Authorize takes care of many of our logic checks now. - $this->authorize('delete', User::class); - - // Check if we are not trying to delete ourselves - if ($user->id === Auth::user()->id) { - // Redirect to the user management page - return redirect()->route('users.index')->with('error', 'This user still has ' . $user->assets()->count() . ' assets associated with them.'); - } - - if ($user->assets->count() > 0) { - // Redirect to the user management page - return redirect()->route('users.index')->with('error', 'This user still has ' . count($user->assets->count()) . ' assets associated with them.'); - } - - if ($user->licenses()->count() > 0) { - // Redirect to the user management page - return redirect()->route('users.index')->with('error', 'This user still has ' . $user->assets()->count() . ' assets associated with them.'); - } - - if ($user->accessories()->count() > 0) { - // Redirect to the user management page - return redirect()->route('users.index')->with('error', 'This user still has ' . $user->accessories()->count() . ' accessories associated with them.'); - } - - if ($user->managedLocations()->count() > 0) { - // Redirect to the user management page - return redirect()->route('users.index')->with('error', 'This user still has ' . $user->managedLocations()->count() . ' locations that they manage.'); - } - - // Delete the user - $user->delete(); - - // Prepare the success message - $success = trans('admin/users/message.success.delete'); - - // Redirect to the user management page - return redirect()->route('users.index')->with('success', $success); - } catch (ModelNotFoundException $e) { - // Prepare the error message - $error = trans('admin/users/message.user_not_found', compact('id')); - // Redirect to the user management page - return redirect()->route('users.index')->with('error', $error); - } - } - - /** - * Returns a view that confirms the user's a bulk delete will be applied to. - * - * @author [A. Gianotto] [] - * @since [v1.7] - * @return \Illuminate\Contracts\View\View - */ - public function postBulkEdit(Request $request) - { - $this->authorize('update', User::class); - - if (($request->has('ids')) && (count($request->input('ids')) > 0)) { - $statuslabel_list = Helper::statusLabelList(); - $user_raw_array = array_keys(Input::get('ids')); - $users = User::whereIn('id', $user_raw_array)->with('groups', 'assets', 'licenses', 'accessories')->get(); - if ($request->input('bulk_actions') == 'edit') { - return view('users/bulk-edit', compact('users')) - ->with('groups', Group::pluck('name', 'id')); - } - return view('users/confirm-bulk-delete', compact('users', 'statuslabel_list')); - } - - return redirect()->back()->with('error', 'No users selected'); - } - - - /** - * Save bulk-edited users - * - * @author [A. Gianotto] [] - * @since [v1.0] - * @return \Illuminate\Http\RedirectResponse - */ - public function postBulkEditSave(Request $request) - { - $this->authorize('update', User::class); - - if (($request->has('ids')) && (count($request->input('ids')) > 0)) { - - $user_raw_array = $request->input('ids'); - $update_array = array(); - $manager_conflict = false; - $users = User::whereIn('id', $user_raw_array)->where('id', '!=', Auth::user()->id)->get(); - - if ($request->has('location_id')) { - $update_array['location_id'] = $request->input('location_id'); - } - if ($request->has('department_id')) { - $update_array['department_id'] = $request->input('department_id'); - } - if ($request->has('company_id')) { - $update_array['company_id'] = $request->input('company_id'); - } - if ($request->has('locale')) { - $update_array['locale'] = $request->input('locale'); - } - - - if ($request->has('manager_id')) { - - // Do not allow a manager update if the selected manager is one of the users being - // edited. - if (!array_key_exists($request->input('manager_id'), $user_raw_array)) { - $update_array['manager_id'] = $request->input('manager_id'); - } else { - $manager_conflict = true; - } - - } - if ($request->has('activated')) { - $update_array['activated'] = $request->input('activated'); - } - - // Save the updated info - if (count($update_array) > 0) { - User::whereIn('id', $user_raw_array)->where('id', '!=', Auth::user()->id)->update($update_array); - } - - // Only sync groups if groups were selected - if ($request->has('groups')) { - foreach ($users as $user) { - $user->groups()->sync($request->input('groups')); - } - } - - if ($manager_conflict) { - return redirect()->route('users.index') - ->with('warning', trans('admin/users/message.bulk_manager_warn')); - } - - return redirect()->route('users.index') - ->with('success', trans('admin/users/message.success.update_bulk')); - } - - return redirect()->back()->with('error', 'No users selected'); - - - - } - - /** - * Soft-delete bulk users - * - * @author [A. Gianotto] [] - * @since [v1.0] - * @return \Illuminate\Http\RedirectResponse - */ - public function postBulkSave(Request $request) - { - $this->authorize('update', User::class); - - if ((!$request->has('ids')) || (count($request->input('ids')) == 0)) { - return redirect()->back()->with('error', 'No users selected'); - } elseif ((!$request->has('status_id')) || ($request->input('status_id')=='')) { - return redirect()->route('users.index')->with('error', 'No status selected'); - } else { - - $user_raw_array = Input::get('ids'); - $asset_array = array(); - - if (($key = array_search(Auth::user()->id, $user_raw_array)) !== false) { - unset($user_raw_array[$key]); - } - - - if (!config('app.lock_passwords')) { - - $users = User::whereIn('id', $user_raw_array)->get(); - $assets = Asset::whereIn('assigned_to', $user_raw_array)->get(); - $accessories = DB::table('accessories_users')->whereIn('assigned_to', $user_raw_array)->get(); - $licenses = DB::table('license_seats')->whereIn('assigned_to', $user_raw_array)->get(); - $license_array = array(); - $accessory_array = array(); - - foreach ($assets as $asset) { - - $asset_array[] = $asset->id; - - // Update the asset log - $logAction = new Actionlog(); - $logAction->item_id = $asset->id; - $logAction->item_type = Asset::class; - $logAction->target_id = $asset->assigned_to; - $logAction->target_type = User::class; - $logAction->user_id = Auth::user()->id; - $logAction->note = 'Bulk checkin asset and delete user'; - $logAction->logaction('checkin from'); - - Asset::whereIn('id', $asset_array)->update([ - 'status_id' => e(Input::get('status_id')), - 'assigned_to' => null, - ]); - } - - foreach ($accessories as $accessory) { - $accessory_array[] = $accessory->accessory_id; - // Update the asset log - $logAction = new Actionlog(); - $logAction->item_id = $accessory->id; - $logAction->item_type = Accessory::class; - $logAction->target_id = $accessory->assigned_to; - $logAction->target_type = User::class; - $logAction->user_id = Auth::user()->id; - $logAction->note = 'Bulk checkin accessory and delete user'; - $logAction->logaction('checkin from'); - } - - foreach ($licenses as $license) { - $license_array[] = $license->id; - // Update the asset log - $logAction = new Actionlog(); - $logAction->item_id = $license->id; - $logAction->item_type = License::class; - $logAction->target_id = $license->assigned_to; - $logAction->target_type = User::class; - $logAction->user_id = Auth::user()->id; - $logAction->note = 'Bulk checkin license and delete user'; - $logAction->logaction('checkin from'); - } - - LicenseSeat::whereIn('id', $license_array)->update(['assigned_to' => null]); - - foreach ($users as $user) { - $user->accessories()->sync(array()); - $user->delete(); - } - - return redirect()->route('users.index')->with('success', 'Your selected users have been deleted and their assets have been updated.'); - } - return redirect()->route('users.index')->with('error', 'Bulk delete is not enabled in this installation'); - } - } - - /** - * Restore a deleted user - * - * @author [A. Gianotto] [] - * @since [v1.0] - * @param int $id - * @return \Illuminate\Http\RedirectResponse - */ - public function getRestore($id = null) - { - $this->authorize('edit', User::class); - // Get user information - if (!$user = User::onlyTrashed()->find($id)) { - return redirect()->route('users.index')->with('error', trans('admin/users/messages.user_not_found')); - } - - // Restore the user - if (User::withTrashed()->where('id', $id)->restore()) { - return redirect()->route('users.index')->with('success', trans('admin/users/message.success.restored')); - } - return redirect()->route('users.index')->with('error', 'User could not be restored.'); - } - - - /** - * Return a view with user detail - * - * @author [A. Gianotto] [] - * @since [v1.0] - * @param int $userId - * @return \Illuminate\Contracts\View\View - */ - public function show($userId = null) - { - if(!$user = User::with('assets', 'assets.model', 'consumables', 'accessories', 'licenses', 'userloc')->withTrashed()->find($userId)) { - $error = trans('admin/users/message.user_not_found', compact('id')); - // Redirect to the user management page - return redirect()->route('users.index')->with('error', $error); - } - - $userlog = $user->userlog->load('item'); - - if (isset($user->id)) { - $this->authorize('view', $user); - return view('users/view', compact('user', 'userlog')); - } - } - - /** - * Unsuspend a user. - * - * @author [A. Gianotto] [] - * @since [v1.0] - * @param int $id - * @return Redirect - */ - public function getUnsuspend($id = null) - { - try { - // Get user information - $user = User::find($id); - $this->authorize('edit', $user); - - // Check if we are not trying to unsuspend ourselves - if ($user->id === Auth::user()->id) { - // Prepare the error message - $error = trans('admin/users/message.error.unsuspend'); - // Redirect to the user management page - return redirect()->route('users.index')->with('error', $error); - } - - // Do we have permission to unsuspend this user? - if ($user->isSuperUser() && !Auth::user()->isSuperUser()) { - // Redirect to the user management page - return redirect()->route('users.index')->with('error', 'Insufficient permissions!'); - } - - // Prepare the success message - $success = trans('admin/users/message.success.unsuspend'); - // Redirect to the user management page - return redirect()->route('users.index')->with('success', $success); - } catch (UserNotFoundException $e) { - // Prepare the error message - $error = trans('admin/users/message.user_not_found', compact('id')); - // Redirect to the user management page - return redirect()->route('users.index')->with('error', $error); - } - } - - - /** - * Return a view containing a pre-populated new user form, - * populated with some fields from an existing user. - * - * @author [A. Gianotto] [] - * @since [v1.0] - * @param int $id - * @return \Illuminate\Contracts\View\View - */ - public function getClone($id = null) - { - $this->authorize('create', User::class); - // We need to reverse the UI specific logic for our - // permissions here before we update the user. - $permissions = Input::get('permissions', array()); - //$this->decodePermissions($permissions); - app('request')->request->set('permissions', $permissions); - - - try { - // Get the user information - $user_to_clone = User::withTrashed()->find($id); - $user = clone $user_to_clone; - $user->first_name = ''; - $user->last_name = ''; - $user->email = substr($user->email, ($pos = strpos($user->email, '@')) !== false ? $pos : 0); - - $user->id = null; - - // Get this user groups - $userGroups = $user_to_clone->groups()->pluck('name', 'id'); - // Get all the available permissions - $permissions = config('permissions'); - $clonedPermissions = $user_to_clone->decodePermissions(); - - $userPermissions =Helper::selectedPermissionsArray($permissions, $clonedPermissions); - - // Show the page - return view('users/edit', compact('permissions', 'userPermissions')) - ->with('user', $user) - ->with('groups', Group::pluck('name', 'id')) - ->with('userGroups', $userGroups) - ->with('clone_user', $user_to_clone); - } catch (UserNotFoundException $e) { - // Prepare the error message - $error = trans('admin/users/message.user_not_found', compact('id')); - // Redirect to the user management page - return redirect()->route('users.index')->with('error', $error); - } - } - - /** - * Return JSON response with a list of user details for the getIndex() view. - * - * @author [A. Gianotto] [] - * @since [v1.6] - * @param AssetFileRequest $request - * @param int $userId - * @return string JSON - */ - public function postUpload(AssetFileRequest $request, $userId = null) - { - - $user = User::find($userId); - $destinationPath = config('app.private_uploads') . '/users'; - - if (isset($user->id)) { - $this->authorize('update', $user); - - foreach (Input::file('file') as $file) { - - $extension = $file->getClientOriginalExtension(); - $filename = 'user-' . $user->id . '-' . str_random(8); - $filename .= '-' . str_slug($file->getClientOriginalName()) . '.' . $extension; - $upload_success = $file->move($destinationPath, $filename); - - //Log the uploaded file to the log - $logAction = new Actionlog(); - $logAction->item_id = $user->id; - $logAction->item_type = User::class; - $logAction->user_id = Auth::user()->id; - $logAction->note = e(Input::get('notes')); - $logAction->target_id = null; - $logAction->created_at = date("Y-m-d H:i:s"); - $logAction->filename = $filename; - $logAction->action_type = 'uploaded'; - $logAction->save(); - - } - return JsonResponse::create($logAction); - - } - return JsonResponse::create(["error" => "Failed validation: ".print_r($logAction->getErrors(), true)], 500); - } - - - /** - * Delete file - * - * @author [A. Gianotto] [] - * @since [v1.6] - * @param int $userId - * @param int $fileId - * @return \Illuminate\Http\RedirectResponse - */ - public function getDeleteFile($userId = null, $fileId = null) - { - $user = User::find($userId); - $destinationPath = config('app.private_uploads').'/users'; - - if (isset($user->id)) { - $this->authorize('update', $user); - $log = Actionlog::find($fileId); - $full_filename = $destinationPath . '/' . $log->filename; - if (file_exists($full_filename)) { - unlink($destinationPath . '/' . $log->filename); - } - $log->delete(); - return redirect()->back()->with('success', trans('admin/users/message.deletefile.success')); - } - // Prepare the error message - $error = trans('admin/users/message.does_not_exist', compact('id')); - // Redirect to the licence management page - return redirect()->route('users.index')->with('error', $error); - - } - - /** - * Display/download the uploaded file - * - * @author [A. Gianotto] [] - * @since [v1.6] - * @param int $userId - * @param int $fileId - * @return mixed - */ - public function displayFile($userId = null, $fileId = null) - { - $user = User::find($userId); - - // the license is valid - if (isset($user->id)) { - $this->authorize('view', $user); - - $log = Actionlog::find($fileId); - $file = $log->get_src('users'); - return Response::download($file); - } - // Prepare the error message - $error = trans('admin/users/message.does_not_exist', compact('id')); - - // Redirect to the licence management page - return redirect()->route('users.index')->with('error', $error); - } - - /** - * Return view for LDAP import - * - * @author Aladin Alaily - * @since [v1.8] - * @return \Illuminate\Contracts\View\View - */ - public function getLDAP() - { - $this->authorize('update', User::class); - try { - $ldapconn = Ldap::connectToLdap(); - } catch (\Exception $e) { - return redirect()->route('users.index')->with('error', $e->getMessage()); - } - - try { - Ldap::bindAdminToLdap($ldapconn); - } catch (\Exception $e) { - return redirect()->route('users.index')->with('error', $e->getMessage()); - } - - return view('users/ldap'); - } - - - /** - * Declare the rules for the ldap fields validation. - * - * @author Aladin Alaily - * @since [v1.8] - * @var array - * @deprecated 3.0 - * @todo remove this method in favor of other validation - * @var array - */ - - protected $ldapValidationRules = array( - 'firstname' => 'required|string|min:2', - 'employee_number' => 'string', - 'username' => 'required|min:2|unique:users,username', - 'email' => 'email|unique:users,email', - ); - - /** - * LDAP form processing. - * - * @author Aladin Alaily - * @since [v1.8] - * @return \Illuminate\Http\RedirectResponse - */ - public function postLDAP(Request $request) - { - // Call Artisan LDAP import command. - $location_id = $request->input('location_id'); - Artisan::call('snipeit:ldap-sync', ['--location_id' => $location_id, '--json_summary' => true]); - - // Collect and parse JSON summary. - $ldap_results_json = Artisan::output(); - $ldap_results = json_decode($ldap_results_json, true); - - // Direct user to appropriate status page. - if ($ldap_results['error']) { - return redirect()->back()->withInput()->with('error', $ldap_results['error_message']); - } else { - return redirect()->route('ldap/user')->with('success', "LDAP Import successful.")->with('summary', $ldap_results['summary']); - } - } - - - /** - * Exports users to CSV - * - * @author [A. Gianotto] [] - * @since [v3.5] - * @return StreamedResponse - */ - public function getExportUserCsv() - { - - $this->authorize('view', User::class); - \Debugbar::disable(); - - $response = new StreamedResponse(function () { - // Open output stream - $handle = fopen('php://output', 'w'); - - User::with('assets', 'accessories', 'consumables', 'department', 'licenses', 'manager', 'groups', 'userloc', 'company','throttle')->orderBy('created_at', 'DESC')->chunk(500, function($users) use($handle) { - $headers=[ - // strtolower to prevent Excel from trying to open it as a SYLK file - strtolower(trans('general.id')), - trans('admin/companies/table.title'), - trans('admin/users/table.title'), - trans('admin/users/table.employee_num'), - trans('admin/users/table.name'), - trans('admin/users/table.username'), - trans('admin/users/table.email'), - trans('admin/users/table.manager'), - trans('admin/users/table.location'), - trans('general.department'), - trans('general.assets'), - trans('general.licenses'), - trans('general.accessories'), - trans('general.consumables'), - trans('admin/users/table.groups'), - trans('general.notes'), - trans('admin/users/table.activated'), - trans('general.created_at') - ]; - - fputcsv($handle, $headers); - - foreach ($users as $user) { - $user_groups = ''; - - foreach ($user->groups as $user_group) { - $user_groups .= $user_group->name.', '; - } - - // Add a new row with data - $values = [ - $user->id, - ($user->company) ? $user->company->name : '', - $user->jobtitle, - $user->employee_num, - $user->present()->fullName(), - $user->username, - $user->email, - ($user->manager) ? $user->manager->present()->fullName() : '', - ($user->userloc) ? $user->userloc->name : '', - ($user->department) ? $user->department->name : '', - $user->assets->count(), - $user->licenses->count(), - $user->accessories->count(), - $user->consumables->count(), - $user_groups, - $user->notes, - ($user->activated=='1') ? trans('general.yes') : trans('general.no'), - $user->created_at, - - ]; - - fputcsv($handle, $values); - } - }); - - // Close the output stream - fclose($handle); - }, 200, [ - 'Content-Type' => 'text/csv', - 'Content-Disposition' => 'attachment; filename="users-'.date('Y-m-d-his').'.csv"', - ]); - - return $response; - - } - - /** - * LDAP form processing. - * - * @author Aladin Alaily - * @since [v1.8] - * @return \Illuminate\Http\RedirectResponse - */ - public function printInventory($id) - { - $this->authorize('view', User::class); - $show_user = User::where('id',$id)->withTrashed()->first(); - $assets = Asset::where('assigned_to', $id)->where('assigned_type', User::class)->with('model', 'model.category')->get(); - $licenses = $show_user->licenses()->get(); - $accessories = $show_user->accessories()->get(); - $consumables = $show_user->consumables()->get(); - return view('users/print')->with('assets', $assets)->with('licenses',$licenses)->with('accessories', $accessories)->with('consumables', $consumables)->with('show_user', $show_user); - - } - -} diff --git a/app/Http/Controllers/ViewAssetsController.php b/app/Http/Controllers/ViewAssetsController.php index 5bf48bb8b0..03aa03bbee 100755 --- a/app/Http/Controllers/ViewAssetsController.php +++ b/app/Http/Controllers/ViewAssetsController.php @@ -1,29 +1,18 @@ withTrashed()->find(Auth::user()->id); + )->withTrashed()->find(Auth::id()); $userlog = $user->userlog->load('item', 'user', 'target'); if (isset($user->id)) { return view('account/view-assets', compact('user', 'userlog')); - } else { - // Prepare the error message - $error = trans('admin/users/message.user_not_found', compact('id')); - - // Redirect to the user management page - return redirect()->route('users.index')->with('error', $error); } + // Redirect to the user management page + return redirect()->route('users.index') + ->with('error', trans('admin/users/message.user_not_found', $user->id)); } + /** + * Returns view of requestable items for a user. + * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View + */ public function getRequestableIndex() { @@ -129,24 +119,23 @@ class ViewAssetsController extends Controller return redirect()->route('requestable-assets')->with('success')->with('success', trans('admin/hardware/message.requests.canceled')); - } else { - $item->request(); - if (($settings->alert_email!='') && ($settings->alerts_enabled=='1') && (!config('app.lock_passwords'))) { - $logaction->logaction('requested'); - $settings->notify(new RequestAssetNotification($data)); - } - - - - return redirect()->route('requestable-assets')->with('success')->with('success', trans('admin/hardware/message.requests.success')); } + $item->request(); + if (($settings->alert_email!='') && ($settings->alerts_enabled=='1') && (!config('app.lock_passwords'))) { + $logaction->logaction('requested'); + $settings->notify(new RequestAssetNotification($data)); + } + + + return redirect()->route('requestable-assets')->with('success')->with('success', trans('admin/hardware/message.requests.success')); } - - - - + /** + * Process a specific requested asset + * @param null $assetId + * @return \Illuminate\Http\RedirectResponse + */ public function getRequestAsset($assetId = null) { @@ -156,7 +145,8 @@ class ViewAssetsController extends Controller if (is_null($asset = Asset::RequestableAssets()->find($assetId))) { return redirect()->route('requestable-assets') ->with('error', trans('admin/hardware/message.does_not_exist_or_not_requestable')); - } elseif (!Company::isCurrentUserHasAccess($asset)) { + } + if (!Company::isCurrentUserHasAccess($asset)) { return redirect()->route('requestable-assets') ->with('error', trans('general.insufficient_permissions')); } @@ -187,17 +177,16 @@ class ViewAssetsController extends Controller $settings->notify(new RequestAssetCancelationNotification($data)); return redirect()->route('requestable-assets') ->with('success')->with('success', trans('admin/hardware/message.requests.cancel-success')); - } else { - - $logaction->logaction('requested'); - $asset->request(); - $asset->increment('requests_counter', 1); - $settings->notify(new RequestAssetNotification($data)); - - - return redirect()->route('requestable-assets')->with('success')->with('success', trans('admin/hardware/message.requests.success')); } + $logaction->logaction('requested'); + $asset->request(); + $asset->increment('requests_counter', 1); + $settings->notify(new RequestAssetNotification($data)); + + + return redirect()->route('requestable-assets')->with('success')->with('success', trans('admin/hardware/message.requests.success')); + } @@ -210,124 +199,6 @@ class ViewAssetsController extends Controller // Get the acceptance screen public function getAcceptAsset($logID = null) { - - $findlog = Actionlog::where('id', $logID)->first(); - - if (!$findlog) { - return redirect()->to('account/view-assets')->with('error', 'No matching record.'); - } - - if ($findlog->accepted_id!='') { - return redirect()->to('account/view-assets')->with('error', trans('admin/users/message.error.asset_already_accepted')); - } - - $user = Auth::user(); - - - // TODO - Fix this for non-assets - if (($findlog->item_type==Asset::class) && ($user->id != $findlog->item->assigned_to)) { - return redirect()->to('account/view-assets')->with('error', trans('admin/users/message.error.incorrect_user_accepted')); - } - - - $item = $findlog->item; - - // Check if the asset exists - if (is_null($item)) { - // Redirect to the asset management page - return redirect()->to('account')->with('error', trans('admin/hardware/message.does_not_exist')); - } elseif (!Company::isCurrentUserHasAccess($item)) { - return redirect()->route('requestable-assets')->with('error', trans('general.insufficient_permissions')); - } else { - return view('account/accept-asset', compact('item'))->with('findlog', $findlog)->with('item', $item); - } - } - - // Save the acceptance - public function postAcceptAsset(Request $request, $logID = null) - { - - // Check if the asset exists - if (is_null($findlog = Actionlog::where('id', $logID)->first())) { - // Redirect to the asset management page - return redirect()->to('account/view-assets')->with('error', trans('admin/hardware/message.does_not_exist')); - } - - - if ($findlog->accepted_id!='') { - // Redirect to the asset management page - return redirect()->to('account/view-assets')->with('error', trans('admin/users/message.error.asset_already_accepted')); - } - - if (!Input::has('asset_acceptance')) { - return redirect()->back()->with('error', trans('admin/users/message.error.accept_or_decline')); - } - - $user = Auth::user(); - - if (($findlog->item_type==Asset::class) && ($user->id != $findlog->item->assigned_to)) { - return redirect()->to('account/view-assets')->with('error', trans('admin/users/message.error.incorrect_user_accepted')); - } - - if ($request->has('signature_output')) { - $path = config('app.private_uploads').'/signatures'; - $sig_filename = "siglog-".$findlog->id.'-'.date('Y-m-d-his').".png"; - $data_uri = e($request->get('signature_output')); - $encoded_image = explode(",", $data_uri); - $decoded_image = base64_decode($encoded_image[1]); - file_put_contents($path."/".$sig_filename, $decoded_image); - } - - - $logaction = new Actionlog(); - - if (Input::get('asset_acceptance')=='accepted') { - $logaction_msg = 'accepted'; - $accepted="accepted"; - $return_msg = trans('admin/users/message.accepted'); - } else { - $logaction_msg = 'declined'; - $accepted="rejected"; - $return_msg = trans('admin/users/message.declined'); - } - $logaction->item_id = $findlog->item_id; - $logaction->item_type = $findlog->item_type; - - // Asset - if (($findlog->item_id!='') && ($findlog->item_type==Asset::class)) { - if (Input::get('asset_acceptance')!='accepted') { - DB::table('assets') - ->where('id', $findlog->item_id) - ->update(array('assigned_to' => null)); - } - } - - $logaction->target_id = $findlog->target_id; - $logaction->target_type = User::class; - $logaction->note = e(Input::get('note')); - $logaction->updated_at = date("Y-m-d H:i:s"); - - - if (isset($sig_filename)) { - $logaction->accept_signature = $sig_filename; - } - $log = $logaction->logaction($logaction_msg); - - $update_checkout = DB::table('action_logs') - ->where('id', $findlog->id) - ->update(array('accepted_id' => $logaction->id)); - - if (($findlog->item_id!='') && ($findlog->item_type==Asset::class)) { - $affected_asset = $logaction->item; - $affected_asset->accepted = $accepted; - $affected_asset->save(); - } - - if ($update_checkout) { - return redirect()->to('account/view-assets')->with('success', $return_msg); - - } else { - return redirect()->to('account/view-assets')->with('error', 'Something went wrong '); - } + return redirect()->route('account.accept'); } } diff --git a/app/Http/Middleware/CheckForSetup.php b/app/Http/Middleware/CheckForSetup.php index e161a912d2..fca16d110e 100644 --- a/app/Http/Middleware/CheckForSetup.php +++ b/app/Http/Middleware/CheckForSetup.php @@ -14,7 +14,10 @@ class CheckForSetup public function handle($request, Closure $next, $guard = null) { - // This is dumb + /** + * This is dumb + * @todo Check on removing this, not sure if it's still needed + */ if ($request->is('_debugbar*')) { return $next($request); } diff --git a/app/Http/Middleware/CheckForTwoFactor.php b/app/Http/Middleware/CheckForTwoFactor.php index 61dcf52690..60df26ad61 100644 --- a/app/Http/Middleware/CheckForTwoFactor.php +++ b/app/Http/Middleware/CheckForTwoFactor.php @@ -1,52 +1,55 @@ route()->getName()=='two-factor') || ($request->route()->getName()=='two-factor-enroll') || ($request->route()->getPrefix()=='setup') || ($request->route()->getName()=='logout')) { + if (in_array($request->route()->getName(), self::IGNORE_ROUTES)) { return $next($request); } // Two-factor is enabled (either optional or required) - if (Setting::getSettings()) { - if (Auth::check() && (Setting::getSettings()->two_factor_enabled!='')) { - + if ($settings = Setting::getSettings()) { + if (Auth::check() && ($settings->two_factor_enabled != '')) { // This user is already 2fa-authed if ($request->session()->get('2fa_authed')) { return $next($request); } // Two-factor is optional and the user has NOT opted in, let them through - if ((Setting::getSettings()->two_factor_enabled=='1') && (Auth::user()->two_factor_optin!='1')) { + if (($settings->two_factor_enabled == '1') && (Auth::user()->two_factor_optin != '1')) { return $next($request); } // Otherwise make sure they're enrolled and show them the 2FA code screen - if ((Auth::user()->two_factor_secret!='') && (Auth::user()->two_factor_enrolled=='1')) { + if ((Auth::user()->two_factor_secret != '') && (Auth::user()->two_factor_enrolled == '1')) { return redirect()->route('two-factor')->with('info', 'Please enter your two-factor authentication code.'); } return redirect()->route('two-factor-enroll')->with('success', 'Please enroll a device in two-factor authentication.'); } } - return $next($request); + return $next($request); } } diff --git a/app/Http/Middleware/CheckLocale.php b/app/Http/Middleware/CheckLocale.php index 2f925e3a0b..3e42a7a901 100644 --- a/app/Http/Middleware/CheckLocale.php +++ b/app/Http/Middleware/CheckLocale.php @@ -4,35 +4,31 @@ namespace App\Http\Middleware; use Closure; use Config; -use Route; -use Schema; use App\Models\Setting; class CheckLocale { - /** - * Handle the locale for the user, default to settings otherwise - * - * @param \Illuminate\Http\Request $request - * @param \Closure $next - * @param string|null $guard - * @return mixed - */ - + /** + * Handle the locale for the user, default to settings otherwise. + * + * @param \Illuminate\Http\Request $request + * @param \Closure $next + * @param string|null $guard + * + * @return mixed + */ public function handle($request, Closure $next, $guard = null) { - - - if (Setting::getSettings()) { + if ($settings = Setting::getSettings()) { // User's preference if (($request->user()) && ($request->user()->locale)) { \App::setLocale($request->user()->locale); - // App setting preference - } elseif ((Setting::getSettings()) && (Setting::getSettings()->locale!='')) { - \App::setLocale(Setting::getSettings()->locale); + // App setting preference + } elseif ($settings->locale != '') { + \App::setLocale($settings->locale); - // Default app setting + // Default app setting } else { \App::setLocale(config('app.locale')); } diff --git a/app/Http/Middleware/EncryptCookies.php b/app/Http/Middleware/EncryptCookies.php index 3aa15f8dd9..e3fe0f8b69 100644 --- a/app/Http/Middleware/EncryptCookies.php +++ b/app/Http/Middleware/EncryptCookies.php @@ -6,6 +6,10 @@ use Illuminate\Cookie\Middleware\EncryptCookies as BaseEncrypter; class EncryptCookies extends BaseEncrypter { + + protected static $serialize = true; + + /** * The names of the cookies that should not be encrypted. * diff --git a/app/Http/Requests/AssetFileRequest.php b/app/Http/Requests/AssetFileRequest.php index 5d3c72f6cb..5a0aa5f003 100644 --- a/app/Http/Requests/AssetFileRequest.php +++ b/app/Http/Requests/AssetFileRequest.php @@ -2,7 +2,8 @@ namespace App\Http\Requests; -use App\Http\Requests\Request; + +use Symfony\Component\HttpFoundation\JsonResponse; class AssetFileRequest extends Request { @@ -25,12 +26,7 @@ class AssetFileRequest extends Request { $max_file_size = \App\Helpers\Helper::file_upload_max_size(); return [ - 'file.*' => 'required|mimes:png,gif,jpg,svg,jpeg,doc,docx,pdf,txt,zip,rar,xls,lic|max:'.$max_file_size, + 'file.*' => 'required|mimes:png,gif,jpg,svg,jpeg,doc,docx,pdf,txt,zip,rar,xls,lic,xml|max:'.$max_file_size, ]; } - - public function response(array $errors) - { - return $this->redirector->back()->withInput()->withErrors($errors, $this->errorBag); - } } diff --git a/app/Http/Requests/AssetRequest.php b/app/Http/Requests/AssetRequest.php deleted file mode 100644 index 4004dcec3f..0000000000 --- a/app/Http/Requests/AssetRequest.php +++ /dev/null @@ -1,68 +0,0 @@ - 'max:255|nullable', - 'model_id' => 'required|integer|exists:models,id', - 'status_id' => 'required|integer|exists:status_labels,id', - 'company_id' => 'integer|nullable', - 'warranty_months' => 'numeric|nullable', - 'physical' => 'integer|nullable', - 'checkout_date' => 'date', - 'checkin_date' => 'date', - 'supplier_id' => 'integer|nullable', - 'status' => 'integer|nullable', - 'purchase_cost' => 'numeric|nullable', - "assigned_user" => 'sometimes:required_without_all:assigned_asset,assigned_location', - "assigned_asset" => 'sometimes:required_without_all:assigned_user,assigned_location', - "assigned_location" => 'sometimes:required_without_all:assigned_user,assigned_asset', - ]; - - $settings = \App\Models\Setting::getSettings(); - - $rules['asset_tag'] = ($settings->auto_increment_assets == '1') ? 'max:255' : 'required'; - - if($this->request->get('model_id') != '') { - $model = AssetModel::find($this->request->get('model_id')); - - if (($model) && ($model->fieldset)) { - $rules += $model->fieldset->validation_rules(); - } - } - - return $rules; - - } - - public function response(array $errors) - { - $this->session()->flash('errors', Session::get('errors', new \Illuminate\Support\ViewErrorBag) - ->put('default', new \Illuminate\Support\MessageBag($errors))); - \Input::flash(); - return parent::response($errors); - } -} diff --git a/app/Http/Requests/ImageUploadRequest.php b/app/Http/Requests/ImageUploadRequest.php index deaecfa61d..19a5453316 100644 --- a/app/Http/Requests/ImageUploadRequest.php +++ b/app/Http/Requests/ImageUploadRequest.php @@ -2,7 +2,10 @@ namespace App\Http\Requests; -use App\Http\Requests\Request; +use App\Models\SnipeModel; +use Intervention\Image\Facades\Image; +use Storage; +use Illuminate\Support\Facades\File; class ImageUploadRequest extends Request { @@ -33,4 +36,53 @@ class ImageUploadRequest extends Request { return $this->redirector->back()->withInput()->withErrors($errors, $this->errorBag); } + + /** + * Handle and store any images attached to request + * @param SnipeModel $item Item the image is associated with + * @param String $path location for uploaded images, defaults to uploads/plural of item type. + * @return SnipeModel Target asset is being checked out to. + */ + public function handleImages($item, $w = 550, $path = null) + { + + $type = strtolower(class_basename(get_class($item))); + + if(is_null($path)) { + $path = str_plural($type); + } + + + if ($this->hasFile('image')) { + if (!config('app.lock_passwords')) { + + if(!Storage::disk('public')->exists($path)) Storage::disk('public')->makeDirectory($path, 775); + + $upload = $image = $this->file('image'); + $ext = $image->getClientOriginalExtension(); + $file_name = $type.'-'.str_random(18).'.'.$ext; + + if ($image->getClientOriginalExtension()!='svg') { + $upload = Image::make($image->getRealPath())->resize(null, $w, function ($constraint) { + $constraint->aspectRatio(); + $constraint->upsize(); + }); + } + + // This requires a string instead of an object, so we use ($string) + Storage::disk('public')->put($path.'/'.$file_name, (string)$upload->encode()); + + // Remove Current image if exists + if (($item->image) && (file_exists($path.'/'.$item->image))) { + Storage::disk('public')->delete($path.'/'.$file_name); + } + + $item->image = $file_name; + } + } elseif ($this->input('image_delete')=='1') { + Storage::disk('public')->delete($path.'/'.$item->image); + $item->image = null; + } + return $item; + } } diff --git a/app/Http/Requests/LicenseCheckoutRequest.php b/app/Http/Requests/LicenseCheckoutRequest.php new file mode 100644 index 0000000000..dd84171452 --- /dev/null +++ b/app/Http/Requests/LicenseCheckoutRequest.php @@ -0,0 +1,32 @@ + 'string|nullable', + 'asset_id' => 'required_without:assigned_to', + ]; + } +} diff --git a/app/Http/Traits/UniqueSerialTrait.php b/app/Http/Traits/UniqueSerialTrait.php index be9a885c08..b5529d7cf8 100644 --- a/app/Http/Traits/UniqueSerialTrait.php +++ b/app/Http/Traits/UniqueSerialTrait.php @@ -1,21 +1,24 @@ unique_serial=='1') { - return 'unique_undeleted:'.$this->table.','. $this->getKey(); + if ($settings = Setting::getSettings()) { + if ($settings->unique_serial == '1') { + return 'unique_undeleted:'.$this->table.','.$this->getKey(); } } } diff --git a/app/Http/Transformers/AccessoriesTransformer.php b/app/Http/Transformers/AccessoriesTransformer.php index fd6832e00c..1f828bd1eb 100644 --- a/app/Http/Transformers/AccessoriesTransformer.php +++ b/app/Http/Transformers/AccessoriesTransformer.php @@ -5,6 +5,7 @@ use App\Models\Accessory; use Gate; use Illuminate\Database\Eloquent\Collection; use App\Helpers\Helper; +use Illuminate\Support\Facades\Storage; class AccessoriesTransformer { @@ -23,6 +24,7 @@ class AccessoriesTransformer $array = [ 'id' => $accessory->id, 'name' => e($accessory->name), + 'image' => ($accessory->image) ? Storage::disk('public')->url('accessories/'.e($accessory->image)) : null, 'company' => ($accessory->company) ? ['id' => $accessory->company->id,'name'=> e($accessory->company->name)] : null, 'manufacturer' => ($accessory->manufacturer) ? ['id' => $accessory->manufacturer->id,'name'=> e($accessory->manufacturer->name)] : null, 'supplier' => ($accessory->supplier) ? ['id' => $accessory->supplier->id,'name'=> e($accessory->supplier->name)] : null, @@ -36,7 +38,7 @@ class AccessoriesTransformer 'order_number' => ($accessory->order_number) ? e($accessory->order_number) : null, 'min_qty' => ($accessory->min_amt) ? (int) $accessory->min_amt : null, 'remaining_qty' => $accessory->numRemaining(), - 'image' => ($accessory->image) ? url('/').'/uploads/accessories/'.e($accessory->image) : null, + 'created_at' => Helper::getFormattedDateObject($accessory->created_at, 'datetime'), 'updated_at' => Helper::getFormattedDateObject($accessory->updated_at, 'datetime'), @@ -61,7 +63,7 @@ class AccessoriesTransformer } - public function transformCheckedoutAccessory ($accessory_users, $total) + public function transformCheckedoutAccessory ($accessory, $accessory_users, $total) { @@ -75,6 +77,7 @@ class AccessoriesTransformer 'first_name'=> e($user->first_name), 'last_name'=> e($user->last_name), 'employee_number' => e($user->employee_num), + 'checkout_notes' => $accessory->lastCheckoutArray[0]['note'], 'type' => 'user', 'available_actions' => ['checkin' => true] ]; diff --git a/app/Http/Transformers/ActionlogsTransformer.php b/app/Http/Transformers/ActionlogsTransformer.php index 53ece05583..c5ea16f598 100644 --- a/app/Http/Transformers/ActionlogsTransformer.php +++ b/app/Http/Transformers/ActionlogsTransformer.php @@ -63,7 +63,7 @@ class ActionlogsTransformer ] : null, 'note' => ($actionlog->note) ? e($actionlog->note): null, - 'signature_file' => ($actionlog->accept_signature) ? route('log.signature.view', ['filename' => $actionlog->accept_signature ]) : null, + 'signature_file' => ($actionlog->signature_filename) ? route('log.signature.view', ['filename' => $actionlog->signature_filename ]) : null, 'log_meta' => ($actionlog->log_meta) ? json_decode($actionlog->log_meta): null, diff --git a/app/Http/Transformers/AssetMaintenancesTransformer.php b/app/Http/Transformers/AssetMaintenancesTransformer.php index ebffa3f744..fc11d7a534 100644 --- a/app/Http/Transformers/AssetMaintenancesTransformer.php +++ b/app/Http/Transformers/AssetMaintenancesTransformer.php @@ -28,6 +28,10 @@ class AssetMaintenancesTransformer 'asset_tag'=> e($assetmaintenance->asset->asset_tag) ] : null, + 'model' => (($assetmaintenance->asset) && ($assetmaintenance->asset->model)) ? [ + 'id' => (int) $assetmaintenance->asset->model->id, + 'name'=> ($assetmaintenance->asset->model->name) ? e($assetmaintenance->asset->model->name).' '.e($assetmaintenance->asset->model->model_number) : null + ] : null, 'company' => (($assetmaintenance->asset) && ($assetmaintenance->asset->company)) ? [ 'id' => (int) $assetmaintenance->asset->company->id, 'name'=> ($assetmaintenance->asset->company->name) ? e($assetmaintenance->asset->company->name) : null, diff --git a/app/Http/Transformers/AssetModelsTransformer.php b/app/Http/Transformers/AssetModelsTransformer.php index 2bb0a9e1a9..a344e76d03 100644 --- a/app/Http/Transformers/AssetModelsTransformer.php +++ b/app/Http/Transformers/AssetModelsTransformer.php @@ -5,6 +5,7 @@ use App\Models\AssetModel; use Illuminate\Database\Eloquent\Collection; use Gate; use App\Helpers\Helper; +use Illuminate\Support\Facades\Storage; class AssetModelsTransformer { @@ -28,7 +29,7 @@ class AssetModelsTransformer 'id' => (int) $assetmodel->manufacturer->id, 'name'=> e($assetmodel->manufacturer->name) ] : null, - 'image' => ($assetmodel->image!='') ? app('models_upload_url').e($assetmodel->image) : null, + 'image' => ($assetmodel->image!='') ? Storage::disk('public')->url('assetmodels/'.e($assetmodel->image)) : null, 'model_number' => e($assetmodel->model_number), 'depreciation' => ($assetmodel->depreciation) ? [ 'id' => (int) $assetmodel->depreciation->id, diff --git a/app/Http/Transformers/AssetsTransformer.php b/app/Http/Transformers/AssetsTransformer.php index 84b5af4193..82b2731cb2 100644 --- a/app/Http/Transformers/AssetsTransformer.php +++ b/app/Http/Transformers/AssetsTransformer.php @@ -120,7 +120,7 @@ class AssetsTransformer 'clone' => Gate::allows('create', Asset::class) ? true : false, 'restore' => false, 'update' => (bool) Gate::allows('update', Asset::class), - 'delete' => (bool) Gate::allows('delete', Asset::class), + 'delete' => ($asset->assigned_to=='' && Gate::allows('delete', Asset::class) ? true : false), ]; if ($asset->deleted_at!='') { diff --git a/app/Http/Transformers/CategoriesTransformer.php b/app/Http/Transformers/CategoriesTransformer.php index 710bf84bc5..b93790f771 100644 --- a/app/Http/Transformers/CategoriesTransformer.php +++ b/app/Http/Transformers/CategoriesTransformer.php @@ -5,6 +5,7 @@ use App\Models\Category; use Illuminate\Database\Eloquent\Collection; use Gate; use App\Helpers\Helper; +use Illuminate\Support\Facades\Storage; class CategoriesTransformer { @@ -25,7 +26,7 @@ class CategoriesTransformer $array = [ 'id' => (int) $category->id, 'name' => e($category->name), - 'image' => ($category->image) ? app('categories_upload_url').e($category->image) : null, + 'image' => ($category->image) ? Storage::disk('public')->url('categories/'.e($category->image)) : null, 'category_type' => e($category->category_type), 'eula' => ($category->getEula()) ? true : false, 'checkin_email' => ($category->checkin_email =='1') ? true : false, diff --git a/app/Http/Transformers/CompaniesTransformer.php b/app/Http/Transformers/CompaniesTransformer.php index 96951bdf85..7fac8ee6d0 100644 --- a/app/Http/Transformers/CompaniesTransformer.php +++ b/app/Http/Transformers/CompaniesTransformer.php @@ -5,6 +5,7 @@ use App\Models\Company; use Illuminate\Database\Eloquent\Collection; use Gate; use App\Helpers\Helper; +use Illuminate\Support\Facades\Storage; class CompaniesTransformer { @@ -25,7 +26,7 @@ class CompaniesTransformer $array = [ 'id' => (int) $company->id, 'name' => e($company->name), - 'image' => ($company->image) ? app('companies_upload_url').e($company->image) : null, + 'image' => ($company->image) ? Storage::disk('public')->url('companies/'.e($company->image)) : null, "created_at" => Helper::getFormattedDateObject($company->created_at, 'datetime'), "updated_at" => Helper::getFormattedDateObject($company->updated_at, 'datetime'), "assets_count" => (int) $company->assets_count, diff --git a/app/Http/Transformers/ComponentsTransformer.php b/app/Http/Transformers/ComponentsTransformer.php index cf51b55d79..6cd4b98c70 100644 --- a/app/Http/Transformers/ComponentsTransformer.php +++ b/app/Http/Transformers/ComponentsTransformer.php @@ -5,6 +5,7 @@ use App\Models\Component; use Illuminate\Database\Eloquent\Collection; use App\Helpers\Helper; use Gate; +use Illuminate\Support\Facades\Storage; class ComponentsTransformer { @@ -22,7 +23,7 @@ class ComponentsTransformer $array = [ 'id' => (int) $component->id, 'name' => e($component->name), - 'image' => ($component->image) ? e(url('/').'/uploads/components/'.e($component->image)) : null, + 'image' => ($component->image) ? Storage::disk('public')->url('components/'.e($component->image)) : null, 'serial' => ($component->serial) ? e($component->serial) : null, 'location' => ($component->location) ? [ 'id' => (int) $component->location->id, diff --git a/app/Http/Transformers/ConsumablesTransformer.php b/app/Http/Transformers/ConsumablesTransformer.php index 3d68697a58..36ec8d9c24 100644 --- a/app/Http/Transformers/ConsumablesTransformer.php +++ b/app/Http/Transformers/ConsumablesTransformer.php @@ -5,6 +5,7 @@ use App\Models\Consumable; use Illuminate\Database\Eloquent\Collection; use App\Helpers\Helper; use Gate; +use Illuminate\Support\Facades\Storage; class ConsumablesTransformer { @@ -23,7 +24,7 @@ class ConsumablesTransformer $array = [ 'id' => (int) $consumable->id, 'name' => e($consumable->name), - 'image' => ($consumable->image) ? e(url('/').'/uploads/consumables/'.e($consumable->image)) : null, + 'image' => ($consumable->image) ? Storage::disk('public')->url('consumables/'.e($consumable->image)) : null, 'category' => ($consumable->category) ? ['id' => $consumable->category->id, 'name' => e($consumable->category->name)] : null, 'company' => ($consumable->company) ? ['id' => (int) $consumable->company->id, 'name' => e($consumable->company->name)] : null, 'item_no' => e($consumable->item_no), diff --git a/app/Http/Transformers/DepartmentsTranformer.php b/app/Http/Transformers/DepartmentsTranformer.php index f81954f947..a24943b96e 100644 --- a/app/Http/Transformers/DepartmentsTranformer.php +++ b/app/Http/Transformers/DepartmentsTranformer.php @@ -5,6 +5,7 @@ use App\Models\Department; use Illuminate\Database\Eloquent\Collection; use Gate; use App\Helpers\Helper; +use Illuminate\Support\Facades\Storage; class DepartmentsTransformer { @@ -25,7 +26,7 @@ class DepartmentsTransformer $array = [ 'id' => (int) $department->id, 'name' => e($department->name), - 'image' => ($department->image) ? app('departments_upload_url').e($department->image) : null, + 'image' => ($department->image) ? Storage::disk('public')->url(app('departments_upload_url').e($department->image)) : null, 'company' => ($department->company) ? [ 'id' => (int) $department->company->id, 'name'=> e($department->company->name) diff --git a/app/Http/Transformers/LocationsTransformer.php b/app/Http/Transformers/LocationsTransformer.php index 5d93db4def..ce018d4f6c 100644 --- a/app/Http/Transformers/LocationsTransformer.php +++ b/app/Http/Transformers/LocationsTransformer.php @@ -5,6 +5,7 @@ use App\Models\Location; use Illuminate\Database\Eloquent\Collection; use Gate; use App\Helpers\Helper; +use Illuminate\Support\Facades\Storage; class LocationsTransformer { @@ -33,7 +34,7 @@ class LocationsTransformer $array = [ 'id' => (int) $location->id, 'name' => e($location->name), - 'image' => ($location->image) ? app('locations_upload_url').e($location->image) : null, + 'image' => ($location->image) ? Storage::disk('public')->url('locations/'.e($location->image)) : null, 'address' => ($location->address) ? e($location->address) : null, 'address2' => ($location->address2) ? e($location->address2) : null, 'city' => ($location->city) ? e($location->city) : null, diff --git a/app/Http/Transformers/LoginAttemptsTransformer.php b/app/Http/Transformers/LoginAttemptsTransformer.php new file mode 100644 index 0000000000..ca6d7ffbe0 --- /dev/null +++ b/app/Http/Transformers/LoginAttemptsTransformer.php @@ -0,0 +1,42 @@ +transformDatatables($array, $total); + } + + public function transformLoginAttempt($login_attempt) + { + + if ($login_attempt) { + $array = [ + 'id' => (int) $login_attempt->id, + 'username' => e($login_attempt->username), + 'user_agent' => e($login_attempt->user_agent), + 'remote_ip' => (!config('app.lock_passwords')) ? e($login_attempt->remote_ip) : '--', + 'successful' => e($login_attempt->successful), + 'created_at' => Helper::getFormattedDateObject($login_attempt->created_at, 'datetime'), + ]; + return $array; + } + + + } + + + +} diff --git a/app/Http/Transformers/ManufacturersTransformer.php b/app/Http/Transformers/ManufacturersTransformer.php index 3db65ee9f0..5457d1c947 100644 --- a/app/Http/Transformers/ManufacturersTransformer.php +++ b/app/Http/Transformers/ManufacturersTransformer.php @@ -5,6 +5,7 @@ use App\Models\Manufacturer; use Illuminate\Database\Eloquent\Collection; use Gate; use App\Helpers\Helper; +use Illuminate\Support\Facades\Storage; class ManufacturersTransformer { @@ -26,7 +27,7 @@ class ManufacturersTransformer 'id' => (int) $manufacturer->id, 'name' => e($manufacturer->name), 'url' => e($manufacturer->url), - 'image' => ($manufacturer->image) ? app('manufacturers_upload_url').e($manufacturer->image) : null, + 'image' => ($manufacturer->image) ? Storage::disk('public')->url('manufacturers/'.e($manufacturer->image)) : null, 'support_url' => e($manufacturer->support_url), 'support_phone' => e($manufacturer->support_phone), 'support_email' => e($manufacturer->support_email), diff --git a/app/Http/Transformers/SuppliersTransformer.php b/app/Http/Transformers/SuppliersTransformer.php index 0070f7c677..a3bb8c6f27 100644 --- a/app/Http/Transformers/SuppliersTransformer.php +++ b/app/Http/Transformers/SuppliersTransformer.php @@ -5,6 +5,7 @@ use App\Models\Supplier; use Illuminate\Database\Eloquent\Collection; use Gate; use App\Helpers\Helper; +use Illuminate\Support\Facades\Storage; class SuppliersTransformer { @@ -25,7 +26,8 @@ class SuppliersTransformer $array = [ 'id' => (int) $supplier->id, 'name' => e($supplier->name), - 'image' => ($supplier->image) ? app('suppliers_upload_url').e($supplier->image) : null, + 'image' => ($supplier->image) ? Storage::disk('public')->url('suppliers/'.e($supplier->image)) : null, + 'url' => e($supplier->url), 'address' => ($supplier->address) ? e($supplier->address) : null, 'address2' => ($supplier->address2) ? e($supplier->address2) : null, 'city' => ($supplier->city) ? e($supplier->city) : null, diff --git a/app/Http/Transformers/UsersTransformer.php b/app/Http/Transformers/UsersTransformer.php index 569b3b56af..1f14ab219c 100644 --- a/app/Http/Transformers/UsersTransformer.php +++ b/app/Http/Transformers/UsersTransformer.php @@ -97,8 +97,4 @@ class UsersTransformer return (new DatatablesTransformer)->transformDatatables($users); } - - - - } diff --git a/app/Importer/AssetImporter.php b/app/Importer/AssetImporter.php index e0977eac6c..b477e4e580 100644 --- a/app/Importer/AssetImporter.php +++ b/app/Importer/AssetImporter.php @@ -28,8 +28,13 @@ class AssetImporter extends ItemImporter foreach ($this->customFields as $customField) { $customFieldValue = $this->array_smart_custom_field_fetch($row, $customField); if ($customFieldValue) { - $this->item['custom_fields'][$customField->db_column_name()] = $customFieldValue; - $this->log('Custom Field '. $customField->name.': '.$customFieldValue); + if($customField->field_encrypted == 1){ + $this->item['custom_fields'][$customField->db_column_name()] = \Crypt::encrypt($customFieldValue); + $this->log('Custom Field '. $customField->name.': '.\Crypt::encrypt($customFieldValue)); + } else { + $this->item['custom_fields'][$customField->db_column_name()] = $customFieldValue; + $this->log('Custom Field '. $customField->name.': '.$customFieldValue); + } } else { // Clear out previous data. $this->item['custom_fields'][$customField->db_column_name()] = null; diff --git a/app/Importer/Importer.php b/app/Importer/Importer.php index b5aafd4bce..dc517efe92 100644 --- a/app/Importer/Importer.php +++ b/app/Importer/Importer.php @@ -117,10 +117,18 @@ abstract class Importer // Cached Values for import lookups protected $customFields; + /** + * Sets up the database transaction and logging for the importer + * + * @return void + * @author Daniel Meltzer + * @since 5.0 + */ public function import() { $headerRow = $this->csv->fetchOne(); - $results = $this->normalizeInputArray($this->csv->fetchAssoc()); + $this->csv->setHeaderOffset(0); + $results = $this->normalizeInputArray($this->csv->getRecords()); $this->populateCustomFields($headerRow); @@ -154,7 +162,7 @@ abstract class Importer // This 'inverts' the fields such that we have a collection of fields indexed by name. $this->customFields = CustomField::All()->reduce(function ($nameLookup, $field) { $nameLookup[$field['name']] = $field; - return $nameLookup; + return $nameLookup; }); // Remove any custom fields that do not exist in the header row. This prevents nulling out values that shouldn't exist. // In detail, we compare the lower case name of custom fields (indexed by name) to the keys in the header row. This @@ -272,7 +280,12 @@ abstract class Importer 'username' => $this->findCsvMatch($row, "username"), 'activated' => $this->fetchHumanBoolean($this->findCsvMatch($row, 'activated')), ]; - \Log::debug('Importer.php Activated: '.$this->findCsvMatch($row, 'activated')); + + // Maybe we're lucky and the user already exists. + if($user = User::where('username', $user_array['username'])->first()) { + $this->log('User '.$user_array['username'].' already exists'); + return $user; + } // If the full name is empty, bail out--we need this to extract first name (at the very least) if(empty($user_array['full_name'])) { @@ -291,7 +304,7 @@ abstract class Importer $user_array['email'] = User::generateEmailFromFullName($user_array['full_name']); } - $user_formatted_array = User::generateFormattedNameFromFullName(Setting::getSettings()->username_format, $user_array['full_name']); + $user_formatted_array = User::generateFormattedNameFromFullName($user_array['full_name'], Setting::getSettings()->username_format); $user_array['first_name'] = $user_formatted_array['first_name']; $user_array['last_name'] = $user_formatted_array['last_name']; @@ -316,14 +329,14 @@ abstract class Importer // No Luck, let's create one. $user = new User; - $user->first_name = $user_array['first_name']; - $user->last_name = $user_array['last_name']; - $user->username = $user_array['username']; - $user->email = $user_array['email']; - $user->manager_id = (isset($user_array['manager_id']) ? $user_array['manager_id'] : null); - $user->department_id = (isset($user_array['department_id']) ? $user_array['department_id']: null); - $user->activated = $user_array['activated']; - $user->password = $this->tempPassword; + $user->first_name = $user_array['first_name']; + $user->last_name = $user_array['last_name']; + $user->username = $user_array['username']; + $user->email = $user_array['email']; + $user->manager_id = $user_array['manager_id'] ?? null; + $user->department_id = $user_array['department_id'] ?? null; + $user->activated = 1; + $user->password = $this->tempPassword; \Log::debug('Creating a user with the following attributes: '.print_r($user_array, true)); @@ -379,9 +392,9 @@ abstract class Importer } /** - * Sets the Are we updating items in the import. + * Sets whether or not we should notify the user with a welcome email * - * @param bool $updating the updating + * @param bool $send_welcome the send-welcome flag * * @return self */ diff --git a/app/Importer/ItemImporter.php b/app/Importer/ItemImporter.php index 224a612e7b..4895545e22 100644 --- a/app/Importer/ItemImporter.php +++ b/app/Importer/ItemImporter.php @@ -61,8 +61,9 @@ class ItemImporter extends Importer $this->item['department_id'] = $this->createOrFetchDepartment($item_department); } - $item_manager_first_name = $this->findCsvMatch($row, "manager_first_name"); - $item_manager_last_name = $this->findCsvMatch($row, "manager_last_name"); + $item_manager_first_name = $this->findCsvMatch($row, "manage_first_name"); + $item_manager_last_name = $this->findCsvMatch($row, "manage_last_name"); + if ($this->shouldUpdateField($item_manager_first_name)) { $this->item['manager_id'] = $this->fetchManager($item_manager_first_name, $item_manager_last_name); } @@ -160,7 +161,7 @@ class ItemImporter extends Importer * @param $field string * @return boolean */ - private function shouldUpdateField($field) + protected function shouldUpdateField($field) { if (empty($field)) { return false; @@ -173,8 +174,7 @@ class ItemImporter extends Importer * @author Daniel Melzter * @since 3.0 * @param array - * @param $category Category - * @param $row Manufacturer + * @param $row Row * @return int Id of asset model created/found * @internal param $asset_modelno string */ @@ -294,6 +294,27 @@ class ItemImporter extends Importer + /** + * Fetch an existing manager + * + * @author A. Gianotto + * @since 4.6.5 + * @param $user_manager string + * @return int id of company created/found + */ + public function fetchManager($user_manager_first_name, $user_manager_last_name) + { + $manager = User::where('first_name', '=', $user_manager_first_name) + ->where('last_name', '=', $user_manager_last_name)->first(); + if ($manager) { + $this->log('A matching Manager ' . $user_manager_first_name . ' '. $user_manager_last_name . ' already exists'); + return $manager->id; + } + $this->log('No matching Manager ' . $user_manager_first_name . ' '. $user_manager_last_name . ' found. If their user account is being created through this import, you should re-process this file again. '); + return null; + } + + /** * Fetch the existing status label or create new if it doesn't exist. * diff --git a/app/Importer/UserImporter.php b/app/Importer/UserImporter.php index bd5bbc1d5b..1bf4be207b 100644 --- a/app/Importer/UserImporter.php +++ b/app/Importer/UserImporter.php @@ -3,6 +3,7 @@ namespace App\Importer; use App\Helpers\Helper; +use App\Models\Department; use App\Models\User; use App\Notifications\WelcomeNotification; @@ -53,10 +54,13 @@ class UserImporter extends ItemImporter \Log::debug('UserImporter.php Activated fetchHumanBoolean: '. $this->fetchHumanBoolean($this->findCsvMatch($row, 'activated'))); $this->item['employee_num'] = $this->findCsvMatch($row, 'employee_num'); - $this->item['department_id'] = $this->createOrFetchDepartment($this->findCsvMatch($row, 'department')) ? $this->createOrFetchDepartment($this->findCsvMatch($row, 'department')) : null; - $this->item['manager_id'] = $this->fetchManager($this->findCsvMatch($row, 'manager_first_name'), $this->findCsvMatch($row, 'manager_last_name')) ? $this->fetchManager($this->findCsvMatch($row, 'manager_first_name'), $this->findCsvMatch($row, 'manager_last_name')) : null; - + $this->item['department_id'] = $this->createOrFetchDepartment($this->findCsvMatch($row, 'department')); + $this->item['manager_id'] = $this->fetchManager($this->findCsvMatch($row, 'manager_first_name'), $this->findCsvMatch($row, 'manager_last_name')); + $user_department = $this->findCsvMatch($row, 'department'); + if ($this->shouldUpdateField($user_department)) { + $this->item["department_id"] = $this->createOrFetchDepartment($user_department); + } $user = User::where('username', $this->item['username'])->first(); if ($user) { if (!$this->updating) { @@ -75,13 +79,14 @@ class UserImporter extends ItemImporter // This needs to be applied after the update logic, otherwise we'll overwrite user passwords // Issue #5408 - $this->item['password'] = $this->tempPassword; + $this->item['password'] = bcrypt($this->tempPassword); $this->log("No matching user, creating one"); $user = new User(); $user->fill($this->sanitizeItemForStoring($user)); if ($user->save()) { + // $user->logCreate('Imported using CSV Importer'); $this->log("User " . $this->item["name"] . ' was created'); if(($user->email) && ($user->activated=='1')) { @@ -92,11 +97,9 @@ class UserImporter extends ItemImporter 'last_name' => $user->last_name, 'password' => $this->tempPassword, ]; - if ($this->send_welcome) { $user->notify(new WelcomeNotification($data)); } - } $user = null; $this->item = null; @@ -106,4 +109,31 @@ class UserImporter extends ItemImporter $this->logError($user, 'User'); return; } + + /** + * Fetch an existing department, or create new if it doesn't exist + * + * @author Daniel Melzter + * @since 5.0 + * @param $department_name string + * @return int id of department created/found + */ + public function createOrFetchDepartment($department_name) + { + $department = Department::where(['name' => $department_name])->first(); + if ($department) { + $this->log('A matching department ' . $department_name . ' already exists'); + return $department->id; + } + $department = new department(); + $department->name = $department_name; + $department->user_id = $this->user_id; + + if ($department->save()) { + $this->log('department ' . $department_name . ' was created'); + return $department->id; + } + $this->logError($department, 'Company'); + return null; + } } diff --git a/app/Importer/import_mappings.md b/app/Importer/import_mappings.md index b65a655b21..0642241525 100644 --- a/app/Importer/import_mappings.md +++ b/app/Importer/import_mappings.md @@ -7,14 +7,13 @@ | department_id | | User ? All | | item name | item_name | All | | image | image | Asset | -| email | | | +| department_id | | User ? All | | expiration date | expiration_date | License | | location | location | All | | notes | notes | All | | licensed to email | license_email | License | | licensed to name | license_name | License | | maintained | maintained | License | -| manager_id | | User | | manufacturer | manufacturer | All | | model name | asset_model | Asset | | model number | model_number | Asset | @@ -33,5 +32,6 @@ | warranty months | warranty_months | Asset | | User Related Fields | assigned_to | Asset | | name | | | +| email | | | | username | | | diff --git a/app/Listeners/CheckoutableListener.php b/app/Listeners/CheckoutableListener.php new file mode 100644 index 0000000000..c209dac612 --- /dev/null +++ b/app/Listeners/CheckoutableListener.php @@ -0,0 +1,198 @@ +checkedOutTo instanceof User) { + return; + } + + /** + * Make a checkout acceptance and attach it in the notification + */ + $acceptance = $this->getCheckoutAcceptance($event); + + if(!$event->checkedOutTo->locale){ + Notification::locale(Setting::getSettings()->locale)->send( + $this->getNotifiables($event), + $this->getCheckoutNotification($event, $acceptance) + ); + } else { + Notification::send( + $this->getNotifiables($event), + $this->getCheckoutNotification($event, $acceptance) + ); + } + } + + /** + * Notify the user about the checked in checkoutable + */ + public function onCheckedIn($event) { + /** + * When the item wasn't checked out to a user, we can't send notifications + */ + if(!$event->checkedOutTo instanceof User) { + return; + } + + /** + * Send the appropriate notification + */ + if(!$event->checkedOutTo->locale){ + Notification::locale(Setting::getSettings()->locale)->send( + $this->getNotifiables($event), + $this->getCheckinNotification($event) + ); + } else { + Notification::send( + $this->getNotifiables($event), + $this->getCheckinNotification($event) + ); + } + } + + /** + * Generates a checkout acceptance + * @param Event $event + * @return mixed + */ + private function getCheckoutAcceptance($event) { + if (!$event->checkoutable->requireAcceptance()) { + return null; + } + + $acceptance = new CheckoutAcceptance; + $acceptance->checkoutable()->associate($event->checkoutable); + $acceptance->assignedTo()->associate($event->checkedOutTo); + $acceptance->save(); + + return $acceptance; + } + + /** + * Gets the entities to be notified of the passed event + * + * @param Event $event + * @return Collection + */ + private function getNotifiables($event) { + $notifiables = collect(); + + /** + * Notify the user who checked out the item + */ + $notifiables->push($event->checkedOutTo); + + /** + * Notify Admin users if the settings is activated + */ + if (Setting::getSettings()->admin_cc_email != '') { + $notifiables->push(new AdminRecipient()); + } + + return $notifiables; + } + + /** + * Get the appropriate notification for the event + * + * @param CheckoutableCheckedIn $event + * @return Notification + */ + private function getCheckinNotification($event) { + + $model = get_class($event->checkoutable); + + $notificationClass = null; + + switch (get_class($event->checkoutable)) { + case Accessory::class: + $notificationClass = CheckinAccessoryNotification::class; + break; + case Asset::class: + $notificationClass = CheckinAssetNotification::class; + break; + case LicenseSeat::class: + $notificationClass = CheckinLicenseSeatNotification::class; + break; + } + + return new $notificationClass($event->checkoutable, $event->checkedOutTo, $event->checkedInBy, $event->note); + } + + /** + * Get the appropriate notification for the event + * + * @param CheckoutableCheckedIn $event + * @param CheckoutAcceptance $acceptance + * @return Notification + */ + private function getCheckoutNotification($event, $acceptance) { + $notificationClass = null; + + switch (get_class($event->checkoutable)) { + case Accessory::class: + $notificationClass = CheckoutAccessoryNotification::class; + break; + case Asset::class: + $notificationClass = CheckoutAssetNotification::class; + break; + case Consumable::class: + $notificationClass = CheckoutConsumableNotification::class; + break; + case LicenseSeat::class: + $notificationClass = CheckoutLicenseSeatNotification::class; + break; + } + + return new $notificationClass($event->checkoutable, $event->checkedOutTo, $event->checkedOutBy, $acceptance, $event->note); + } + + /** + * Register the listeners for the subscriber. + * + * @param Illuminate\Events\Dispatcher $events + */ + public function subscribe($events) + { + $events->listen( + 'App\Events\CheckoutableCheckedIn', + 'App\Listeners\CheckoutableListener@onCheckedIn' + ); + + $events->listen( + 'App\Events\CheckoutableCheckedOut', + 'App\Listeners\CheckoutableListener@onCheckedOut' + ); + } + +} \ No newline at end of file diff --git a/app/Listeners/LogListener.php b/app/Listeners/LogListener.php new file mode 100644 index 0000000000..cdb4fda1fc --- /dev/null +++ b/app/Listeners/LogListener.php @@ -0,0 +1,90 @@ +checkoutable->logCheckin($event->checkedOutTo, $event->note); + } + + public function onCheckoutableCheckedOut(CheckoutableCheckedOut $event) { + $event->checkoutable->logCheckout($event->note, $event->checkedOutTo); + } + + public function onCheckoutAccepted(CheckoutAccepted $event) { + $logaction = new Actionlog(); + + $logaction->item()->associate($event->acceptance->checkoutable); + $logaction->target()->associate($event->acceptance->assignedTo); + $logaction->accept_signature = $event->acceptance->signature_filename; + $logaction->action_type = 'accepted'; + + // TODO: log the actual license seat that was checked out + if($event->acceptance->checkoutable instanceof LicenseSeat) { + $logaction->item()->associate($event->acceptance->checkoutable->license); + } + + $logaction->save(); + } + + public function onCheckoutDeclined(CheckoutDeclined $event) { + $logaction = new Actionlog(); + $logaction->item()->associate($event->acceptance->checkoutable); + $logaction->target()->associate($event->acceptance->assignedTo); + $logaction->accept_signature = $event->acceptance->signature_filename; + $logaction->action_type = 'declined'; + + // TODO: log the actual license seat that was checked out + if($event->acceptance->checkoutable instanceof LicenseSeat) { + $logaction->item()->associate($event->acceptance->checkoutable->license); + } + + $logaction->save(); + } + + /** + * Register the listeners for the subscriber. + * + * @param Illuminate\Events\Dispatcher $events + */ + public function subscribe($events) + { + $list = [ + 'CheckoutableCheckedIn', + 'CheckoutableCheckedOut', + 'CheckoutAccepted', + 'CheckoutDeclined', + ]; + + foreach($list as $event) { + $events->listen( + 'App\Events\\' . $event, + 'App\Listeners\LogListener@on' . $event + ); + } + } + +} \ No newline at end of file diff --git a/app/Models/Accessory.php b/app/Models/Accessory.php index 944304d806..41dee8ef13 100755 --- a/app/Models/Accessory.php +++ b/app/Models/Accessory.php @@ -1,12 +1,14 @@ ['name'], 'location' => ['name'] ]; - - /** - * Set static properties to determine which checkout/checkin handlers we should use - */ - public static $checkoutClass = CheckoutAccessoryNotification::class; - public static $checkinClass = CheckinAccessoryNotification::class; - /** * Accessory validation rules @@ -101,13 +98,26 @@ class Accessory extends SnipeModel - + /** + * Establishes the accessory -> supplier relationship + * + * @author [A. Gianotto] [] + * @since [v3.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function supplier() { return $this->belongsTo('\App\Models\Supplier', 'supplier_id'); } - + + /** + * Sets the requestable attribute on the accessory + * + * @author [A. Gianotto] [] + * @since [v4.0] + * @return void + */ public function setRequestableAttribute($value) { if ($value == '') { @@ -117,62 +127,176 @@ class Accessory extends SnipeModel return; } + /** + * Establishes the accessory -> company relationship + * + * @author [A. Gianotto] [] + * @since [v3.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function company() { return $this->belongsTo('\App\Models\Company', 'company_id'); } + /** + * Establishes the accessory -> location relationship + * + * @author [A. Gianotto] [] + * @since [v3.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function location() { return $this->belongsTo('\App\Models\Location', 'location_id'); } + /** + * Establishes the accessory -> category relationship + * + * @author [A. Gianotto] [] + * @since [v3.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function category() { return $this->belongsTo('\App\Models\Category', 'category_id')->where('category_type', '=', 'accessory'); } /** - * Get action logs for this accessory - */ + * Returns the action logs associated with the accessory + * + * @author [A. Gianotto] [] + * @since [v3.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function assetlog() { return $this->hasMany('\App\Models\Actionlog', 'item_id')->where('item_type', Accessory::class)->orderBy('created_at', 'desc')->withTrashed(); } + /** + * Get the LAST checkout for this accessory. + * + * This is kinda gross, but is necessary for how the accessory + * pivot stuff works for now. + * + * It looks like we should be able to use ->first() here and + * return an object instead of a collection, but we actually + * cannot. + * + * In short, you cannot execute the query defined when you're eager loading. + * and in order to avoid 1001 query problems when displaying the most + * recent checkout note, we have to eager load this. + * + * This means we technically return a collection of one here, and then + * in the controller, we convert that collection to an array, so we can + * use it in the transformer to display only the notes of the LAST + * checkout. + * + * It's super-mega-assy, but it's the best I could do for now. + * + * @author A. Gianotto + * @since v5.0.0 + * + * @see \App\Http\Controllers\Api\AccessoriesController\checkedout() + * + */ + public function lastCheckout() + { + return $this->assetlog()->where('action_type','=','checkout')->take(1); + } + + + /** + * Sets the full image url + * + * @todo this should probably be moved out of the model and into a + * presenter or service provider + * + * @author [A. Gianotto] [] + * @since [v3.0] + * @return string + */ public function getImageUrl() { if ($this->image) { - return url('/').'/uploads/accessories/'.$this->image; + return Storage::disk('public')->url(app('accessories_upload_path').$this->image); } return false; } + /** + * Establishes the accessory -> users relationship + * + * @author [A. Gianotto] [] + * @since [v3.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ + public function users() { return $this->belongsToMany('\App\Models\User', 'accessories_users', 'accessory_id', 'assigned_to')->withPivot('id')->withTrashed(); } + /** + * Checks whether or not the accessory has users + * + * @author [A. Gianotto] [] + * @since [v3.0] + * @return int + */ public function hasUsers() { return $this->belongsToMany('\App\Models\User', 'accessories_users', 'accessory_id', 'assigned_to')->count(); } + /** + * Establishes the accessory -> manufacturer relationship + * + * @author [A. Gianotto] [] + * @since [v3.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function manufacturer() { return $this->belongsTo('\App\Models\Manufacturer', 'manufacturer_id'); } + /** + * Determins whether or not an email should be sent for checkin/checkout of this + * accessory based on the category it belongs to. + * + * @author [A. Gianotto] [] + * @since [v3.0] + * @return boolean + */ public function checkin_email() { return $this->category->checkin_email; } + /** + * Determines whether or not the accessory should require the user to + * accept it via email. + * + * @author [A. Gianotto] [] + * @since [v3.0] + * @return boolean + */ public function requireAcceptance() { return $this->category->require_acceptance; } + /** + * Checks for a category-specific EULA, and if that doesn't exist, + * checks for a settings level EULA + * + * @author [A. Gianotto] [] + * @since [v3.0] + * @return string + */ public function getEula() { @@ -186,6 +310,13 @@ class Accessory extends SnipeModel return null; } + /** + * Check how many items of an accessory remain + * + * @author [A. Gianotto] [] + * @since [v3.0] + * @return int + */ public function numRemaining() { $checkedout = $this->users->count(); diff --git a/app/Models/Actionlog.php b/app/Models/Actionlog.php index b2945b8d13..f28ab36895 100755 --- a/app/Models/Actionlog.php +++ b/app/Models/Actionlog.php @@ -41,9 +41,15 @@ class Actionlog extends SnipeModel */ protected $searchableRelations = [ 'company' => ['name'] - ]; + ]; - // Overridden from Builder to automatically add the company + /** + * Override from Builder to automatically add the company + * + * @author [A. Gianotto] [] + * @since [v3.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public static function boot() { parent::boot(); @@ -60,17 +66,39 @@ class Actionlog extends SnipeModel } }); } - // Eloquent Relationships below + + + /** + * Establishes the actionlog -> item relationship + * + * @author [A. Gianotto] [] + * @since [v3.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function item() { return $this->morphTo('item')->withTrashed(); } + /** + * Establishes the actionlog -> company relationship + * + * @author [A. Gianotto] [] + * @since [v3.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function company() { return $this->hasMany('\App\Models\Company', 'id', 'company_id'); } + /** + * Establishes the actionlog -> item type relationship + * + * @author [A. Gianotto] [] + * @since [v3.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function itemType() { @@ -80,6 +108,13 @@ class Actionlog extends SnipeModel return camel_case(class_basename($this->item_type)); } + /** + * Establishes the actionlog -> target type relationship + * + * @author [A. Gianotto] [] + * @since [v3.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function targetType() { if ($this->target_type == User::class) { @@ -88,28 +123,14 @@ class Actionlog extends SnipeModel return camel_case(class_basename($this->target_type)); } - public function parseItemRoute() - { - if ($this->itemType() == "asset") { - $itemroute = 'assets'; - } elseif ($this->itemType() == "accessory") { - $itemroute = 'accessories'; - } elseif ($this->itemType()=="consumable") { - $itemroute = 'consumables'; - } elseif ($this->itemType()=="license") { - $itemroute = 'licenses'; - } elseif ($this->itemType()=="component") { - $itemroute = 'components'; - } else { - $itemroute = ''; - } - - return $itemroute; - } - - - + /** + * Establishes the actionlog -> uploads relationship + * + * @author [A. Gianotto] [] + * @since [v3.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function uploads() { return $this->morphTo('item') @@ -117,39 +138,62 @@ class Actionlog extends SnipeModel ->withTrashed(); } + /** + * Establishes the actionlog -> userlog relationship + * + * @author [A. Gianotto] [] + * @since [v3.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function userlog() { return $this->target(); } + /** + * Establishes the actionlog -> user relationship + * + * @author [A. Gianotto] [] + * @since [v3.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function user() { return $this->belongsTo(User::class, 'user_id') ->withTrashed(); } + /** + * Establishes the actionlog -> target relationship + * + * @author [A. Gianotto] [] + * @since [v3.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function target() { return $this->morphTo('target')->withTrashed(); } - public function childlogs() - { - return $this->hasMany('\App\Models\ActionLog', 'thread_id'); - } - - public function parentlog() - { - return $this->belongsTo('\App\Models\ActionLog', 'thread_id'); - } - + /** + * Establishes the actionlog -> location relationship + * + * @author [A. Gianotto] [] + * @since [v3.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function location() { return $this->belongsTo('\App\Models\Location', 'location_id' )->withTrashed(); } + /** - * Check if the file exists, and if it does, force a download - **/ + * Check if the file exists, and if it does, force a download + * + * @author [A. Gianotto] [] + * @since [v3.0] + * @return string | false + */ public function get_src($type = 'assets', $fieldname = 'filename') { if ($this->filename!='') { @@ -162,8 +206,12 @@ class Actionlog extends SnipeModel /** - * Get the parent category name - */ + * Saves the log record with the action type + * + * @author [A. Gianotto] [] + * @since [v3.0] + * @return boolean + */ public function logaction($actiontype) { @@ -176,6 +224,13 @@ class Actionlog extends SnipeModel } } + /** + * Calculate the number of days until the next audit + * + * @author [A. Gianotto] [] + * @since [v4.0] + * @return int + */ public function daysUntilNextAudit($monthInterval = 12, $asset = null) { $now = Carbon::now(); @@ -192,6 +247,13 @@ class Actionlog extends SnipeModel return $next_audit_days; } + /** + * Calculate the date of the next audit + * + * @author [A. Gianotto] [] + * @since [v4.0] + * @return \Datetime + */ public function calcNextAuditDate($monthInterval = 12, $asset = null) { $last_audit_date = Carbon::parse($this->created_at); @@ -204,12 +266,12 @@ class Actionlog extends SnipeModel } /** - * getListingOfActionLogsChronologicalOrder - * - * @return mixed - * @author Vincent Sposato - * @version v1.0 - */ + * Gets action logs in chronological order, excluding uploads + * + * @author Vincent Sposato + * @since v1.0 + * @return \Illuminate\Database\Eloquent\Collection + */ public function getListingOfActionLogsChronologicalOrder() { diff --git a/app/Models/Asset.php b/app/Models/Asset.php index bf96e06965..8909636059 100644 --- a/app/Models/Asset.php +++ b/app/Models/Asset.php @@ -1,10 +1,14 @@ assigned_to = null; + $this->assigned_type = null; + $this->accepted = null; + $this->save(); + } /** @@ -148,7 +160,32 @@ class Asset extends Depreciable 'model' => ['name', 'model_number'], 'model.category' => ['name'], 'model.manufacturer' => ['name'], - ]; + ]; + + + /** + * This handles the custom field validation for assets + * + * @var array + */ + public function save(array $params = []) + { + $settings = \App\Models\Setting::getSettings(); + + // I don't remember why we have this here? Asset tag would always be required, even if auto increment is on... + $this->rules['asset_tag'] = ($settings->auto_increment_assets == '1') ? 'max:255' : 'required'; + + if($this->model_id != '') { + $model = AssetModel::find($this->model_id); + + if (($model) && ($model->fieldset)) { + $this->rules += $model->fieldset->validation_rules(); + } + } + + return parent::save($params); + } + public function getDisplayNameAttribute() { @@ -174,12 +211,26 @@ class Asset extends Depreciable return null; } + + /** + * Establishes the asset -> company relationship + * + * @author [A. Gianotto] [] + * @since [v3.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function company() { return $this->belongsTo('\App\Models\Company', 'company_id'); } - + /** + * Determines if an asset is available for checkout + * + * @author [A. Gianotto] [] + * @since [v3.0] + * @return boolean + */ public function availableForCheckout() { if ( @@ -192,8 +243,13 @@ class Asset extends Depreciable return false; } + /** - * Checkout asset + * Checks the asset out to the target + * + * @todo The admin parameter is never used. Can probably be removed. + * + * @author [A. Gianotto] [] * @param User $user * @param User $admin * @param Carbon $checkout_at @@ -201,8 +257,9 @@ class Asset extends Depreciable * @param string $note * @param null $name * @return bool + * @since [v3.0] + * @return boolean */ - //FIXME: The admin parameter is never used. Can probably be removed. public function checkOut($target, $admin = null, $checkout_at = null, $expected_checkin = null, $note = null, $name = null, $location = null) { if (!$target) { @@ -232,27 +289,24 @@ class Asset extends Depreciable $this->location_id = $target->id; } } - - /** - * Does the user have to confirm that they accept the asset? - * - * If so, set the acceptance-status to "pending". - * This value is used in the unaccepted assets reports, for example - * - * @see https://github.com/snipe/snipe-it/issues/5772 - */ - if ($this->requireAcceptance() && $target instanceof User) { - $this->accepted = self::ACCEPTANCE_PENDING; - } if ($this->save()) { - $this->logCheckout($note, $target); + + event(new CheckoutableCheckedOut($this, $target, Auth::user(), $note)); + $this->increment('checkout_counter', 1); return true; } return false; } + /** + * Sets the detailedNameAttribute + * + * @author [A. Gianotto] [] + * @since [v3.0] + * @return string + */ public function getDetailedNameAttribute() { if ($this->assignedto) { @@ -263,31 +317,54 @@ class Asset extends Depreciable return $this->asset_tag . ' - ' . $this->name . ' (' . $user_name . ') ' . ($this->model) ? $this->model->name: ''; } - public function validationRules($id = '0') + /** + * Pulls in the validation rules + * + * @author [A. Gianotto] [] + * @since [v3.0] + * @return array + */ + public function validationRules() { return $this->rules; } /** - * Set depreciation relationship - */ + * Establishes the asset -> depreciation relationship + * + * @author [A. Gianotto] [] + * @since [v3.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function depreciation() { return $this->model->belongsTo('\App\Models\Depreciation', 'depreciation_id'); } + /** * Get components assigned to this asset + * + * @author [A. Gianotto] [] + * @since [v4.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation */ public function components() { return $this->belongsToMany('\App\Models\Component', 'components_assets', 'asset_id', 'component_id')->withPivot('id', 'assigned_qty')->withTrashed(); } - /** - * Get depreciation attribute from associated asset model - */ + + /** + * Get depreciation attribute from associated asset model + * + * @todo Is this still needed? + * + * @author [A. Gianotto] [] + * @since [v4.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function get_depreciation() { if (($this->model) && ($this->model->depreciation)) { @@ -295,9 +372,14 @@ class Asset extends Depreciable } } - /** - * Get uploads for this asset - */ + + /** + * Get uploads for this asset + * + * @author [A. Gianotto] [] + * @since [v4.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function uploads() { return $this->hasMany('\App\Models\Actionlog', 'item_id') @@ -307,29 +389,58 @@ class Asset extends Depreciable ->orderBy('created_at', 'desc'); } + /** + * Determines whether the asset is checked out to a user + * * Even though we allow allow for checkout to things beyond users * this method is an easy way of seeing if we are checked out to a user. - * @return mixed + * + * @author [A. Gianotto] [] + * @since [v4.0] + * @return boolean */ public function checkedOutToUser() { return $this->assignedType() === self::USER; } + /** + * Get the target this asset is checked out to + * + * @author [A. Gianotto] [] + * @since [v4.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function assignedTo() { return $this->morphTo('assigned', 'assigned_type', 'assigned_to'); } + /** + * Gets assets assigned to this asset + * + * Sigh. + * + * @author [A. Gianotto] [] + * @since [v4.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function assignedAssets() { return $this->morphMany('App\Models\Asset', 'assigned', 'assigned_type', 'assigned_to')->withTrashed(); } - /** - * Get the asset's location based on the assigned user - **/ + + /** + * Get the asset's location based on the assigned user + * + * @todo Refactor this if possible. It's awful. + * + * @author [A. Gianotto] [] + * @since [v4.0] + * @return \ArrayObject + */ public function assetLoc($iterations = 1,$first_asset = null) { if (!empty($this->assignedType())) { @@ -364,33 +475,58 @@ class Asset extends Depreciable return $this->defaultLoc; } + /** + * Gets the lowercased name of the type of target the asset is assigned to + * + * @author [A. Gianotto] [] + * @since [v4.0] + * @return string + */ public function assignedType() { return strtolower(class_basename($this->assigned_type)); } - /** - * Get the asset's location based on default RTD location - **/ + + /** + * Get the asset's location based on default RTD location + * + * @author [A. Gianotto] [] + * @since [v2.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function defaultLoc() { return $this->belongsTo('\App\Models\Location', 'rtd_location_id'); } - + /** + * Get the image URL of the asset. + * + * Check first to see if there is a specific image uploaded to the asset, + * and if not, check for an image uploaded to the asset model. + * + * @author [A. Gianotto] [] + * @since [v2.0] + * @return string | false + */ public function getImageUrl() { if ($this->image && !empty($this->image)) { - return url('/').'/uploads/assets/'.$this->image; + return Storage::disk('public')->url(app('assets_upload_path').e($this->image)); } elseif ($this->model && !empty($this->model->image)) { - return url('/').'/uploads/models/'.$this->model->image; + return Storage::disk('public')->url(app('models_upload_path').e($this->model->image)); } return false; } - /** - * Get action logs for this asset - */ + /** + * Get the asset's logs + * + * @author [A. Gianotto] [] + * @since [v2.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function assetlog() { return $this->hasMany('\App\Models\Actionlog', 'item_id') @@ -400,7 +536,11 @@ class Asset extends Depreciable } /** - * Get checkouts + * Get the list of checkouts for this asset + * + * @author [A. Gianotto] [] + * @since [v2.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation */ public function checkouts() { @@ -410,7 +550,11 @@ class Asset extends Depreciable } /** - * Get checkins + * Get the list of checkins for this asset + * + * @author [A. Gianotto] [] + * @since [v2.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation */ public function checkins() { @@ -421,7 +565,11 @@ class Asset extends Depreciable } /** - * Get user requests + * Get the asset's user requests + * + * @author [A. Gianotto] [] + * @since [v2.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation */ public function userRequests() { @@ -432,71 +580,65 @@ class Asset extends Depreciable } - /** - * assetmaintenances - * Get improvements for this asset - * - * @return mixed - * @author Vincent Sposato - * @version v1.0 - */ + /** + * Get maintenances for this asset + * + * @author Vincent Sposato + * @since 1.0 + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function assetmaintenances() { return $this->hasMany('\App\Models\AssetMaintenance', 'asset_id') ->orderBy('created_at', 'desc'); } - /** - * Get action logs for this asset - */ + /** + * Get action logs history for this asset + * + * @author [A. Gianotto] [] + * @since [v1.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function adminuser() { return $this->belongsTo('\App\Models\User', 'user_id'); } - /** - * Get total assets - */ - public static function assetcount() - { - return Company::scopeCompanyables(Asset::where('physical', '=', '1')) - ->whereNull('deleted_at', 'and') - ->count(); - } - /** - * Get total assets not checked out - */ - public static function availassetcount() - { - return Asset::RTD() - ->whereNull('deleted_at') - ->count(); - } - /** - * Get requestable assets - */ - public static function getRequestable() - { - return Asset::Requestable() - ->whereNull('deleted_at') - ->count(); - } - - /** - * Get asset status - */ + /** + * Establishes the asset -> status relationship + * + * @author [A. Gianotto] [] + * @since [v1.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function assetstatus() { return $this->belongsTo('\App\Models\Statuslabel', 'status_id'); } + /** + * Establishes the asset -> model relationship + * + * @author [A. Gianotto] [] + * @since [v1.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function model() { return $this->belongsTo('\App\Models\AssetModel', 'model_id')->withTrashed(); } + /** + * Return the assets with a warranty expiring within x days + * + * @param $days + * @author [A. Gianotto] [] + * @since [v2.0] + * @return mixed + */ public static function getExpiringWarrantee($days = 30) { return Asset::where('archived', '=', '0') @@ -510,25 +652,50 @@ class Asset extends Depreciable ->get(); } - /** - * Get the license seat information - **/ + + /** + * Establishes the asset -> assigned licenses relationship + * + * @author [A. Gianotto] [] + * @since [v4.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function licenses() { return $this->belongsToMany('\App\Models\License', 'license_seats', 'asset_id', 'license_id'); } + /** + * Establishes the asset -> status relationship + * + * @author [A. Gianotto] [] + * @since [v4.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function licenseseats() { return $this->hasMany('\App\Models\LicenseSeat', 'asset_id'); } + /** + * Establishes the asset -> aupplier relationship + * + * @author [A. Gianotto] [] + * @since [v2.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function supplier() { return $this->belongsTo('\App\Models\Supplier', 'supplier_id'); } - + /** + * Establishes the asset -> location relationship + * + * @author [A. Gianotto] [] + * @since [v2.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function location() { return $this->belongsTo('\App\Models\Location', 'location_id'); @@ -536,9 +703,13 @@ class Asset extends Depreciable - /** - * Get auto-increment - */ + /** + * Get the next autoincremented asset tag + * + * @author [A. Gianotto] [] + * @since [v4.0] + * @return string | false + */ public static function autoincrement_asset() { $settings = \App\Models\Setting::getSettings(); @@ -561,10 +732,15 @@ class Asset extends Depreciable } } - /* - * Get the next base number for the auto-incrementer. We'll add the zerofill and - * prefixes on the fly as we generate the number + + /** + * Get the next base number for the auto-incrementer. * + * We'll add the zerofill and prefixes on the fly as we generate the number. + * + * @author [A. Gianotto] [] + * @since [v4.0] + * @return int */ public static function nextAutoIncrement($assets) { @@ -590,23 +766,53 @@ class Asset extends Depreciable - + /** + * Add zerofilling based on Settings + * + * We'll add the zerofill and prefixes on the fly as we generate the number. + * + * @author [A. Gianotto] [] + * @since [v4.0] + * @return string + */ public static function zerofill($num, $zerofill = 3) { return str_pad($num, $zerofill, '0', STR_PAD_LEFT); } - + /** + * Determine whether to send a checkin/checkout email based on + * asset model category + * + * @author [A. Gianotto] [] + * @since [v4.0] + * @return boolean + */ public function checkin_email() { return $this->model->category->checkin_email; } + /** + * Determine whether this asset requires acceptance by the assigned user + * + * @author [A. Gianotto] [] + * @since [v4.0] + * @return boolean + */ public function requireAcceptance() { return $this->model->category->require_acceptance; } + /** + * Checks for a category-specific EULA, and if that doesn't exist, + * checks for a settings level EULA + * + * @author [A. Gianotto] [] + * @since [v4.0] + * @return string | false + */ public function getEula() { $Parsedown = new \Parsedown(); @@ -620,91 +826,92 @@ class Asset extends Depreciable } } + + /** + * ----------------------------------------------- + * BEGIN QUERY SCOPES + * ----------------------------------------------- + **/ + /** * Run additional, advanced searches. - * - * @param Illuminate\Database\Eloquent\Builder $query + * + * @param \Illuminate\Database\Eloquent\Builder $query * @param array $terms The search terms - * @return Illuminate\Database\Eloquent\Builder + * @return \Illuminate\Database\Eloquent\Builder */ public function advancedTextSearch(Builder $query, array $terms) { - - /** - * Assigned user - */ - $query = $query->leftJoin('users as assets_users',function ($leftJoin) { + /** + * Assigned user + */ + $query = $query->leftJoin('users as assets_users',function ($leftJoin) { $leftJoin->on("assets_users.id", "=", "assets.assigned_to") ->where("assets.assigned_type", "=", User::class); - }); + }); - foreach($terms as $term) { + foreach($terms as $term) { - $query = $query - ->orWhere('assets_users.first_name', 'LIKE', '%'.$term.'%') - ->orWhere('assets_users.last_name', 'LIKE', '%'.$term.'%') - ->orWhere('assets_users.username', 'LIKE', '%'.$term.'%') - ->orWhereRaw('CONCAT('.DB::getTablePrefix().'assets_users.first_name," ",'.DB::getTablePrefix().'assets_users.last_name) LIKE ?', ["%$term%", "%$term%"]); + $query = $query + ->orWhere('assets_users.first_name', 'LIKE', '%'.$term.'%') + ->orWhere('assets_users.last_name', 'LIKE', '%'.$term.'%') + ->orWhere('assets_users.username', 'LIKE', '%'.$term.'%') + ->orWhereRaw('CONCAT('.DB::getTablePrefix().'assets_users.first_name," ",'.DB::getTablePrefix().'assets_users.last_name) LIKE ?', ["%$term%", "%$term%"]); - } + } - /** - * Assigned location - */ - $query = $query->leftJoin('locations as assets_locations',function ($leftJoin) { - $leftJoin->on("assets_locations.id","=","assets.assigned_to") - ->where("assets.assigned_type","=",Location::class); - }); + /** + * Assigned location + */ + $query = $query->leftJoin('locations as assets_locations',function ($leftJoin) { + $leftJoin->on("assets_locations.id","=","assets.assigned_to") + ->where("assets.assigned_type","=",Location::class); + }); - foreach($terms as $term) { + foreach($terms as $term) { - $query = $query->orWhere('assets_locations.name', 'LIKE', '%'.$term.'%'); + $query = $query->orWhere('assets_locations.name', 'LIKE', '%'.$term.'%'); - } + } - /** - * Assigned assets - */ - $query = $query->leftJoin('assets as assigned_assets',function ($leftJoin) { - $leftJoin->on('assigned_assets.id', '=', 'assets.assigned_to') - ->where('assets.assigned_type', '=', Asset::class); - }); + /** + * Assigned assets + */ + $query = $query->leftJoin('assets as assigned_assets',function ($leftJoin) { + $leftJoin->on('assigned_assets.id', '=', 'assets.assigned_to') + ->where('assets.assigned_type', '=', Asset::class); + }); - foreach($terms as $term) { + foreach($terms as $term) { - $query = $query->orWhere('assigned_assets.name', 'LIKE', '%'.$term.'%'); - - } + $query = $query->orWhere('assigned_assets.name', 'LIKE', '%'.$term.'%'); - return $query; + } + + return $query; } - /** - * ----------------------------------------------- - * BEGIN QUERY SCOPES - * ----------------------------------------------- - **/ - /** - * Query builder scope for hardware - * - * @param \Illuminate\Database\Query\Builder $query Query builder instance - * - * @return \Illuminate\Database\Query\Builder Modified query builder - */ + /** + * Query builder scope for hardware + * + * @param \Illuminate\Database\Query\Builder $query Query builder instance + * + * @return \Illuminate\Database\Query\Builder Modified query builder + */ public function scopeHardware($query) { return $query->where('physical', '=', '1'); } - /** - * Query builder scope for pending assets - * - * @param \Illuminate\Database\Query\Builder $query Query builder instance - * - * @return \Illuminate\Database\Query\Builder Modified query builder - */ + /** + * Query builder scope for pending assets + * + * @param \Illuminate\Database\Query\Builder $query Query builder instance + * + * @return \Illuminate\Database\Query\Builder Modified query builder + */ public function scopePending($query) { @@ -756,7 +963,7 @@ class Asset extends Depreciable public function scopeRTD($query) { - return $query->whereNULL('assets.assigned_to') + return $query->whereNull('assets.assigned_to') ->whereHas('assetstatus', function ($query) { $query->where('deployable', '=', 1) ->where('pending', '=', 0) @@ -845,19 +1052,6 @@ class Asset extends Depreciable } - /** - * Query builder scope for Deleted assets - * - * @param \Illuminate\Database\Query\Builder $query Query builder instance - * - * @return \Illuminate\Database\Query\Builder Modified query builder - */ - - public function scopeDeleted($query) - { - return $query->whereNotNull('assets.deleted_at'); - } - /** * scopeInModelList * Get all assets in the provided listing of model ids @@ -967,6 +1161,26 @@ class Asset extends Depreciable })->withTrashed()->whereNull("assets.deleted_at"); //workaround for laravel bug } + /** + * Query builder scope to search the department ID of users assigned to assets + * + * @author [A. Gianotto] [] + * @since [v5.0] + * @return string | false + * + * @return \Illuminate\Database\Query\Builder Modified query builder + */ + public function scopeCheckedOutToTargetInDepartment($query, $search) + { + return $query->leftJoin('users as assets_dept_users',function ($leftJoin) { + $leftJoin->on("assets_dept_users.id", "=", "assets.assigned_to") + ->where("assets.assigned_type", "=", User::class); + })->where(function ($query) use ($search) { + $query->where('assets_dept_users.department_id', '=', $search); + + })->withTrashed()->whereNull("assets.deleted_at"); //workaround for laravel bug + } + /** diff --git a/app/Models/AssetMaintenance.php b/app/Models/AssetMaintenance.php index 2a72a3d220..557f3fd791 100644 --- a/app/Models/AssetMaintenance.php +++ b/app/Models/AssetMaintenance.php @@ -22,7 +22,6 @@ class AssetMaintenance extends Model implements ICompanyableChild protected $dates = [ 'deleted_at', 'start_date' , 'completion_date']; protected $table = 'asset_maintenances'; - // Declaring rules for form validation protected $rules = [ 'asset_id' => 'required|integer', 'supplier_id' => 'required|integer', @@ -49,7 +48,10 @@ class AssetMaintenance extends Model implements ICompanyableChild * * @var array */ - protected $searchableRelations = []; + protected $searchableRelations = [ + 'asset' => ['name', 'asset_tag'], + 'asset.model' => ['name', 'model_number'], + ]; public function getCompanyableParents() @@ -155,6 +157,7 @@ class AssetMaintenance extends Model implements ICompanyableChild ->withTrashed(); } + /** * ----------------------------------------------- * BEGIN QUERY SCOPES @@ -165,10 +168,10 @@ class AssetMaintenance extends Model implements ICompanyableChild /** * Query builder scope to order on admin user * - * @param Illuminate\Database\Query\Builder $query Query builder instance - * @param text $order Order + * @param \Illuminate\Database\Query\Builder $query Query builder instance + * @param string $order Order * - * @return Illuminate\Database\Query\Builder Modified query builder + * @return \Illuminate\Database\Query\Builder Modified query builder */ public function scopeOrderAdmin($query, $order) { @@ -180,10 +183,10 @@ class AssetMaintenance extends Model implements ICompanyableChild /** * Query builder scope to order on asset tag * - * @param Illuminate\Database\Query\Builder $query Query builder instance - * @param text $order Order + * @param \Illuminate\Database\Query\Builder $query Query builder instance + * @param string $order Order * - * @return Illuminate\Database\Query\Builder Modified query builder + * @return \Illuminate\Database\Query\Builder Modified query builder */ public function scopeOrderByTag($query, $order) { @@ -194,14 +197,16 @@ class AssetMaintenance extends Model implements ICompanyableChild /** * Query builder scope to order on asset tag * - * @param Illuminate\Database\Query\Builder $query Query builder instance - * @param text $order Order + * @param \Illuminate\Database\Query\Builder $query Query builder instance + * @param string $order Order * - * @return Illuminate\Database\Query\Builder Modified query builder + * @return \Illuminate\Database\Query\Builder Modified query builder */ public function scopeOrderByAssetName($query, $order) { return $query->leftJoin('assets', 'asset_maintenances.asset_id', '=', 'assets.id') ->orderBy('assets.name', $order); } + + } diff --git a/app/Models/AssetModel.php b/app/Models/AssetModel.php index 9c18f522a5..e2d58fa40d 100755 --- a/app/Models/AssetModel.php +++ b/app/Models/AssetModel.php @@ -8,6 +8,7 @@ use App\Presenters\Presentable; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\SoftDeletes; use Watson\Validating\ValidatingTrait; +use Illuminate\Support\Facades\Storage; /** * Model for Asset Models. Asset Models contain higher level @@ -87,47 +88,95 @@ class AssetModel extends SnipeModel 'depreciation' => ['name'], 'category' => ['name'], 'manufacturer' => ['name'], - ]; + ]; + + /** + * Establishes the model -> assets relationship + * + * @author [A. Gianotto] [] + * @since [v1.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function assets() { return $this->hasMany('\App\Models\Asset', 'model_id'); } + /** + * Establishes the model -> category relationship + * + * @author [A. Gianotto] [] + * @since [v1.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function category() { return $this->belongsTo('\App\Models\Category', 'category_id'); } + /** + * Establishes the model -> depreciation relationship + * + * @author [A. Gianotto] [] + * @since [v1.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function depreciation() { return $this->belongsTo('\App\Models\Depreciation', 'depreciation_id'); } - public function adminuser() - { - return $this->belongsTo('\App\Models\User', 'user_id'); - } + /** + * Establishes the model -> manufacturer relationship + * + * @author [A. Gianotto] [] + * @since [v1.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function manufacturer() { return $this->belongsTo('\App\Models\Manufacturer', 'manufacturer_id'); } + /** + * Establishes the model -> fieldset relationship + * + * @author [A. Gianotto] [] + * @since [v2.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function fieldset() { return $this->belongsTo('\App\Models\CustomFieldset', 'fieldset_id'); } + /** + * Establishes the model -> custom field default values relationship + * + * @author hannah tinkler + * @since [v4.3] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function defaultValues() { return $this->belongsToMany('\App\Models\CustomField', 'models_custom_fields')->withPivot('default_value'); } + /** + * Gets the full url for the image + * + * @todo this should probably be moved + * + * @author [A. Gianotto] [] + * @since [v2.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function getImageUrl() { if ($this->image) { - return url('/').'/uploads/models/'.$this->image; + return Storage::disk('public')->url(app('models_upload_path').$this->image); } return false; } @@ -138,17 +187,6 @@ class AssetModel extends SnipeModel * ----------------------------------------------- **/ - /** - * Query builder scope for Deleted assets - * - * @param Illuminate\Database\Query\Builder $query Query builder instance - * @return Illuminate\Database\Query\Builder Modified query builder - */ - - public function scopeDeleted($query) - { - return $query->whereNotNull('deleted_at'); - } /** * scopeInCategory diff --git a/app/Models/Category.php b/app/Models/Category.php index 7650cdde76..c88280df0e 100755 --- a/app/Models/Category.php +++ b/app/Models/Category.php @@ -80,31 +80,62 @@ class Category extends SnipeModel */ protected $searchableRelations = []; - public function has_models() - { - return $this->hasMany('\App\Models\AssetModel', 'category_id')->count(); - } + /** + * Establishes the category -> accessories relationship + * + * @author [A. Gianotto] [] + * @since [v2.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function accessories() { return $this->hasMany('\App\Models\Accessory'); } + /** + * Establishes the category -> licenses relationship + * + * @author [A. Gianotto] [] + * @since [v4.3] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function licenses() { return $this->hasMany('\App\Models\License'); } + /** + * Establishes the category -> consumables relationship + * + * @author [A. Gianotto] [] + * @since [v3.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function consumables() { return $this->hasMany('\App\Models\Consumable'); } + /** + * Establishes the category -> consumables relationship + * + * @author [A. Gianotto] [] + * @since [v3.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function components() { return $this->hasMany('\App\Models\Component'); } + /** + * Get the number of items in the category + * + * @author [A. Gianotto] [] + * @since [v2.0] + * @return int + */ public function itemCount() { switch ($this->category_type) { @@ -120,16 +151,38 @@ class Category extends SnipeModel return '0'; } + /** + * Establishes the category -> assets relationship + * + * @author [A. Gianotto] [] + * @since [v2.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function assets() { return $this->hasManyThrough('\App\Models\Asset', '\App\Models\AssetModel', 'category_id', 'model_id'); } + /** + * Establishes the category -> models relationship + * + * @author [A. Gianotto] [] + * @since [v2.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function models() { return $this->hasMany('\App\Models\AssetModel', 'category_id'); } + /** + * Checks for a category-specific EULA, and if that doesn't exist, + * checks for a settings level EULA + * + * @author [A. Gianotto] [] + * @since [v2.0] + * @return string | null + */ public function getEula() { @@ -145,15 +198,22 @@ class Category extends SnipeModel } + /** - * scopeRequiresAcceptance + * ----------------------------------------------- + * BEGIN QUERY SCOPES + * ----------------------------------------------- + **/ + + /** + * Query builder scope for whether or not the category requires acceptance * - * @param $query - * - * @return mixed * @author Vincent Sposato - * @version v1.0 + * + * @param \Illuminate\Database\Query\Builder $query Query builder instance + * @return \Illuminate\Database\Query\Builder Modified query builder */ + public function scopeRequiresAcceptance($query) { diff --git a/app/Models/CheckoutAcceptance.php b/app/Models/CheckoutAcceptance.php new file mode 100644 index 0000000000..6ff850f41f --- /dev/null +++ b/app/Models/CheckoutAcceptance.php @@ -0,0 +1,114 @@ +morphTo(); + } + + /** + * The user that the checkoutable was checked out to + * + * @return Illuminate\Database\Eloquent\Relations\BelongsTo + */ + public function assignedTo() { + return $this->belongsTo(User::class); + } + + /** + * Is this checkout acceptance pending? + * + * @return boolean + */ + public function isPending() { + return $this->accepted_at == null && $this->declined_at == null; + } + + /** + * Was the checkoutable checked out to this user? + * + * @param User $user + * @return boolean + */ + public function isCheckedOutTo(User $user) { + return $this->assignedTo->is($user); + } + + /** + * Accept the checkout acceptance + * + * @param string $signature_filename + */ + public function accept($signature_filename) { + $this->accepted_at = now(); + $this->signature_filename = $signature_filename; + $this->save(); + + /** + * Update state for the checked out item + */ + $this->checkoutable->acceptedCheckout($this->assignedTo, $signature_filename); + } + + /** + * Decline the checkout acceptance + * + * @param string $signature_filename + */ + public function decline($signature_filename) { + $this->declined_at = now(); + $this->signature_filename = $signature_filename; + $this->save(); + + /** + * Update state for the checked out item + */ + $this->checkoutable->declinedCheckout($this->assignedTo, $signature_filename); + } + + /** + * Filter checkout acceptences by the user + * @param Illuminate\Database\Eloquent\Builder $query + * @param User $user + * @return Illuminate\Database\Eloquent\Builder + */ + public function scopeForUser(Builder $query, User $user) { + return $query->where('assigned_to_id', $user->id); + } + + /** + * Filter to only get pending acceptances + * @param Illuminate\Database\Eloquent\Builder $query + * @return Illuminate\Database\Eloquent\Builder + */ + public function scopePending(Builder $query) { + return $query->whereNull('accepted_at')->whereNull('declined_at'); + } +} diff --git a/app/Models/Component.php b/app/Models/Component.php index cc973c6bf5..e880234ba7 100644 --- a/app/Models/Component.php +++ b/app/Models/Component.php @@ -20,13 +20,6 @@ class Component extends SnipeModel protected $dates = ['deleted_at', 'purchase_date']; protected $table = 'components'; - - /** - * Set static properties to determine which checkout/checkin handlers we should use - */ - public static $checkoutClass = null; - public static $checkinClass = null; - /** * Category validation rules @@ -86,43 +79,89 @@ class Component extends SnipeModel 'category' => ['name'], 'company' => ['name'], 'location' => ['name'], - ]; + ]; + /** + * Establishes the component -> location relationship + * + * @author [A. Gianotto] [] + * @since [v3.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function location() { return $this->belongsTo('\App\Models\Location', 'location_id'); } + /** + * Establishes the component -> assets relationship + * + * @author [A. Gianotto] [] + * @since [v3.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function assets() { return $this->belongsToMany('\App\Models\Asset', 'components_assets')->withPivot('id', 'assigned_qty', 'created_at', 'user_id'); } + /** + * Establishes the component -> admin user relationship + * + * @todo this is probably not needed - refactor + * + * @author [A. Gianotto] [] + * @since [v3.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function admin() { return $this->belongsTo('\App\Models\User', 'user_id'); } + /** + * Establishes the component -> company relationship + * + * @author [A. Gianotto] [] + * @since [v3.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function company() { return $this->belongsTo('\App\Models\Company', 'company_id'); } - + /** + * Establishes the component -> category relationship + * + * @author [A. Gianotto] [] + * @since [v3.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function category() { return $this->belongsTo('\App\Models\Category', 'category_id'); } /** - * Get action logs for this consumable - */ + * Establishes the component -> action logs relationship + * + * @author [A. Gianotto] [] + * @since [v3.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function assetlog() { return $this->hasMany('\App\Models\Actionlog', 'item_id')->where('item_type', Component::class)->orderBy('created_at', 'desc')->withTrashed(); } - + /** + * Check how many items within a component are remaining + * + * @author [A. Gianotto] [] + * @since [v3.0] + * @return int + */ public function numRemaining() { $checkedout = 0; @@ -140,10 +179,10 @@ class Component extends SnipeModel /** * Query builder scope to order on company * - * @param Illuminate\Database\Query\Builder $query Query builder instance - * @param text $order Order + * @param \Illuminate\Database\Query\Builder $query Query builder instance + * @param string $order Order * - * @return Illuminate\Database\Query\Builder Modified query builder + * @return \Illuminate\Database\Query\Builder Modified query builder */ public function scopeOrderCategory($query, $order) { @@ -153,10 +192,10 @@ class Component extends SnipeModel /** * Query builder scope to order on company * - * @param Illuminate\Database\Query\Builder $query Query builder instance - * @param text $order Order + * @param \Illuminate\Database\Query\Builder $query Query builder instance + * @param string $order Order * - * @return Illuminate\Database\Query\Builder Modified query builder + * @return \Illuminate\Database\Query\Builder Modified query builder */ public function scopeOrderLocation($query, $order) { @@ -167,10 +206,10 @@ class Component extends SnipeModel /** * Query builder scope to order on company * - * @param Illuminate\Database\Query\Builder $query Query builder instance - * @param text $order Order + * @param \Illuminate\Database\Query\Builder $query Query builder instance + * @param string $order Order * - * @return Illuminate\Database\Query\Builder Modified query builder + * @return \Illuminate\Database\Query\Builder Modified query builder */ public function scopeOrderCompany($query, $order) { diff --git a/app/Models/Consumable.php b/app/Models/Consumable.php index 55bfb8aae6..67a01250b4 100644 --- a/app/Models/Consumable.php +++ b/app/Models/Consumable.php @@ -1,11 +1,13 @@ 'boolean' ]; - /** - * Set static properties to determine which checkout/checkin handlers we should use - */ - public static $checkoutClass = CheckoutConsumableNotification::class; - public static $checkinClass = null; - /** * Category validation rules @@ -88,8 +86,21 @@ class Consumable extends SnipeModel 'company' => ['name'], 'location' => ['name'], 'manufacturer' => ['name'], - ]; + ]; + /** + * Sets the attribute of whether or not the consumable is requestable + * + * This isn't really implemented yet, as you can't currently request a consumable + * however it will be implemented in the future, and we needed to include + * this method here so all of our polymorphic methods don't break. + * + * @todo Update this comment once it's been implemented + * + * @author [A. Gianotto] [] + * @since [v3.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function setRequestableAttribute($value) { if ($value == '') { @@ -99,73 +110,152 @@ class Consumable extends SnipeModel return; } + /** + * Establishes the consumable -> admin user relationship + * + * @author [A. Gianotto] [] + * @since [v3.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function admin() { return $this->belongsTo('\App\Models\User', 'user_id'); } + /** + * Establishes the component -> assignments relationship + * + * @author [A. Gianotto] [] + * @since [v3.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function consumableAssignments() { return $this->hasMany('\App\Models\ConsumableAssignment'); } + /** + * Establishes the component -> company relationship + * + * @author [A. Gianotto] [] + * @since [v3.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function company() { return $this->belongsTo('\App\Models\Company', 'company_id'); } + /** + * Establishes the component -> manufacturer relationship + * + * @author [A. Gianotto] [] + * @since [v3.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function manufacturer() { return $this->belongsTo('\App\Models\Manufacturer', 'manufacturer_id'); } + /** + * Establishes the component -> location relationship + * + * @author [A. Gianotto] [] + * @since [v3.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function location() { return $this->belongsTo('\App\Models\Location', 'location_id'); } + /** + * Establishes the component -> category relationship + * + * @author [A. Gianotto] [] + * @since [v3.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function category() { return $this->belongsTo('\App\Models\Category', 'category_id'); } + /** - * Get action logs for this consumable - */ + * Establishes the component -> action logs relationship + * + * @author [A. Gianotto] [] + * @since [v3.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function assetlog() { return $this->hasMany('\App\Models\Actionlog', 'item_id')->where('item_type', Consumable::class)->orderBy('created_at', 'desc')->withTrashed(); } + /** + * Gets the full image url for the consumable + * + * @author [A. Gianotto] [] + * @since [v3.0] + * @return string | false + */ public function getImageUrl() { if ($this->image) { - return url('/').'/uploads/consumables/'.$this->image; + return Storage::disk('public')->url(app('consumables_upload_path').$this->image); } return false; } - + /** + * Establishes the component -> users relationship + * + * @author [A. Gianotto] [] + * @since [v3.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function users() { return $this->belongsToMany('\App\Models\User', 'consumables_users', 'consumable_id', 'assigned_to')->withPivot('user_id')->withTrashed()->withTimestamps(); } - public function hasUsers() - { - return $this->belongsToMany('\App\Models\User', 'consumables_users', 'consumable_id', 'assigned_to')->count(); - } + /** + * Determine whether to send a checkin/checkout email based on + * asset model category + * + * @author [A. Gianotto] [] + * @since [v4.0] + * @return boolean + */ public function checkin_email() { return $this->category->checkin_email; - } + } + /** + * Determine whether this asset requires acceptance by the assigned user + * + * @author [A. Gianotto] [] + * @since [v4.0] + * @return boolean + */ public function requireAcceptance() { return $this->category->require_acceptance; } + /** + * Checks for a category-specific EULA, and if that doesn't exist, + * checks for a settings level EULA + * + * @author [A. Gianotto] [] + * @since [v4.0] + * @return string | false + */ public function getEula() { @@ -181,6 +271,13 @@ class Consumable extends SnipeModel } + /** + * Checks the number of available consumables + * + * @author [A. Gianotto] [] + * @since [v4.0] + * @return int + */ public function numRemaining() { $checkedout = $this->users->count(); @@ -192,10 +289,10 @@ class Consumable extends SnipeModel /** * Query builder scope to order on company * - * @param Illuminate\Database\Query\Builder $query Query builder instance - * @param text $order Order + * @param \Illuminate\Database\Query\Builder $query Query builder instance + * @param string $order Order * - * @return Illuminate\Database\Query\Builder Modified query builder + * @return \Illuminate\Database\Query\Builder Modified query builder */ public function scopeOrderCategory($query, $order) { @@ -205,10 +302,10 @@ class Consumable extends SnipeModel /** * Query builder scope to order on location * - * @param Illuminate\Database\Query\Builder $query Query builder instance + * @param \Illuminate\Database\Query\Builder $query Query builder instance * @param text $order Order * - * @return Illuminate\Database\Query\Builder Modified query builder + * @return \Illuminate\Database\Query\Builder Modified query builder */ public function scopeOrderLocation($query, $order) { @@ -218,10 +315,10 @@ class Consumable extends SnipeModel /** * Query builder scope to order on manufacturer * - * @param Illuminate\Database\Query\Builder $query Query builder instance - * @param text $order Order + * @param \Illuminate\Database\Query\Builder $query Query builder instance + * @param string $order Order * - * @return Illuminate\Database\Query\Builder Modified query builder + * @return \Illuminate\Database\Query\Builder Modified query builder */ public function scopeOrderManufacturer($query, $order) { @@ -232,10 +329,10 @@ class Consumable extends SnipeModel /** * Query builder scope to order on company * - * @param Illuminate\Database\Query\Builder $query Query builder instance - * @param text $order Order + * @param \Illuminate\Database\Query\Builder $query Query builder instance + * @param string $order Order * - * @return Illuminate\Database\Query\Builder Modified query builder + * @return \Illuminate\Database\Query\Builder Modified query builder */ public function scopeOrderCompany($query, $order) { diff --git a/app/Models/CustomField.php b/app/Models/CustomField.php index 4ea44fef90..eb3da01715 100644 --- a/app/Models/CustomField.php +++ b/app/Models/CustomField.php @@ -12,25 +12,43 @@ use Illuminate\Validation\Rule; class CustomField extends Model { - use ValidatingTrait, UniqueUndeletedTrait; - public $guarded=["id"]; - public static $PredefinedFormats=[ - "ANY" => "", - "CUSTOM REGEX" => "", - "ALPHA" => "alpha", - "ALPHA-DASH" => "alpha_dash", - "NUMERIC" => "numeric", - "ALPHA-NUMERIC" => "alpha_num", - "EMAIL" => "email", - "DATE" => "date", - "URL" => "url", - "IP" => "ip", - "IPV4" => "ipv4", - "IPV6" => "ipv6", - "MAC" => "regex:/^[a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}$/", - "BOOLEAN" => "boolean", + use ValidatingTrait, + UniqueUndeletedTrait; + + /** + * Custom field predfined formats + * + * @var array + */ + const PREDEFINED_FORMATS = [ + 'ANY' => '', + 'CUSTOM REGEX' => '', + 'ALPHA' => 'alpha', + 'ALPHA-DASH' => 'alpha_dash', + 'NUMERIC' => 'numeric', + 'ALPHA-NUMERIC' => 'alpha_num', + 'EMAIL' => 'email', + 'DATE' => 'date', + 'URL' => 'url', + 'IP' => 'ip', + 'IPV4' => 'ipv4', + 'IPV6' => 'ipv6', + 'MAC' => 'regex:/^[a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}$/', + 'BOOLEAN' => 'boolean', + ]; + + public $guarded = [ + "id" ]; + /** + * Validation rules. + * At least empty array must be provided if using ValidatingTrait. + * + * @var array + */ + protected $rules = []; + /** * The attributes that are mass assignable. * @@ -46,13 +64,17 @@ class CustomField extends Model 'show_in_email', ]; - // This is confusing, since it's actually the custom fields table that - // we're usually modifying, but since we alter the assets table, we have to - // say that here, otherwise the new fields get added onto the custom fields - // table instead of the assets table. + /** + * This is confusing, since it's actually the custom fields table that + * we're usually modifying, but since we alter the assets table, we have to + * say that here, otherwise the new fields get added onto the custom fields + * table instead of the assets table. + * + * @author [Brady Wetherington] [] + * @since [v3.0] + */ public static $table_name = "assets"; - /** * Convert the custom field's name property to a db-safe string. * @@ -82,6 +104,7 @@ class CustomField extends Model */ public static function boot() { + parent::boot(); self::created(function ($custom_field) { // Column already exists on the assets table - nothing to do here. @@ -138,16 +161,37 @@ class CustomField extends Model }); } + /** + * Establishes the customfield -> fieldset relationship + * + * @author [A. Gianotto] [] + * @since [v3.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function fieldset() { return $this->belongsToMany('\App\Models\CustomFieldset'); } + /** + * Establishes the customfield -> admin user relationship + * + * @author [A. Gianotto] [] + * @since [v3.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function user() { return $this->belongsTo('\App\Models\User'); } + /** + * Establishes the customfield -> default values relationship + * + * @author Hannah Tinkler + * @since [v3.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function defaultValues() { return $this->belongsToMany('\App\Models\AssetModel', 'models_custom_fields')->withPivot('default_value'); @@ -169,11 +213,28 @@ class CustomField extends Model })->first(); } + /** + * Checks the format of the attribute + * + * @author [A. Gianotto] [] + * @param $value string + * @since [v3.0] + * @return boolean + */ public function check_format($value) { return preg_match('/^'.$this->attributes['format'].'$/', $value)===1; } + /** + * Gets the DB column name. + * + * @todo figure out if this is still needed? I don't know WTF it's for. + * + * @author [A. Gianotto] [] + * @since [v3.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function db_column_name() { return $this->db_column; @@ -188,15 +249,16 @@ class CustomField extends Model * * @author [A. Gianotto] [] * @since [v3.4] - * @return Array + * @return string */ public function getFormatAttribute($value) { - foreach (self::$PredefinedFormats as $name => $pattern) { + foreach (self::PREDEFINED_FORMATS as $name => $pattern) { if ($pattern === $value || $name === $value) { return $name; } } + return $value; } @@ -205,12 +267,12 @@ class CustomField extends Model * * @author [A. Gianotto] [] * @since [v3.4] - * @return Array + * @return array */ public function setFormatAttribute($value) { - if (isset(self::$PredefinedFormats[$value])) { - $this->attributes['format']=self::$PredefinedFormats[$value]; + if (isset(self::PREDEFINED_FORMATS[$value])) { + $this->attributes['format']=self::PREDEFINED_FORMATS[$value]; } else { $this->attributes['format']=$value; } @@ -221,7 +283,7 @@ class CustomField extends Model * * @author [A. Gianotto] [] * @since [v3.4] - * @return Array + * @return array */ public function formatFieldValuesAsArray() { @@ -249,7 +311,7 @@ class CustomField extends Model * * @author [A. Gianotto] [] * @since [v3.4] - * @return Boolean + * @return boolean */ public function isFieldDecryptable($string) { @@ -266,7 +328,7 @@ class CustomField extends Model * * @author [A. Gianotto] [] * @since [v3.4] - * @return Boolean + * @return boolean */ public function convertUnicodeDbSlug($original = null) { @@ -287,7 +349,7 @@ class CustomField extends Model * @author [V. Cordes] [] * @param int $id * @since [v4.1.10] - * @return Array + * @return array */ public function validationRules() { @@ -298,9 +360,28 @@ class CustomField extends Model Rule::in(['text', 'listbox']) ], 'format' => [ - Rule::in(array_merge(array_keys(CustomField::$PredefinedFormats), CustomField::$PredefinedFormats)) + Rule::in(array_merge(array_keys(CustomField::PREDEFINED_FORMATS), CustomField::PREDEFINED_FORMATS)) ], 'field_encrypted' => "nullable|boolean" ]; } + + /** + * Check to see if there is a custom regex format type + * @see https://github.com/snipe/snipe-it/issues/5896 + * + * @author Wes Hulette + * + * @since 5.0.0 + * + * @return string + */ + public function getFormatType() + { + if(stripos($this->format,'regex') === 0 && ($this->format !== self::PREDEFINED_FORMATS['MAC'])) { + return 'CUSTOM REGEX'; + } + + return $this->format; + } } diff --git a/app/Models/CustomFieldset.php b/app/Models/CustomFieldset.php index d0aa33aa23..82c62750ab 100644 --- a/app/Models/CustomFieldset.php +++ b/app/Models/CustomFieldset.php @@ -7,10 +7,16 @@ use Watson\Validating\ValidatingTrait; class CustomFieldset extends Model { + use ValidatingTrait; + protected $guarded=["id"]; - public $rules=[ - "name" => "required|unique:custom_fieldsets" + /** + * Validation rules + * @var array + */ + public $rules = [ + "name" => "required|unique:custom_fieldsets" ]; /** @@ -21,24 +27,52 @@ class CustomFieldset extends Model * @var boolean */ protected $injectUniqueIdentifier = true; - use ValidatingTrait; - + + /** + * Establishes the fieldset -> field relationship + * + * @author [Brady Wetherington] [] + * @since [v3.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function fields() { return $this->belongsToMany('\App\Models\CustomField')->withPivot(["required","order"])->orderBy("pivot_order"); } + /** + * Establishes the fieldset -> models relationship + * + * @author [Brady Wetherington] [] + * @since [v3.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function models() { return $this->hasMany('\App\Models\AssetModel', "fieldset_id"); } + /** + * Establishes the fieldset -> admin user relationship + * + * @author [Brady Wetherington] [] + * @since [v3.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function user() { return $this->belongsTo('\App\Models\User'); //WARNING - not all CustomFieldsets have a User!! } + /** + * Determine the validation rules we should apply based on the + * custom field format + * + * @author [A. Gianotto] [] + * @since [v3.0] + * @return array + */ public function validation_rules() { $rules=[]; diff --git a/app/Models/Department.php b/app/Models/Department.php index e864afda37..2589fd6baa 100644 --- a/app/Models/Department.php +++ b/app/Models/Department.php @@ -60,18 +60,27 @@ class Department extends SnipeModel * * @var array */ - protected $searchableRelations = []; - + protected $searchableRelations = []; + /** + * Establishes the department -> company relationship + * + * @author A. Gianotto + * @since [v4.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function company() { return $this->belongsTo('\App\Models\Company', 'company_id'); } + /** - * Even though we allow allow for checkout to things beyond users - * this method is an easy way of seeing if we are checked out to a user. - * @return mixed + * Establishes the department -> users relationship + * + * @author A. Gianotto + * @since [v4.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation */ public function users() { @@ -80,15 +89,24 @@ class Department extends SnipeModel /** - * Return the manager in charge of the dept - * @return mixed - */ + * Establishes the department -> manager relationship + * + * @author A. Gianotto + * @since [v4.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function manager() { return $this->belongsTo('\App\Models\User', 'manager_id'); } - + /** + * Establishes the department -> location relationship + * + * @author A. Gianotto + * @since [v4.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function location() { return $this->belongsTo('\App\Models\Location', 'location_id'); diff --git a/app/Models/Depreciable.php b/app/Models/Depreciable.php index ee12a6506a..b7769fd360 100644 --- a/app/Models/Depreciable.php +++ b/app/Models/Depreciable.php @@ -49,7 +49,29 @@ class Depreciable extends SnipeModel if ($this->get_depreciation()->months <= 0) { return $this->purchase_cost; } + $depreciation = 0; + $setting = Setting::getSettings(); + switch($setting->depreciation_method) { + case 'half_1': + $depreciation = $this->getHalfYearDepreciatedValue(true); + break; + + case 'half_2': + $depreciation = $this->getHalfYearDepreciatedValue(false); + break; + default: + $depreciation = $this->getLinearDepreciatedValue(); + } + return $depreciation; + } + + /** + * @return float|int + */ + + public function getLinearDepreciatedValue() + { // fraction of value left $months_remaining = $this->time_until_depreciated()->m + 12*$this->time_until_depreciated()->y; //UGlY $current_value = round(($months_remaining/ $this->get_depreciation()->months) * $this->purchase_cost, 2); @@ -60,6 +82,62 @@ class Depreciable extends SnipeModel return $current_value; } + /** + * @param onlyHalfFirstYear Boolean always applied only second half of the first year + * @return float|int + */ + public function getHalfYearDepreciatedValue($onlyHalfFirstYear = false) + { + // @link http://www.php.net/manual/en/class.dateinterval.php + $current_date = $this->getDateTime(); + $purchase_date = date_create($this->purchase_date); + $currentYear = $this->get_fiscal_year( $current_date ); + $purchaseYear = $this->get_fiscal_year( $purchase_date ); + $yearsPast = $currentYear - $purchaseYear; + $deprecationYears = ceil($this->get_depreciation()->months / 12); + if( $onlyHalfFirstYear ) { + $yearsPast -= 0.5; + } + else if( !$this->is_first_half_of_year($purchase_date) ) { + $yearsPast -= 0.5; + } + if( !$this->is_first_half_of_year($current_date) ) { + $yearsPast += 0.5; + } + + if($yearsPast >= $deprecationYears) { + $yearsPast = $deprecationYears; + } + else if($yearsPast < 0) { + $yearsPast = 0; + } + return round($yearsPast / $deprecationYears * $this->purchase_cost, 2); + } + + /** + * @param \DateTime $date + * @return int + */ + protected function get_fiscal_year($date) { + $year = intval($date->format('Y')); + // also, maybe it'll have to set fiscal year date + if($date->format('nj') === '1231') { + return $year; + } + else { + return $year - 1; + } + } + + /** + * @param \DateTime $date + * @return bool + */ + protected function is_first_half_of_year($date) { + $date0m0d = intval($date->format('md')); + return ($date0m0d < 601) || ($date0m0d >= 1231); + } + public function time_until_depreciated() { // @link http://www.php.net/manual/en/class.datetime.php @@ -81,4 +159,10 @@ class Depreciable extends SnipeModel date_add($date, date_interval_create_from_date_string($this->get_depreciation()->months . ' months')); return $date; //date_format($date, 'Y-m-d'); //don't bake-in format, for internationalization } + + // it's necessary for unit tests + protected function getDateTime($time = null) + { + return new \DateTime($time); + } } diff --git a/app/Models/Depreciation.php b/app/Models/Depreciation.php index e67d4d7fa4..c706f2f1e7 100755 --- a/app/Models/Depreciation.php +++ b/app/Models/Depreciation.php @@ -48,14 +48,28 @@ class Depreciation extends SnipeModel */ protected $searchableRelations = []; - - public function has_models() + /** + * Establishes the depreciation -> models relationship + * + * @author A. Gianotto + * @since [v5.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ + public function models() { - return $this->hasMany('\App\Models\AssetModel', 'depreciation_id')->count(); + return $this->hasMany('\App\Models\AssetModel', 'depreciation_id'); } - public function has_licenses() + + /** + * Establishes the depreciation -> licenses relationship + * + * @author A. Gianotto + * @since [v5.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ + public function licenses() { - return $this->hasMany('\App\Models\License', 'depreciation_id')->count(); + return $this->hasMany('\App\Models\License', 'depreciation_id'); } } diff --git a/app/Models/Group.php b/app/Models/Group.php index 1003e0d03f..ea04f035f5 100755 --- a/app/Models/Group.php +++ b/app/Models/Group.php @@ -37,17 +37,27 @@ class Group extends SnipeModel * * @var array */ - protected $searchableRelations = []; + protected $searchableRelations = []; /** - * Get user groups - */ + * Establishes the groups -> users relationship + * + * @author A. Gianotto + * @since [v1.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function users() { return $this->belongsToMany('\App\Models\User', 'users_groups'); } - + /** + * Decode JSON permissions into array + * + * @author A. Gianotto + * @since [v1.0] + * @return array + */ public function decodePermissions() { return json_decode($this->permissions, true); diff --git a/app/Models/Ldap.php b/app/Models/Ldap.php deleted file mode 100644 index 593e5eee96..0000000000 --- a/app/Models/Ldap.php +++ /dev/null @@ -1,295 +0,0 @@ - Settings. - * - * @author [A. Gianotto] [] - * @since [v3.0] - * @return connection - */ - - public static function connectToLdap() - { - - $ldap_host = Setting::getSettings()->ldap_server; - $ldap_version = Setting::getSettings()->ldap_version; - $ldap_server_cert_ignore = Setting::getSettings()->ldap_server_cert_ignore; - $ldap_use_tls = Setting::getSettings()->ldap_tls; - - - // If we are ignoring the SSL cert we need to setup the environment variable - // before we create the connection - if ($ldap_server_cert_ignore=='1') { - putenv('LDAPTLS_REQCERT=never'); - } - - // If the user specifies where CA Certs are, make sure to use them - if (env("LDAPTLS_CACERT")) { - putenv("LDAPTLS_CACERT=".env("LDAPTLS_CACERT")); - } - - $connection = @ldap_connect($ldap_host); - - if (!$connection) { - throw new Exception('Could not connect to LDAP server at '.$ldap_host.'. Please check your LDAP server name and port number in your settings.'); - } - - // Needed for AD - ldap_set_option($connection, LDAP_OPT_REFERRALS, 0); - ldap_set_option($connection, LDAP_OPT_PROTOCOL_VERSION, $ldap_version); - ldap_set_option($connection, LDAP_OPT_NETWORK_TIMEOUT, 20); - - if ($ldap_use_tls=='1') { - ldap_start_tls($connection); - } - - return $connection; - } - - - /** - * Binds/authenticates the user to LDAP, and returns their attributes. - * - * @author [A. Gianotto] [] - * @since [v3.0] - * @param $username - * @param $password - * @param bool|false $user - * @return bool true if the username and/or password provided are valid - * false if the username and/or password provided are invalid - * array of ldap_attributes if $user is true - * - */ - static function findAndBindUserLdap($username, $password) - { - $settings = Setting::getSettings(); - $connection = Ldap::connectToLdap(); - $ldap_username_field = $settings->ldap_username_field; - $baseDn = $settings->ldap_basedn; - $userDn = $ldap_username_field.'='.$username.','.$settings->ldap_basedn; - - if ($settings->is_ad =='1') { - // Check if they are using the userprincipalname for the username field. - // If they are, we can skip building the UPN to authenticate against AD - if ($ldap_username_field=='userprincipalname') { - $userDn = $username; - } else { - // In case they haven't added an AD domain - $userDn = ($settings->ad_domain != '') ? $username.'@'.$settings->ad_domain : $username.'@'.$settings->email_domain; - } - - } - - \Log::debug('Attempting to login using distinguished name:'.$userDn); - - - $filterQuery = $settings->ldap_auth_filter_query . $username; - - - if (!$ldapbind = @ldap_bind($connection, $userDn, $password)) { - if(!$ldapbind = Ldap::bindAdminToLdap($connection)){ - return false; - } - } - - if (!$results = ldap_search($connection, $baseDn, $filterQuery)) { - throw new Exception('Could not search LDAP: '); - } - - if (!$entry = ldap_first_entry($connection, $results)) { - return false; - } - - if (!$user = ldap_get_attributes($connection, $entry)) { - return false; - } - - return array_change_key_case($user); - - } - - - /** - * Binds/authenticates an admin to LDAP for LDAP searching/syncing. - * Here we also return a better error if the app key is donked. - * - * @author [A. Gianotto] [] - * @since [v3.0] - * @param bool|false $user - * @return bool true if the username and/or password provided are valid - * false if the username and/or password provided are invalid - * - */ - static function bindAdminToLdap($connection) - { - - $ldap_username = Setting::getSettings()->ldap_uname; - - // Lets return some nicer messages for users who donked their app key, and disable LDAP - try { - $ldap_pass = \Crypt::decrypt(Setting::getSettings()->ldap_pword); - } catch (Exception $e) { - - throw new Exception('Your app key has changed! Could not decrypt LDAP password using your current app key, so LDAP authentication has been disabled. Login with a local account, update the LDAP password and re-enable it in Admin > Settings.'); - } - - - if (!$ldapbind = @ldap_bind($connection, $ldap_username, $ldap_pass)) { - throw new Exception('Could not bind to LDAP: '.ldap_error($connection)); - } - - } - - - /** - * Parse and map LDAP attributes based on settings - * - * @author [A. Gianotto] [] - * @since [v3.0] - * - * @param $ldapatttibutes - * @return array|bool - */ - static function parseAndMapLdapAttributes($ldapatttibutes) - { - //Get LDAP attribute config - $ldap_result_username = Setting::getSettings()->ldap_username_field; - $ldap_result_emp_num = Setting::getSettings()->ldap_emp_num; - $ldap_result_last_name = Setting::getSettings()->ldap_lname_field; - $ldap_result_first_name = Setting::getSettings()->ldap_fname_field; - $ldap_result_email = Setting::getSettings()->ldap_email; - - // Get LDAP user data - $item = array(); - $item["username"] = isset($ldapatttibutes[$ldap_result_username][0]) ? $ldapatttibutes[$ldap_result_username][0] : ""; - $item["employee_number"] = isset($ldapatttibutes[$ldap_result_emp_num][0]) ? $ldapatttibutes[$ldap_result_emp_num][0] : ""; - $item["lastname"] = isset($ldapatttibutes[$ldap_result_last_name][0]) ? $ldapatttibutes[$ldap_result_last_name][0] : ""; - $item["firstname"] = isset($ldapatttibutes[$ldap_result_first_name][0]) ? $ldapatttibutes[$ldap_result_first_name][0] : ""; - $item["email"] = isset($ldapatttibutes[$ldap_result_email][0]) ? $ldapatttibutes[$ldap_result_email][0] : "" ; - - return $item; - - - } - - /** - * Create user from LDAP attributes - * - * @author [A. Gianotto] [] - * @since [v3.0] - * @param $ldapatttibutes - * @return array|bool - */ - static function createUserFromLdap($ldapatttibutes) - { - $item = Ldap::parseAndMapLdapAttributes($ldapatttibutes); - - - // Create user from LDAP data - if (!empty($item["username"])) { - $user = new User; - $user->first_name = $item["firstname"]; - $user->last_name = $item["lastname"]; - $user->username = $item["username"]; - $user->email = $item["email"]; - - if (Setting::getSettings()->ldap_pw_sync=='1') { - $user->password = bcrypt(Input::get("password")); - } else { - $pass = substr(str_shuffle("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"), 0, 25); - $user->password = bcrypt($pass); - } - - $user->activated = 1; - $user->ldap_import = 1; - $user->notes = 'Imported on first login from LDAP'; - - if ($user->save()) { - return $user; - } else { - LOG::debug('Could not create user.'.$user->getErrors()); - throw new Exception("Could not create user: ".$user->getErrors()); - } - } - - return false; - - } - - /** - * Searches LDAP - * - * @author [A. Gianotto] [] - * @since [v3.0] - * @param $ldapatttibutes - * @param $base_dn - * @return array|bool - */ - static function findLdapUsers($base_dn = null) - { - - $ldapconn = Ldap::connectToLdap(); - $ldap_bind = Ldap::bindAdminToLdap($ldapconn); - // Default to global base DN if nothing else is provided. - if (is_null($base_dn)) { - $base_dn = Setting::getSettings()->ldap_basedn; - } - $filter = Setting::getSettings()->ldap_filter; - - // Set up LDAP pagination for very large databases - $page_size = 500; - $cookie = ''; - $result_set = array(); - $global_count = 0; - - // Perform the search - do { - - // Paginate (non-critical, if not supported by server) - if (!$ldap_paging = @ldap_control_paged_result($ldapconn, $page_size, false, $cookie)) { - throw new Exception('Problem with your LDAP connection. Try checking the Use TLS setting in Admin > Settings. '); - } - - - $search_results = ldap_search($ldapconn, $base_dn, '('.$filter.')'); - - if (!$search_results) { - return redirect()->route('users.index')->with('error', trans('admin/users/message.error.ldap_could_not_search').ldap_error($ldapconn)); - } - - // Get results from page - $results = ldap_get_entries($ldapconn, $search_results); - if (!$results) { - return redirect()->route('users.index')->with('error', trans('admin/users/message.error.ldap_could_not_get_entries').ldap_error($ldapconn)); - } - - // Add results to result set - $global_count += $results['count']; - $result_set = array_merge($result_set, $results); - - @ldap_control_paged_result_response($ldapconn, $search_results, $cookie); - - } while ($cookie !== null && $cookie != ''); - - - // Clean up after search - $result_set['count'] = $global_count; - $results = $result_set; - ldap_control_paged_result($ldapconn, 0); - - return $results; - - - } -} diff --git a/app/Models/License.php b/app/Models/License.php index 337b30943e..90e3365b08 100755 --- a/app/Models/License.php +++ b/app/Models/License.php @@ -18,12 +18,6 @@ class License extends Depreciable { protected $presenter = 'App\Presenters\LicensePresenter'; - /** - * Set static properties to determine which checkout/checkin handlers we should use - */ - public static $checkoutClass = CheckoutLicenseNotification::class; - public static $checkinClass = CheckinLicenseNotification::class; - use SoftDeletes; use CompanyableTrait; @@ -111,8 +105,14 @@ class License extends Depreciable 'manufacturer' => ['name'], 'company' => ['name'], 'category' => ['name'], - ]; + ]; + /** + * Update seat counts when the license is updated + * + * @author A. Gianotto + * @since [v3.0] + */ public static function boot() { parent::boot(); @@ -129,6 +129,13 @@ class License extends Depreciable }); } + /** + * Balance seat counts + * + * @author A. Gianotto + * @since [v3.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public static function adjustSeatCount($license, $oldSeats, $newSeats) { // If the seats haven't changed, continue on happily. @@ -182,15 +189,37 @@ class License extends Depreciable return true; } + /** + * Sets the attribute for whether or not the license is maintained + * + * @author A. Gianotto + * @since [v1.0] + * @return mixed + */ public function setMaintainedAttribute($value) { $this->attributes['maintained'] = filter_var($value, FILTER_VALIDATE_BOOLEAN); } + + /** + * Sets the reassignable attribute + * + * @author A. Gianotto + * @since [v1.0] + * @return mixed + */ public function setReassignableAttribute($value) { $this->attributes['reassignable'] = filter_var($value, FILTER_VALIDATE_BOOLEAN); } + /** + * Sets expiration date attribute + * + * @author A. Gianotto + * @since [v1.0] + * @return mixed + */ public function setExpirationDateAttribute($value) { @@ -202,6 +231,13 @@ class License extends Depreciable $this->attributes['expiration_date'] = $value; } + /** + * Sets termination date attribute + * + * @author A. Gianotto + * @since [v2.0] + * @return mixed + */ public function setTerminationDateAttribute($value) { if ($value == '' || $value == '0000-00-00') { @@ -212,31 +248,74 @@ class License extends Depreciable $this->attributes['termination_date'] = $value; } + /** + * Establishes the license -> company relationship + * + * @author A. Gianotto + * @since [v2.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function company() { return $this->belongsTo('\App\Models\Company', 'company_id'); } + /** + * Establishes the license -> category relationship + * + * @author A. Gianotto + * @since [v4.4.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function category() { return $this->belongsTo('\App\Models\Category', 'category_id'); } + /** + * Establishes the license -> manufacturer relationship + * + * @author A. Gianotto + * @since [v2.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function manufacturer() { return $this->belongsTo('\App\Models\Manufacturer', 'manufacturer_id'); } + /** + * Determine whether the user should be emailed on checkin/checkout + * + * @author A. Gianotto + * @since [v2.0] + * @return boolean + */ public function checkin_email() { return $this->category->checkin_email; } + /** + * Determine whether the user should be required to accept the license + * + * @author A. Gianotto + * @since [v4.0] + * @return boolean + */ public function requireAcceptance() { return $this->category->require_acceptance; } + /** + * Checks for a category-specific EULA, and if that doesn't exist, + * checks for a settings level EULA + * + * @author [A. Gianotto] [] + * @since [v4.0] + * @return string | false + */ public function getEula() { $Parsedown = new \Parsedown(); @@ -251,7 +330,11 @@ class License extends Depreciable } /** - * Get the assigned user + * Establishes the license -> assigned user relationship + * + * @author A. Gianotto + * @since [v2.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation */ public function assignedusers() { @@ -259,8 +342,12 @@ class License extends Depreciable } /** - * Get asset logs for this asset - */ + * Establishes the license -> action logs relationship + * + * @author A. Gianotto + * @since [v2.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function assetlog() { return $this->hasMany('\App\Models\Actionlog', 'item_id') @@ -269,8 +356,12 @@ class License extends Depreciable } /** - * Get uploads for this asset - */ + * Establishes the license -> action logs -> uploads relationship + * + * @author A. Gianotto + * @since [v2.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function uploads() { return $this->hasMany('\App\Models\Actionlog', 'item_id') @@ -282,16 +373,26 @@ class License extends Depreciable /** - * Get admin user for this asset - */ + * Establishes the license -> admin user relationship + * + * @author A. Gianotto + * @since [v2.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function adminuser() { return $this->belongsTo('\App\Models\User', 'user_id'); } /** - * Get total licenses - */ + * Returns the total number of all license seats + * + * @todo this can probably be refactored at some point. We don't need counting methods. + * + * @author A. Gianotto + * @since [v2.0] + * @return int + */ public static function assetcount() { return LicenseSeat::whereNull('deleted_at') @@ -300,8 +401,14 @@ class License extends Depreciable /** - * Get total licenses - */ + * Return the number of seats for this asset + * + * @todo this can also probably be refactored at some point. + * + * @author A. Gianotto + * @since [v2.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function totalSeatsByLicenseID() { return LicenseSeat::where('license_id', '=', $this->id) @@ -309,12 +416,28 @@ class License extends Depreciable ->count(); } - // We do this to eager load the "count" of seats from the controller. Otherwise calling "count()" on each model results in n+1 + /** + * Establishes the license -> seat relationship + * + * We do this to eager load the "count" of seats from the controller. + * Otherwise calling "count()" on each model results in n+1 sadness. + * + * @author A. Gianotto + * @since [v2.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function licenseSeatsRelation() { return $this->hasMany(LicenseSeat::class)->whereNull('deleted_at')->selectRaw('license_id, count(*) as count')->groupBy('license_id'); } + /** + * Sets the license seat count attribute + * + * @author A. Gianotto + * @since [v2.0] + * @return int + */ public function getLicenseSeatsCountAttribute() { if ($this->licenseSeatsRelation->first()) { @@ -325,8 +448,12 @@ class License extends Depreciable } /** - * Get total licenses not checked out - */ + * Returns the number of total available seats across all licenses + * + * @author A. Gianotto + * @since [v2.0] + * @return int + */ public static function availassetcount() { return LicenseSeat::whereNull('assigned_to') @@ -336,7 +463,11 @@ class License extends Depreciable } /** - * Get the number of available seats + * Returns the number of total available seats for this license + * + * @author A. Gianotto + * @since [v2.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation */ public function availCount() { @@ -346,6 +477,13 @@ class License extends Depreciable ->whereNull('deleted_at'); } + /** + * Sets the available seats attribute + * + * @author A. Gianotto + * @since [v3.0] + * @return mixed + */ public function getAvailSeatsCountAttribute() { if ($this->availCount->first()) { @@ -356,8 +494,11 @@ class License extends Depreciable } /** - * Get the number of assigned seats + * Retuns the number of assigned seats for this asset * + * @author A. Gianotto + * @since [v3.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation */ public function assignedCount() { @@ -367,9 +508,15 @@ class License extends Depreciable }); } + /** + * Sets the assigned seats attribute + * + * @author A. Gianotto + * @since [v1.0] + * @return int + */ public function getAssignedSeatsCountAttribute() { - // dd($this->licenseSeatsRelation->first()); if ($this->assignedCount->first()) { return $this->assignedCount->first()->count; } @@ -377,6 +524,13 @@ class License extends Depreciable return 0; } + /** + * Calculates the number of remaining seats + * + * @author A. Gianotto + * @since [v1.0] + * @return int + */ public function remaincount() { $total = $this->licenseSeatsCount; @@ -386,7 +540,11 @@ class License extends Depreciable } /** - * Get the total number of seats + * Returns the total number of seats for this license + * + * @author A. Gianotto + * @since [v1.0] + * @return int */ public function totalcount() { @@ -397,21 +555,37 @@ class License extends Depreciable } /** - * Get license seat data + * Establishes the license -> seats relationship + * + * @author A. Gianotto + * @since [v1.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation */ public function licenseseats() { return $this->hasMany('\App\Models\LicenseSeat'); } + /** + * Establishes the license -> supplier relationship + * + * @author A. Gianotto + * @since [v1.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function supplier() { return $this->belongsTo('\App\Models\Supplier', 'supplier_id'); } - /* - * Get the next available free seat - used by + + /** + * Gets the next available free seat - used by * the API to populate next_seat + * + * @author A. Gianotto + * @since [v3.0] + * @return mixed */ public function freeSeat() { @@ -425,15 +599,28 @@ class License extends Depreciable ->first(); } - /* - * Get the next available free seat - used by - * the API to populate next_seat - */ + + /** + * Establishes the license -> free seats relationship + * + * @author A. Gianotto + * @since [v1.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function freeSeats() { return $this->hasMany('\App\Models\LicenseSeat')->whereNull('assigned_to')->whereNull('deleted_at')->whereNull('asset_id'); } + /** + * Returns expiring licenses + * + * @todo should refactor. I don't like get() in model methods + * + * @author A. Gianotto + * @since [v1.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public static function getExpiringLicenses($days = 60) { @@ -449,10 +636,10 @@ class License extends Depreciable /** * Query builder scope to order on manufacturer * - * @param Illuminate\Database\Query\Builder $query Query builder instance - * @param text $order Order + * @param \Illuminate\Database\Query\Builder $query Query builder instance + * @param string $order Order * - * @return Illuminate\Database\Query\Builder Modified query builder + * @return \Illuminate\Database\Query\Builder Modified query builder */ public function scopeOrderManufacturer($query, $order) { @@ -464,7 +651,7 @@ class License extends Depreciable * Query builder scope to order on supplier * * @param \Illuminate\Database\Query\Builder $query Query builder instance - * @param text $order Order + * @param string $order Order * * @return \Illuminate\Database\Query\Builder Modified query builder */ @@ -477,10 +664,10 @@ class License extends Depreciable /** * Query builder scope to order on company * - * @param Illuminate\Database\Query\Builder $query Query builder instance + * @param \Illuminate\Database\Query\Builder $query Query builder instance * @param text $order Order * - * @return Illuminate\Database\Query\Builder Modified query builder + * @return \Illuminate\Database\Query\Builder Modified query builder */ public function scopeOrderCompany($query, $order) { diff --git a/app/Models/LicenseSeat.php b/app/Models/LicenseSeat.php index 17703ad2c6..e86959f152 100755 --- a/app/Models/LicenseSeat.php +++ b/app/Models/LicenseSeat.php @@ -2,47 +2,93 @@ namespace App\Models; use App\Models\Loggable; +use App\Models\Traits\Acceptable; +use App\Notifications\CheckinLicenseNotification; +use App\Notifications\CheckoutLicenseNotification; +use App\Presenters\Presentable; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\SoftDeletes; -use App\Notifications\CheckoutLicenseNotification; -use App\Notifications\CheckinLicenseNotification; -class LicenseSeat extends Model implements ICompanyableChild +class LicenseSeat extends SnipeModel implements ICompanyableChild { use CompanyableChildTrait; use SoftDeletes; use Loggable; + protected $presenter = 'App\Presenters\LicenseSeatPresenter'; + use Presentable; + protected $dates = ['deleted_at']; protected $guarded = 'id'; protected $table = 'license_seats'; - /** - * Set static properties to determine which checkout/checkin handlers we should use - */ - public static $checkoutClass = CheckoutLicenseNotification::class; - public static $checkinClass = CheckinLicenseNotification::class; + use Acceptable; public function getCompanyableParents() { return ['asset', 'license']; } + /** + * Determine whether the user should be required to accept the license + * + * @author A. Gianotto + * @since [v4.0] + * @return boolean + */ + public function requireAcceptance() + { + return $this->license->category->require_acceptance; + } + + public function getEula() { + return $this->license->getEula(); + } + + /** + * Establishes the seat -> license relationship + * + * @author A. Gianotto + * @since [v1.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function license() { return $this->belongsTo('\App\Models\License', 'license_id'); } + /** + * Establishes the seat -> assignee relationship + * + * @author A. Gianotto + * @since [v1.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function user() { return $this->belongsTo('\App\Models\User', 'assigned_to')->withTrashed(); } + /** + * Establishes the seat -> asset relationship + * + * @author A. Gianotto + * @since [v4.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function asset() { return $this->belongsTo('\App\Models\Asset', 'asset_id')->withTrashed(); } + /** + * Determines the assigned seat's location based on user + * or asset its assigned to + * + * @author A. Gianotto + * @since [v4.0] + * @return string + */ public function location() { if (($this->user) && ($this->user->location)) { @@ -55,4 +101,6 @@ class LicenseSeat extends Model implements ICompanyableChild return false; } + + } diff --git a/app/Models/Location.php b/app/Models/Location.php index d0cbec3fdc..91e209075e 100755 --- a/app/Models/Location.php +++ b/app/Models/Location.php @@ -20,13 +20,13 @@ class Location extends SnipeModel protected $dates = ['deleted_at']; protected $table = 'locations'; protected $rules = array( - 'name' => 'required|min:2|max:255|unique_undeleted', - 'city' => 'min:2|max:255|nullable', - 'country' => 'min:2|max:2|nullable', + 'name' => 'required|min:2|max:255|unique_undeleted', + 'city' => 'min:2|max:255|nullable', + 'country' => 'min:2|max:2|nullable', 'address' => 'max:80|nullable', 'address2' => 'max:80|nullable', - 'zip' => 'min:3|max:10|nullable', - 'manager_id' => 'exists:users,id|nullable' + 'zip' => 'min:3|max:10|nullable', + 'manager_id' => 'exists:users,id|nullable' ); /** @@ -56,6 +56,7 @@ class Location extends SnipeModel 'country', 'zip', 'ldap_ou', + 'manager_id', 'currency', 'manager_id', 'image', @@ -80,11 +81,25 @@ class Location extends SnipeModel 'parent' => ['name'] ]; + /** + * Establishes the location -> users relationship + * + * @author A. Gianotto + * @since [v1.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function users() { return $this->hasMany('\App\Models\User', 'location_id'); } + /** + * Establishes the location -> assets relationship + * + * @author A. Gianotto + * @since [v1.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function assets() { return $this->hasMany('\App\Models\Asset', 'location_id') @@ -95,52 +110,103 @@ class Location extends SnipeModel }); } + /** + * Establishes the location -> asset's RTD relationship + * + * This used to have an ...->orHas() clause that referred to + * assignedAssets, and that was probably incorrect, as well as + * definitely was setting fire to the query-planner. So don't do that. + * + * It is arguable that we should have a '...->whereNull('assigned_to') + * bit in there, but that isn't always correct either (in the case + * where a user has no location, for example). + * + * In all likelihood, we need to denorm an "effective_location" column + * into Assets to make this slightly less miserable. + * + * @author A. Gianotto + * @since [v1.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function rtd_assets() { - /* This used to have an ...->orHas() clause that referred to - assignedAssets, and that was probably incorrect, as well as - definitely was setting fire to the query-planner. So don't do that. - - It is arguable that we should have a '...->whereNull('assigned_to') - bit in there, but that isn't always correct either (in the case - where a user has no location, for example). - - In all likelyhood, we need to denorm an "effective_location" column - into Assets to make this slightly less miserable. + /* */ return $this->hasMany('\App\Models\Asset', 'rtd_location_id'); } + /** + * Establishes the location -> parent location relationship + * + * @author A. Gianotto + * @since [v3.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function parent() { return $this->belongsTo('\App\Models\Location', 'parent_id','id'); } + /** + * Establishes the location -> manager relationship + * + * @author A. Gianotto + * @since [v3.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function manager() { return $this->belongsTo('\App\Models\User', 'manager_id'); } + /** + * Establishes the location -> child locations relationship + * + * @author A. Gianotto + * @since [v3.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function childLocations() { return $this->hasMany('\App\Models\Location', 'parent_id'); } - // I don't think we need this anymore since we de-normed location_id in assets? + /** + * Establishes the location -> assigned assets relationship + * + * I don't think we need this anymore since we de-normed location_id in assets? + * + * @author A. Gianotto + * @since [v1.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function assignedAssets() { return $this->morphMany('App\Models\Asset', 'assigned', 'assigned_type', 'assigned_to')->withTrashed(); } + /** + * Sets the location-specific OU attribute + * + * @author A. Gianotto + * @since [v3.0] + * @return mixed + */ public function setLdapOuAttribute($ldap_ou) { return $this->attributes['ldap_ou'] = empty($ldap_ou) ? null : $ldap_ou; } + /** + * Recursion to determine location hierarchy + * + * @author A. Gianotto + * @since [v3.0] + * @return mixed + */ public static function getLocationHierarchy($locations, $parent_id = null) { - $op = array(); foreach ($locations as $location) { @@ -164,7 +230,15 @@ class Location extends SnipeModel return $op; } - + /** + * Flattens the location array for display on the front-end + * + * @todo maybe move to presenters? + * + * @author A. Gianotto + * @since [v3.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public static function flattenLocationsArray($location_options_array = null) { $location_options = array(); @@ -194,14 +268,15 @@ class Location extends SnipeModel /** * Query builder scope to order on parent * - * @param Illuminate\Database\Query\Builder $query Query builder instance - * @param text $order Order + * We have to use a Left join here, or it will only return results with parents * - * @return Illuminate\Database\Query\Builder Modified query builder + * @param \Illuminate\Database\Query\Builder $query Query builder instance + * @param string $order Order + * + * @return \Illuminate\Database\Query\Builder Modified query builder */ public function scopeOrderParent($query, $order) { - // Left join here, or it will only return results with parents return $query->leftJoin('locations as parent_loc', 'locations.parent_id', '=', 'parent_loc.id')->orderBy('parent_loc.name', $order); } @@ -209,7 +284,7 @@ class Location extends SnipeModel * Query builder scope to order on manager name * * @param \Illuminate\Database\Query\Builder $query Query builder instance - * @param text $order Order + * @param string $order Order * * @return \Illuminate\Database\Query\Builder Modified query builder */ diff --git a/app/Models/Loggable.php b/app/Models/Loggable.php index f2a96ca99b..65236785c3 100644 --- a/app/Models/Loggable.php +++ b/app/Models/Loggable.php @@ -6,14 +6,7 @@ use App\Models\Actionlog; use App\Models\Asset; use App\Models\CheckoutRequest; use App\Models\User; -use App\Notifications\CheckinAssetNotification; use App\Notifications\AuditNotification; -use App\Notifications\CheckoutAssetNotification; -use App\Notifications\CheckoutAccessoryNotification; -use App\Notifications\CheckinAccessoryNotification; -use App\Notifications\CheckoutConsumableNotification; -use App\Notifications\CheckoutLicenseNotification; -use App\Notifications\CheckinLicenseNotification; use Illuminate\Support\Facades\Auth; @@ -38,7 +31,6 @@ trait Loggable */ public function logCheckout($note, $target /* What are we checking out to? */) { - $settings = Setting::getSettings(); $log = new Actionlog; $log = $this->determineLogItemType($log); if(Auth::user()) @@ -64,29 +56,6 @@ trait Loggable $log->note = $note; $log->logaction('checkout'); - $params = [ - 'item' => $log->item, - 'target_type' => $log->target_type, - 'target' => $target, - 'admin' => $log->user, - 'note' => $note, - 'log_id' => $log->id, - 'settings' => $settings, - ]; - - $checkoutClass = null; - - if (method_exists($target, 'notify')) { - $target->notify(new static::$checkoutClass($params)); - } - - // Send to the admin, if settings dictate - $recipient = new \App\Models\Recipients\AdminRecipient(); - - if (($settings->admin_cc_email!='') && (static::$checkoutClass!='')) { - $recipient->notify(new static::$checkoutClass($params)); - } - return $log; } @@ -113,7 +82,6 @@ trait Loggable */ public function logCheckin($target, $note) { - $settings = Setting::getSettings(); $log = new Actionlog; $log->target_type = get_class($target); $log->target_id = $target->id; @@ -141,29 +109,6 @@ trait Loggable $log->user_id = Auth::user()->id; $log->logaction('checkin from'); - $params = [ - 'target' => $target, - 'item' => $log->item, - 'admin' => $log->user, - 'note' => $note, - 'target_type' => $log->target_type, - 'settings' => $settings, - ]; - - - $checkinClass = null; - - if (method_exists($target, 'notify')) { - $target->notify(new static::$checkinClass($params)); - } - - // Send to the admin, if settings dictate - $recipient = new \App\Models\Recipients\AdminRecipient(); - - if (($settings->admin_cc_email!='') && (static::$checkinClass!='')) { - $recipient->notify(new static::$checkinClass($params)); - } - return $log; } diff --git a/app/Models/Manufacturer.php b/app/Models/Manufacturer.php index 81dbfdac8b..c684c068d1 100755 --- a/app/Models/Manufacturer.php +++ b/app/Models/Manufacturer.php @@ -66,11 +66,6 @@ class Manufacturer extends SnipeModel - public function has_models() - { - return $this->hasMany('\App\Models\AssetModel', 'manufacturer_id')->count(); - } - public function assets() { return $this->hasManyThrough('\App\Models\Asset', '\App\Models\AssetModel', 'manufacturer_id', 'model_id'); diff --git a/app/Models/Recipients/AlertRecipient.php b/app/Models/Recipients/AlertRecipient.php index 548d39d752..07557649c9 100644 --- a/app/Models/Recipients/AlertRecipient.php +++ b/app/Models/Recipients/AlertRecipient.php @@ -1,13 +1,11 @@ email = trim($email); } - } diff --git a/app/Models/Recipients/Recipient.php b/app/Models/Recipients/Recipient.php index 888dd8e611..d04fd1f116 100644 --- a/app/Models/Recipients/Recipient.php +++ b/app/Models/Recipients/Recipient.php @@ -1,12 +1,12 @@ 'required|min:1|numeric', - 'qr_text' => 'max:31|nullable', - 'logo_img' => 'mimes:jpeg,bmp,png,gif', - 'alert_email' => 'email_array|nullable', - 'admin_cc_email' => 'email|nullable', - 'default_currency' => 'required', - 'locale' => 'required', - 'slack_endpoint' => 'url|required_with:slack_channel|nullable', - 'slack_channel' => 'regex:/(? 'string|nullable', - 'labels_per_page' => 'numeric', - 'labels_width' => 'numeric', - 'labels_height' => 'numeric', - 'labels_pmargin_left' => 'numeric|nullable', - 'labels_pmargin_right' => 'numeric|nullable', - 'labels_pmargin_top' => 'numeric|nullable', - 'labels_pmargin_bottom' => 'numeric|nullable', - 'labels_display_bgutter' => 'numeric|nullable', - 'labels_display_sgutter' => 'numeric|nullable', - 'labels_fontsize' => 'numeric|min:5', - 'labels_pagewidth' => 'numeric|nullable', - 'labels_pageheight' => 'numeric|nullable', - 'login_remote_user_enabled' => 'numeric|nullable', - 'login_common_disabled' => 'numeric|nullable', - 'login_remote_user_custom_logout_url' => 'string|nullable', - 'thumbnail_max_h' => 'numeric|max:500|min:25', - 'pwd_secure_min' => 'numeric|required|min:5', - 'audit_warning_days' => 'numeric|nullable', - 'audit_interval' => 'numeric|nullable', - 'custom_forgot_pass_url' => 'url|nullable', - 'privacy_policy_link' => 'nullable|url' + /** + * The app settings cache key name. + * + * @var string + */ + const APP_SETTINGS_KEY = 'snipeit_app_settings'; + + /** + * The setup check cache key name. + * + * @var string + */ + const SETUP_CHECK_KEY = 'snipeit_setup_check'; + + /** + * Whether the model should inject it's identifier to the unique + * validation rules before attempting validation. If this property + * is not set in the model it will default to true. + * + * @var bool + */ + protected $injectUniqueIdentifier = true; + + /** + * The event map for the model. + * + * @var array + */ + protected $dispatchesEvents = [ + 'saved' => SettingSaved::class, ]; - protected $fillable = ['site_name','email_domain','email_format','username_format']; + /** + * Model rules. + * + * @var array + */ + protected $rules = [ + 'brand' => 'required|min:1|numeric', + 'qr_text' => 'max:31|nullable', + 'logo_img' => 'mimes:jpeg,bmp,png,gif', + 'alert_email' => 'email_array|nullable', + 'admin_cc_email' => 'email|nullable', + 'default_currency' => 'required', + 'locale' => 'required', + 'slack_endpoint' => 'url|required_with:slack_channel|nullable', + 'slack_channel' => 'regex:/^[\#\@]?\w+/|required_with:slack_endpoint|nullable', + 'slack_botname' => 'string|nullable', + 'labels_per_page' => 'numeric', + 'labels_width' => 'numeric', + 'labels_height' => 'numeric', + 'labels_pmargin_left' => 'numeric|nullable', + 'labels_pmargin_right' => 'numeric|nullable', + 'labels_pmargin_top' => 'numeric|nullable', + 'labels_pmargin_bottom' => 'numeric|nullable', + 'labels_display_bgutter' => 'numeric|nullable', + 'labels_display_sgutter' => 'numeric|nullable', + 'labels_fontsize' => 'numeric|min:5', + 'labels_pagewidth' => 'numeric|nullable', + 'labels_pageheight' => 'numeric|nullable', + 'login_remote_user_enabled' => 'numeric|nullable', + 'login_common_disabled' => 'numeric|nullable', + 'login_remote_user_custom_logout_url' => 'string|nullable', + 'thumbnail_max_h' => 'numeric|max:500|min:25', + 'pwd_secure_min' => 'numeric|required|min:5', + 'audit_warning_days' => 'numeric|nullable', + 'audit_interval' => 'numeric|nullable', + 'custom_forgot_pass_url' => 'url|nullable', + 'privacy_policy_link' => 'nullable|url', + ]; - public static function getSettings() + protected $fillable = [ + 'site_name', + 'email_domain', + 'email_format', + 'username_format', + ]; + + /** + * Get the app settings. + * Cache is expired on Setting model saved in EventServiceProvider. + * + * @author Wes Hulette + * + * @since 5.0.0 + * + * @return \App\Models\Setting|null + */ + public static function getSettings(): ?Setting { - static $static_cache = null; - - if (!$static_cache) { - if (Schema::hasTable('settings')) { - $static_cache = Setting::first(); + return Cache::rememberForever(self::APP_SETTINGS_KEY, function () { + // Need for setup as no tables exist + try { + return self::first(); + } catch (\Throwable $th) { + return null; } - } - - return $static_cache; - + }); } - public static function setupCompleted() + /** + * Check to see if setup process is complete. + * Cache is expired on Setting model saved in EventServiceProvider. + * + * @return bool + */ + public static function setupCompleted(): bool { + return Cache::rememberForever(self::SETUP_CHECK_KEY, function () { + try { + $usercount = User::withTrashed()->count(); + $settingsCount = self::count(); - $users_table_exists = Schema::hasTable('users'); - $settings_table_exists = Schema::hasTable('settings'); - - if ($users_table_exists && $settings_table_exists) { - $usercount = User::withTrashed()->count(); - $settingsCount = Setting::count(); - return ($usercount > 0 && $settingsCount > 0); - } + return $usercount > 0 && $settingsCount > 0; + } catch (\Throwable $th) { + // Catche the error if the tables dont exit + } + return false; + }); } - public function lar_ver() + /** + * Get the current Laravel version. + * + * @return string + */ + public function lar_ver(): string { - $app = \App::getFacadeApplication(); + $app = App::getFacadeApplication(); + return $app::VERSION; } - public static function getDefaultEula() + /** + * Get the default EULA text. + * + * @return string|null + */ + public static function getDefaultEula(): ?string { - $Parsedown = new \Parsedown(); - if (Setting::getSettings()->default_eula_text) { - return $Parsedown->text(e(Setting::getSettings()->default_eula_text)); + if (self::getSettings()->default_eula_text) { + $parsedown = new Parsedown(); + + return $parsedown->text(e(self::getSettings()->default_eula_text)); } + return null; } - public function modellistCheckedValue ($element) { - + /** + * Check wether to show in model dropdowns. + * + * @param string $element + * + * @return bool + */ + public function modellistCheckedValue($element): bool + { + $settings = self::getSettings(); // If the value is blank for some reason - if ($this->modellist_displays=='') { + if ($settings->modellist_displays == '') { return false; } - $values = explode(',', $this->modellist_displays); + + $values = explode(',', $settings->modellist_displays); foreach ($values as $value) { if ($value == $element) { return true; } } - return false; + return false; } /** * Escapes the custom CSS, and then un-escapes the greater-than symbol * so it can work with direct descendant characters for bootstrap - * menu overrides like: - * + * menu overrides like:. + * * .skin-blue .sidebar-menu>li.active>a, .skin-blue .sidebar-menu>li:hover>a - * + * * Important: Do not remove the e() escaping here, as we output raw in the blade. * * @return string escaped CSS + * * @author A. Gianotto */ - public function show_custom_css() + public function show_custom_css(): string { - $custom_css = Setting::getSettings()->custom_css; + $custom_css = self::getSettings()->custom_css; $custom_css = e($custom_css); // Needed for modifying the bootstrap nav :( $custom_css = str_ireplace('script', 'SCRIPTS-NOT-ALLOWED-HERE', $custom_css); $custom_css = str_replace('>', '>', $custom_css); + return $custom_css; } /** - * Converts bytes into human readable file size. - * - * @param string $bytes - * @return string human readable file size (2,87 Мб) - * @author Mogilev Arseny - */ - public static function fileSizeConvert($bytes) + * Converts bytes into human readable file size. + * + * @param string $bytes + * + * @return string human readable file size (2,87 Мб) + * + * @author Mogilev Arseny + */ + public static function fileSizeConvert($bytes): string { $bytes = floatval($bytes); - $arBytes = array( - 0 => array( - "UNIT" => "TB", - "VALUE" => pow(1024, 4) - ), - 1 => array( - "UNIT" => "GB", - "VALUE" => pow(1024, 3) - ), - 2 => array( - "UNIT" => "MB", - "VALUE" => pow(1024, 2) - ), - 3 => array( - "UNIT" => "KB", - "VALUE" => 1024 - ), - 4 => array( - "UNIT" => "B", - "VALUE" => 1 - ), - ); + $arBytes = [ + 0 => [ + 'UNIT' => 'TB', + 'VALUE' => pow(1024, 4), + ], + 1 => [ + 'UNIT' => 'GB', + 'VALUE' => pow(1024, 3), + ], + 2 => [ + 'UNIT' => 'MB', + 'VALUE' => pow(1024, 2), + ], + 3 => [ + 'UNIT' => 'KB', + 'VALUE' => 1024, + ], + 4 => [ + 'UNIT' => 'B', + 'VALUE' => 1, + ], + ]; - foreach ($arBytes as $arItem) { - if ($bytes >= $arItem["VALUE"]) { - $result = $bytes / $arItem["VALUE"]; - $result = round($result, 2) .$arItem["UNIT"]; - break; - } + foreach ($arBytes as $arItem) { + if ($bytes >= $arItem['VALUE']) { + $result = $bytes / $arItem['VALUE']; + $result = round($result, 2).$arItem['UNIT']; + break; } - return $result; + } + + return $result; } /** * The url for slack notifications. - * Used by Notifiable trait. - * @return mixed + * Used by Notifiable trait. + * + * @return string */ - public function routeNotificationForSlack() + public function routeNotificationForSlack(): string { // At this point the endpoint is the same for everything. // In the future this may want to be adapted for individual notifications. - return $this->slack_endpoint; + return self::getSettings()->slack_endpoint; } - public function routeNotificationForMail() + /** + * Get the mail reply to address from configuration. + * + * @return string + */ + public function routeNotificationForMail(): string { // At this point the endpoint is the same for everything. // In the future this may want to be adapted for individual notifications. return config('mail.reply_to.address'); } - public static function passwordComplexityRulesSaving($action = 'update') + /** + * Get the password complexity rule. + * + * @return string + */ + public static function passwordComplexityRulesSaving($action = 'update'): string { $security_rules = ''; - $settings = Setting::getSettings(); + $settings = self::getSettings(); // Check if they have uncommon password enforcement selected in settings if ($settings->pwd_secure_uncommon == 1) { @@ -203,8 +306,8 @@ class Setting extends Model } // Check for any secure password complexity rules that may have been selected - if ($settings->pwd_secure_complexity!='') { - $security_rules .= '|'.$settings->pwd_secure_complexity; + if ($settings->pwd_secure_complexity != '') { + $security_rules .= '|'.$settings->pwd_secure_complexity; } if ($action == 'update') { @@ -212,9 +315,44 @@ class Setting extends Model } return 'required|min:'.$settings->pwd_secure_min.$security_rules; - } + /** + * Get the specific LDAP settings + * + * @author Wes Hulette + * + * @since 5.0.0 + * + * @return Collection + */ + public static function getLdapSettings(): Collection + { + $ldapSettings = self::select([ + 'ldap_enabled', + 'ldap_server', + 'ldap_uname', + 'ldap_pword', + 'ldap_basedn', + 'ldap_filter', + 'ldap_username_field', + 'ldap_lname_field', + 'ldap_fname_field', + 'ldap_auth_filter_query', + 'ldap_version', + 'ldap_active_flag', + 'ldap_emp_num', + 'ldap_email', + 'ldap_server_cert_ignore', + 'ldap_port', + 'ldap_tls', + 'ldap_pw_sync', + 'is_ad', + 'ad_domain' + ])->first()->getAttributes(); + + return collect($ldapSettings); + } } diff --git a/app/Models/Statuslabel.php b/app/Models/Statuslabel.php index fa6f6df1ba..c97b6c9c70 100755 --- a/app/Models/Statuslabel.php +++ b/app/Models/Statuslabel.php @@ -50,19 +50,28 @@ class Statuslabel extends SnipeModel * * @var array */ - protected $searchableRelations = []; + protected $searchableRelations = []; /** - * Get assets with associated status label + * Establishes the status label -> assets relationship * - * @return \Illuminate\Support\Collection + * @author A. Gianotto + * @since [v1.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation */ public function assets() { return $this->hasMany('\App\Models\Asset', 'status_id'); } + /** + * Gets the status label type + * + * @author A. Gianotto + * @since [v1.0] + * @return string + */ public function getStatuslabelType() { @@ -78,6 +87,11 @@ class Statuslabel extends SnipeModel } + /** + * Query builder scope to for pending status types + * + * @return \Illuminate\Database\Query\Builder Modified query builder + */ public function scopePending() { return $this->where('pending', '=', 1) @@ -85,6 +99,11 @@ class Statuslabel extends SnipeModel ->where('deployable', '=', 0); } + /** + * Query builder scope for archived status types + * + * @return \Illuminate\Database\Query\Builder Modified query builder + */ public function scopeArchived() { return $this->where('pending', '=', 0) @@ -92,6 +111,11 @@ class Statuslabel extends SnipeModel ->where('deployable', '=', 0); } + /** + * Query builder scope for deployable status types + * + * @return \Illuminate\Database\Query\Builder Modified query builder + */ public function scopeDeployable() { return $this->where('pending', '=', 0) @@ -99,7 +123,13 @@ class Statuslabel extends SnipeModel ->where('deployable', '=', 1); } - + /** + * Helper function to determine type attributes + * + * @author A. Gianotto + * @since [v1.0] + * @return string + */ public static function getStatuslabelTypesForDB($type) { diff --git a/app/Models/Supplier.php b/app/Models/Supplier.php index 82c3a0770c..2313e998a9 100755 --- a/app/Models/Supplier.php +++ b/app/Models/Supplier.php @@ -66,13 +66,30 @@ class Supplier extends SnipeModel protected $fillable = ['name','address','address2','city','state','country','zip','phone','fax','email','contact','url','notes']; - // Eager load counts. - // We do this to eager load the "count" of seats from the controller. Otherwise calling "count()" on each model results in n+1 + /** + * Eager load counts + * + * We do this to eager load the "count" of seats from the controller. + * Otherwise calling "count()" on each model results in n+1. + * + * @author A. Gianotto + * @since [v4.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function assetsRelation() { return $this->hasMany(Asset::class)->whereNull('deleted_at')->selectRaw('supplier_id, count(*) as count')->groupBy('supplier_id'); } + /** + * Sets the license seat count attribute + * + * @todo I don't see the licenseSeatsRelation here? + * + * @author A. Gianotto + * @since [v1.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function getLicenseSeatsCountAttribute() { if ($this->licenseSeatsRelation->first()) { @@ -81,21 +98,50 @@ class Supplier extends SnipeModel return 0; } + + /** + * Establishes the supplier -> assets relationship + * + * @author A. Gianotto + * @since [v1.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function assets() { return $this->hasMany('\App\Models\Asset', 'supplier_id'); } + /** + * Establishes the supplier -> accessories relationship + * + * @author A. Gianotto + * @since [v1.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function accessories() { return $this->hasMany('\App\Models\Accessory', 'supplier_id'); } + /** + * Establishes the supplier -> asset maintenances relationship + * + * @author A. Gianotto + * @since [v1.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function asset_maintenances() { return $this->hasMany('\App\Models\AssetMaintenance', 'supplier_id'); } + /** + * Return the number of assets by supplier + * + * @author A. Gianotto + * @since [v1.0] + * @return int + */ public function num_assets() { if ($this->assetsRelation->first()) { @@ -105,16 +151,39 @@ class Supplier extends SnipeModel return 0; } + /** + * Establishes the supplier -> license relationship + * + * @author A. Gianotto + * @since [v1.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function licenses() { return $this->hasMany('\App\Models\License', 'supplier_id'); } + /** + * Return the number of licenses by supplier + * + * @author A. Gianotto + * @since [v1.0] + * @return int + */ public function num_licenses() { return $this->licenses()->count(); } + /** + * Add http to the url in suppliers if the user didn't give one + * + * @todo this should be handled via validation, no? + * + * @author A. Gianotto + * @since [v3.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function addhttp($url) { if (!preg_match("~^(?:f|ht)tps?://~i", $url)) { diff --git a/app/Models/Throttle.php b/app/Models/Throttle.php deleted file mode 100644 index 85e447378e..0000000000 --- a/app/Models/Throttle.php +++ /dev/null @@ -1,14 +0,0 @@ -belongsTo('User', 'user_id'); - } -} diff --git a/app/Models/Traits/Acceptable.php b/app/Models/Traits/Acceptable.php new file mode 100644 index 0000000000..a0c93a861b --- /dev/null +++ b/app/Models/Traits/Acceptable.php @@ -0,0 +1,31 @@ + + */ +trait Acceptable { + /** + * Run after the checkout acceptance was accepted by the user + * + * @param User $acceptedBy + * @param string $signature + */ + public function acceptedCheckout(User $acceptedBy, $signature) {} + + /** + * Run after the checkout acceptance was declined by the user + * + * @param User $acceptedBy + * @param string $signature + */ + public function declinedCheckout(User $declinedBy, $signature) {} +} diff --git a/app/Models/Traits/Searchable.php b/app/Models/Traits/Searchable.php index 96e88f7cb5..e43081e557 100644 --- a/app/Models/Traits/Searchable.php +++ b/app/Models/Traits/Searchable.php @@ -17,9 +17,9 @@ trait Searchable { /** * Performs a search on the model, using the provided search terms * - * @param Illuminate\Database\Eloquent\Builder $query The query to start the search on + * @param \Illuminate\Database\Eloquent\Builder $query The query to start the search on * @param string $search - * @return Illuminate\Database\Eloquent\Builder A query with added "where" clauses + * @return \Illuminate\Database\Eloquent\Builder A query with added "where" clauses */ public function scopeTextSearch($query, $search) { diff --git a/app/Models/User.php b/app/Models/User.php index c783bdbba5..8da80c7101 100755 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -3,11 +3,11 @@ namespace App\Models; use App\Models\Traits\Searchable; use App\Presenters\Presentable; -use Illuminate\Auth\Authenticatable; use Illuminate\Auth\Passwords\CanResetPassword; -use Illuminate\Foundation\Auth\Access\Authorizable; -use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; +use Illuminate\Auth\Authenticatable; +use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; +use Illuminate\Foundation\Auth\Access\Authorizable; use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract; use Watson\Validating\ValidatingTrait; use Illuminate\Database\Eloquent\Builder; @@ -15,9 +15,12 @@ use Illuminate\Database\Eloquent\SoftDeletes; use App\Http\Traits\UniqueUndeletedTrait; use Illuminate\Notifications\Notifiable; use Laravel\Passport\HasApiTokens; +use Illuminate\Contracts\Translation\HasLocalePreference; use DB; -class User extends SnipeModel implements AuthenticatableContract, CanResetPasswordContract + + +class User extends SnipeModel implements AuthenticatableContract, AuthorizableContract, CanResetPasswordContract, HasLocalePreference { protected $presenter = 'App\Presenters\UserPresenter'; use SoftDeletes, ValidatingTrait; @@ -69,6 +72,7 @@ class User extends SnipeModel implements AuthenticatableContract, CanResetPasswo 'email' => 'email|nullable', 'password' => 'required|min:6', 'locale' => 'max:10|nullable', + 'manager_id' => 'exists:users,id|nullable' ]; use Searchable; @@ -98,9 +102,20 @@ class User extends SnipeModel implements AuthenticatableContract, CanResetPasswo 'userloc' => ['name'], 'department' => ['name'], 'groups' => ['name'], + 'company' => ['name'], 'manager' => ['first_name', 'last_name', 'username'] - ]; + ]; + /** + * Check user permissions + * + * Parses the user and group permission masks to see if the user + * is authorized to do the thing + * + * @author A. Gianotto + * @since [v1.0] + * @return boolean + */ public function hasAccess($section) { if ($this->isSuperUser()) { @@ -115,12 +130,13 @@ class User extends SnipeModel implements AuthenticatableContract, CanResetPasswo $user_permissions = json_decode($this->permissions, true); + $is_user_section_permissions_set = ($user_permissions != '') && array_key_exists($section, $user_permissions); //If the user is explicitly granted, return true - if (($user_permissions!='') && ((array_key_exists($section, $user_permissions)) && ($user_permissions[$section]=='1'))) { + if ($is_user_section_permissions_set && ($user_permissions[$section]=='1')) { return true; } // If the user is explicitly denied, return false - if (($user_permissions=='') || array_key_exists($section, $user_permissions) && ($user_permissions[$section]=='-1')) { + if ($is_user_section_permissions_set && ($user_permissions[$section]=='-1')) { return false; } @@ -135,6 +151,13 @@ class User extends SnipeModel implements AuthenticatableContract, CanResetPasswo return false; } + /** + * Checks if the user is a SuperUser + * + * @author A. Gianotto + * @since [v1.0] + * @return boolean + */ public function isSuperUser() { if (!$user_permissions = json_decode($this->permissions, true)) { @@ -157,21 +180,63 @@ class User extends SnipeModel implements AuthenticatableContract, CanResetPasswo } + /** + * Establishes the user -> company relationship + * + * @author A. Gianotto + * @since [v2.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function company() { return $this->belongsTo('\App\Models\Company', 'company_id'); } + /** + * Establishes the user -> department relationship + * + * @author A. Gianotto + * @since [v4.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function department() { return $this->belongsTo('\App\Models\Department', 'department_id'); } + /** + * Checks activated status + * + * @author A. Gianotto + * @since [v1.0] + * @return boolean + */ + public function isActivated() + { + return $this->activated ==1; + } + + /** + * Returns the full name attribute + * + * @author A. Gianotto + * @since [v2.0] + * @return string + */ public function getFullNameAttribute() { return $this->first_name . " " . $this->last_name; } + /** + * Returns the complete name attribute with username + * + * @todo refactor this so it's less repetitive and dumb + * + * @author A. Gianotto + * @since [v2.0] + * @return string + */ public function getCompleteNameAttribute() { return $this->last_name . ", " . $this->first_name . " (" . $this->username . ")"; @@ -192,7 +257,11 @@ class User extends SnipeModel implements AuthenticatableContract, CanResetPasswo /** - * Get assets assigned to this user + * Establishes the user -> assets relationship + * + * @author A. Gianotto + * @since [v1.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation */ public function assets() { @@ -200,7 +269,14 @@ class User extends SnipeModel implements AuthenticatableContract, CanResetPasswo } /** - * Get assets assigned to this user + * Establishes the user -> maintenances relationship + * + * This would only be used to return maintenances that this user + * created. + * + * @author A. Gianotto + * @since [v4.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation */ public function assetmaintenances() { @@ -208,7 +284,11 @@ class User extends SnipeModel implements AuthenticatableContract, CanResetPasswo } /** - * Get accessories assigned to this user + * Establishes the user -> accessories relationship + * + * @author A. Gianotto + * @since [v2.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation */ public function accessories() { @@ -216,7 +296,11 @@ class User extends SnipeModel implements AuthenticatableContract, CanResetPasswo } /** - * Get consumables assigned to this user + * Establishes the user -> consumables relationship + * + * @author A. Gianotto + * @since [v3.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation */ public function consumables() { @@ -224,7 +308,11 @@ class User extends SnipeModel implements AuthenticatableContract, CanResetPasswo } /** - * Get licenses assigned to this user + * Establishes the user -> license seats relationship + * + * @author A. Gianotto + * @since [v1.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation */ public function licenses() { @@ -232,78 +320,105 @@ class User extends SnipeModel implements AuthenticatableContract, CanResetPasswo } /** - * Get action logs for this user + * Establishes the user -> actionlogs relationship + * + * @author A. Gianotto + * @since [v1.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation */ public function userlog() { return $this->hasMany('\App\Models\Actionlog', 'target_id')->orderBy('created_at', 'DESC')->withTrashed(); } + /** + * Establishes the user -> location relationship + * * Get the asset's location based on the assigned user - * @todo - this should be removed once we're sure we've switched it - * to location() - **/ + * + * @todo - this should be removed once we're sure we've switched it to location() + * + * @author A. Gianotto + * @since [v4.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ + public function userloc() { return $this->belongsTo('\App\Models\Location', 'location_id')->withTrashed(); } + /** - * Get the asset's location based on the assigned user - **/ + * Establishes the user -> location relationship + * + * @author A. Gianotto + * @since [v3.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function location() { return $this->belongsTo('\App\Models\Location', 'location_id')->withTrashed(); } + /** - * Get the user's manager based on the assigned user - **/ + * Establishes the user -> manager relationship + * + * @author A. Gianotto + * @since [v4.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function manager() { return $this->belongsTo('\App\Models\User', 'manager_id')->withTrashed(); } /** - * Get any locations the user manages. - **/ + * Establishes the user -> managed locations relationship + * + * @author A. Gianotto + * @since [v4.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function managedLocations() { return $this->hasMany('\App\Models\Location', 'manager_id'); } /** - * Get user groups + * Establishes the user -> groups relationship + * + * @author A. Gianotto + * @since [v1.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation */ public function groups() { return $this->belongsToMany('\App\Models\Group', 'users_groups'); } - - public function accountStatus() - { - if ($this->throttle) { - if ($this->throttle->suspended==1) { - return 'suspended'; - } elseif ($this->throttle->banned==1) { - return 'banned'; - } else { - return false; - } - } else { - return false; - } - } - + /** + * Establishes the user -> assets relationship + * + * @author A. Gianotto + * @since [v4.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ public function assetlog() { return $this->hasMany('\App\Models\Asset', 'id')->withTrashed(); } /** - * Get uploads for this asset + * Establishes the user -> uploads relationship + * + * @todo I don't think we use this? + * + * @author A. Gianotto + * @since [v3.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation */ public function uploads() { @@ -315,28 +430,42 @@ class User extends SnipeModel implements AuthenticatableContract, CanResetPasswo } /** - * Fetch Items User has requested + * Establishes the user -> requested assets relationship + * + * @author A. Gianotto + * @since [v2.0] + * @return \Illuminate\Database\Eloquent\Relations\Relation */ public function checkoutRequests() { return $this->belongsToMany(Asset::class, 'checkout_requests', 'user_id', 'requestable_id')->whereNull('canceled_at'); } - public function throttle() - { - return $this->hasOne('\App\Models\Throttle'); - } - - public function scopeGetDeleted($query) - { - return $query->withTrashed()->whereNotNull('users.deleted_at'); - } + /** + * Query builder scope to return NOT-deleted users + * @author A. Gianotto + * @since [v2.0] + * + * @param string $query + * @return \Illuminate\Database\Query\Builder + */ public function scopeGetNotDeleted($query) { return $query->whereNull('deleted_at'); } + /** + * Query builder scope to return users by email or username + * + * @author A. Gianotto + * @since [v2.0] + * + * @param string $query + * @param string $user_username + * @param string $user_email + * @return \Illuminate\Database\Query\Builder + */ public function scopeMatchEmailOrUsername($query, $user_username, $user_email) { return $query->where('email', '=', $user_email) @@ -344,13 +473,22 @@ class User extends SnipeModel implements AuthenticatableContract, CanResetPasswo ->orWhere('username', '=', $user_email); } + /** + * Generate email from full name + * + * @author A. Gianotto + * @since [v2.0] + * + * @param string $query + * @return string + */ public static function generateEmailFromFullName($name) { - $username = User::generateFormattedNameFromFullName(Setting::getSettings()->email_format, $name); + $username = User::generateFormattedNameFromFullName($name, Setting::getSettings()->email_format); return $username['username'].'@'.Setting::getSettings()->email_domain; } - public static function generateFormattedNameFromFullName($format = 'filastname', $users_name) + public static function generateFormattedNameFromFullName($users_name, $format = 'filastname') { // If there was only one name given @@ -416,9 +554,9 @@ class User extends SnipeModel implements AuthenticatableContract, CanResetPasswo /** * Run additional, advanced searches. * - * @param Illuminate\Database\Eloquent\Builder $query - * @param array $term The search terms - * @return Illuminate\Database\Eloquent\Builder + * @param \Illuminate\Database\Query\Builder $query Query builder instance + * @param array $terms The search terms + * @return \Illuminate\Database\Eloquent\Builder */ public function advancedTextSearch(Builder $query, array $terms) { @@ -429,34 +567,27 @@ class User extends SnipeModel implements AuthenticatableContract, CanResetPasswo return $query; } - + /** + * Query builder scope to return users by group + * + * @param \Illuminate\Database\Query\Builder $query Query builder instance + * @param int $id + * @return \Illuminate\Database\Query\Builder + */ public function scopeByGroup($query, $id) { return $query->whereHas('groups', function ($query) use ($id) { $query->where('groups.id', '=', $id); }); } - /** - * Query builder scope for Deleted users - * - * @param Illuminate\Database\Query\Builder $query Query builder instance - * - * @return Illuminate\Database\Query\Builder Modified query builder - */ - - public function scopeDeleted($query) - { - return $query->whereNotNull('users.deleted_at'); - } - /** * Query builder scope to order on manager * - * @param Illuminate\Database\Query\Builder $query Query builder instance - * @param text $order Order + * @param \Illuminate\Database\Query\Builder $query Query builder instance + * @param string $order Order * - * @return Illuminate\Database\Query\Builder Modified query builder + * @return \Illuminate\Database\Query\Builder Modified query builder */ public function scopeOrderManager($query, $order) { @@ -467,10 +598,10 @@ class User extends SnipeModel implements AuthenticatableContract, CanResetPasswo /** * Query builder scope to order on company * - * @param Illuminate\Database\Query\Builder $query Query builder instance - * @param text $order Order + * @param \Illuminate\Database\Query\Builder $query Query builder instance + * @param string $order Order * - * @return Illuminate\Database\Query\Builder Modified query builder + * @return \Illuminate\Database\Query\Builder Modified query builder */ public function scopeOrderLocation($query, $order) { @@ -481,13 +612,17 @@ class User extends SnipeModel implements AuthenticatableContract, CanResetPasswo /** * Query builder scope to order on department * - * @param Illuminate\Database\Query\Builder $query Query builder instance - * @param text $order Order + * @param \Illuminate\Database\Query\Builder $query Query builder instance + * @param string $order Order * - * @return Illuminate\Database\Query\Builder Modified query builder + * @return \Illuminate\Database\Query\Builder Modified query builder */ public function scopeOrderDepartment($query, $order) { return $query->leftJoin('departments as departments_users', 'users.department_id', '=', 'departments_users.id')->orderBy('departments_users.name', $order); } + + public function preferredLocale(){ + return $this->locale; + } } diff --git a/app/Notifications/CheckinAccessoryNotification.php b/app/Notifications/CheckinAccessoryNotification.php index 052279892e..ee3bcac6ab 100644 --- a/app/Notifications/CheckinAccessoryNotification.php +++ b/app/Notifications/CheckinAccessoryNotification.php @@ -2,6 +2,7 @@ namespace App\Notifications; +use App\Models\Accessory; use App\Models\Setting; use App\Models\SnipeModel; use App\Models\User; @@ -15,31 +16,19 @@ use Illuminate\Support\Facades\Mail; class CheckinAccessoryNotification extends Notification { use Queueable; - /** - * @var - */ - private $params; /** * Create a new notification instance. * * @param $params */ - public function __construct($params) + public function __construct(Accessory $accessory, $checkedOutTo, User $checkedInby, $note) { - $this->target = $params['target']; - $this->item = $params['item']; - $this->admin = $params['admin']; - $this->note = ''; - $this->target_type = $params['target']; - $this->settings = $params['settings']; - - if (array_key_exists('note', $params)) { - $this->note = $params['note']; - } - - - + $this->item = $accessory; + $this->target = $checkedOutTo; + $this->admin = $checkedInby; + $this->note = $note; + $this->settings = Setting::getSettings(); } /** diff --git a/app/Notifications/CheckinAssetNotification.php b/app/Notifications/CheckinAssetNotification.php index 78f3f00664..4053f22ffc 100644 --- a/app/Notifications/CheckinAssetNotification.php +++ b/app/Notifications/CheckinAssetNotification.php @@ -2,13 +2,14 @@ namespace App\Notifications; +use App\Models\Asset; use App\Models\Setting; -use Illuminate\Bus\Queueable; use App\Models\User; -use Illuminate\Notifications\Notification; +use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Notifications\Messages\MailMessage; use Illuminate\Notifications\Messages\SlackMessage; +use Illuminate\Notifications\Notification; class CheckinAssetNotification extends Notification { @@ -20,19 +21,15 @@ class CheckinAssetNotification extends Notification * * @param $params */ - public function __construct($params) + public function __construct(Asset $asset, $checkedOutTo, User $checkedInBy, $note) { - $this->target = $params['target']; - $this->item = $params['item']; - $this->admin = $params['admin']; - $this->note = ''; - $this->expected_checkin = ''; - $this->target_type = $params['target_type']; - $this->settings = $params['settings']; + $this->target = $checkedOutTo; + $this->item = $asset; + $this->admin = $checkedInBy; + $this->note = $note; - if (array_key_exists('note', $params)) { - $this->note = $params['note']; - } + $this->settings = Setting::getSettings(); + $this->expected_checkin = ''; if ($this->item->expected_checkin) { $this->expected_checkin = \App\Helpers\Helper::getFormattedDateObject($this->item->expected_checkin, 'date', diff --git a/app/Notifications/CheckinLicenseNotification.php b/app/Notifications/CheckinLicenseSeatNotification.php similarity index 86% rename from app/Notifications/CheckinLicenseNotification.php rename to app/Notifications/CheckinLicenseSeatNotification.php index f8a52ccf3c..6851055ce0 100644 --- a/app/Notifications/CheckinLicenseNotification.php +++ b/app/Notifications/CheckinLicenseSeatNotification.php @@ -2,6 +2,8 @@ namespace App\Notifications; +use App\Models\License; +use App\Models\LicenseSeat; use App\Models\Setting; use App\Models\SnipeModel; use App\Models\User; @@ -12,7 +14,7 @@ use Illuminate\Notifications\Messages\SlackMessage; use Illuminate\Notifications\Notification; use Illuminate\Support\Facades\Mail; -class CheckinLicenseNotification extends Notification +class CheckinLicenseSeatNotification extends Notification { use Queueable; /** @@ -25,19 +27,13 @@ class CheckinLicenseNotification extends Notification * * @param $params */ - public function __construct($params) + public function __construct(LicenseSeat $licenseSeat, $checkedOutTo, User $checkedInBy, $note) { - $this->target = $params['target']; - $this->item = $params['item']; - $this->admin = $params['admin']; - $this->note = ''; - $this->settings = $params['settings']; - $this->target_type = $params['target_type']; - - if (array_key_exists('note', $params)) { - $this->note = $params['note']; - } - + $this->target = $checkedOutTo; + $this->item = $licenseSeat->license; + $this->admin = $checkedInBy; + $this->note = $note; + $this->settings = Setting::getSettings(); } /** @@ -100,7 +96,6 @@ class CheckinLicenseNotification extends Notification */ public function toMail($notifiable) { - return (new MailMessage)->markdown('notifications.markdown.checkin-license', [ 'item' => $this->item, diff --git a/app/Notifications/CheckoutAccessoryNotification.php b/app/Notifications/CheckoutAccessoryNotification.php index 4e8950619d..11368bf06c 100644 --- a/app/Notifications/CheckoutAccessoryNotification.php +++ b/app/Notifications/CheckoutAccessoryNotification.php @@ -2,6 +2,7 @@ namespace App\Notifications; +use App\Models\Accessory; use App\Models\Setting; use App\Models\SnipeModel; use App\Models\User; @@ -15,33 +16,20 @@ use Illuminate\Support\Facades\Mail; class CheckoutAccessoryNotification extends Notification { use Queueable; - /** - * @var - */ - private $params; /** * Create a new notification instance. - * - * @param $params */ - public function __construct($params) + public function __construct(Accessory $accessory, $checkedOutTo, User $checkedOutBy, $acceptance, $note) { - $this->target = $params['target']; - $this->item = $params['item']; - $this->admin = $params['admin']; - $this->log_id = $params['log_id']; - $this->note = ''; - $this->last_checkout = ''; - $this->expected_checkin = ''; - $this->target_type = $params['target_type']; - $this->settings = $params['settings']; - - if (array_key_exists('note', $params)) { - $this->note = $params['note']; - } - + $this->item = $accessory; + $this->admin = $checkedOutBy; + $this->note = $note; + $this->target = $checkedOutTo; + $this->acceptance = $acceptance; + + $this->settings = Setting::getSettings(); } @@ -132,6 +120,8 @@ class CheckoutAccessoryNotification extends Notification $eula = $this->item->getEula(); $req_accept = $this->item->requireAcceptance(); + $accept_url = is_null($this->acceptance) ? null : route('account.accept.item', $this->acceptance); + return (new MailMessage)->markdown('notifications.markdown.checkout-accessory', [ 'item' => $this->item, @@ -140,7 +130,7 @@ class CheckoutAccessoryNotification extends Notification 'target' => $this->target, 'eula' => $eula, 'req_accept' => $req_accept, - 'accept_url' => url('/').'/account/accept-asset/'.$this->log_id, + 'accept_url' => $accept_url, ]) ->subject(trans('mail.Confirm_accessory_delivery')); diff --git a/app/Notifications/CheckoutAssetNotification.php b/app/Notifications/CheckoutAssetNotification.php index 8451d6dcd9..db4ba294f5 100644 --- a/app/Notifications/CheckoutAssetNotification.php +++ b/app/Notifications/CheckoutAssetNotification.php @@ -2,6 +2,7 @@ namespace App\Notifications; +use App\Models\Asset; use App\Models\Setting; use App\Models\User; use Illuminate\Bus\Queueable; @@ -13,31 +14,25 @@ use Illuminate\Contracts\Queue\ShouldQueue; class CheckoutAssetNotification extends Notification { use Queueable; - /** - * @var - */ - private $params; /** * Create a new notification instance. * * @param $params */ - public function __construct($params) + public function __construct(Asset $asset, $checkedOutTo, User $checkedOutBy, $acceptance, $note) { - $this->target = $params['target']; - $this->item = $params['item']; - $this->admin = $params['admin']; - $this->log_id = $params['log_id']; - $this->note = ''; + + $this->item = $asset; + $this->admin = $checkedOutBy; + $this->note = $note; + $this->target = $checkedOutTo; + $this->acceptance = $acceptance; + + $this->settings = Setting::getSettings(); + $this->last_checkout = ''; $this->expected_checkin = ''; - $this->target_type = $params['target_type']; - $this->settings = $params['settings']; - - if (array_key_exists('note', $params)) { - $this->note = $params['note']; - } if ($this->item->last_checkout) { $this->last_checkout = \App\Helpers\Helper::getFormattedDateObject($this->item->last_checkout, 'date', @@ -146,17 +141,18 @@ class CheckoutAssetNotification extends Notification $fields = $this->item->model->fieldset->fields; } + $accept_url = is_null($this->acceptance) ? null : route('account.accept.item', $this->acceptance); + $message = (new MailMessage)->markdown('notifications.markdown.checkout-asset', [ 'item' => $this->item, 'admin' => $this->admin, 'note' => $this->note, - 'log_id' => $this->note, 'target' => $this->target, 'fields' => $fields, 'eula' => $eula, 'req_accept' => $req_accept, - 'accept_url' => url('/').'/account/accept-asset/'.$this->log_id, + 'accept_url' => $accept_url, 'last_checkout' => $this->last_checkout, 'expected_checkin' => $this->expected_checkin, ]) diff --git a/app/Notifications/CheckoutConsumableNotification.php b/app/Notifications/CheckoutConsumableNotification.php index 1811c70401..40780c7abc 100644 --- a/app/Notifications/CheckoutConsumableNotification.php +++ b/app/Notifications/CheckoutConsumableNotification.php @@ -2,6 +2,7 @@ namespace App\Notifications; +use App\Models\Consumable; use App\Models\Setting; use App\Models\SnipeModel; use App\Models\User; @@ -25,21 +26,16 @@ class CheckoutConsumableNotification extends Notification * * @param $params */ - public function __construct($params) + public function __construct(Consumable $consumable, $checkedOutTo, User $checkedOutBy, $acceptance, $note) { - $this->target = $params['target']; - $this->item = $params['item']; - $this->admin = $params['admin']; - $this->log_id = $params['log_id']; - $this->note = ''; - $this->last_checkout = ''; - $this->expected_checkin = ''; - $this->target_type = $params['target_type']; - $this->settings = $params['settings']; - if (array_key_exists('note', $params)) { - $this->note = $params['note']; - } + $this->item = $consumable; + $this->admin = $checkedOutBy; + $this->note = $note; + $this->target = $checkedOutTo; + $this->acceptance = $acceptance; + + $this->settings = Setting::getSettings(); } @@ -80,7 +76,9 @@ class CheckoutConsumableNotification extends Notification /** * Send an email if an email should be sent at checkin/checkout */ + if ((method_exists($this->item, 'checkin_email')) && ($this->item->checkin_email())) { + $notifyBy[1] = 'mail'; } @@ -124,16 +122,17 @@ class CheckoutConsumableNotification extends Notification $eula = $this->item->getEula(); $req_accept = $this->item->requireAcceptance(); + $accept_url = is_null($this->acceptance) ? null : route('account.accept.item', $this->acceptance); + return (new MailMessage)->markdown('notifications.markdown.checkout-consumable', [ 'item' => $this->item, 'admin' => $this->admin, 'note' => $this->note, - 'log_id' => $this->note, 'target' => $this->target, 'eula' => $eula, 'req_accept' => $req_accept, - 'accept_url' => url('/').'/account/accept-asset/'.$this->log_id, + 'accept_url' => $accept_url, ]) ->subject(trans('mail.Confirm_consumable_delivery')); diff --git a/app/Notifications/CheckoutLicenseNotification.php b/app/Notifications/CheckoutLicenseSeatNotification.php similarity index 85% rename from app/Notifications/CheckoutLicenseNotification.php rename to app/Notifications/CheckoutLicenseSeatNotification.php index 93530e2cde..74df6e2f46 100644 --- a/app/Notifications/CheckoutLicenseNotification.php +++ b/app/Notifications/CheckoutLicenseSeatNotification.php @@ -2,6 +2,8 @@ namespace App\Notifications; +use App\Models\License; +use App\Models\LicenseSeat; use App\Models\Setting; use App\Models\SnipeModel; use App\Models\User; @@ -12,7 +14,7 @@ use Illuminate\Notifications\Messages\SlackMessage; use Illuminate\Notifications\Notification; use Illuminate\Support\Facades\Mail; -class CheckoutLicenseNotification extends Notification +class CheckoutLicenseSeatNotification extends Notification { use Queueable; /** @@ -25,23 +27,15 @@ class CheckoutLicenseNotification extends Notification * * @param $params */ - public function __construct($params) + public function __construct(LicenseSeat $licenseSeat, $checkedOutTo, User $checkedOutBy, $acceptance, $note) { - $this->target = $params['target']; - $this->item = $params['item']; - $this->admin = $params['admin']; - $this->log_id = $params['log_id']; - $this->note = ''; - $this->target_type = $params['target_type']; - $this->settings = $params['settings']; - $this->target_type = $params['target_type']; - - if (array_key_exists('note', $params)) { - $this->note = $params['note']; - } - - + $this->item = $licenseSeat->license; + $this->admin = $checkedOutBy; + $this->note = $note; + $this->target = $checkedOutTo; + $this->acceptance = $acceptance; + $this->settings = Setting::getSettings(); } /** @@ -125,6 +119,8 @@ class CheckoutLicenseNotification extends Notification $eula = method_exists($this->item, 'getEula') ? $this->item->getEula() : ''; $req_accept = method_exists($this->item, 'requireAcceptance') ? $this->item->requireAcceptance() : 0; + $accept_url = is_null($this->acceptance) ? null : route('account.accept.item', $this->acceptance); + return (new MailMessage)->markdown('notifications.markdown.checkout-license', [ 'item' => $this->item, @@ -133,7 +129,7 @@ class CheckoutLicenseNotification extends Notification 'target' => $this->target, 'eula' => $eula, 'req_accept' => $req_accept, - 'accept_url' => url('/').'/account/accept-asset/'.$this->log_id, + 'accept_url' => $accept_url, ]) ->subject(trans('mail.Confirm_license_delivery')); diff --git a/app/Notifications/CurrentInventory.php b/app/Notifications/CurrentInventory.php new file mode 100644 index 0000000000..b39c7245c6 --- /dev/null +++ b/app/Notifications/CurrentInventory.php @@ -0,0 +1,66 @@ +user = $user; + } + + /** + * Get the notification's delivery channels. + * + * @param mixed $notifiable + * @return array + */ + public function via($notifiable) + { + return ['mail']; + } + + /** + * Get the mail representation of the notification. + * + * @param mixed $notifiable + * @return \Illuminate\Notifications\Messages\MailMessage + */ + public function toMail($notifiable) + { + $message = (new MailMessage)->markdown('notifications.markdown.user-inventory', + [ + 'assets' => $this->user->assets, + 'accessories' => $this->user->accessories, + 'licenses' => $this->user->licenses, + ]) + ->subject('Inventory Report'); + + return $message; + } + + /** + * Get the array representation of the notification. + * + * @param mixed $notifiable + * @return array + */ + public function toArray($notifiable) + { + return [ + // + ]; + } +} diff --git a/app/Notifications/InventoryAlert.php b/app/Notifications/InventoryAlert.php index 3dee49134a..0d9a26fc2e 100644 --- a/app/Notifications/InventoryAlert.php +++ b/app/Notifications/InventoryAlert.php @@ -3,8 +3,8 @@ namespace App\Notifications; use Illuminate\Bus\Queueable; -use Illuminate\Notifications\Messages\MailMessage; use Illuminate\Notifications\Notification; +use Illuminate\Notifications\Messages\MailMessage; class InventoryAlert extends Notification { @@ -33,14 +33,13 @@ class InventoryAlert extends Notification */ public function via($notifiable) { - $notifyBy = []; - $notifyBy[]='mail'; + $notifyBy[] = 'mail'; + return $notifyBy; } public function toSlack($notifiable) { - } /** @@ -51,17 +50,16 @@ class InventoryAlert extends Notification */ public function toMail($params) { - - $message = (new MailMessage)->markdown('notifications.markdown.report-low-inventory', + $message = (new MailMessage)->markdown( + 'notifications.markdown.report-low-inventory', [ 'items' => $this->items, 'threshold' => $this->threshold, - ]) + ] + ) ->subject(trans('mail.Low_Inventory_Report')); return $message; - - } /** diff --git a/app/Observers/AssetObserver.php b/app/Observers/AssetObserver.php index df466d3753..2a42a26873 100644 --- a/app/Observers/AssetObserver.php +++ b/app/Observers/AssetObserver.php @@ -57,7 +57,7 @@ class AssetObserver */ public function created(Asset $asset) { - if ($settings = Setting::first()) { + if ($settings = Setting::getSettings()) { $settings->increment('next_auto_tag_base'); } diff --git a/app/Presenters/AssetMaintenancesPresenter.php b/app/Presenters/AssetMaintenancesPresenter.php index 452253b900..f2671f040f 100644 --- a/app/Presenters/AssetMaintenancesPresenter.php +++ b/app/Presenters/AssetMaintenancesPresenter.php @@ -46,6 +46,14 @@ class AssetMaintenancesPresenter extends Presenter "title" => trans('admin/hardware/table.asset_tag'), "formatter" => "assetTagLinkFormatter" ], [ + "field" => "model", + "searchable" => true, + "sortable" => true, + "switchable" => true, + "title" => trans('admin/hardware/form.model'), + "visible" => false, + "formatter" => "modelsLinkObjFormatter" + ],[ "field" => "supplier", "searchable" => true, "sortable" => true, diff --git a/app/Presenters/LicenseSeatPresenter.php b/app/Presenters/LicenseSeatPresenter.php new file mode 100644 index 0000000000..5267aa7290 --- /dev/null +++ b/app/Presenters/LicenseSeatPresenter.php @@ -0,0 +1,18 @@ +model->license->name; + } +} diff --git a/app/Presenters/UserPresenter.php b/app/Presenters/UserPresenter.php index 0d49852263..f42010972a 100644 --- a/app/Presenters/UserPresenter.php +++ b/app/Presenters/UserPresenter.php @@ -6,6 +6,7 @@ use App\Helpers\Helper; use App\Models\Setting; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Gate; +use Illuminate\Support\Facades\Storage; /** * Class UserPresenter @@ -320,16 +321,20 @@ class UserPresenter extends Presenter { if ($this->avatar) { - return config('app.url').'/uploads/avatars/'.$this->avatar; + return Storage::disk('public')->url('avatars/'.$this->avatar, $this->avatar); } - if ((Setting::getSettings()->load_remote=='1') && ($this->email!='')) { + if ($this->email != '') { + /** + * @see https://en.gravatar.com/site/implement/images/ + * Return a default [Myster Person] gravatar if the user does not have one + */ $gravatar = md5(strtolower(trim($this->email))); - return "//gravatar.com/avatar/".$gravatar; + // return "//gravatar.com/avatar/".$gravatar.'?d=mp'; } - // Set a fun, gender-neutral default icon - return url('/').'/img/default-sm.png'; + // Set a fun, gender-neutral default icon when there is no email + return url('/img/default-sm.png'); } diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index 35f392f9e1..90f4c15fc5 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -52,15 +52,10 @@ class AppServiceProvider extends ServiceProvider */ public function register() { - $monolog = Log::getMonolog(); - $log_level = config('app.log_level'); if (($this->app->environment('production')) && (config('services.rollbar.access_token'))){ $this->app->register(\Rollbar\Laravel\RollbarServiceProvider::class); } - - foreach ($monolog->getHandlers() as $handler) { - $handler->setLevel($log_level); - } + } } diff --git a/app/Providers/AuthServiceProvider.php b/app/Providers/AuthServiceProvider.php index bff39fbf18..d5f1dbd582 100644 --- a/app/Providers/AuthServiceProvider.php +++ b/app/Providers/AuthServiceProvider.php @@ -139,6 +139,10 @@ class AuthServiceProvider extends ServiceProvider return $user->hasAccess('self.edit_location'); }); + Gate::define('self.checkout_assets', function($user) { + return $user->hasAccess('self.checkout_assets'); + }); + Gate::define('backend.interact', function ($user) { return $user->can('view', Statuslabel::class) || $user->can('view', AssetModel::class) diff --git a/app/Providers/EventServiceProvider.php b/app/Providers/EventServiceProvider.php index 9d3e0f8a98..db9677d8a7 100644 --- a/app/Providers/EventServiceProvider.php +++ b/app/Providers/EventServiceProvider.php @@ -2,7 +2,12 @@ namespace App\Providers; +use App\Models\Setting; +use App\Events\SettingSaved; +use App\Listeners\LogListener; +use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\Event; +use App\Listeners\CheckoutableListener; use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider; class EventServiceProvider extends ServiceProvider @@ -23,6 +28,15 @@ class EventServiceProvider extends ServiceProvider ], ]; + /** + * The subscriber classes to register. + * + * @var array + */ + protected $subscribe = [ + LogListener::class, + CheckoutableListener::class + ]; /** * Register any events for your application. @@ -33,6 +47,12 @@ class EventServiceProvider extends ServiceProvider { parent::boot(); - // + /** + * Clear the LDAP settings cache when the settings model is saved + */ + Event::listen(SettingSaved::class, function () { + Cache::forget(Setting::APP_SETTINGS_KEY); + Cache::forget(Setting::SETUP_CHECK_KEY); + }); } } diff --git a/app/Providers/LdapServiceProvider.php b/app/Providers/LdapServiceProvider.php new file mode 100644 index 0000000000..fc1354a468 --- /dev/null +++ b/app/Providers/LdapServiceProvider.php @@ -0,0 +1,29 @@ +app->singleton(LdapAd::class, LdapAd::class); + } + + + /** + * Register any application services. + * + * @return void + */ + public function register() + { + + } +} diff --git a/app/Providers/SettingsServiceProvider.php b/app/Providers/SettingsServiceProvider.php index ed965bf9c7..56d95868f7 100644 --- a/app/Providers/SettingsServiceProvider.php +++ b/app/Providers/SettingsServiceProvider.php @@ -39,76 +39,88 @@ class SettingsServiceProvider extends ServiceProvider * Set some common variables so that they're globally available. * The paths should always be public (versus private uploads) */ + + + // Model paths and URLs + + \App::singleton('assets_upload_path', function(){ + return 'assets/'; + }); + + \App::singleton('accessories_upload_path', function() { + return 'accessories/'; + }); + \App::singleton('models_upload_path', function(){ - return public_path('/uploads/models/'); + return 'assetmodels/'; }); \App::singleton('models_upload_url', function(){ - return url('/').'/uploads/models/'; + return 'assetmodels/'; }); // Categories \App::singleton('categories_upload_path', function(){ - return public_path('/uploads/categories/'); + return 'categories/'; }); \App::singleton('categories_upload_url', function(){ - return url('/').'/uploads/categories/'; + return 'categories/'; }); // Locations \App::singleton('locations_upload_path', function(){ - return public_path('/uploads/locations/'); + return 'locations/'; }); \App::singleton('locations_upload_url', function(){ - return url('/').'/uploads/locations/'; + return 'storage/public_uploads/locations/'; }); // Users \App::singleton('users_upload_path', function(){ - return public_path('/uploads/users/'); + return 'users/'; }); \App::singleton('users_upload_url', function(){ - return url('/').'/uploads/users/'; + return 'public_uploads/users/'; }); // Manufacturers \App::singleton('manufacturers_upload_path', function(){ - return public_path('/uploads/manufacturers/'); + return 'manufacturers/'; }); \App::singleton('manufacturers_upload_url', function(){ - return url('/').'/uploads/manufacturers/'; + return 'public_uploads/manufacturers/'; }); // Suppliers \App::singleton('suppliers_upload_path', function(){ - return public_path('/uploads/suppliers/'); + return 'suppliers/'; }); \App::singleton('suppliers_upload_url', function(){ - return url('/').'/uploads/suppliers/'; + return 'storage/public_uploads/suppliers/'; }); // Departments \App::singleton('departments_upload_path', function(){ - return public_path('/uploads/departments/'); + return 'departments/'; }); \App::singleton('departments_upload_url', function(){ - return url('/').'/uploads/departments/'; + return 'departments/'; }); // Company paths and URLs \App::singleton('companies_upload_path', function(){ - return public_path('/uploads/companies/'); + return 'companies/'; }); \App::singleton('companies_upload_url', function(){ - return url('/').'/uploads/companies/'; + return 'storage/public_uploads/companies/'; }); diff --git a/app/Services/LdapAd.php b/app/Services/LdapAd.php new file mode 100644 index 0000000000..6718631e2c --- /dev/null +++ b/app/Services/LdapAd.php @@ -0,0 +1,450 @@ + + * + * @since 5.0.0 + */ +class LdapAd extends LdapAdConfiguration +{ + /** + * @see https://wdmsb.wordpress.com/2014/12/03/descriptions-of-active-directory-useraccountcontrol-value/ + */ + const AD_USER_ACCOUNT_CONTROL_FLAGS = ['512', '544', '66048', '66080', '262656', '262688', '328192', '328224']; + + /** + * The LDAP results per page. + */ + const PAGE_SIZE = 500; + + /** + * A base dn. + * + * @var string + */ + public $baseDn = null; + + /** + * Adldap instance. + * + * @var \Adldap\Adldap + */ + protected $ldap; + + /** + * Initialize LDAP from user settings + * + * @since 5.0.0 + * + * @return bool + */ + public function init() : bool + { + // Already initialized + if($this->ldap) { + return true; + } + + parent::init(); + if($this->isLdapEnabled()) { + $this->ldap = new Adldap(); + $this->ldap->addProvider($this->ldapConfig); + return true; + } + return false; + } + + /** + * Create a user if they successfully login to the LDAP server. + * + * @author Wes Hulette + * + * @since 5.0.0 + * + * @param string $username + * @param string $password + * + * @return \App\Models\User + * + * @throws Exception + */ + public function ldapLogin(string $username, string $password): User + { + try { + $this->ldap->auth()->attempt($username, $password); + } catch (Exception $e) { + Log::error($e->getMessage()); + throw new Exception('Unable to validate user credentials!'); + } + + // Should we sync the logged in user + Log::debug('Attempting to find user in LDAP directory'); + $record = $this->ldap->search()->findBy($this->ldapSettings['ldap_username_field'], $username); + + if($record) { + if ($this->isLdapSync($record)) { + $this->syncUserLdapLogin($record, $password); + } + } + else { + throw new Exception('Unable to find user in LDAP directory!'); + } + + return User::where('username', $username) + ->whereNull('deleted_at')->where('ldap_import', '=', 1) + ->where('activated', '=', '1')->first(); + } + + /** + * Set the user information based on the LDAP settings. + * + * @author Wes Hulette + * + * @since 5.0.0 + * + * @param \Adldap\Models\User $user + * @param null|Collection $defaultLocation + * @param null|Collection $mappedLocations + * + * @return null|\App\Models\User + */ + public function processUser(AdldapUser $user, ?Collection $defaultLocation=null, ?Collection $mappedLocations=null): ?User + { + // Only sync active users + if(!$user) { + return null; + } + $snipeUser = []; + $snipeUser['username'] = $user->{$this->ldapSettings['ldap_username_field']}[0] ?? ''; + $snipeUser['employee_number'] = $user->{$this->ldapSettings['ldap_emp_num']}[0] ?? ''; + $snipeUser['lastname'] = $user->{$this->ldapSettings['ldap_lname_field']}[0] ?? ''; + $snipeUser['firstname'] = $user->{$this->ldapSettings['ldap_fname_field']}[0] ?? ''; + $snipeUser['email'] = $user->{$this->ldapSettings['ldap_email']}[0] ?? ''; + $snipeUser['title'] = $user->getTitle() ?? ''; + $snipeUser['telephonenumber'] = $user->getTelephoneNumber() ?? ''; + $snipeUser['location_id'] = $this->getLocationId($user, $defaultLocation, $mappedLocations); + $snipeUser['activated'] = $this->getActiveStatus($user); + + return $this->setUserModel($snipeUser); + } + + /** + * Set the User model information. + * + * @author Wes Hulette + * + * @since 5.0.0 + * + * @param array $userInfo The user info to save to the database + * + * @return \App\Models\User + */ + public function setUserModel(array $userInfo): User + { + // If the username exists, return the user object, otherwise create a new user object + $user = User::firstOrNew([ + 'username' => $userInfo['username'], + ]); + $user->username = $user->username ?? trim($userInfo['username']); + $user->password = $user->password ?? Helper::generateEncyrptedPassword(); + $user->first_name = trim($userInfo['firstname']); + $user->last_name = trim($userInfo['lastname']); + $user->email = trim($userInfo['email']); + $user->employee_num = trim($userInfo['employee_number']); + $user->jobtitle = trim($userInfo['title']); + $user->phone = trim($userInfo['telephonenumber']); + $user->activated = $userInfo['activated']; + $user->location_id = $userInfo['location_id']; + $user->notes = 'Imported from LDAP'; + $user->ldap_import = 1; + + return $user; + } + + /** + * Sync a user who has logged in by LDAP. + * + * @author Wes Hulette + * + * @since 5.0.0 + * + * @param \Adldap\Models\User $record + * @param string $password + * + * @throws Exception + */ + private function syncUserLdapLogin(AdldapUser $record, string $password): void + { + $user = $this->processUser($record); + + if (is_null($user->last_login)) { + $user->notes = 'Imported on first login from LDAP2'; + } + + if ($this->ldapSettings['ldap_pw_sync']) { + Log::debug('Syncing users password with LDAP directory.'); + $user->password = bcrypt($password); + } + + if (!$user->save()) { + Log::debug('Could not save user. '.$user->getErrors()); + throw new Exception('Could not save user: '.$user->getErrors()); + } + } + + /** + * Check to see if we should sync the user with the LDAP directory. + * + * @author Wes Hulette + * + * @since 5.0.0 + * + * @param \Adldap\Models\User $user + * + * @return bool + */ + private function isLdapSync(AdldapUser $user): bool + { + return (false == $this->ldapSettings['ldap_active_flag']) + || ('true' == strtolower($user->{$this->ldapSettings['ldap_active_flag']}[0])); + } + + /** + * Set the active status of the user. + * + * @author Wes Hulette + * + * @since 5.0.0 + * + * @param \Adldap\Models\User $user + * + * @return int + */ + private function getActiveStatus(AdldapUser $user): int + { + $activeStatus = 0; + /* + * Check to see if we are connected to an AD server + * if so, check the Active Directory User Account Control Flags + */ + if ($user->hasAttribute($user->getSchema()->userAccountControl())) { + $activeStatus = (in_array($user->getUserAccountControl(), self::AD_USER_ACCOUNT_CONTROL_FLAGS)) ? 1 : 0; + } else { + // If there is no activated flag, assume this is handled via the OU and activate the users + if (false == $this->ldapSettings['ldap_active_flag']) { + $activeStatus = 1; + } + } + + return $activeStatus; + } + + /** + * Get a default selected location, or a OU mapped location if available. + * + * @author Wes Hulette + * + * @since 5.0.0 + * + * @param \Adldap\Models\User $user + * @param Collection|null $defaultLocation + * @param Collection|null $mappedLocations + * + * @return null|int + */ + private function getLocationId(AdldapUser $user, ?Collection $defaultLocation, ?Collection $mappedLocations): ?int + { + $locationId = null; + // Set the users default locations, if set + if ($defaultLocation) { + $locationId = $defaultLocation->keys()->first(); + } + + // Check to see if the user is in a mapped location + if ($mappedLocations) { + $location = $mappedLocations->filter(function ($value, $key) use ($user) { + if ($user->inOu($value)) { + return $key; + } + }); + + if ($location->count() > 0) { + $locationId = $location->keys()->first(); + } + } + + return $locationId; + } + + /** + * Get the base dn for the query. + * + * @author Wes Hulette + * + * @since 5.0.0 + * + * @return string + */ + private function getBaseDn(): string + { + if (!is_null($this->baseDn)) { + return $this->baseDn; + } + + return $this->ldapSettings['ldap_basedn']; + } + + /** + * Format the ldap filter if needed. + * + * @author Wes Hulette + * + * @since 5.0.0 + * + * @return null|string + */ + private function getFilter(): ?string + { + $filter = $this->ldapSettings['ldap_filter']; + if ('' === $filter) { + return null; + } + // Add surrounding parentheses as needed + $paren = mb_substr($filter, 0, 1, 'utf-8'); + if ('(' !== $paren) { + return '('.$filter.')'; + } + + return $filter; + } + + /** + * Get the selected fields to return + * This should help with memory on large result sets as we are not returning all fields. + * + * @author Wes Hulette + * + * @since 5.0.0 + * + * @return array + */ + private function getSelectedFields(): array + { + /** @var Schema $schema */ + $schema = new $this->ldapConfig['schema']; + return [ + $this->ldapSettings['ldap_username_field'], + $this->ldapSettings['ldap_fname_field'], + $this->ldapSettings['ldap_lname_field'], + $this->ldapSettings['ldap_email'], + $this->ldapSettings['ldap_emp_num'], + $this->ldapSettings['ldap_active_flag'], + $schema->memberOf(), + $schema->userAccountControl(), + $schema->title(), + $schema->telephone(), + ]; + } + + /** + * Test the bind user connection. + * + * @author Wes Hulette + * + * @since 5.0.0 + */ + public function testLdapAdBindConnection(): void + { + try { + $this->ldap->search()->ous()->get()->count(); + } catch (Exception $th) { + Log::error($th->getMessage()); + throw new Exception('Unable to search LDAP directory!'); + } + } + + /** + * Test the user can connect to the LDAP server. + * + * @author Wes Hulette + * + * @since 5.0.0 + */ + public function testLdapAdUserConnection(): void + { + try { + $this->ldap->connect(); + } catch (\Adldap\Auth\BindException $e) { + Log::error($e); + throw new Exception('Unable to connect to LDAP directory!'); + } + } + + /** + * Test the LDAP configuration by returning up to 10 users. + * + * @author Wes Hulette + * + * @since 5.0.0 + * + * @return Collection + */ + public function testUserImportSync(): Collection + { + $testUsers = collect($this->getLdapUsers()->getResults())->chunk(10)->first(); + if ($testUsers) { + return $testUsers->map(function ($item) { + return (object) [ + 'username' => $item->{$this->ldapSettings['ldap_username_field']}[0] ?? null, + 'employee_number' => $item->{$this->ldapSettings['ldap_emp_num']}[0] ?? null, + 'lastname' => $item->{$this->ldapSettings['ldap_lname_field']}[0] ?? null, + 'firstname' => $item->{$this->ldapSettings['ldap_fname_field']}[0] ?? null, + 'email' => $item->{$this->ldapSettings['ldap_email']}[0] ?? null, + ]; + }); + } + + return collect(); + } + + /** + * Query the LDAP server to get the users to process and return a page set. + * + * @author Wes Hulette + * + * @since 5.0.0 + * + * @param int $page The paged results to get + * + * @return \Adldap\Query\Paginator + */ + public function getLdapUsers(int $page=0): Paginator + { + $search = $this->ldap->search()->users()->in($this->getBaseDn()); + + $filter = $this->getFilter(); + if (!is_null($filter)) { + $search = $search->rawFilter($filter); + } + + return $search->select($this->getSelectedFields()) + ->paginate(self::PAGE_SIZE, $page); + } +} diff --git a/app/Services/LdapAdConfiguration.php b/app/Services/LdapAdConfiguration.php new file mode 100644 index 0000000000..d25679faaa --- /dev/null +++ b/app/Services/LdapAdConfiguration.php @@ -0,0 +1,277 @@ + + * + * @since 5.0.0 + */ +class LdapAdConfiguration +{ + const LDAP_PORT = 389; + const CONNECTION_TIMEOUT = 5; + const DEFAULT_LDAP_VERSION = 3; + const LDAP_BOOLEAN_SETTINGS = ['ldap_enabled', 'ldap_server_cert_ignore', 'ldap_tls', 'ldap_tls', 'ldap_pw_sync', 'is_ad']; + + /** + * Ldap Settings. + * + * @var Collection + */ + public $ldapSettings; + + /** + * LDAP Config. + * + * @var array + */ + public $ldapConfig; + + /** + * Initialize LDAP from user settings + * + * @since 5.0.0 + */ + public function init() { + $this->ldapSettings = $this->getSnipeItLdapSettings(); + if ($this->isLdapEnabled()) { + $this->setSnipeItConfig(); + } + } + + /** + * Merge the default Adlap config with the SnipeIT config. + * + * @author Wes Hulette + * + * @since 5.0.0 + */ + private function setSnipeItConfig() + { + $this->ldapConfig = $this->setLdapConnectionConfiguration(); + $this->certificateCheck(); + } + + /** + * Get the LDAP settings from the Settings model. + * + * @author Wes Hulette + * + * @since 5.0.0 + * + * @return \Illuminate\Support\Collection + */ + private function getSnipeItLdapSettings(): Collection + { + $ldapSettings = Setting::getLdapSettings() + ->map(function ($item, $key) { + // Trim the items + if (is_string($item)) { + $item = trim($item); + } + // Get the boolean value of the LDAP setting, makes it easier to work with them + if (in_array($key, self::LDAP_BOOLEAN_SETTINGS)) { + return boolval($item); + } + + // Decrypt the admin password + if ('ldap_pword' === $key && !empty($item)) { + try { + return decrypt($item); + } catch (Exception $e) { + throw new Exception('Your app key has changed! Could not decrypt LDAP password using your current app key, so LDAP authentication has been disabled. Login with a local account, update the LDAP password and re-enable it in Admin > Settings.'); + } + } + + if ($item && 'ldap_server' === $key) { + return collect(parse_url($item)); + } + + return $item; + }); + + return $ldapSettings; + } + + /** + * Set the server certificate environment variable. + * + * @author Wes Hulette + * + * @since 5.0.0 + */ + private function certificateCheck(): void + { + // If we are ignoring the SSL cert we need to setup the environment variable + // before we create the connection + if ($this->ldapSettings['ldap_server_cert_ignore']) { + putenv('LDAPTLS_REQCERT=never'); + } + + // If the user specifies where CA Certs are, make sure to use them + if (env('LDAPTLS_CACERT')) { + putenv('LDAPTLS_CACERT='.env('LDAPTLS_CACERT')); + } + } + + /** + * Set the Adlap2 connection configuration values based on SnipeIT settings. + * + * @author Wes Hulette + * + * @since 5.0.0 + * + * @return array + */ + private function setLdapConnectionConfiguration(): array + { + // Create the configuration array. + return [ + // Mandatory Configuration Options + 'hosts' => $this->getServerUrlBase(), + 'base_dn' => $this->ldapSettings['ldap_basedn'], + 'username' => $this->ldapSettings['ldap_uname'], + 'password' => $this->ldapSettings['ldap_pword'], + + // Optional Configuration Options + 'schema' => $this->getSchema(), + 'account_prefix' => '', + 'account_suffix' => '', + 'port' => $this->getPort(), + 'follow_referrals' => false, + 'use_ssl' => $this->isSsl(), + 'use_tls' => $this->ldapSettings['ldap_tls'], + 'version' => $this->ldapSettings['ldap_version'] ?? self::DEFAULT_LDAP_VERSION, + 'timeout' => self::CONNECTION_TIMEOUT, + + // Custom LDAP Options + 'custom_options' => [ + // See: http://php.net/ldap_set_option + // LDAP_OPT_X_TLS_REQUIRE_CERT => LDAP_OPT_X_TLS_HARD, + ], + ]; + } + + /** + * Get the schema to use for the connection. + * + * @author Wes Hulette + * + * @since 5.0.0 + * + * @return string + */ + private function getSchema(): string + { + $schema = \Adldap\Schemas\OpenLDAP::class; + if ($this->ldapSettings['is_ad']) { + $schema = \Adldap\Schemas\ActiveDirectory::class; + } + + return $schema; + } + + /** + * Get the port number from the connection url. + * + * @author Wes Hulette + * + * @since 5.0.0 + * + * @return int + */ + private function getPort(): int + { + $port = $this->getLdapServerData('port'); + if ($port && is_int($port)) { + return $port; + } + return self::LDAP_PORT; + } + + /** + * Get ldap scheme from url to determin ssl use. + * + * @author Wes Hulette + * + * @since 5.0.0 + * + * @return bool + */ + private function isSsl(): bool + { + $scheme = $this->getLdapServerData('scheme'); + if ($scheme && 'ldaps' === strtolower($scheme)) { + return true; + } + return false; + } + + /** + * Return the base url to the LDAP server. + * + * @author Wes Hulette + * + * @since 5.0.0 + * + * @return array + */ + private function getServerUrlBase(): array + { + if ($this->ldapSettings['is_ad']) { + return collect(explode(',', $this->ldapSettings['ad_domain']))->map(function ($item) { + return trim($item); + })->toArray(); + } + + $url = $this->getLdapServerData('host'); + return $url ? [$url] : []; + } + + /** + * Get ldap enabled setting + * + * @author Steffen Buehl + * + * @since 5.0.0 + * + * @return bool + */ + public function isLdapEnabled(): bool + { + return $this->ldapSettings && $this->ldapSettings->get('ldap_enabled'); + } + + /** + * Get parsed ldap server information + * + * @author Steffen Buehl + * + * @since 5.0.0 + * + * @param $key + * @return mixed|null + */ + protected function getLdapServerData($key) + { + if ($this->ldapSettings) { + $ldapServer = $this->ldapSettings->get('ldap_server'); + if ($ldapServer && $ldapServer instanceof Collection) { + return $ldapServer->get($key); + } + } + + return null; + } +} diff --git a/composer.json b/composer.json index 6822043467..342907a3ef 100644 --- a/composer.json +++ b/composer.json @@ -4,78 +4,95 @@ "keywords": ["assets", "asset-management", "laravel"], "license": "AGPL-3.0-or-later", "type": "project", - "require": { - "php": ">=5.6.4", - "barryvdh/laravel-debugbar": "^2.4", + "require": { + "php": ">=7.1.3", + "adldap2/adldap2": "^9.1", + "bacon/bacon-qr-code": "^1.0", "doctrine/cache": "^1.6", "doctrine/common": "^2.7", - "doctrine/dbal": "^2.5.13", - "doctrine/inflector": "1.1.*", - "doctrine/instantiator": "1.0.*", + "doctrine/dbal": "^2.8.0", + "doctrine/inflector": "1.3.*", + "doctrine/instantiator": "1.1.*", "eduardokum/laravel-mail-auto-embed": "^1.0", "erusev/parsedown": "^1.6", - "fideloper/proxy": "^3.3", + "fideloper/proxy": "~4.0", "intervention/image": "^2.3", "javiereguiluz/easyslugger": "^1.0", - "laravel/framework": "5.4.35", - "laravel/passport": "^3.0", + "laravel/framework": "5.7.*", + "laravel/passport": "~6.0", "laravel/tinker": "^1.0", "laravelcollective/html": "^5.3", - "league/csv": "^8.1", + "league/csv": "^9.0", + "league/flysystem-aws-s3-v3": "~1.0", + "league/flysystem-cached-adapter": "^1.0", + "league/flysystem-rackspace": "^1.0", + "league/flysystem-sftp": "~1.0", "maknz/slack": "^1.7", "neitanod/forceutf8": "^2.0", "patchwork/utf8": "~1.2", "phpdocumentor/reflection-docblock": "3.2.2", - "phpspec/prophecy": "1.6.2", - "pragmarx/google2fa": "^1.0", + "phpspec/prophecy": "1.7.5", + "pragmarx/google2fa": "^3.0", + "pragmarx/google2fa-laravel": "^0.2.0", "predis/predis": "^1.1", - "rollbar/rollbar-laravel": "2.4.1", + "rollbar/rollbar-laravel": "^4.0", "schuppo/password-strength": "~1.5", - "spatie/laravel-backup": "3.11.0", + "spatie/laravel-backup": "^5.6", "tecnickcom/tc-lib-barcode": "^1.15", - "tightenco/ziggy": "^0.4.1", + "tightenco/ziggy": "^0.6.3", "unicodeveloper/laravel-password": "^1.0", - "watson/validating": "^3.0" + "watson/validating": "3.1.7" }, - "require-dev": { - "codeception/codeception": "2.3.6", + "require-dev": { + "barryvdh/laravel-debugbar": "^3.2", + "codeception/codeception": "^2.4", + "filp/whoops": "~2.0", "fzaninotto/faker": "~1.4", - "phpunit/php-token-stream": "1.4.11", - "phpunit/phpunit": "~5.7", + "roave/security-advisories": "dev-master", "squizlabs/php_codesniffer": "*", - "symfony/css-selector": "3.1.*", - "symfony/dom-crawler": "3.1.*" + "symfony/css-selector": "4.0.*", + "symfony/dom-crawler": "4.0.*" }, - "autoload": { - "classmap": [ - "database" - ], - "psr-4": { - "App\\": "app/" - } - }, - "autoload-dev": { - "classmap": [ - "tests/TestCase.php", - "tests/unit/BaseTest.php" - ] - }, - "scripts": { - "post-root-package-install": [ - "php -r \"file_exists('.env') || copy('.env.example', '.env');\"" - ], - "post-create-project-cmd": [ - "php artisan key:generate" - ] - }, - "config": { - "preferred-install": "dist", - "sort-packages": true, - "optimize-autoloader": true, - "process-timeout":3000, - "platform": { - "php": "5.6.4" - } + "extra": { + "laravel": { + "dont-discover": [ + "rollbar/rollbar-laravel" + ] } + }, + "autoload": { + "classmap": [ + "database" + ], + "psr-4": { + "App\\": "app/" + } + }, + "autoload-dev": { + "classmap": [ + "tests/TestCase.php", + "tests/unit/BaseTest.php" + ] + }, + "scripts": { + "post-autoload-dump": [ + "Illuminate\\Foundation\\ComposerScripts::postAutoloadDump", + "@php artisan package:discover" + ], + "post-root-package-install": [ + "php -r \"file_exists('.env') || copy('.env.example', '.env');\"" + ], + "post-create-project-cmd": [ + "php artisan key:generate" + ] + }, + "config": { + "preferred-install": "dist", + "sort-packages": true, + "optimize-autoloader": true, + "platform": { + "php": "7.1.3" + } + } } diff --git a/composer.lock b/composer.lock index e42a3de8d3..caf0ea961d 100644 --- a/composer.lock +++ b/composer.lock @@ -4,36 +4,37 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "f44697f67c1de6fd46cb9a7cb8bc20a6", + "content-hash": "3b6a6bea98c5876c05f1130cf7ad7e97", "packages": [ { - "name": "barryvdh/laravel-debugbar", - "version": "v2.4.3", + "name": "adldap2/adldap2", + "version": "v9.1.4", "source": { "type": "git", - "url": "https://github.com/barryvdh/laravel-debugbar.git", - "reference": "d7c88f08131f6404cb714f3f6cf0642f6afa3903" + "url": "https://github.com/Adldap2/Adldap2.git", + "reference": "e74bf7e3762b35e828179b11eb100da4a12ff701" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/barryvdh/laravel-debugbar/zipball/d7c88f08131f6404cb714f3f6cf0642f6afa3903", - "reference": "d7c88f08131f6404cb714f3f6cf0642f6afa3903", + "url": "https://api.github.com/repos/Adldap2/Adldap2/zipball/e74bf7e3762b35e828179b11eb100da4a12ff701", + "reference": "e74bf7e3762b35e828179b11eb100da4a12ff701", "shasum": "" }, "require": { - "illuminate/support": "5.1.*|5.2.*|5.3.*|5.4.*|5.5.*", - "maximebf/debugbar": "~1.13.0", - "php": ">=5.5.9", - "symfony/finder": "~2.7|~3.0" + "ext-ldap": "*", + "illuminate/contracts": "~5.0", + "php": ">=7.0", + "tightenco/collect": "~5.0" + }, + "require-dev": { + "mockery/mockery": "~1.0", + "phpunit/phpunit": "~6.0" }, "type": "library", "autoload": { "psr-4": { - "Barryvdh\\Debugbar\\": "src/" - }, - "files": [ - "src/helpers.php" - ] + "Adldap\\": "src/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -41,73 +42,151 @@ ], "authors": [ { - "name": "Barry vd. Heuvel", - "email": "barryvdh@gmail.com" + "name": "Steve Bauman", + "email": "steven_bauman@outlook.com", + "role": "Developer" } ], - "description": "PHP Debugbar integration for Laravel", + "description": "A PHP LDAP Package for humans.", "keywords": [ - "debug", - "debugbar", - "laravel", - "profiler", - "webprofiler" + "active directory", + "ad", + "adLDAP", + "adldap2", + "directory", + "ldap", + "windows" ], - "time": "2017-07-21T11:56:48+00:00" + "time": "2018-12-06T15:03:32+00:00" }, { - "name": "christian-riesen/base32", - "version": "1.3.1", + "name": "aws/aws-sdk-php", + "version": "3.81.2", "source": { "type": "git", - "url": "https://github.com/ChristianRiesen/base32.git", - "reference": "0a31e50c0fa9b1692d077c86ac188eecdcbaf7fa" + "url": "https://github.com/aws/aws-sdk-php.git", + "reference": "1dd023879874ce22a7f8e2b2e014166cd1160b0d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ChristianRiesen/base32/zipball/0a31e50c0fa9b1692d077c86ac188eecdcbaf7fa", - "reference": "0a31e50c0fa9b1692d077c86ac188eecdcbaf7fa", + "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/1dd023879874ce22a7f8e2b2e014166cd1160b0d", + "reference": "1dd023879874ce22a7f8e2b2e014166cd1160b0d", "shasum": "" }, "require": { - "php": ">=5.3.0" + "ext-json": "*", + "ext-pcre": "*", + "ext-simplexml": "*", + "ext-spl": "*", + "guzzlehttp/guzzle": "^5.3.3|^6.2.1", + "guzzlehttp/promises": "~1.0", + "guzzlehttp/psr7": "^1.4.1", + "mtdowling/jmespath.php": "~2.2", + "php": ">=5.5" }, "require-dev": { - "phpunit/phpunit": "4.*", - "satooshi/php-coveralls": "0.*" + "andrewsville/php-token-reflection": "^1.4", + "aws/aws-php-sns-message-validator": "~1.0", + "behat/behat": "~3.0", + "doctrine/cache": "~1.4", + "ext-dom": "*", + "ext-openssl": "*", + "ext-pcntl": "*", + "ext-sockets": "*", + "nette/neon": "^2.3", + "phpunit/phpunit": "^4.8.35|^5.4.3", + "psr/cache": "^1.0" + }, + "suggest": { + "aws/aws-php-sns-message-validator": "To validate incoming SNS notifications", + "doctrine/cache": "To use the DoctrineCacheAdapter", + "ext-curl": "To send requests using cURL", + "ext-openssl": "Allows working with CloudFront private distributions and verifying received SNS messages", + "ext-sockets": "To use client-side monitoring" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.1.x-dev" + "dev-master": "3.0-dev" } }, "autoload": { "psr-4": { - "Base32\\": "src/" + "Aws\\": "src/" + }, + "files": [ + "src/functions.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Amazon Web Services", + "homepage": "http://aws.amazon.com" + } + ], + "description": "AWS SDK for PHP - Use Amazon Web Services in your PHP project", + "homepage": "http://aws.amazon.com/sdkforphp", + "keywords": [ + "amazon", + "aws", + "cloud", + "dynamodb", + "ec2", + "glacier", + "s3", + "sdk" + ], + "time": "2018-12-07T19:55:05+00:00" + }, + { + "name": "bacon/bacon-qr-code", + "version": "1.0.3", + "source": { + "type": "git", + "url": "https://github.com/Bacon/BaconQrCode.git", + "reference": "5a91b62b9d37cee635bbf8d553f4546057250bee" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Bacon/BaconQrCode/zipball/5a91b62b9d37cee635bbf8d553f4546057250bee", + "reference": "5a91b62b9d37cee635bbf8d553f4546057250bee", + "shasum": "" + }, + "require": { + "ext-iconv": "*", + "php": "^5.4|^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8" + }, + "suggest": { + "ext-gd": "to generate QR code images" + }, + "type": "library", + "autoload": { + "psr-0": { + "BaconQrCode": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-2-Clause" ], "authors": [ { - "name": "Christian Riesen", - "email": "chris.riesen@gmail.com", - "homepage": "http://christianriesen.com", + "name": "Ben Scholzen 'DASPRiD'", + "email": "mail@dasprids.de", + "homepage": "http://www.dasprids.de", "role": "Developer" } ], - "description": "Base32 encoder/decoder according to RFC 4648", - "homepage": "https://github.com/ChristianRiesen/base32", - "keywords": [ - "base32", - "decode", - "encode", - "rfc4648" - ], - "time": "2016-05-05T11:49:03+00:00" + "description": "BaconQrCode is a QR code generator for PHP.", + "homepage": "https://github.com/Bacon/BaconQrCode", + "time": "2017-10-17T09:59:25+00:00" }, { "name": "defuse/php-encryption", @@ -207,30 +286,30 @@ }, { "name": "doctrine/annotations", - "version": "v1.4.0", + "version": "v1.6.0", "source": { "type": "git", "url": "https://github.com/doctrine/annotations.git", - "reference": "54cacc9b81758b14e3ce750f205a393d52339e97" + "reference": "c7f2050c68a9ab0bdb0f98567ec08d80ea7d24d5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/annotations/zipball/54cacc9b81758b14e3ce750f205a393d52339e97", - "reference": "54cacc9b81758b14e3ce750f205a393d52339e97", + "url": "https://api.github.com/repos/doctrine/annotations/zipball/c7f2050c68a9ab0bdb0f98567ec08d80ea7d24d5", + "reference": "c7f2050c68a9ab0bdb0f98567ec08d80ea7d24d5", "shasum": "" }, "require": { "doctrine/lexer": "1.*", - "php": "^5.6 || ^7.0" + "php": "^7.1" }, "require-dev": { "doctrine/cache": "1.*", - "phpunit/phpunit": "^5.7" + "phpunit/phpunit": "^6.4" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.4.x-dev" + "dev-master": "1.6.x-dev" } }, "autoload": { @@ -271,37 +350,42 @@ "docblock", "parser" ], - "time": "2017-02-24T16:22:25+00:00" + "time": "2017-12-06T07:11:42+00:00" }, { "name": "doctrine/cache", - "version": "v1.6.2", + "version": "v1.8.0", "source": { "type": "git", "url": "https://github.com/doctrine/cache.git", - "reference": "eb152c5100571c7a45470ff2a35095ab3f3b900b" + "reference": "d768d58baee9a4862ca783840eca1b9add7a7f57" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/cache/zipball/eb152c5100571c7a45470ff2a35095ab3f3b900b", - "reference": "eb152c5100571c7a45470ff2a35095ab3f3b900b", + "url": "https://api.github.com/repos/doctrine/cache/zipball/d768d58baee9a4862ca783840eca1b9add7a7f57", + "reference": "d768d58baee9a4862ca783840eca1b9add7a7f57", "shasum": "" }, "require": { - "php": "~5.5|~7.0" + "php": "~7.1" }, "conflict": { "doctrine/common": ">2.2,<2.4" }, "require-dev": { - "phpunit/phpunit": "~4.8|~5.0", - "predis/predis": "~1.0", - "satooshi/php-coveralls": "~0.6" + "alcaeus/mongo-php-adapter": "^1.1", + "doctrine/coding-standard": "^4.0", + "mongodb/mongodb": "^1.1", + "phpunit/phpunit": "^7.0", + "predis/predis": "~1.0" + }, + "suggest": { + "alcaeus/mongo-php-adapter": "Required to use legacy MongoDB driver" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.6.x-dev" + "dev-master": "1.8.x-dev" } }, "autoload": { @@ -336,29 +420,29 @@ } ], "description": "Caching library offering an object-oriented API for many cache backends", - "homepage": "http://www.doctrine-project.org", + "homepage": "https://www.doctrine-project.org", "keywords": [ "cache", "caching" ], - "time": "2017-07-22T12:49:21+00:00" + "time": "2018-08-21T18:01:43+00:00" }, { "name": "doctrine/collections", - "version": "v1.4.0", + "version": "v1.5.0", "source": { "type": "git", "url": "https://github.com/doctrine/collections.git", - "reference": "1a4fb7e902202c33cce8c55989b945612943c2ba" + "reference": "a01ee38fcd999f34d9bfbcee59dbda5105449cbf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/collections/zipball/1a4fb7e902202c33cce8c55989b945612943c2ba", - "reference": "1a4fb7e902202c33cce8c55989b945612943c2ba", + "url": "https://api.github.com/repos/doctrine/collections/zipball/a01ee38fcd999f34d9bfbcee59dbda5105449cbf", + "reference": "a01ee38fcd999f34d9bfbcee59dbda5105449cbf", "shasum": "" }, "require": { - "php": "^5.6 || ^7.0" + "php": "^7.1" }, "require-dev": { "doctrine/coding-standard": "~0.1@dev", @@ -408,37 +492,43 @@ "collections", "iterator" ], - "time": "2017-01-03T10:49:41+00:00" + "time": "2017-07-22T10:37:32+00:00" }, { "name": "doctrine/common", - "version": "v2.7.3", + "version": "v2.10.0", "source": { "type": "git", "url": "https://github.com/doctrine/common.git", - "reference": "4acb8f89626baafede6ee5475bc5844096eba8a9" + "reference": "30e33f60f64deec87df728c02b107f82cdafad9d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/common/zipball/4acb8f89626baafede6ee5475bc5844096eba8a9", - "reference": "4acb8f89626baafede6ee5475bc5844096eba8a9", + "url": "https://api.github.com/repos/doctrine/common/zipball/30e33f60f64deec87df728c02b107f82cdafad9d", + "reference": "30e33f60f64deec87df728c02b107f82cdafad9d", "shasum": "" }, "require": { - "doctrine/annotations": "1.*", - "doctrine/cache": "1.*", - "doctrine/collections": "1.*", - "doctrine/inflector": "1.*", - "doctrine/lexer": "1.*", - "php": "~5.6|~7.0" + "doctrine/annotations": "^1.0", + "doctrine/cache": "^1.0", + "doctrine/collections": "^1.0", + "doctrine/event-manager": "^1.0", + "doctrine/inflector": "^1.0", + "doctrine/lexer": "^1.0", + "doctrine/persistence": "^1.1", + "doctrine/reflection": "^1.0", + "php": "^7.1" }, "require-dev": { - "phpunit/phpunit": "^5.4.6" + "doctrine/coding-standard": "^1.0", + "phpunit/phpunit": "^6.3", + "squizlabs/php_codesniffer": "^3.0", + "symfony/phpunit-bridge": "^4.0.5" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.7.x-dev" + "dev-master": "2.10.x-dev" } }, "autoload": { @@ -470,40 +560,48 @@ { "name": "Johannes Schmitt", "email": "schmittjoh@gmail.com" + }, + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com" } ], - "description": "Common Library for Doctrine projects", - "homepage": "http://www.doctrine-project.org", + "description": "PHP Doctrine Common project is a library that provides additional functionality that other Doctrine projects depend on such as better reflection support, persistence interfaces, proxies, event system and much more.", + "homepage": "https://www.doctrine-project.org/projects/common.html", "keywords": [ - "annotations", - "collections", - "eventmanager", - "persistence", - "spl" + "common", + "doctrine", + "php" ], - "time": "2017-07-22T08:35:12+00:00" + "time": "2018-11-21T01:24:55+00:00" }, { "name": "doctrine/dbal", - "version": "v2.5.13", + "version": "v2.9.0", "source": { "type": "git", "url": "https://github.com/doctrine/dbal.git", - "reference": "729340d8d1eec8f01bff708e12e449a3415af873" + "reference": "21fdabe2fc01e004e1966f200d900554876bc63c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/dbal/zipball/729340d8d1eec8f01bff708e12e449a3415af873", - "reference": "729340d8d1eec8f01bff708e12e449a3415af873", + "url": "https://api.github.com/repos/doctrine/dbal/zipball/21fdabe2fc01e004e1966f200d900554876bc63c", + "reference": "21fdabe2fc01e004e1966f200d900554876bc63c", "shasum": "" }, "require": { - "doctrine/common": ">=2.4,<2.8-dev", - "php": ">=5.3.2" + "doctrine/cache": "^1.0", + "doctrine/event-manager": "^1.0", + "ext-pdo": "*", + "php": "^7.1" }, "require-dev": { - "phpunit/phpunit": "4.*", - "symfony/console": "2.*||^3.0" + "doctrine/coding-standard": "^5.0", + "jetbrains/phpstorm-stubs": "^2018.1.2", + "phpstan/phpstan": "^0.10.1", + "phpunit/phpunit": "^7.4", + "symfony/console": "^2.0.5|^3.0|^4.0", + "symfony/phpunit-bridge": "^3.4.5|^4.0.5" }, "suggest": { "symfony/console": "For helpful console commands such as SQL execution and import of files." @@ -514,12 +612,13 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.5.x-dev" + "dev-master": "2.9.x-dev", + "dev-develop": "3.0.x-dev" } }, "autoload": { - "psr-0": { - "Doctrine\\DBAL\\": "lib/" + "psr-4": { + "Doctrine\\DBAL\\": "lib/Doctrine/DBAL" } }, "notification-url": "https://packagist.org/downloads/", @@ -544,45 +643,123 @@ "email": "jonwage@gmail.com" } ], - "description": "Database Abstraction Layer", - "homepage": "http://www.doctrine-project.org", + "description": "Powerful PHP database abstraction layer (DBAL) with many features for database schema introspection and management.", + "homepage": "https://www.doctrine-project.org/projects/dbal.html", "keywords": [ + "abstraction", "database", "dbal", + "mysql", "persistence", + "pgsql", + "php", "queryobject" ], - "time": "2017-07-22T20:44:48+00:00" + "time": "2018-12-04T04:39:48+00:00" }, { - "name": "doctrine/inflector", - "version": "v1.1.0", + "name": "doctrine/event-manager", + "version": "v1.0.0", "source": { "type": "git", - "url": "https://github.com/doctrine/inflector.git", - "reference": "90b2128806bfde671b6952ab8bea493942c1fdae" + "url": "https://github.com/doctrine/event-manager.git", + "reference": "a520bc093a0170feeb6b14e9d83f3a14452e64b3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/inflector/zipball/90b2128806bfde671b6952ab8bea493942c1fdae", - "reference": "90b2128806bfde671b6952ab8bea493942c1fdae", + "url": "https://api.github.com/repos/doctrine/event-manager/zipball/a520bc093a0170feeb6b14e9d83f3a14452e64b3", + "reference": "a520bc093a0170feeb6b14e9d83f3a14452e64b3", "shasum": "" }, "require": { - "php": ">=5.3.2" + "php": "^7.1" + }, + "conflict": { + "doctrine/common": "<2.9@dev" }, "require-dev": { - "phpunit/phpunit": "4.*" + "doctrine/coding-standard": "^4.0", + "phpunit/phpunit": "^7.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.1.x-dev" + "dev-master": "1.0.x-dev" } }, "autoload": { - "psr-0": { - "Doctrine\\Common\\Inflector\\": "lib/" + "psr-4": { + "Doctrine\\Common\\": "lib/Doctrine/Common" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + }, + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com" + } + ], + "description": "Doctrine Event Manager component", + "homepage": "https://www.doctrine-project.org/projects/event-manager.html", + "keywords": [ + "event", + "eventdispatcher", + "eventmanager" + ], + "time": "2018-06-11T11:59:03+00:00" + }, + { + "name": "doctrine/inflector", + "version": "v1.3.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/inflector.git", + "reference": "5527a48b7313d15261292c149e55e26eae771b0a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/inflector/zipball/5527a48b7313d15261292c149e55e26eae771b0a", + "reference": "5527a48b7313d15261292c149e55e26eae771b0a", + "shasum": "" + }, + "require": { + "php": "^7.1" + }, + "require-dev": { + "phpunit/phpunit": "^6.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\Inflector\\": "lib/Doctrine/Common/Inflector" } }, "notification-url": "https://packagist.org/downloads/", @@ -619,36 +796,36 @@ "singularize", "string" ], - "time": "2015-11-06T14:35:42+00:00" + "time": "2018-01-09T20:05:19+00:00" }, { "name": "doctrine/instantiator", - "version": "1.0.5", + "version": "1.1.0", "source": { "type": "git", "url": "https://github.com/doctrine/instantiator.git", - "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d" + "reference": "185b8868aa9bf7159f5f953ed5afb2d7fcdc3bda" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d", - "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/185b8868aa9bf7159f5f953ed5afb2d7fcdc3bda", + "reference": "185b8868aa9bf7159f5f953ed5afb2d7fcdc3bda", "shasum": "" }, "require": { - "php": ">=5.3,<8.0-DEV" + "php": "^7.1" }, "require-dev": { "athletic/athletic": "~0.1.8", "ext-pdo": "*", "ext-phar": "*", - "phpunit/phpunit": "~4.0", - "squizlabs/php_codesniffer": "~2.0" + "phpunit/phpunit": "^6.2.3", + "squizlabs/php_codesniffer": "^3.0.2" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "1.2.x-dev" } }, "autoload": { @@ -673,7 +850,7 @@ "constructor", "instantiate" ], - "time": "2015-06-14T21:17:01+00:00" + "time": "2017-07-22T11:58:36+00:00" }, { "name": "doctrine/lexer", @@ -729,6 +906,212 @@ ], "time": "2014-09-09T13:34:57+00:00" }, + { + "name": "doctrine/persistence", + "version": "v1.1.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/persistence.git", + "reference": "c0f1c17602afc18b4cbd8e1c8125f264c9cf7d38" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/persistence/zipball/c0f1c17602afc18b4cbd8e1c8125f264c9cf7d38", + "reference": "c0f1c17602afc18b4cbd8e1c8125f264c9cf7d38", + "shasum": "" + }, + "require": { + "doctrine/annotations": "^1.0", + "doctrine/cache": "^1.0", + "doctrine/collections": "^1.0", + "doctrine/event-manager": "^1.0", + "doctrine/reflection": "^1.0", + "php": "^7.1" + }, + "conflict": { + "doctrine/common": "<2.10@dev" + }, + "require-dev": { + "doctrine/coding-standard": "^5.0", + "phpstan/phpstan": "^0.8", + "phpunit/phpunit": "^7.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\": "lib/Doctrine/Common" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + }, + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com" + } + ], + "description": "The Doctrine Persistence project is a set of shared interfaces and functionality that the different Doctrine object mappers share.", + "homepage": "https://doctrine-project.org/projects/persistence.html", + "keywords": [ + "mapper", + "object", + "odm", + "orm", + "persistence" + ], + "time": "2018-11-21T00:33:13+00:00" + }, + { + "name": "doctrine/reflection", + "version": "v1.0.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/reflection.git", + "reference": "02538d3f95e88eb397a5f86274deb2c6175c2ab6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/reflection/zipball/02538d3f95e88eb397a5f86274deb2c6175c2ab6", + "reference": "02538d3f95e88eb397a5f86274deb2c6175c2ab6", + "shasum": "" + }, + "require": { + "doctrine/annotations": "^1.0", + "ext-tokenizer": "*", + "php": "^7.1" + }, + "require-dev": { + "doctrine/coding-standard": "^4.0", + "doctrine/common": "^2.8", + "phpstan/phpstan": "^0.9.2", + "phpstan/phpstan-phpunit": "^0.9.4", + "phpunit/phpunit": "^7.0", + "squizlabs/php_codesniffer": "^3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\": "lib/Doctrine/Common" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + }, + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com" + } + ], + "description": "Doctrine Reflection component", + "homepage": "https://www.doctrine-project.org/projects/reflection.html", + "keywords": [ + "reflection" + ], + "time": "2018-06-14T14:45:07+00:00" + }, + { + "name": "dragonmantank/cron-expression", + "version": "v2.2.0", + "source": { + "type": "git", + "url": "https://github.com/dragonmantank/cron-expression.git", + "reference": "92a2c3768d50e21a1f26a53cb795ce72806266c5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dragonmantank/cron-expression/zipball/92a2c3768d50e21a1f26a53cb795ce72806266c5", + "reference": "92a2c3768d50e21a1f26a53cb795ce72806266c5", + "shasum": "" + }, + "require": { + "php": ">=7.0.0" + }, + "require-dev": { + "phpunit/phpunit": "~6.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "Cron\\": "src/Cron/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Chris Tankersley", + "email": "chris@ctankersley.com", + "homepage": "https://github.com/dragonmantank" + } + ], + "description": "CRON for PHP: Calculate the next or previous run date and determine if a CRON expression is due", + "keywords": [ + "cron", + "schedule" + ], + "time": "2018-06-06T03:12:17+00:00" + }, { "name": "eduardokum/laravel-mail-auto-embed", "version": "1.0.4", @@ -784,6 +1167,63 @@ ], "time": "2017-09-21T12:11:32+00:00" }, + { + "name": "egulias/email-validator", + "version": "2.1.7", + "source": { + "type": "git", + "url": "https://github.com/egulias/EmailValidator.git", + "reference": "709f21f92707308cdf8f9bcfa1af4cb26586521e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/egulias/EmailValidator/zipball/709f21f92707308cdf8f9bcfa1af4cb26586521e", + "reference": "709f21f92707308cdf8f9bcfa1af4cb26586521e", + "shasum": "" + }, + "require": { + "doctrine/lexer": "^1.0.1", + "php": ">= 5.5" + }, + "require-dev": { + "dominicsayers/isemail": "dev-master", + "phpunit/phpunit": "^4.8.35||^5.7||^6.0", + "satooshi/php-coveralls": "^1.0.1" + }, + "suggest": { + "ext-intl": "PHP Internationalization Libraries are required to use the SpoofChecking validation" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Egulias\\EmailValidator\\": "EmailValidator" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Eduardo Gulias Davis" + } + ], + "description": "A library for validating emails against several RFCs", + "homepage": "https://github.com/egulias/EmailValidator", + "keywords": [ + "email", + "emailvalidation", + "emailvalidator", + "validation", + "validator" + ], + "time": "2018-12-04T22:38:24+00:00" + }, { "name": "erusev/parsedown", "version": "1.7.1", @@ -832,16 +1272,16 @@ }, { "name": "fideloper/proxy", - "version": "3.3.4", + "version": "4.0.0", "source": { "type": "git", "url": "https://github.com/fideloper/TrustedProxy.git", - "reference": "9cdf6f118af58d89764249bbcc7bb260c132924f" + "reference": "cf8a0ca4b85659b9557e206c90110a6a4dba980a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/fideloper/TrustedProxy/zipball/9cdf6f118af58d89764249bbcc7bb260c132924f", - "reference": "9cdf6f118af58d89764249bbcc7bb260c132924f", + "url": "https://api.github.com/repos/fideloper/TrustedProxy/zipball/cf8a0ca4b85659b9557e206c90110a6a4dba980a", + "reference": "cf8a0ca4b85659b9557e206c90110a6a4dba980a", "shasum": "" }, "require": { @@ -849,15 +1289,12 @@ "php": ">=5.4.0" }, "require-dev": { - "illuminate/http": "~5.0", - "mockery/mockery": "~0.9.3", - "phpunit/phpunit": "^5.7" + "illuminate/http": "~5.6", + "mockery/mockery": "~1.0", + "phpunit/phpunit": "^6.0" }, "type": "library", "extra": { - "branch-alias": { - "dev-master": "3.3-dev" - }, "laravel": { "providers": [ "Fideloper\\Proxy\\TrustedProxyServiceProvider" @@ -885,25 +1322,28 @@ "proxy", "trusted proxy" ], - "time": "2017-06-15T17:19:42+00:00" + "time": "2018-02-07T20:20:57+00:00" }, { "name": "firebase/php-jwt", - "version": "v4.0.0", + "version": "v5.0.0", "source": { "type": "git", "url": "https://github.com/firebase/php-jwt.git", - "reference": "dccf163dc8ed7ed6a00afc06c51ee5186a428d35" + "reference": "9984a4d3a32ae7673d6971ea00bae9d0a1abba0e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/firebase/php-jwt/zipball/dccf163dc8ed7ed6a00afc06c51ee5186a428d35", - "reference": "dccf163dc8ed7ed6a00afc06c51ee5186a428d35", + "url": "https://api.github.com/repos/firebase/php-jwt/zipball/9984a4d3a32ae7673d6971ea00bae9d0a1abba0e", + "reference": "9984a4d3a32ae7673d6971ea00bae9d0a1abba0e", "shasum": "" }, "require": { "php": ">=5.3.0" }, + "require-dev": { + "phpunit/phpunit": " 4.8.35" + }, "type": "library", "autoload": { "psr-4": { @@ -928,7 +1368,100 @@ ], "description": "A simple library to encode and decode JSON Web Tokens (JWT) in PHP. Should conform to the current spec.", "homepage": "https://github.com/firebase/php-jwt", - "time": "2016-07-18T04:51:16+00:00" + "time": "2017-06-27T22:17:23+00:00" + }, + { + "name": "guzzle/guzzle", + "version": "v3.8.1", + "source": { + "type": "git", + "url": "https://github.com/guzzle/guzzle.git", + "reference": "4de0618a01b34aa1c8c33a3f13f396dcd3882eba" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/4de0618a01b34aa1c8c33a3f13f396dcd3882eba", + "reference": "4de0618a01b34aa1c8c33a3f13f396dcd3882eba", + "shasum": "" + }, + "require": { + "ext-curl": "*", + "php": ">=5.3.3", + "symfony/event-dispatcher": ">=2.1" + }, + "replace": { + "guzzle/batch": "self.version", + "guzzle/cache": "self.version", + "guzzle/common": "self.version", + "guzzle/http": "self.version", + "guzzle/inflection": "self.version", + "guzzle/iterator": "self.version", + "guzzle/log": "self.version", + "guzzle/parser": "self.version", + "guzzle/plugin": "self.version", + "guzzle/plugin-async": "self.version", + "guzzle/plugin-backoff": "self.version", + "guzzle/plugin-cache": "self.version", + "guzzle/plugin-cookie": "self.version", + "guzzle/plugin-curlauth": "self.version", + "guzzle/plugin-error-response": "self.version", + "guzzle/plugin-history": "self.version", + "guzzle/plugin-log": "self.version", + "guzzle/plugin-md5": "self.version", + "guzzle/plugin-mock": "self.version", + "guzzle/plugin-oauth": "self.version", + "guzzle/service": "self.version", + "guzzle/stream": "self.version" + }, + "require-dev": { + "doctrine/cache": "*", + "monolog/monolog": "1.*", + "phpunit/phpunit": "3.7.*", + "psr/log": "1.0.*", + "symfony/class-loader": "*", + "zendframework/zend-cache": "<2.3", + "zendframework/zend-log": "<2.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.8-dev" + } + }, + "autoload": { + "psr-0": { + "Guzzle": "src/", + "Guzzle\\Tests": "tests/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Guzzle Community", + "homepage": "https://github.com/guzzle/guzzle/contributors" + } + ], + "description": "Guzzle is a PHP HTTP client library and framework for building RESTful web service clients", + "homepage": "http://guzzlephp.org/", + "keywords": [ + "client", + "curl", + "framework", + "http", + "http client", + "rest", + "web service" + ], + "abandoned": "guzzlehttp/guzzle", + "time": "2014-01-28T22:29:15+00:00" }, { "name": "guzzlehttp/guzzle", @@ -1048,32 +1581,33 @@ }, { "name": "guzzlehttp/psr7", - "version": "1.4.2", + "version": "1.5.2", "source": { "type": "git", "url": "https://github.com/guzzle/psr7.git", - "reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c" + "reference": "9f83dded91781a01c63574e387eaa769be769115" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/f5b8a8512e2b58b0071a7280e39f14f72e05d87c", - "reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/9f83dded91781a01c63574e387eaa769be769115", + "reference": "9f83dded91781a01c63574e387eaa769be769115", "shasum": "" }, "require": { "php": ">=5.4.0", - "psr/http-message": "~1.0" + "psr/http-message": "~1.0", + "ralouphie/getallheaders": "^2.0.5" }, "provide": { "psr/http-message-implementation": "1.0" }, "require-dev": { - "phpunit/phpunit": "~4.0" + "phpunit/phpunit": "~4.8.36 || ^5.7.27 || ^6.5.8" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.4-dev" + "dev-master": "1.5-dev" } }, "autoload": { @@ -1103,13 +1637,14 @@ "keywords": [ "http", "message", + "psr-7", "request", "response", "stream", "uri", "url" ], - "time": "2017-03-20T17:10:46+00:00" + "time": "2018-12-04T20:46:45+00:00" }, { "name": "intervention/image", @@ -1301,41 +1836,48 @@ }, { "name": "laravel/framework", - "version": "v5.4.35", + "version": "v5.7.16", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "54aa18a4e8495c4b6902d9665ec9fa4d3a1f3d2e" + "reference": "9acea9e0a356cba7e6a13f8784d5532a82fee92a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/54aa18a4e8495c4b6902d9665ec9fa4d3a1f3d2e", - "reference": "54aa18a4e8495c4b6902d9665ec9fa4d3a1f3d2e", + "url": "https://api.github.com/repos/laravel/framework/zipball/9acea9e0a356cba7e6a13f8784d5532a82fee92a", + "reference": "9acea9e0a356cba7e6a13f8784d5532a82fee92a", "shasum": "" }, "require": { - "doctrine/inflector": "~1.1", - "erusev/parsedown": "~1.6", + "doctrine/inflector": "^1.1", + "dragonmantank/cron-expression": "^2.0", + "erusev/parsedown": "^1.7", "ext-mbstring": "*", "ext-openssl": "*", - "league/flysystem": "~1.0", - "monolog/monolog": "~1.11", - "mtdowling/cron-expression": "~1.0", - "nesbot/carbon": "~1.20", - "paragonie/random_compat": "~1.4|~2.0", - "php": ">=5.6.4", - "ramsey/uuid": "~3.0", - "swiftmailer/swiftmailer": "~5.4", - "symfony/console": "~3.2", - "symfony/debug": "~3.2", - "symfony/finder": "~3.2", - "symfony/http-foundation": "~3.2", - "symfony/http-kernel": "~3.2", - "symfony/process": "~3.2", - "symfony/routing": "~3.2", - "symfony/var-dumper": "~3.2", - "tijsverkoyen/css-to-inline-styles": "~2.2", - "vlucas/phpdotenv": "~2.2" + "laravel/nexmo-notification-channel": "^1.0", + "laravel/slack-notification-channel": "^1.0", + "league/flysystem": "^1.0.8", + "monolog/monolog": "^1.12", + "nesbot/carbon": "^1.26.3", + "opis/closure": "^3.1", + "php": "^7.1.3", + "psr/container": "^1.0", + "psr/simple-cache": "^1.0", + "ramsey/uuid": "^3.7", + "swiftmailer/swiftmailer": "^6.0", + "symfony/console": "^4.1", + "symfony/debug": "^4.1", + "symfony/finder": "^4.1", + "symfony/http-foundation": "^4.1", + "symfony/http-kernel": "^4.1", + "symfony/process": "^4.1", + "symfony/routing": "^4.1", + "symfony/var-dumper": "^4.1", + "tijsverkoyen/css-to-inline-styles": "^2.2.1", + "vlucas/phpdotenv": "^2.2" + }, + "conflict": { + "tightenco/collect": "<5.5.33" }, "replace": { "illuminate/auth": "self.version", @@ -1350,7 +1892,6 @@ "illuminate/database": "self.version", "illuminate/encryption": "self.version", "illuminate/events": "self.version", - "illuminate/exception": "self.version", "illuminate/filesystem": "self.version", "illuminate/hashing": "self.version", "illuminate/http": "self.version", @@ -1366,39 +1907,50 @@ "illuminate/support": "self.version", "illuminate/translation": "self.version", "illuminate/validation": "self.version", - "illuminate/view": "self.version", - "tightenco/collect": "self.version" + "illuminate/view": "self.version" }, "require-dev": { - "aws/aws-sdk-php": "~3.0", - "doctrine/dbal": "~2.5", - "mockery/mockery": "~0.9.4", - "pda/pheanstalk": "~3.0", - "phpunit/phpunit": "~5.7", - "predis/predis": "~1.0", - "symfony/css-selector": "~3.2", - "symfony/dom-crawler": "~3.2" + "aws/aws-sdk-php": "^3.0", + "doctrine/dbal": "^2.6", + "filp/whoops": "^2.1.4", + "guzzlehttp/guzzle": "^6.3", + "league/flysystem-cached-adapter": "^1.0", + "mockery/mockery": "^1.0", + "moontoast/math": "^1.1", + "orchestra/testbench-core": "3.7.*", + "pda/pheanstalk": "^3.0", + "phpunit/phpunit": "^7.0", + "predis/predis": "^1.1.1", + "symfony/css-selector": "^4.1", + "symfony/dom-crawler": "^4.1", + "true/punycode": "^2.1" }, "suggest": { - "aws/aws-sdk-php": "Required to use the SQS queue driver and SES mail driver (~3.0).", - "doctrine/dbal": "Required to rename columns and drop SQLite columns (~2.5).", - "fzaninotto/faker": "Required to use the eloquent factory builder (~1.4).", - "guzzlehttp/guzzle": "Required to use the Mailgun and Mandrill mail drivers and the ping methods on schedules (~6.0).", - "laravel/tinker": "Required to use the tinker console command (~1.0).", - "league/flysystem-aws-s3-v3": "Required to use the Flysystem S3 driver (~1.0).", - "league/flysystem-rackspace": "Required to use the Flysystem Rackspace driver (~1.0).", - "nexmo/client": "Required to use the Nexmo transport (~1.0).", - "pda/pheanstalk": "Required to use the beanstalk queue driver (~3.0).", - "predis/predis": "Required to use the redis cache and queue drivers (~1.0).", - "pusher/pusher-php-server": "Required to use the Pusher broadcast driver (~2.0).", - "symfony/css-selector": "Required to use some of the crawler integration testing tools (~3.2).", - "symfony/dom-crawler": "Required to use most of the crawler integration testing tools (~3.2).", - "symfony/psr-http-message-bridge": "Required to psr7 bridging features (0.2.*)." + "aws/aws-sdk-php": "Required to use the SQS queue driver and SES mail driver (^3.0).", + "doctrine/dbal": "Required to rename columns and drop SQLite columns (^2.6).", + "ext-pcntl": "Required to use all features of the queue worker.", + "ext-posix": "Required to use all features of the queue worker.", + "filp/whoops": "Required for friendly error pages in development (^2.1.4).", + "fzaninotto/faker": "Required to use the eloquent factory builder (^1.4).", + "guzzlehttp/guzzle": "Required to use the Mailgun and Mandrill mail drivers and the ping methods on schedules (^6.0).", + "laravel/tinker": "Required to use the tinker console command (^1.0).", + "league/flysystem-aws-s3-v3": "Required to use the Flysystem S3 driver (^1.0).", + "league/flysystem-cached-adapter": "Required to use the Flysystem cache (^1.0).", + "league/flysystem-rackspace": "Required to use the Flysystem Rackspace driver (^1.0).", + "league/flysystem-sftp": "Required to use the Flysystem SFTP driver (^1.0).", + "moontoast/math": "Required to use ordered UUIDs (^1.1).", + "nexmo/client": "Required to use the Nexmo transport (^1.0).", + "pda/pheanstalk": "Required to use the beanstalk queue driver (^3.0).", + "predis/predis": "Required to use the redis cache and queue drivers (^1.0).", + "pusher/pusher-php-server": "Required to use the Pusher broadcast driver (^3.0).", + "symfony/css-selector": "Required to use some of the crawler integration testing tools (^4.1).", + "symfony/dom-crawler": "Required to use most of the crawler integration testing tools (^4.1).", + "symfony/psr-http-message-bridge": "Required to psr7 bridging features (^1.0)." }, "type": "library", "extra": { "branch-alias": { - "dev-master": "5.4-dev" + "dev-master": "5.7-dev" } }, "autoload": { @@ -1426,47 +1978,104 @@ "framework", "laravel" ], - "time": "2017-08-24T12:30:18+00:00" + "time": "2018-12-05T14:36:24+00:00" }, { - "name": "laravel/passport", - "version": "v3.0.2", + "name": "laravel/nexmo-notification-channel", + "version": "v1.0.1", "source": { "type": "git", - "url": "https://github.com/laravel/passport.git", - "reference": "c6a23ff4f05543767b2828b582dd9e74cdb9b014" + "url": "https://github.com/laravel/nexmo-notification-channel.git", + "reference": "03edd42a55b306ff980c9950899d5a2b03260d48" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/passport/zipball/c6a23ff4f05543767b2828b582dd9e74cdb9b014", - "reference": "c6a23ff4f05543767b2828b582dd9e74cdb9b014", + "url": "https://api.github.com/repos/laravel/nexmo-notification-channel/zipball/03edd42a55b306ff980c9950899d5a2b03260d48", + "reference": "03edd42a55b306ff980c9950899d5a2b03260d48", "shasum": "" }, "require": { - "firebase/php-jwt": "~3.0|~4.0", + "nexmo/client": "^1.0", + "php": "^7.1.3" + }, + "require-dev": { + "illuminate/notifications": "~5.7", + "mockery/mockery": "^1.0", + "phpunit/phpunit": "^7.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + }, + "laravel": { + "providers": [ + "Illuminate\\Notifications\\NexmoChannelServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Illuminate\\Notifications\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "Nexmo Notification Channel for laravel.", + "keywords": [ + "laravel", + "nexmo", + "notifications" + ], + "time": "2018-12-04T12:57:08+00:00" + }, + { + "name": "laravel/passport", + "version": "v6.0.7", + "source": { + "type": "git", + "url": "https://github.com/laravel/passport.git", + "reference": "5a3dbeb0904573fcfecf11c018eaa42bfc935372" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/passport/zipball/5a3dbeb0904573fcfecf11c018eaa42bfc935372", + "reference": "5a3dbeb0904573fcfecf11c018eaa42bfc935372", + "shasum": "" + }, + "require": { + "firebase/php-jwt": "~3.0|~4.0|~5.0", "guzzlehttp/guzzle": "~6.0", - "illuminate/auth": "~5.4", - "illuminate/console": "~5.4", - "illuminate/container": "~5.4", - "illuminate/contracts": "~5.4", - "illuminate/database": "~5.4", - "illuminate/encryption": "~5.4", - "illuminate/http": "~5.4", - "illuminate/support": "~5.4", - "league/oauth2-server": "^6.0", - "php": ">=5.6.4", + "illuminate/auth": "~5.6", + "illuminate/console": "~5.6", + "illuminate/container": "~5.6", + "illuminate/contracts": "~5.6", + "illuminate/database": "~5.6", + "illuminate/encryption": "~5.6", + "illuminate/http": "~5.6", + "illuminate/support": "~5.6", + "league/oauth2-server": "^7.0", + "php": ">=7.1", "phpseclib/phpseclib": "^2.0", "symfony/psr-http-message-bridge": "~1.0", "zendframework/zend-diactoros": "~1.0" }, "require-dev": { - "mockery/mockery": "~0.9", - "phpunit/phpunit": "~5.0" + "mockery/mockery": "~1.0", + "phpunit/phpunit": "~6.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-master": "6.0-dev" }, "laravel": { "providers": [ @@ -1495,7 +2104,64 @@ "oauth", "passport" ], - "time": "2017-08-16T13:10:52+00:00" + "time": "2018-08-09T19:10:08+00:00" + }, + { + "name": "laravel/slack-notification-channel", + "version": "v1.0.2", + "source": { + "type": "git", + "url": "https://github.com/laravel/slack-notification-channel.git", + "reference": "0ede60acbbf5f91be2e45d0c0b4d95e2f3837252" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/slack-notification-channel/zipball/0ede60acbbf5f91be2e45d0c0b4d95e2f3837252", + "reference": "0ede60acbbf5f91be2e45d0c0b4d95e2f3837252", + "shasum": "" + }, + "require": { + "guzzlehttp/guzzle": "^6.0", + "php": "^7.1.3" + }, + "require-dev": { + "illuminate/notifications": "~5.7", + "mockery/mockery": "^1.0", + "phpunit/phpunit": "^7.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + }, + "laravel": { + "providers": [ + "Illuminate\\Notifications\\SlackChannelServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Illuminate\\Notifications\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "Slack Notification Channel for laravel.", + "keywords": [ + "laravel", + "notifications", + "slack" + ], + "time": "2018-12-04T12:58:59+00:00" }, { "name": "laravel/tinker", @@ -1562,32 +2228,46 @@ }, { "name": "laravelcollective/html", - "version": "v5.4.9", + "version": "v5.7.1", "source": { "type": "git", "url": "https://github.com/LaravelCollective/html.git", - "reference": "f04965dc688254f4c77f684ab0b42264f9eb9634" + "reference": "777b6d390811ba249255ed5750bf17a019cd88a5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/LaravelCollective/html/zipball/f04965dc688254f4c77f684ab0b42264f9eb9634", - "reference": "f04965dc688254f4c77f684ab0b42264f9eb9634", + "url": "https://api.github.com/repos/LaravelCollective/html/zipball/777b6d390811ba249255ed5750bf17a019cd88a5", + "reference": "777b6d390811ba249255ed5750bf17a019cd88a5", "shasum": "" }, "require": { - "illuminate/http": "5.4.*", - "illuminate/routing": "5.4.*", - "illuminate/session": "5.4.*", - "illuminate/support": "5.4.*", - "illuminate/view": "5.4.*", - "php": ">=5.6.4" + "illuminate/http": "5.7.*", + "illuminate/routing": "5.7.*", + "illuminate/session": "5.7.*", + "illuminate/support": "5.7.*", + "illuminate/view": "5.7.*", + "php": ">=7.1.3" }, "require-dev": { - "illuminate/database": "5.4.*", - "mockery/mockery": "~0.9.4", - "phpunit/phpunit": "~5.4" + "illuminate/database": "5.7.*", + "mockery/mockery": "~1.0", + "phpunit/phpunit": "~7.1" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.7-dev" + }, + "laravel": { + "providers": [ + "Collective\\Html\\HtmlServiceProvider" + ], + "aliases": { + "Form": "Collective\\Html\\FormFacade", + "Html": "Collective\\Html\\HtmlFacade" + } + } + }, "autoload": { "psr-4": { "Collective\\Html\\": "src/" @@ -1611,21 +2291,21 @@ } ], "description": "HTML and Form Builders for the Laravel Framework", - "homepage": "http://laravelcollective.com", - "time": "2017-08-12T15:52:38+00:00" + "homepage": "https://laravelcollective.com", + "time": "2018-09-05T18:32:53+00:00" }, { "name": "lcobucci/jwt", - "version": "3.2.4", + "version": "3.2.5", "source": { "type": "git", "url": "https://github.com/lcobucci/jwt.git", - "reference": "c9704b751315d21735dc98d78d4f37bd73596da7" + "reference": "82be04b4753f8b7693b62852b7eab30f97524f9b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/lcobucci/jwt/zipball/c9704b751315d21735dc98d78d4f37bd73596da7", - "reference": "c9704b751315d21735dc98d78d4f37bd73596da7", + "url": "https://api.github.com/repos/lcobucci/jwt/zipball/82be04b4753f8b7693b62852b7eab30f97524f9b", + "reference": "82be04b4753f8b7693b62852b7eab30f97524f9b", "shasum": "" }, "require": { @@ -1670,40 +2350,50 @@ "JWS", "jwt" ], - "time": "2018-08-03T11:23:50+00:00" + "time": "2018-11-11T12:22:26+00:00" }, { "name": "league/csv", - "version": "8.2.3", + "version": "9.1.4", "source": { "type": "git", "url": "https://github.com/thephpleague/csv.git", - "reference": "d2aab1e7bde802582c3879acf03d92716577c76d" + "reference": "9c8ad06fb5d747c149875beb6133566c00eaa481" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/csv/zipball/d2aab1e7bde802582c3879acf03d92716577c76d", - "reference": "d2aab1e7bde802582c3879acf03d92716577c76d", + "url": "https://api.github.com/repos/thephpleague/csv/zipball/9c8ad06fb5d747c149875beb6133566c00eaa481", + "reference": "9c8ad06fb5d747c149875beb6133566c00eaa481", "shasum": "" }, "require": { "ext-mbstring": "*", - "php": ">=5.5.0" + "php": ">=7.0.10" }, "require-dev": { - "friendsofphp/php-cs-fixer": "^1.9", - "phpunit/phpunit": "^4.0" + "ext-curl": "*", + "friendsofphp/php-cs-fixer": "^2.0", + "phpstan/phpstan": "^0.9.2", + "phpstan/phpstan-phpunit": "^0.9.4", + "phpstan/phpstan-strict-rules": "^0.9.0", + "phpunit/phpunit": "^6.0" + }, + "suggest": { + "ext-iconv": "Needed to ease transcoding CSV using iconv stream filters" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "8.2-dev" + "dev-master": "9.x-dev" } }, "autoload": { "psr-4": { "League\\Csv\\": "src" - } + }, + "files": [ + "src/functions_include.php" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -1727,20 +2417,20 @@ "read", "write" ], - "time": "2018-02-06T08:27:03+00:00" + "time": "2018-05-01T18:32:48+00:00" }, { "name": "league/event", - "version": "2.1.2", + "version": "2.2.0", "source": { "type": "git", "url": "https://github.com/thephpleague/event.git", - "reference": "e4bfc88dbcb60c8d8a2939a71f9813e141bbe4cd" + "reference": "d2cc124cf9a3fab2bb4ff963307f60361ce4d119" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/event/zipball/e4bfc88dbcb60c8d8a2939a71f9813e141bbe4cd", - "reference": "e4bfc88dbcb60c8d8a2939a71f9813e141bbe4cd", + "url": "https://api.github.com/repos/thephpleague/event/zipball/d2cc124cf9a3fab2bb4ff963307f60361ce4d119", + "reference": "d2cc124cf9a3fab2bb4ff963307f60361ce4d119", "shasum": "" }, "require": { @@ -1748,7 +2438,7 @@ }, "require-dev": { "henrikbjorn/phpspec-code-coverage": "~1.0.1", - "phpspec/phpspec": "~2.0.0" + "phpspec/phpspec": "^2.2" }, "type": "library", "extra": { @@ -1777,20 +2467,20 @@ "event", "listener" ], - "time": "2015-05-21T12:24:47+00:00" + "time": "2018-11-26T11:52:41+00:00" }, { "name": "league/flysystem", - "version": "1.0.48", + "version": "1.0.49", "source": { "type": "git", "url": "https://github.com/thephpleague/flysystem.git", - "reference": "a6ded5b2f6055e2db97b4b859fdfca2b952b78aa" + "reference": "a63cc83d8a931b271be45148fa39ba7156782ffd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/a6ded5b2f6055e2db97b4b859fdfca2b952b78aa", - "reference": "a6ded5b2f6055e2db97b4b859fdfca2b952b78aa", + "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/a63cc83d8a931b271be45148fa39ba7156782ffd", + "reference": "a63cc83d8a931b271be45148fa39ba7156782ffd", "shasum": "" }, "require": { @@ -1861,38 +2551,224 @@ "sftp", "storage" ], - "time": "2018-10-15T13:53:10+00:00" + "time": "2018-11-23T23:41:29+00:00" }, { - "name": "league/oauth2-server", - "version": "6.1.1", + "name": "league/flysystem-aws-s3-v3", + "version": "1.0.21", "source": { "type": "git", - "url": "https://github.com/thephpleague/oauth2-server.git", - "reference": "a0cabb573c7cd5ee01803daec992d6ee3677c4ae" + "url": "https://github.com/thephpleague/flysystem-aws-s3-v3.git", + "reference": "43523fec10a831ea48bedb3277e3f3fa218f4e49" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/oauth2-server/zipball/a0cabb573c7cd5ee01803daec992d6ee3677c4ae", - "reference": "a0cabb573c7cd5ee01803daec992d6ee3677c4ae", + "url": "https://api.github.com/repos/thephpleague/flysystem-aws-s3-v3/zipball/43523fec10a831ea48bedb3277e3f3fa218f4e49", + "reference": "43523fec10a831ea48bedb3277e3f3fa218f4e49", + "shasum": "" + }, + "require": { + "aws/aws-sdk-php": "^3.0.0", + "league/flysystem": "^1.0.40", + "php": ">=5.5.0" + }, + "require-dev": { + "henrikbjorn/phpspec-code-coverage": "~1.0.1", + "phpspec/phpspec": "^2.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "psr-4": { + "League\\Flysystem\\AwsS3v3\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Frank de Jonge", + "email": "info@frenky.net" + } + ], + "description": "Flysystem adapter for the AWS S3 SDK v3.x", + "time": "2018-10-08T07:53:55+00:00" + }, + { + "name": "league/flysystem-cached-adapter", + "version": "1.0.9", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/flysystem-cached-adapter.git", + "reference": "08ef74e9be88100807a3b92cc9048a312bf01d6f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/flysystem-cached-adapter/zipball/08ef74e9be88100807a3b92cc9048a312bf01d6f", + "reference": "08ef74e9be88100807a3b92cc9048a312bf01d6f", + "shasum": "" + }, + "require": { + "league/flysystem": "~1.0", + "psr/cache": "^1.0.0" + }, + "require-dev": { + "mockery/mockery": "~0.9", + "phpspec/phpspec": "^3.4", + "phpunit/phpunit": "^5.7", + "predis/predis": "~1.0", + "tedivm/stash": "~0.12" + }, + "suggest": { + "ext-phpredis": "Pure C implemented extension for PHP" + }, + "type": "library", + "autoload": { + "psr-4": { + "League\\Flysystem\\Cached\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "frankdejonge", + "email": "info@frenky.net" + } + ], + "description": "An adapter decorator to enable meta-data caching.", + "time": "2018-07-09T20:51:04+00:00" + }, + { + "name": "league/flysystem-rackspace", + "version": "1.0.5", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/flysystem-rackspace.git", + "reference": "ba877e837f5dce60e78a0555de37eb9bfc7dd6b9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/flysystem-rackspace/zipball/ba877e837f5dce60e78a0555de37eb9bfc7dd6b9", + "reference": "ba877e837f5dce60e78a0555de37eb9bfc7dd6b9", + "shasum": "" + }, + "require": { + "league/flysystem": "~1.0", + "php": ">=5.4.0", + "rackspace/php-opencloud": "~1.16" + }, + "require-dev": { + "mockery/mockery": "0.9.*", + "phpunit/phpunit": "~4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "psr-4": { + "League\\Flysystem\\Rackspace\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Frank de Jonge", + "email": "info@frenky.net" + } + ], + "description": "Flysystem adapter for Rackspace", + "time": "2016-03-11T12:13:42+00:00" + }, + { + "name": "league/flysystem-sftp", + "version": "1.0.17", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/flysystem-sftp.git", + "reference": "49e216f1074b42e3ff344809e700672c2a3264ed" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/flysystem-sftp/zipball/49e216f1074b42e3ff344809e700672c2a3264ed", + "reference": "49e216f1074b42e3ff344809e700672c2a3264ed", + "shasum": "" + }, + "require": { + "league/flysystem": "~1.0", + "php": ">=5.6.0", + "phpseclib/phpseclib": "~2.0" + }, + "require-dev": { + "mockery/mockery": "0.9.*", + "phpunit/phpunit": "^5.7.25" + }, + "type": "library", + "autoload": { + "psr-4": { + "League\\Flysystem\\Sftp\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Frank de Jonge", + "email": "info@frenky.net" + } + ], + "description": "Flysystem adapter for SFTP", + "time": "2018-10-14T21:07:28+00:00" + }, + { + "name": "league/oauth2-server", + "version": "7.3.2", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/oauth2-server.git", + "reference": "b71f382cd76e3f6905dfc53ef8148b3eebe1fd41" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/oauth2-server/zipball/b71f382cd76e3f6905dfc53ef8148b3eebe1fd41", + "reference": "b71f382cd76e3f6905dfc53ef8148b3eebe1fd41", "shasum": "" }, "require": { "defuse/php-encryption": "^2.1", "ext-openssl": "*", - "lcobucci/jwt": "^3.1", + "lcobucci/jwt": "^3.2.2", "league/event": "^2.1", - "paragonie/random_compat": "^2.0", - "php": ">=5.6.0", - "psr/http-message": "^1.0" + "php": ">=7.0.0", + "psr/http-message": "^1.0.1" }, "replace": { "league/oauth2server": "*", "lncd/oauth2": "*" }, "require-dev": { - "phpunit/phpunit": "^4.8.38 || ^5.7.21", - "zendframework/zend-diactoros": "^1.0" + "phpstan/phpstan": "^0.9.2", + "phpstan/phpstan-phpunit": "^0.9.4", + "phpstan/phpstan-strict-rules": "^0.9.0", + "phpunit/phpunit": "^6.3 || ^7.0", + "roave/security-advisories": "dev-master", + "zendframework/zend-diactoros": "^1.3.2" }, "type": "library", "autoload": { @@ -1910,6 +2786,12 @@ "email": "hello@alexbilbie.com", "homepage": "http://www.alexbilbie.com", "role": "Developer" + }, + { + "name": "Andy Millington", + "email": "andrew@noexceptions.io", + "homepage": "https://www.noexceptions.io", + "role": "Developer" } ], "description": "A lightweight and powerful OAuth 2.0 authorization and resource server library with support for all the core specification grants. This library will allow you to secure your API with OAuth and allow your applications users to approve apps that want to access their data from your API.", @@ -1929,7 +2811,7 @@ "secure", "server" ], - "time": "2017-12-23T23:33:42+00:00" + "time": "2018-11-21T21:42:43+00:00" }, { "name": "maknz/slack", @@ -1981,78 +2863,44 @@ "time": "2015-06-03T03:35:16+00:00" }, { - "name": "maximebf/debugbar", - "version": "1.13.1", + "name": "mikemccabe/json-patch-php", + "version": "0.1.0", "source": { "type": "git", - "url": "https://github.com/maximebf/php-debugbar.git", - "reference": "afee79a236348e39a44cb837106b7c5b4897ac2a" + "url": "https://github.com/mikemccabe/json-patch-php.git", + "reference": "b3af30a6aec7f6467c773cd49b2d974a70f7c0d4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/maximebf/php-debugbar/zipball/afee79a236348e39a44cb837106b7c5b4897ac2a", - "reference": "afee79a236348e39a44cb837106b7c5b4897ac2a", + "url": "https://api.github.com/repos/mikemccabe/json-patch-php/zipball/b3af30a6aec7f6467c773cd49b2d974a70f7c0d4", + "reference": "b3af30a6aec7f6467c773cd49b2d974a70f7c0d4", "shasum": "" }, - "require": { - "php": ">=5.3.0", - "psr/log": "^1.0", - "symfony/var-dumper": "^2.6|^3.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.0|^5.0" - }, - "suggest": { - "kriswallsmith/assetic": "The best way to manage assets", - "monolog/monolog": "Log using Monolog", - "predis/predis": "Redis storage" - }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.13-dev" - } - }, "autoload": { "psr-4": { - "DebugBar\\": "src/DebugBar/" + "mikemccabe\\JsonPatch\\": "src" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "LGPL-3.0" ], - "authors": [ - { - "name": "Maxime Bouroumeau-Fuseau", - "email": "maxime.bouroumeau@gmail.com", - "homepage": "http://maximebf.com" - }, - { - "name": "Barry vd. Heuvel", - "email": "barryvdh@gmail.com" - } - ], - "description": "Debug bar in the browser for php application", - "homepage": "https://github.com/maximebf/php-debugbar", - "keywords": [ - "debug", - "debugbar" - ], - "time": "2017-01-05T08:46:19+00:00" + "description": "Produce and apply json-patch objects", + "time": "2015-01-05T21:19:54+00:00" }, { "name": "monolog/monolog", - "version": "1.23.0", + "version": "1.24.0", "source": { "type": "git", "url": "https://github.com/Seldaek/monolog.git", - "reference": "fd8c787753b3a2ad11bc60c063cff1358a32a3b4" + "reference": "bfc9ebb28f97e7a24c45bdc3f0ff482e47bb0266" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/monolog/zipball/fd8c787753b3a2ad11bc60c063cff1358a32a3b4", - "reference": "fd8c787753b3a2ad11bc60c063cff1358a32a3b4", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/bfc9ebb28f97e7a24c45bdc3f0ff482e47bb0266", + "reference": "bfc9ebb28f97e7a24c45bdc3f0ff482e47bb0266", "shasum": "" }, "require": { @@ -2117,33 +2965,44 @@ "logging", "psr-3" ], - "time": "2017-06-19T01:22:40+00:00" + "time": "2018-11-05T09:00:11+00:00" }, { - "name": "mtdowling/cron-expression", - "version": "v1.2.1", + "name": "mtdowling/jmespath.php", + "version": "2.4.0", "source": { "type": "git", - "url": "https://github.com/mtdowling/cron-expression.git", - "reference": "9504fa9ea681b586028adaaa0877db4aecf32bad" + "url": "https://github.com/jmespath/jmespath.php.git", + "reference": "adcc9531682cf87dfda21e1fd5d0e7a41d292fac" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/mtdowling/cron-expression/zipball/9504fa9ea681b586028adaaa0877db4aecf32bad", - "reference": "9504fa9ea681b586028adaaa0877db4aecf32bad", + "url": "https://api.github.com/repos/jmespath/jmespath.php/zipball/adcc9531682cf87dfda21e1fd5d0e7a41d292fac", + "reference": "adcc9531682cf87dfda21e1fd5d0e7a41d292fac", "shasum": "" }, "require": { - "php": ">=5.3.2" + "php": ">=5.4.0" }, "require-dev": { - "phpunit/phpunit": "~4.0|~5.0" + "phpunit/phpunit": "~4.0" }, + "bin": [ + "bin/jp.php" + ], "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, "autoload": { "psr-4": { - "Cron\\": "src/Cron/" - } + "JmesPath\\": "src/" + }, + "files": [ + "src/JmesPath.php" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -2156,12 +3015,12 @@ "homepage": "https://github.com/mtdowling" } ], - "description": "CRON for PHP: Calculate the next or previous run date and determine if a CRON expression is due", + "description": "Declaratively specify how to extract elements from a JSON document", "keywords": [ - "cron", - "schedule" + "json", + "jsonpath" ], - "time": "2017-01-23T04:29:33+00:00" + "time": "2016-12-03T22:08:25+00:00" }, { "name": "neitanod/forceutf8", @@ -2202,16 +3061,16 @@ }, { "name": "nesbot/carbon", - "version": "1.34.0", + "version": "1.36.1", "source": { "type": "git", "url": "https://github.com/briannesbitt/Carbon.git", - "reference": "1dbd3cb01c5645f3e7deda7aa46ef780d95fcc33" + "reference": "63da8cdf89d7a5efe43aabc794365f6e7b7b8983" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/1dbd3cb01c5645f3e7deda7aa46ef780d95fcc33", - "reference": "1dbd3cb01c5645f3e7deda7aa46ef780d95fcc33", + "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/63da8cdf89d7a5efe43aabc794365f6e7b7b8983", + "reference": "63da8cdf89d7a5efe43aabc794365f6e7b7b8983", "shasum": "" }, "require": { @@ -2219,9 +3078,12 @@ "symfony/translation": "~2.6 || ~3.0 || ~4.0" }, "require-dev": { - "friendsofphp/php-cs-fixer": "~2", "phpunit/phpunit": "^4.8.35 || ^5.7" }, + "suggest": { + "friendsofphp/php-cs-fixer": "Needed for the `composer phpcs` command. Allow to automatically fix code style.", + "phpstan/phpstan": "Needed for the `composer phpstan` command. Allow to detect potential errors." + }, "type": "library", "extra": { "laravel": { @@ -2253,28 +3115,76 @@ "datetime", "time" ], - "time": "2018-09-20T19:36:25+00:00" + "time": "2018-11-22T18:23:02+00:00" }, { - "name": "nikic/php-parser", - "version": "v3.1.5", + "name": "nexmo/client", + "version": "1.5.2", "source": { "type": "git", - "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "bb87e28e7d7b8d9a7fda231d37457c9210faf6ce" + "url": "https://github.com/Nexmo/nexmo-php.git", + "reference": "f192c84ec3cc3e2657fc754e0da1a17e39ac5542" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/bb87e28e7d7b8d9a7fda231d37457c9210faf6ce", - "reference": "bb87e28e7d7b8d9a7fda231d37457c9210faf6ce", + "url": "https://api.github.com/repos/Nexmo/nexmo-php/zipball/f192c84ec3cc3e2657fc754e0da1a17e39ac5542", + "reference": "f192c84ec3cc3e2657fc754e0da1a17e39ac5542", + "shasum": "" + }, + "require": { + "lcobucci/jwt": "^3.2", + "php": ">=5.6", + "php-http/client-implementation": "^1.0", + "php-http/guzzle6-adapter": "^1.0", + "zendframework/zend-diactoros": "^1.3" + }, + "require-dev": { + "estahn/phpunit-json-assertions": "^1.0.0", + "php-http/mock-client": "^0.3.0", + "phpunit/phpunit": "^5.7", + "squizlabs/php_codesniffer": "^3.1" + }, + "type": "library", + "autoload": { + "psr-4": { + "Nexmo\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Tim Lytle", + "email": "tim@nexmo.com", + "homepage": "http://twitter.com/tjlytle", + "role": "Developer" + } + ], + "description": "PHP Client for using Nexmo's API.", + "time": "2018-11-14T14:12:22+00:00" + }, + { + "name": "nikic/php-parser", + "version": "v4.1.0", + "source": { + "type": "git", + "url": "https://github.com/nikic/PHP-Parser.git", + "reference": "d0230c5c77a7e3cfa69446febf340978540958c0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/d0230c5c77a7e3cfa69446febf340978540958c0", + "reference": "d0230c5c77a7e3cfa69446febf340978540958c0", "shasum": "" }, "require": { "ext-tokenizer": "*", - "php": ">=5.5" + "php": ">=7.0" }, "require-dev": { - "phpunit/phpunit": "~4.0|~5.0" + "phpunit/phpunit": "^6.5 || ^7.0" }, "bin": [ "bin/php-parse" @@ -2282,7 +3192,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-master": "4.1-dev" } }, "autoload": { @@ -2304,37 +3214,156 @@ "parser", "php" ], - "time": "2018-02-28T20:30:58+00:00" + "time": "2018-10-10T09:24:14+00:00" }, { - "name": "paragonie/random_compat", - "version": "v2.0.17", + "name": "opis/closure", + "version": "3.1.1", "source": { "type": "git", - "url": "https://github.com/paragonie/random_compat.git", - "reference": "29af24f25bab834fcbb38ad2a69fa93b867e070d" + "url": "https://github.com/opis/closure.git", + "reference": "d3209e46ad6c69a969b705df0738fd0dbe26ef9e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/paragonie/random_compat/zipball/29af24f25bab834fcbb38ad2a69fa93b867e070d", - "reference": "29af24f25bab834fcbb38ad2a69fa93b867e070d", + "url": "https://api.github.com/repos/opis/closure/zipball/d3209e46ad6c69a969b705df0738fd0dbe26ef9e", + "reference": "d3209e46ad6c69a969b705df0738fd0dbe26ef9e", "shasum": "" }, "require": { - "php": ">=5.2.0" + "php": "^5.4 || ^7.0" }, "require-dev": { - "phpunit/phpunit": "4.*|5.*" + "jeremeamia/superclosure": "^2.0", + "phpunit/phpunit": "^4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Opis\\Closure\\": "src/" + }, + "files": [ + "functions.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marius Sarca", + "email": "marius.sarca@gmail.com" + }, + { + "name": "Sorin Sarca", + "email": "sarca_sorin@hotmail.com" + } + ], + "description": "A library that can be used to serialize closures (anonymous functions) and arbitrary objects.", + "homepage": "https://opis.io/closure", + "keywords": [ + "anonymous functions", + "closure", + "function", + "serializable", + "serialization", + "serialize" + ], + "time": "2018-10-02T13:36:53+00:00" + }, + { + "name": "paragonie/constant_time_encoding", + "version": "v2.2.2", + "source": { + "type": "git", + "url": "https://github.com/paragonie/constant_time_encoding.git", + "reference": "eccf915f45f911bfb189d1d1638d940ec6ee6e33" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/paragonie/constant_time_encoding/zipball/eccf915f45f911bfb189d1d1638d940ec6ee6e33", + "reference": "eccf915f45f911bfb189d1d1638d940ec6ee6e33", + "shasum": "" + }, + "require": { + "php": "^7" + }, + "require-dev": { + "phpunit/phpunit": "^6|^7", + "vimeo/psalm": "^1" + }, + "type": "library", + "autoload": { + "psr-4": { + "ParagonIE\\ConstantTime\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Paragon Initiative Enterprises", + "email": "security@paragonie.com", + "homepage": "https://paragonie.com", + "role": "Maintainer" + }, + { + "name": "Steve 'Sc00bz' Thomas", + "email": "steve@tobtu.com", + "homepage": "https://www.tobtu.com", + "role": "Original Developer" + } + ], + "description": "Constant-time Implementations of RFC 4648 Encoding (Base-64, Base-32, Base-16)", + "keywords": [ + "base16", + "base32", + "base32_decode", + "base32_encode", + "base64", + "base64_decode", + "base64_encode", + "bin2hex", + "encoding", + "hex", + "hex2bin", + "rfc4648" + ], + "time": "2018-03-10T19:47:49+00:00" + }, + { + "name": "paragonie/random_compat", + "version": "v9.99.99", + "source": { + "type": "git", + "url": "https://github.com/paragonie/random_compat.git", + "reference": "84b4dfb120c6f9b4ff7b3685f9b8f1aa365a0c95" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/paragonie/random_compat/zipball/84b4dfb120c6f9b4ff7b3685f9b8f1aa365a0c95", + "reference": "84b4dfb120c6f9b4ff7b3685f9b8f1aa365a0c95", + "shasum": "" + }, + "require": { + "php": "^7" + }, + "require-dev": { + "phpunit/phpunit": "4.*|5.*", + "vimeo/psalm": "^1" }, "suggest": { "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes." }, "type": "library", - "autoload": { - "files": [ - "lib/random.php" - ] - }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" @@ -2353,7 +3382,7 @@ "pseudorandom", "random" ], - "time": "2018-07-04T16:31:37+00:00" + "time": "2018-07-02T15:55:56+00:00" }, { "name": "patchwork/utf8", @@ -2414,6 +3443,172 @@ ], "time": "2016-05-18T13:57:10+00:00" }, + { + "name": "php-http/guzzle6-adapter", + "version": "v1.1.1", + "source": { + "type": "git", + "url": "https://github.com/php-http/guzzle6-adapter.git", + "reference": "a56941f9dc6110409cfcddc91546ee97039277ab" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-http/guzzle6-adapter/zipball/a56941f9dc6110409cfcddc91546ee97039277ab", + "reference": "a56941f9dc6110409cfcddc91546ee97039277ab", + "shasum": "" + }, + "require": { + "guzzlehttp/guzzle": "^6.0", + "php": ">=5.5.0", + "php-http/httplug": "^1.0" + }, + "provide": { + "php-http/async-client-implementation": "1.0", + "php-http/client-implementation": "1.0" + }, + "require-dev": { + "ext-curl": "*", + "php-http/adapter-integration-tests": "^0.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2-dev" + } + }, + "autoload": { + "psr-4": { + "Http\\Adapter\\Guzzle6\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com" + }, + { + "name": "David de Boer", + "email": "david@ddeboer.nl" + } + ], + "description": "Guzzle 6 HTTP Adapter", + "homepage": "http://httplug.io", + "keywords": [ + "Guzzle", + "http" + ], + "time": "2016-05-10T06:13:32+00:00" + }, + { + "name": "php-http/httplug", + "version": "v1.1.0", + "source": { + "type": "git", + "url": "https://github.com/php-http/httplug.git", + "reference": "1c6381726c18579c4ca2ef1ec1498fdae8bdf018" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-http/httplug/zipball/1c6381726c18579c4ca2ef1ec1498fdae8bdf018", + "reference": "1c6381726c18579c4ca2ef1ec1498fdae8bdf018", + "shasum": "" + }, + "require": { + "php": ">=5.4", + "php-http/promise": "^1.0", + "psr/http-message": "^1.0" + }, + "require-dev": { + "henrikbjorn/phpspec-code-coverage": "^1.0", + "phpspec/phpspec": "^2.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1-dev" + } + }, + "autoload": { + "psr-4": { + "Http\\Client\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Eric GELOEN", + "email": "geloen.eric@gmail.com" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com" + } + ], + "description": "HTTPlug, the HTTP client abstraction for PHP", + "homepage": "http://httplug.io", + "keywords": [ + "client", + "http" + ], + "time": "2016-08-31T08:30:17+00:00" + }, + { + "name": "php-http/promise", + "version": "v1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-http/promise.git", + "reference": "dc494cdc9d7160b9a09bd5573272195242ce7980" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-http/promise/zipball/dc494cdc9d7160b9a09bd5573272195242ce7980", + "reference": "dc494cdc9d7160b9a09bd5573272195242ce7980", + "shasum": "" + }, + "require-dev": { + "henrikbjorn/phpspec-code-coverage": "^1.0", + "phpspec/phpspec": "^2.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1-dev" + } + }, + "autoload": { + "psr-4": { + "Http\\Promise\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com" + }, + { + "name": "Joel Wurtz", + "email": "joel.wurtz@gmail.com" + } + ], + "description": "Promise used for asynchronous HTTP requests", + "homepage": "http://httplug.io", + "keywords": [ + "promise" + ], + "time": "2016-01-26T13:27:02+00:00" + }, { "name": "phpdocumentor/reflection-common", "version": "1.0.1", @@ -2562,16 +3757,16 @@ }, { "name": "phpseclib/phpseclib", - "version": "2.0.11", + "version": "2.0.12", "source": { "type": "git", "url": "https://github.com/phpseclib/phpseclib.git", - "reference": "7053f06f91b3de78e143d430e55a8f7889efc08b" + "reference": "8814dc7841db159daed0b32c2b08fb7e03c6afe7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/7053f06f91b3de78e143d430e55a8f7889efc08b", - "reference": "7053f06f91b3de78e143d430e55a8f7889efc08b", + "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/8814dc7841db159daed0b32c2b08fb7e03c6afe7", + "reference": "8814dc7841db159daed0b32c2b08fb7e03c6afe7", "shasum": "" }, "require": { @@ -2650,37 +3845,37 @@ "x.509", "x509" ], - "time": "2018-04-15T16:55:05+00:00" + "time": "2018-11-04T05:45:48+00:00" }, { "name": "phpspec/prophecy", - "version": "v1.6.2", + "version": "1.7.5", "source": { "type": "git", "url": "https://github.com/phpspec/prophecy.git", - "reference": "6c52c2722f8460122f96f86346600e1077ce22cb" + "reference": "dfd6be44111a7c41c2e884a336cc4f461b3b2401" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/6c52c2722f8460122f96f86346600e1077ce22cb", - "reference": "6c52c2722f8460122f96f86346600e1077ce22cb", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/dfd6be44111a7c41c2e884a336cc4f461b3b2401", + "reference": "dfd6be44111a7c41c2e884a336cc4f461b3b2401", "shasum": "" }, "require": { "doctrine/instantiator": "^1.0.2", "php": "^5.3|^7.0", - "phpdocumentor/reflection-docblock": "^2.0|^3.0.2", - "sebastian/comparator": "^1.1", - "sebastian/recursion-context": "^1.0|^2.0" + "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0", + "sebastian/comparator": "^1.1|^2.0", + "sebastian/recursion-context": "^1.0|^2.0|^3.0" }, "require-dev": { - "phpspec/phpspec": "^2.0", - "phpunit/phpunit": "^4.8 || ^5.6.5" + "phpspec/phpspec": "^2.5|^3.2", + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.6.x-dev" + "dev-master": "1.7.x-dev" } }, "autoload": { @@ -2713,47 +3908,118 @@ "spy", "stub" ], - "time": "2016-11-21T14:58:47+00:00" + "time": "2018-02-19T10:16:54+00:00" }, { "name": "pragmarx/google2fa", - "version": "v1.0.1", + "version": "v3.0.3", "source": { "type": "git", "url": "https://github.com/antonioribeiro/google2fa.git", - "reference": "b346dc138339b745c5831405d00cff7c1351aa0d" + "reference": "6949226739e4424f40031e6f1c96b1fd64047335" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/antonioribeiro/google2fa/zipball/b346dc138339b745c5831405d00cff7c1351aa0d", - "reference": "b346dc138339b745c5831405d00cff7c1351aa0d", + "url": "https://api.github.com/repos/antonioribeiro/google2fa/zipball/6949226739e4424f40031e6f1c96b1fd64047335", + "reference": "6949226739e4424f40031e6f1c96b1fd64047335", "shasum": "" }, "require": { - "christian-riesen/base32": "~1.3", - "paragonie/random_compat": "~1.4|~2.0", + "paragonie/constant_time_encoding": "~1.0|~2.0", + "paragonie/random_compat": ">=1", "php": ">=5.4", "symfony/polyfill-php56": "~1.2" }, "require-dev": { - "phpspec/phpspec": "~2.1" + "bacon/bacon-qr-code": "~1.0", + "phpunit/phpunit": "~4|~5|~6" }, "suggest": { "bacon/bacon-qr-code": "Required to generate inline QR Codes." }, "type": "library", + "extra": { + "component": "package", + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "psr-4": { + "PragmaRX\\Google2FA\\": "src/", + "PragmaRX\\Google2FA\\Tests\\": "tests/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Antonio Carlos Ribeiro", + "email": "acr@antoniocarlosribeiro.com", + "role": "Creator & Designer" + } + ], + "description": "A One Time Password Authentication package, compatible with Google Authenticator.", + "keywords": [ + "2fa", + "Authentication", + "Two Factor Authentication", + "google2fa", + "laravel" + ], + "time": "2018-08-29T13:28:06+00:00" + }, + { + "name": "pragmarx/google2fa-laravel", + "version": "v0.2.0", + "source": { + "type": "git", + "url": "https://github.com/antonioribeiro/google2fa-laravel.git", + "reference": "54f0c30c9be5497a7bd248844f1099156457e719" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/antonioribeiro/google2fa-laravel/zipball/54f0c30c9be5497a7bd248844f1099156457e719", + "reference": "54f0c30c9be5497a7bd248844f1099156457e719", + "shasum": "" + }, + "require": { + "laravel/framework": ">=5.2", + "php": ">=5.4", + "pragmarx/google2fa": "~3.0" + }, + "require-dev": { + "orchestra/testbench-browser-kit": "~3.4|~3.5|~3.6", + "phpunit/phpunit": "~5|~6|~7" + }, + "suggest": { + "bacon/bacon-qr-code": "Required to generate inline QR Codes.", + "pragmarx/recovery": "Generate recovery codes." + }, + "type": "library", "extra": { "component": "package", "frameworks": [ "Laravel" ], "branch-alias": { - "dev-master": "1.0-dev" + "dev-master": "0.2-dev" + }, + "laravel": { + "providers": [ + "PragmaRX\\Google2FALaravel\\ServiceProvider" + ], + "aliases": { + "Google2FA": "PragmaRX\\Google2FALaravel\\Facade" + } } }, "autoload": { "psr-4": { - "PragmaRX\\Google2FA\\": "src/" + "PragmaRX\\Google2FALaravel\\": "src/", + "PragmaRX\\Google2FALaravel\\Tests\\": "tests/" } }, "notification-url": "https://packagist.org/downloads/", @@ -2774,7 +4040,7 @@ "google2fa", "laravel" ], - "time": "2016-07-18T20:25:04+00:00" + "time": "2018-03-08T04:08:14+00:00" }, { "name": "predis/predis", @@ -2826,6 +4092,101 @@ ], "time": "2016-06-16T16:22:20+00:00" }, + { + "name": "psr/cache", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/cache.git", + "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/cache/zipball/d11b50ad223250cf17b86e38383413f5a6764bf8", + "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Cache\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for caching libraries", + "keywords": [ + "cache", + "psr", + "psr-6" + ], + "time": "2016-08-06T20:24:11+00:00" + }, + { + "name": "psr/container", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/b7ce3b176482dbbc1245ebf52b181af44c2cf55f", + "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", + "keywords": [ + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" + ], + "time": "2017-02-14T16:28:37+00:00" + }, { "name": "psr/http-message", "version": "1.0.1", @@ -2878,16 +4239,16 @@ }, { "name": "psr/log", - "version": "1.0.2", + "version": "1.1.0", "source": { "type": "git", "url": "https://github.com/php-fig/log.git", - "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d" + "reference": "6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", - "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", + "url": "https://api.github.com/repos/php-fig/log/zipball/6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd", + "reference": "6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd", "shasum": "" }, "require": { @@ -2921,7 +4282,55 @@ "psr", "psr-3" ], - "time": "2016-10-10T12:19:37+00:00" + "time": "2018-11-20T15:27:04+00:00" + }, + { + "name": "psr/simple-cache", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/simple-cache.git", + "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/simple-cache/zipball/408d5eafb83c57f6365a3ca330ff23aa4a5fa39b", + "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\SimpleCache\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interfaces for simple caching", + "keywords": [ + "cache", + "caching", + "psr", + "psr-16", + "simple-cache" + ], + "time": "2017-10-23T01:57:42+00:00" }, { "name": "psy/psysh", @@ -2997,6 +4406,103 @@ ], "time": "2018-10-13T15:16:03+00:00" }, + { + "name": "rackspace/php-opencloud", + "version": "v1.16.0", + "source": { + "type": "git", + "url": "https://github.com/rackspace/php-opencloud.git", + "reference": "d6b71feed7f9e7a4b52e0240a79f06473ba69c8c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/rackspace/php-opencloud/zipball/d6b71feed7f9e7a4b52e0240a79f06473ba69c8c", + "reference": "d6b71feed7f9e7a4b52e0240a79f06473ba69c8c", + "shasum": "" + }, + "require": { + "guzzle/guzzle": "~3.8", + "mikemccabe/json-patch-php": "~0.1", + "php": ">=5.4", + "psr/log": "~1.0" + }, + "require-dev": { + "apigen/apigen": "~4.0", + "fabpot/php-cs-fixer": "1.0.*@dev", + "jakub-onderka/php-parallel-lint": "0.*", + "phpspec/prophecy": "~1.4", + "phpunit/phpunit": "4.3.*", + "satooshi/php-coveralls": "0.6.*@dev" + }, + "type": "library", + "autoload": { + "psr-0": { + "OpenCloud": [ + "lib/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Jamie Hannaford", + "email": "jamie.hannaford@rackspace.com", + "homepage": "https://github.com/jamiehannaford" + } + ], + "description": "PHP SDK for Rackspace/OpenStack APIs", + "keywords": [ + "Openstack", + "nova", + "opencloud", + "rackspace", + "swift" + ], + "time": "2016-01-29T10:34:57+00:00" + }, + { + "name": "ralouphie/getallheaders", + "version": "2.0.5", + "source": { + "type": "git", + "url": "https://github.com/ralouphie/getallheaders.git", + "reference": "5601c8a83fbba7ef674a7369456d12f1e0d0eafa" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/5601c8a83fbba7ef674a7369456d12f1e0d0eafa", + "reference": "5601c8a83fbba7ef674a7369456d12f1e0d0eafa", + "shasum": "" + }, + "require": { + "php": ">=5.3" + }, + "require-dev": { + "phpunit/phpunit": "~3.7.0", + "satooshi/php-coveralls": ">=1.0" + }, + "type": "library", + "autoload": { + "files": [ + "src/getallheaders.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ralph Khattar", + "email": "ralph.khattar@gmail.com" + } + ], + "description": "A polyfill for getallheaders.", + "time": "2016-02-11T07:05:27+00:00" + }, { "name": "ramsey/uuid", "version": "3.8.0", @@ -3081,16 +4587,16 @@ }, { "name": "rollbar/rollbar", - "version": "v1.6.3", + "version": "v1.7.1", "source": { "type": "git", "url": "https://github.com/rollbar/rollbar-php.git", - "reference": "149590adc3bd5ed1188c48f8159f257aa1bf2d19" + "reference": "c2f8be87983ecdd3c46ceb3c459de02376af4707" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/rollbar/rollbar-php/zipball/149590adc3bd5ed1188c48f8159f257aa1bf2d19", - "reference": "149590adc3bd5ed1188c48f8159f257aa1bf2d19", + "url": "https://api.github.com/repos/rollbar/rollbar-php/zipball/c2f8be87983ecdd3c46ceb3c459de02376af4707", + "reference": "c2f8be87983ecdd3c46ceb3c459de02376af4707", "shasum": "" }, "require": { @@ -3137,33 +4643,33 @@ "logging", "monitoring" ], - "time": "2018-09-06T21:34:17+00:00" + "time": "2018-11-12T12:03:55+00:00" }, { "name": "rollbar/rollbar-laravel", - "version": "v2.4.1", + "version": "v4.0.1", "source": { "type": "git", "url": "https://github.com/rollbar/rollbar-php-laravel.git", - "reference": "2f1d086f842a671bf2af387e1b9dabc782025050" + "reference": "e02e4d1715340ffde2c47b3edea0c8c89befe993" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/rollbar/rollbar-php-laravel/zipball/2f1d086f842a671bf2af387e1b9dabc782025050", - "reference": "2f1d086f842a671bf2af387e1b9dabc782025050", + "url": "https://api.github.com/repos/rollbar/rollbar-php-laravel/zipball/e02e4d1715340ffde2c47b3edea0c8c89befe993", + "reference": "e02e4d1715340ffde2c47b3edea0c8c89befe993", "shasum": "" }, "require": { - "illuminate/support": "^4.0|^5.0", - "php": ">=5.4", + "illuminate/support": "^5.0", + "php": ">=7.0", "rollbar/rollbar": "^1" }, "require-dev": { - "mockery/mockery": "^0.9", - "orchestra/testbench": "~3.0", - "phpunit/phpunit": "~4.0|~5.0", + "mockery/mockery": "^1", + "orchestra/testbench": "~3.6", + "phpunit/phpunit": "~7.0", "satooshi/php-coveralls": "^1.0", - "squizlabs/php_codesniffer": "2.*" + "squizlabs/php_codesniffer": "3.*" }, "type": "library", "extra": { @@ -3205,7 +4711,7 @@ "monitoring", "rollbar" ], - "time": "2018-10-04T22:37:43+00:00" + "time": "2018-09-26T07:27:49+00:00" }, { "name": "schuppo/password-strength", @@ -3266,30 +4772,30 @@ }, { "name": "sebastian/comparator", - "version": "1.2.4", + "version": "2.1.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be" + "reference": "34369daee48eafb2651bea869b4b15d75ccc35f9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2b7424b55f5047b47ac6e5ccb20b2aea4011d9be", - "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/34369daee48eafb2651bea869b4b15d75ccc35f9", + "reference": "34369daee48eafb2651bea869b4b15d75ccc35f9", "shasum": "" }, "require": { - "php": ">=5.3.3", - "sebastian/diff": "~1.2", - "sebastian/exporter": "~1.2 || ~2.0" + "php": "^7.0", + "sebastian/diff": "^2.0 || ^3.0", + "sebastian/exporter": "^3.1" }, "require-dev": { - "phpunit/phpunit": "~4.4" + "phpunit/phpunit": "^6.4" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.2.x-dev" + "dev-master": "2.1.x-dev" } }, "autoload": { @@ -3320,38 +4826,39 @@ } ], "description": "Provides the functionality to compare PHP values for equality", - "homepage": "http://www.github.com/sebastianbergmann/comparator", + "homepage": "https://github.com/sebastianbergmann/comparator", "keywords": [ "comparator", "compare", "equality" ], - "time": "2017-01-29T09:50:25+00:00" + "time": "2018-02-01T13:46:46+00:00" }, { "name": "sebastian/diff", - "version": "1.4.3", + "version": "3.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "7f066a26a962dbe58ddea9f72a4e82874a3975a4" + "reference": "366541b989927187c4ca70490a35615d3fef2dce" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/7f066a26a962dbe58ddea9f72a4e82874a3975a4", - "reference": "7f066a26a962dbe58ddea9f72a4e82874a3975a4", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/366541b989927187c4ca70490a35615d3fef2dce", + "reference": "366541b989927187c4ca70490a35615d3fef2dce", "shasum": "" }, "require": { - "php": "^5.3.3 || ^7.0" + "php": "^7.1" }, "require-dev": { - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" + "phpunit/phpunit": "^7.0", + "symfony/process": "^2 || ^3.3 || ^4" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.4-dev" + "dev-master": "3.0-dev" } }, "autoload": { @@ -3376,36 +4883,39 @@ "description": "Diff implementation", "homepage": "https://github.com/sebastianbergmann/diff", "keywords": [ - "diff" + "diff", + "udiff", + "unidiff", + "unified diff" ], - "time": "2017-05-22T07:24:03+00:00" + "time": "2018-06-10T07:54:39+00:00" }, { "name": "sebastian/exporter", - "version": "2.0.0", + "version": "3.1.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "ce474bdd1a34744d7ac5d6aad3a46d48d9bac4c4" + "reference": "234199f4528de6d12aaa58b612e98f7d36adb937" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/ce474bdd1a34744d7ac5d6aad3a46d48d9bac4c4", - "reference": "ce474bdd1a34744d7ac5d6aad3a46d48d9bac4c4", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/234199f4528de6d12aaa58b612e98f7d36adb937", + "reference": "234199f4528de6d12aaa58b612e98f7d36adb937", "shasum": "" }, "require": { - "php": ">=5.3.3", - "sebastian/recursion-context": "~2.0" + "php": "^7.0", + "sebastian/recursion-context": "^3.0" }, "require-dev": { "ext-mbstring": "*", - "phpunit/phpunit": "~4.4" + "phpunit/phpunit": "^6.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0.x-dev" + "dev-master": "3.1.x-dev" } }, "autoload": { @@ -3445,32 +4955,32 @@ "export", "exporter" ], - "time": "2016-11-19T08:54:04+00:00" + "time": "2017-04-03T13:19:02+00:00" }, { "name": "sebastian/recursion-context", - "version": "2.0.0", + "version": "3.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "2c3ba150cbec723aa057506e73a8d33bdb286c9a" + "reference": "5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/2c3ba150cbec723aa057506e73a8d33bdb286c9a", - "reference": "2c3ba150cbec723aa057506e73a8d33bdb286c9a", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8", + "reference": "5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": "^7.0" }, "require-dev": { - "phpunit/phpunit": "~4.4" + "phpunit/phpunit": "^6.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0.x-dev" + "dev-master": "3.0.x-dev" } }, "autoload": { @@ -3498,28 +5008,28 @@ ], "description": "Provides functionality to recursively process PHP variables", "homepage": "http://www.github.com/sebastianbergmann/recursion-context", - "time": "2016-11-19T07:33:16+00:00" + "time": "2017-03-03T06:23:57+00:00" }, { "name": "spatie/db-dumper", - "version": "1.5.1", + "version": "2.12.0", "source": { "type": "git", "url": "https://github.com/spatie/db-dumper.git", - "reference": "efdf41891a9dd4bb63fb6253044c9e51f34fff41" + "reference": "61cf73e3b53e163d6e888a0013b9df6bb235752c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/db-dumper/zipball/efdf41891a9dd4bb63fb6253044c9e51f34fff41", - "reference": "efdf41891a9dd4bb63fb6253044c9e51f34fff41", + "url": "https://api.github.com/repos/spatie/db-dumper/zipball/61cf73e3b53e163d6e888a0013b9df6bb235752c", + "reference": "61cf73e3b53e163d6e888a0013b9df6bb235752c", "shasum": "" }, "require": { - "php": "^5.5|^7.0", - "symfony/process": "^2.7|^3.0" + "php": "^7.0", + "symfony/process": "^3.0|^4.0" }, "require-dev": { - "phpunit/phpunit": "^4.8" + "phpunit/phpunit": "^6.0" }, "type": "library", "autoload": { @@ -3548,41 +5058,46 @@ "mysqldump", "spatie" ], - "time": "2016-06-14T13:23:01+00:00" + "time": "2018-12-10T10:41:18+00:00" }, { "name": "spatie/laravel-backup", - "version": "3.11.0", + "version": "5.11.3", "source": { "type": "git", "url": "https://github.com/spatie/laravel-backup.git", - "reference": "2382532ce52e3929ccb0e930539d14dfd09d22eb" + "reference": "ff06262cfa2fa1104f727e758fc4111a6f7413da" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/laravel-backup/zipball/2382532ce52e3929ccb0e930539d14dfd09d22eb", - "reference": "2382532ce52e3929ccb0e930539d14dfd09d22eb", + "url": "https://api.github.com/repos/spatie/laravel-backup/zipball/ff06262cfa2fa1104f727e758fc4111a6f7413da", + "reference": "ff06262cfa2fa1104f727e758fc4111a6f7413da", "shasum": "" }, "require": { - "illuminate/console": "~5.1.0|~5.2.0|~5.3.0|~5.4.0", - "illuminate/filesystem": "~5.1.20|~5.2.0|~5.3.0|~5.4.0", - "illuminate/support": "~5.1.0|~5.2.0|~5.3.0|~5.4.0", - "league/flysystem": "^1.0.8", - "php": "^5.5|^7.0", - "spatie/db-dumper": "^1.3", - "symfony/finder": "^2.7|^3.0" + "laravel/framework": "~5.5.0|~5.6.0|~5.7.0", + "league/flysystem": "^1.0.27", + "php": "^7.1", + "spatie/db-dumper": "^2.11.1", + "spatie/temporary-directory": "^1.1", + "symfony/finder": "^3.3|^4.0" }, "require-dev": { - "mockery/mockery": "^0.9.4", - "orchestra/testbench": "^3.2", - "phpunit/phpunit": "^4.8" + "mockery/mockery": "^1.0", + "orchestra/testbench": "~3.5.0|~3.6.0|~3.7.0", + "phpunit/phpunit": "^7.3" }, "suggest": { - "irazasyed/telegram-bot-sdk": "Allows notifications to be sent using Telegram Bot", - "maknz/slack": "Allows notifications to be sent via Slack" + "guzzlehttp/guzzle": "Allows notifications to be sent via Slack" }, "type": "library", + "extra": { + "laravel": { + "providers": [ + "Spatie\\Backup\\BackupServiceProvider" + ] + } + }, "autoload": { "psr-4": { "Spatie\\Backup\\": "src" @@ -3611,33 +5126,84 @@ "laravel-backup", "spatie" ], - "time": "2017-02-18T09:54:12+00:00" + "time": "2018-11-05T13:09:53+00:00" }, { - "name": "swiftmailer/swiftmailer", - "version": "v5.4.12", + "name": "spatie/temporary-directory", + "version": "1.1.4", "source": { "type": "git", - "url": "https://github.com/swiftmailer/swiftmailer.git", - "reference": "181b89f18a90f8925ef805f950d47a7190e9b950" + "url": "https://github.com/spatie/temporary-directory.git", + "reference": "5e1799fa2297363ebfb4df296fea90afbd4ef9b7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/swiftmailer/swiftmailer/zipball/181b89f18a90f8925ef805f950d47a7190e9b950", - "reference": "181b89f18a90f8925ef805f950d47a7190e9b950", + "url": "https://api.github.com/repos/spatie/temporary-directory/zipball/5e1799fa2297363ebfb4df296fea90afbd4ef9b7", + "reference": "5e1799fa2297363ebfb4df296fea90afbd4ef9b7", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": "^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.3" + }, + "type": "library", + "autoload": { + "psr-4": { + "Spatie\\TemporaryDirectory\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Alex Vanderbist", + "email": "alex@spatie.be", + "homepage": "https://spatie.be", + "role": "Developer" + } + ], + "description": "Easily create, use and destroy temporary directories", + "homepage": "https://github.com/spatie/temporary-directory", + "keywords": [ + "spatie", + "temporary-directory" + ], + "time": "2018-04-12T09:34:43+00:00" + }, + { + "name": "swiftmailer/swiftmailer", + "version": "v6.1.3", + "source": { + "type": "git", + "url": "https://github.com/swiftmailer/swiftmailer.git", + "reference": "8ddcb66ac10c392d3beb54829eef8ac1438595f4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/swiftmailer/swiftmailer/zipball/8ddcb66ac10c392d3beb54829eef8ac1438595f4", + "reference": "8ddcb66ac10c392d3beb54829eef8ac1438595f4", + "shasum": "" + }, + "require": { + "egulias/email-validator": "~2.0", + "php": ">=7.0.0" }, "require-dev": { "mockery/mockery": "~0.9.1", - "symfony/phpunit-bridge": "~3.2" + "symfony/phpunit-bridge": "~3.3@dev" + }, + "suggest": { + "ext-intl": "Needed to support internationalized email addresses", + "true/punycode": "Needed to support internationalized email addresses, if ext-intl is not installed" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "5.4-dev" + "dev-master": "6.1-dev" } }, "autoload": { @@ -3665,25 +5231,25 @@ "mail", "mailer" ], - "time": "2018-07-31T09:26:32+00:00" + "time": "2018-09-11T07:12:52+00:00" }, { "name": "symfony/console", - "version": "v3.4.17", + "version": "v4.2.1", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "3b2b415d4c48fbefca7dc742aa0a0171bfae4e0b" + "reference": "4dff24e5d01e713818805c1862d2e3f901ee7dd0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/3b2b415d4c48fbefca7dc742aa0a0171bfae4e0b", - "reference": "3b2b415d4c48fbefca7dc742aa0a0171bfae4e0b", + "url": "https://api.github.com/repos/symfony/console/zipball/4dff24e5d01e713818805c1862d2e3f901ee7dd0", + "reference": "4dff24e5d01e713818805c1862d2e3f901ee7dd0", "shasum": "" }, "require": { - "php": "^5.5.9|>=7.0.8", - "symfony/debug": "~2.8|~3.0|~4.0", + "php": "^7.1.3", + "symfony/contracts": "^1.0", "symfony/polyfill-mbstring": "~1.0" }, "conflict": { @@ -3692,11 +5258,11 @@ }, "require-dev": { "psr/log": "~1.0", - "symfony/config": "~3.3|~4.0", + "symfony/config": "~3.4|~4.0", "symfony/dependency-injection": "~3.4|~4.0", - "symfony/event-dispatcher": "~2.8|~3.0|~4.0", + "symfony/event-dispatcher": "~3.4|~4.0", "symfony/lock": "~3.4|~4.0", - "symfony/process": "~3.3|~4.0" + "symfony/process": "~3.4|~4.0" }, "suggest": { "psr/log-implementation": "For using the console logger", @@ -3707,7 +5273,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-master": "4.2-dev" } }, "autoload": { @@ -3734,29 +5300,97 @@ ], "description": "Symfony Console Component", "homepage": "https://symfony.com", - "time": "2018-10-02T16:33:53+00:00" + "time": "2018-11-27T07:40:44+00:00" }, { - "name": "symfony/css-selector", - "version": "v3.1.10", + "name": "symfony/contracts", + "version": "v1.0.2", "source": { "type": "git", - "url": "https://github.com/symfony/css-selector.git", - "reference": "722a87478a72d95dc2a3bcf41dc9c2d13fd4cb2d" + "url": "https://github.com/symfony/contracts.git", + "reference": "1aa7ab2429c3d594dd70689604b5cf7421254cdf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/css-selector/zipball/722a87478a72d95dc2a3bcf41dc9c2d13fd4cb2d", - "reference": "722a87478a72d95dc2a3bcf41dc9c2d13fd4cb2d", + "url": "https://api.github.com/repos/symfony/contracts/zipball/1aa7ab2429c3d594dd70689604b5cf7421254cdf", + "reference": "1aa7ab2429c3d594dd70689604b5cf7421254cdf", "shasum": "" }, "require": { - "php": ">=5.5.9" + "php": "^7.1.3" + }, + "require-dev": { + "psr/cache": "^1.0", + "psr/container": "^1.0" + }, + "suggest": { + "psr/cache": "When using the Cache contracts", + "psr/container": "When using the Service contracts", + "symfony/cache-contracts-implementation": "", + "symfony/service-contracts-implementation": "", + "symfony/translation-contracts-implementation": "" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.1-dev" + "dev-master": "1.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\": "" + }, + "exclude-from-classmap": [ + "**/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "A set of abstractions extracted out of the Symfony components", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "time": "2018-12-05T08:06:11+00:00" + }, + { + "name": "symfony/css-selector", + "version": "v4.0.15", + "source": { + "type": "git", + "url": "https://github.com/symfony/css-selector.git", + "reference": "72a316c5034bddd69710146ce8e72e34e15ef154" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/72a316c5034bddd69710146ce8e72e34e15ef154", + "reference": "72a316c5034bddd69710146ce8e72e34e15ef154", + "shasum": "" + }, + "require": { + "php": "^7.1.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" } }, "autoload": { @@ -3787,36 +5421,36 @@ ], "description": "Symfony CssSelector Component", "homepage": "https://symfony.com", - "time": "2017-01-02T20:31:54+00:00" + "time": "2018-07-26T09:08:35+00:00" }, { "name": "symfony/debug", - "version": "v3.4.17", + "version": "v4.2.1", "source": { "type": "git", "url": "https://github.com/symfony/debug.git", - "reference": "0a612e9dfbd2ccce03eb174365f31ecdca930ff6" + "reference": "e0a2b92ee0b5b934f973d90c2f58e18af109d276" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/debug/zipball/0a612e9dfbd2ccce03eb174365f31ecdca930ff6", - "reference": "0a612e9dfbd2ccce03eb174365f31ecdca930ff6", + "url": "https://api.github.com/repos/symfony/debug/zipball/e0a2b92ee0b5b934f973d90c2f58e18af109d276", + "reference": "e0a2b92ee0b5b934f973d90c2f58e18af109d276", "shasum": "" }, "require": { - "php": "^5.5.9|>=7.0.8", + "php": "^7.1.3", "psr/log": "~1.0" }, "conflict": { - "symfony/http-kernel": ">=2.3,<2.3.24|~2.4.0|>=2.5,<2.5.9|>=2.6,<2.6.2" + "symfony/http-kernel": "<3.4" }, "require-dev": { - "symfony/http-kernel": "~2.8|~3.0|~4.0" + "symfony/http-kernel": "~3.4|~4.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-master": "4.2-dev" } }, "autoload": { @@ -3843,34 +5477,35 @@ ], "description": "Symfony Debug Component", "homepage": "https://symfony.com", - "time": "2018-10-02T16:33:53+00:00" + "time": "2018-11-28T18:24:18+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v3.4.17", + "version": "v4.2.1", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "b2e1f19280c09a42dc64c0b72b80fe44dd6e88fb" + "reference": "921f49c3158a276d27c0d770a5a347a3b718b328" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/b2e1f19280c09a42dc64c0b72b80fe44dd6e88fb", - "reference": "b2e1f19280c09a42dc64c0b72b80fe44dd6e88fb", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/921f49c3158a276d27c0d770a5a347a3b718b328", + "reference": "921f49c3158a276d27c0d770a5a347a3b718b328", "shasum": "" }, "require": { - "php": "^5.5.9|>=7.0.8" + "php": "^7.1.3", + "symfony/contracts": "^1.0" }, "conflict": { - "symfony/dependency-injection": "<3.3" + "symfony/dependency-injection": "<3.4" }, "require-dev": { "psr/log": "~1.0", - "symfony/config": "~2.8|~3.0|~4.0", - "symfony/dependency-injection": "~3.3|~4.0", - "symfony/expression-language": "~2.8|~3.0|~4.0", - "symfony/stopwatch": "~2.8|~3.0|~4.0" + "symfony/config": "~3.4|~4.0", + "symfony/dependency-injection": "~3.4|~4.0", + "symfony/expression-language": "~3.4|~4.0", + "symfony/stopwatch": "~3.4|~4.0" }, "suggest": { "symfony/dependency-injection": "", @@ -3879,7 +5514,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-master": "4.2-dev" } }, "autoload": { @@ -3906,29 +5541,29 @@ ], "description": "Symfony EventDispatcher Component", "homepage": "https://symfony.com", - "time": "2018-07-26T09:06:28+00:00" + "time": "2018-12-01T08:52:38+00:00" }, { "name": "symfony/finder", - "version": "v3.4.17", + "version": "v4.2.1", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "54ba444dddc5bd5708a34bd095ea67c6eb54644d" + "reference": "e53d477d7b5c4982d0e1bfd2298dbee63d01441d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/54ba444dddc5bd5708a34bd095ea67c6eb54644d", - "reference": "54ba444dddc5bd5708a34bd095ea67c6eb54644d", + "url": "https://api.github.com/repos/symfony/finder/zipball/e53d477d7b5c4982d0e1bfd2298dbee63d01441d", + "reference": "e53d477d7b5c4982d0e1bfd2298dbee63d01441d", "shasum": "" }, "require": { - "php": "^5.5.9|>=7.0.8" + "php": "^7.1.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-master": "4.2-dev" } }, "autoload": { @@ -3955,34 +5590,34 @@ ], "description": "Symfony Finder Component", "homepage": "https://symfony.com", - "time": "2018-10-03T08:46:40+00:00" + "time": "2018-11-11T19:52:12+00:00" }, { "name": "symfony/http-foundation", - "version": "v3.4.17", + "version": "v4.2.1", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "3a4498236ade473c52b92d509303e5fd1b211ab1" + "reference": "1b31f3017fadd8cb05cf2c8aebdbf3b12a943851" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/3a4498236ade473c52b92d509303e5fd1b211ab1", - "reference": "3a4498236ade473c52b92d509303e5fd1b211ab1", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/1b31f3017fadd8cb05cf2c8aebdbf3b12a943851", + "reference": "1b31f3017fadd8cb05cf2c8aebdbf3b12a943851", "shasum": "" }, "require": { - "php": "^5.5.9|>=7.0.8", - "symfony/polyfill-mbstring": "~1.1", - "symfony/polyfill-php70": "~1.6" + "php": "^7.1.3", + "symfony/polyfill-mbstring": "~1.1" }, "require-dev": { - "symfony/expression-language": "~2.8|~3.0|~4.0" + "predis/predis": "~1.0", + "symfony/expression-language": "~3.4|~4.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-master": "4.2-dev" } }, "autoload": { @@ -4009,34 +5644,36 @@ ], "description": "Symfony HttpFoundation Component", "homepage": "https://symfony.com", - "time": "2018-10-03T08:48:18+00:00" + "time": "2018-11-26T10:55:26+00:00" }, { "name": "symfony/http-kernel", - "version": "v3.4.17", + "version": "v4.2.1", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "a0944a9a1d8845da724236cde9a310964acadb1c" + "reference": "b39ceffc0388232c309cbde3a7c3685f2ec0a624" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/a0944a9a1d8845da724236cde9a310964acadb1c", - "reference": "a0944a9a1d8845da724236cde9a310964acadb1c", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/b39ceffc0388232c309cbde3a7c3685f2ec0a624", + "reference": "b39ceffc0388232c309cbde3a7c3685f2ec0a624", "shasum": "" }, "require": { - "php": "^5.5.9|>=7.0.8", + "php": "^7.1.3", "psr/log": "~1.0", - "symfony/debug": "~2.8|~3.0|~4.0", - "symfony/event-dispatcher": "~2.8|~3.0|~4.0", - "symfony/http-foundation": "~3.4.12|~4.0.12|^4.1.1", + "symfony/contracts": "^1.0.2", + "symfony/debug": "~3.4|~4.0", + "symfony/event-dispatcher": "~4.1", + "symfony/http-foundation": "^4.1.1", "symfony/polyfill-ctype": "~1.8" }, "conflict": { - "symfony/config": "<2.8", - "symfony/dependency-injection": "<3.4.10|<4.0.10,>=4", - "symfony/var-dumper": "<3.3", + "symfony/config": "<3.4", + "symfony/dependency-injection": "<4.2", + "symfony/translation": "<4.2", + "symfony/var-dumper": "<4.1.1", "twig/twig": "<1.34|<2.4,>=2" }, "provide": { @@ -4044,34 +5681,32 @@ }, "require-dev": { "psr/cache": "~1.0", - "symfony/browser-kit": "~2.8|~3.0|~4.0", - "symfony/class-loader": "~2.8|~3.0", - "symfony/config": "~2.8|~3.0|~4.0", - "symfony/console": "~2.8|~3.0|~4.0", - "symfony/css-selector": "~2.8|~3.0|~4.0", - "symfony/dependency-injection": "^3.4.10|^4.0.10", - "symfony/dom-crawler": "~2.8|~3.0|~4.0", - "symfony/expression-language": "~2.8|~3.0|~4.0", - "symfony/finder": "~2.8|~3.0|~4.0", - "symfony/process": "~2.8|~3.0|~4.0", + "symfony/browser-kit": "~3.4|~4.0", + "symfony/config": "~3.4|~4.0", + "symfony/console": "~3.4|~4.0", + "symfony/css-selector": "~3.4|~4.0", + "symfony/dependency-injection": "^4.2", + "symfony/dom-crawler": "~3.4|~4.0", + "symfony/expression-language": "~3.4|~4.0", + "symfony/finder": "~3.4|~4.0", + "symfony/process": "~3.4|~4.0", "symfony/routing": "~3.4|~4.0", - "symfony/stopwatch": "~2.8|~3.0|~4.0", - "symfony/templating": "~2.8|~3.0|~4.0", - "symfony/translation": "~2.8|~3.0|~4.0", - "symfony/var-dumper": "~3.3|~4.0" + "symfony/stopwatch": "~3.4|~4.0", + "symfony/templating": "~3.4|~4.0", + "symfony/translation": "~4.2", + "symfony/var-dumper": "^4.1.1" }, "suggest": { "symfony/browser-kit": "", "symfony/config": "", "symfony/console": "", "symfony/dependency-injection": "", - "symfony/finder": "", "symfony/var-dumper": "" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-master": "4.2-dev" } }, "autoload": { @@ -4098,11 +5733,11 @@ ], "description": "Symfony HttpKernel Component", "homepage": "https://symfony.com", - "time": "2018-10-03T12:03:34+00:00" + "time": "2018-12-06T17:39:52+00:00" }, { "name": "symfony/polyfill-ctype", - "version": "v1.9.0", + "version": "v1.10.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", @@ -4160,16 +5795,16 @@ }, { "name": "symfony/polyfill-mbstring", - "version": "v1.9.0", + "version": "v1.10.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "d0cd638f4634c16d8df4508e847f14e9e43168b8" + "reference": "c79c051f5b3a46be09205c73b80b346e4153e494" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/d0cd638f4634c16d8df4508e847f14e9e43168b8", - "reference": "d0cd638f4634c16d8df4508e847f14e9e43168b8", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/c79c051f5b3a46be09205c73b80b346e4153e494", + "reference": "c79c051f5b3a46be09205c73b80b346e4153e494", "shasum": "" }, "require": { @@ -4215,20 +5850,20 @@ "portable", "shim" ], - "time": "2018-08-06T14:22:27+00:00" + "time": "2018-09-21T13:07:52+00:00" }, { "name": "symfony/polyfill-php56", - "version": "v1.9.0", + "version": "v1.10.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php56.git", - "reference": "7b4fc009172cc0196535b0328bd1226284a28000" + "reference": "ff208829fe1aa48ab9af356992bb7199fed551af" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php56/zipball/7b4fc009172cc0196535b0328bd1226284a28000", - "reference": "7b4fc009172cc0196535b0328bd1226284a28000", + "url": "https://api.github.com/repos/symfony/polyfill-php56/zipball/ff208829fe1aa48ab9af356992bb7199fed551af", + "reference": "ff208829fe1aa48ab9af356992bb7199fed551af", "shasum": "" }, "require": { @@ -4271,24 +5906,23 @@ "portable", "shim" ], - "time": "2018-08-06T14:22:27+00:00" + "time": "2018-09-21T06:26:08+00:00" }, { - "name": "symfony/polyfill-php70", - "version": "v1.9.0", + "name": "symfony/polyfill-php72", + "version": "v1.10.0", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-php70.git", - "reference": "1e24b0c4a56d55aaf368763a06c6d1c7d3194934" + "url": "https://github.com/symfony/polyfill-php72.git", + "reference": "9050816e2ca34a8e916c3a0ae8b9c2fccf68b631" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php70/zipball/1e24b0c4a56d55aaf368763a06c6d1c7d3194934", - "reference": "1e24b0c4a56d55aaf368763a06c6d1c7d3194934", + "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/9050816e2ca34a8e916c3a0ae8b9c2fccf68b631", + "reference": "9050816e2ca34a8e916c3a0ae8b9c2fccf68b631", "shasum": "" }, "require": { - "paragonie/random_compat": "~1.0|~2.0|~9.99", "php": ">=5.3.3" }, "type": "library", @@ -4299,13 +5933,10 @@ }, "autoload": { "psr-4": { - "Symfony\\Polyfill\\Php70\\": "" + "Symfony\\Polyfill\\Php72\\": "" }, "files": [ "bootstrap.php" - ], - "classmap": [ - "Resources/stubs" ] }, "notification-url": "https://packagist.org/downloads/", @@ -4322,7 +5953,7 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill backporting some PHP 7.0+ features to lower PHP versions", + "description": "Symfony polyfill backporting some PHP 7.2+ features to lower PHP versions", "homepage": "https://symfony.com", "keywords": [ "compatibility", @@ -4330,20 +5961,20 @@ "portable", "shim" ], - "time": "2018-08-06T14:22:27+00:00" + "time": "2018-09-21T13:07:52+00:00" }, { "name": "symfony/polyfill-util", - "version": "v1.9.0", + "version": "v1.10.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-util.git", - "reference": "8e15d04ba3440984d23e7964b2ee1d25c8de1581" + "reference": "3b58903eae668d348a7126f999b0da0f2f93611c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-util/zipball/8e15d04ba3440984d23e7964b2ee1d25c8de1581", - "reference": "8e15d04ba3440984d23e7964b2ee1d25c8de1581", + "url": "https://api.github.com/repos/symfony/polyfill-util/zipball/3b58903eae668d348a7126f999b0da0f2f93611c", + "reference": "3b58903eae668d348a7126f999b0da0f2f93611c", "shasum": "" }, "require": { @@ -4382,29 +6013,29 @@ "polyfill", "shim" ], - "time": "2018-08-06T14:22:27+00:00" + "time": "2018-09-30T16:36:12+00:00" }, { "name": "symfony/process", - "version": "v3.4.17", + "version": "v4.2.1", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "1dc2977afa7d70f90f3fefbcd84152813558910e" + "reference": "2b341009ccec76837a7f46f59641b431e4d4c2b0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/1dc2977afa7d70f90f3fefbcd84152813558910e", - "reference": "1dc2977afa7d70f90f3fefbcd84152813558910e", + "url": "https://api.github.com/repos/symfony/process/zipball/2b341009ccec76837a7f46f59641b431e4d4c2b0", + "reference": "2b341009ccec76837a7f46f59641b431e4d4c2b0", "shasum": "" }, "require": { - "php": "^5.5.9|>=7.0.8" + "php": "^7.1.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-master": "4.2-dev" } }, "autoload": { @@ -4431,7 +6062,7 @@ ], "description": "Symfony Process Component", "homepage": "https://symfony.com", - "time": "2018-10-02T12:28:39+00:00" + "time": "2018-11-20T16:22:05+00:00" }, { "name": "symfony/psr-http-message-bridge", @@ -4496,33 +6127,33 @@ }, { "name": "symfony/routing", - "version": "v3.4.17", + "version": "v4.2.1", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "585f6e2d740393d546978769dd56e496a6233e0b" + "reference": "649460207e77da6c545326c7f53618d23ad2c866" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/585f6e2d740393d546978769dd56e496a6233e0b", - "reference": "585f6e2d740393d546978769dd56e496a6233e0b", + "url": "https://api.github.com/repos/symfony/routing/zipball/649460207e77da6c545326c7f53618d23ad2c866", + "reference": "649460207e77da6c545326c7f53618d23ad2c866", "shasum": "" }, "require": { - "php": "^5.5.9|>=7.0.8" + "php": "^7.1.3" }, "conflict": { - "symfony/config": "<3.3.1", - "symfony/dependency-injection": "<3.3", + "symfony/config": "<4.2", + "symfony/dependency-injection": "<3.4", "symfony/yaml": "<3.4" }, "require-dev": { "doctrine/annotations": "~1.0", "psr/log": "~1.0", - "symfony/config": "^3.3.1|~4.0", - "symfony/dependency-injection": "~3.3|~4.0", - "symfony/expression-language": "~2.8|~3.0|~4.0", - "symfony/http-foundation": "~2.8|~3.0|~4.0", + "symfony/config": "~4.2", + "symfony/dependency-injection": "~3.4|~4.0", + "symfony/expression-language": "~3.4|~4.0", + "symfony/http-foundation": "~3.4|~4.0", "symfony/yaml": "~3.4|~4.0" }, "suggest": { @@ -4536,7 +6167,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-master": "4.2-dev" } }, "autoload": { @@ -4569,37 +6200,42 @@ "uri", "url" ], - "time": "2018-10-02T12:28:39+00:00" + "time": "2018-12-03T22:08:12+00:00" }, { "name": "symfony/translation", - "version": "v3.4.17", + "version": "v4.2.1", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "94bc3a79008e6640defedf5e14eb3b4f20048352" + "reference": "c0e2191e9bed845946ab3d99767513b56ca7dcd6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/94bc3a79008e6640defedf5e14eb3b4f20048352", - "reference": "94bc3a79008e6640defedf5e14eb3b4f20048352", + "url": "https://api.github.com/repos/symfony/translation/zipball/c0e2191e9bed845946ab3d99767513b56ca7dcd6", + "reference": "c0e2191e9bed845946ab3d99767513b56ca7dcd6", "shasum": "" }, "require": { - "php": "^5.5.9|>=7.0.8", + "php": "^7.1.3", + "symfony/contracts": "^1.0.2", "symfony/polyfill-mbstring": "~1.0" }, "conflict": { - "symfony/config": "<2.8", + "symfony/config": "<3.4", "symfony/dependency-injection": "<3.4", "symfony/yaml": "<3.4" }, + "provide": { + "symfony/translation-contracts-implementation": "1.0" + }, "require-dev": { "psr/log": "~1.0", - "symfony/config": "~2.8|~3.0|~4.0", + "symfony/config": "~3.4|~4.0", + "symfony/console": "~3.4|~4.0", "symfony/dependency-injection": "~3.4|~4.0", "symfony/finder": "~2.8|~3.0|~4.0", - "symfony/intl": "^2.8.18|^3.2.5|~4.0", + "symfony/intl": "~3.4|~4.0", "symfony/yaml": "~3.4|~4.0" }, "suggest": { @@ -4610,7 +6246,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-master": "4.2-dev" } }, "autoload": { @@ -4637,42 +6273,48 @@ ], "description": "Symfony Translation Component", "homepage": "https://symfony.com", - "time": "2018-10-02T16:33:53+00:00" + "time": "2018-12-06T10:45:32+00:00" }, { "name": "symfony/var-dumper", - "version": "v3.4.17", + "version": "v4.2.1", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "ff8ac19e97e5c7c3979236b584719a1190f84181" + "reference": "db61258540350725f4beb6b84006e32398acd120" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/ff8ac19e97e5c7c3979236b584719a1190f84181", - "reference": "ff8ac19e97e5c7c3979236b584719a1190f84181", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/db61258540350725f4beb6b84006e32398acd120", + "reference": "db61258540350725f4beb6b84006e32398acd120", "shasum": "" }, "require": { - "php": "^5.5.9|>=7.0.8", - "symfony/polyfill-mbstring": "~1.0" + "php": "^7.1.3", + "symfony/polyfill-mbstring": "~1.0", + "symfony/polyfill-php72": "~1.5" }, "conflict": { - "phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0" + "phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0", + "symfony/console": "<3.4" }, "require-dev": { "ext-iconv": "*", + "symfony/process": "~3.4|~4.0", "twig/twig": "~1.34|~2.4" }, "suggest": { "ext-iconv": "To convert non-UTF-8 strings to UTF-8 (or symfony/polyfill-iconv in case ext-iconv cannot be used).", "ext-intl": "To show region name in time zone dump", - "ext-symfony_debug": "" + "symfony/console": "To use the ServerDumpCommand and/or the bin/var-dump-server script" }, + "bin": [ + "Resources/bin/var-dump-server" + ], "type": "library", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-master": "4.2-dev" } }, "autoload": { @@ -4706,7 +6348,7 @@ "debug", "dump" ], - "time": "2018-10-02T16:33:53+00:00" + "time": "2018-11-25T12:50:42+00:00" }, { "name": "tecnickcom/tc-lib-barcode", @@ -4862,24 +6504,75 @@ "time": "2018-06-23T09:21:30+00:00" }, { - "name": "tightenco/ziggy", - "version": "v0.4.1", + "name": "tightenco/collect", + "version": "v5.7.16", "source": { "type": "git", - "url": "https://github.com/tightenco/ziggy.git", - "reference": "88ceae070d5af218379ac22489d72afc846c489f" + "url": "https://github.com/tightenco/collect.git", + "reference": "52a7b56dc0a9d265dd5911dff433dedd3417dcc4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/tightenco/ziggy/zipball/88ceae070d5af218379ac22489d72afc846c489f", - "reference": "88ceae070d5af218379ac22489d72afc846c489f", + "url": "https://api.github.com/repos/tightenco/collect/zipball/52a7b56dc0a9d265dd5911dff433dedd3417dcc4", + "reference": "52a7b56dc0a9d265dd5911dff433dedd3417dcc4", "shasum": "" }, "require": { - "laravel/framework": "^5.4.29" + "php": "^7.1.3", + "symfony/var-dumper": ">=3.4 <5" }, "require-dev": { - "orchestra/testbench": "~3.4" + "mockery/mockery": "^1.0", + "nesbot/carbon": "^1.26.3", + "phpunit/phpunit": "^7.0" + }, + "type": "library", + "autoload": { + "files": [ + "src/Collect/Support/helpers.php", + "src/Collect/Support/alias.php" + ], + "psr-4": { + "Tightenco\\Collect\\": "src/Collect" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylorotwell@gmail.com" + } + ], + "description": "Collect - Illuminate Collections as a separate package.", + "keywords": [ + "collection", + "laravel" + ], + "time": "2018-12-07T15:32:04+00:00" + }, + { + "name": "tightenco/ziggy", + "version": "v0.6.9", + "source": { + "type": "git", + "url": "https://github.com/tightenco/ziggy.git", + "reference": "0f59b703236f6b19002bc28d1d3eafcbf479bd43" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/tightenco/ziggy/zipball/0f59b703236f6b19002bc28d1d3eafcbf479bd43", + "reference": "0f59b703236f6b19002bc28d1d3eafcbf479bd43", + "shasum": "" + }, + "require": { + "laravel/framework": "~5.4" + }, + "require-dev": { + "mikey179/vfsstream": "^1.6", + "orchestra/testbench": "~3.6" }, "type": "library", "extra": { @@ -4909,7 +6602,7 @@ } ], "description": "Generates a Blade directive exporting all of your named Laravel routes. Also provides a nice route() helper function in JavaScript.", - "time": "2017-08-23T11:48:08+00:00" + "time": "2018-10-29T06:06:46+00:00" }, { "name": "tijsverkoyen/css-to-inline-styles", @@ -5070,16 +6763,16 @@ }, { "name": "watson/validating", - "version": "3.1.8", + "version": "3.1.7", "source": { "type": "git", "url": "https://github.com/dwightwatson/validating.git", - "reference": "ddb12d04de1a541961e1ca82837693382dfe8967" + "reference": "0264ff53f69fc32de480f3105706a4c255ead325" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/dwightwatson/validating/zipball/ddb12d04de1a541961e1ca82837693382dfe8967", - "reference": "ddb12d04de1a541961e1ca82837693382dfe8967", + "url": "https://api.github.com/repos/dwightwatson/validating/zipball/0264ff53f69fc32de480f3105706a4c255ead325", + "reference": "0264ff53f69fc32de480f3105706a4c255ead325", "shasum": "" }, "require": { @@ -5116,7 +6809,7 @@ "laravel", "validation" ], - "time": "2018-09-19T23:52:11+00:00" + "time": "2018-09-05T23:01:34+00:00" }, { "name": "webmozart/assert", @@ -5235,17 +6928,85 @@ ], "packages-dev": [ { - "name": "behat/gherkin", - "version": "v4.4.5", + "name": "barryvdh/laravel-debugbar", + "version": "v3.2.1", "source": { "type": "git", - "url": "https://github.com/Behat/Gherkin.git", - "reference": "5c14cff4f955b17d20d088dec1bde61c0539ec74" + "url": "https://github.com/barryvdh/laravel-debugbar.git", + "reference": "9d5caf43c5f3a3aea2178942f281054805872e7c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Behat/Gherkin/zipball/5c14cff4f955b17d20d088dec1bde61c0539ec74", - "reference": "5c14cff4f955b17d20d088dec1bde61c0539ec74", + "url": "https://api.github.com/repos/barryvdh/laravel-debugbar/zipball/9d5caf43c5f3a3aea2178942f281054805872e7c", + "reference": "9d5caf43c5f3a3aea2178942f281054805872e7c", + "shasum": "" + }, + "require": { + "illuminate/routing": "5.5.x|5.6.x|5.7.x", + "illuminate/session": "5.5.x|5.6.x|5.7.x", + "illuminate/support": "5.5.x|5.6.x|5.7.x", + "maximebf/debugbar": "~1.15.0", + "php": ">=7.0", + "symfony/debug": "^3|^4", + "symfony/finder": "^3|^4" + }, + "require-dev": { + "laravel/framework": "5.5.x" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.2-dev" + }, + "laravel": { + "providers": [ + "Barryvdh\\Debugbar\\ServiceProvider" + ], + "aliases": { + "Debugbar": "Barryvdh\\Debugbar\\Facade" + } + } + }, + "autoload": { + "psr-4": { + "Barryvdh\\Debugbar\\": "src/" + }, + "files": [ + "src/helpers.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Barry vd. Heuvel", + "email": "barryvdh@gmail.com" + } + ], + "description": "PHP Debugbar integration for Laravel", + "keywords": [ + "debug", + "debugbar", + "laravel", + "profiler", + "webprofiler" + ], + "time": "2018-11-09T08:37:55+00:00" + }, + { + "name": "behat/gherkin", + "version": "v4.5.1", + "source": { + "type": "git", + "url": "https://github.com/Behat/Gherkin.git", + "reference": "74ac03d52c5e23ad8abd5c5cce4ab0e8dc1b530a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Behat/Gherkin/zipball/74ac03d52c5e23ad8abd5c5cce4ab0e8dc1b530a", + "reference": "74ac03d52c5e23ad8abd5c5cce4ab0e8dc1b530a", "shasum": "" }, "require": { @@ -5291,65 +7052,63 @@ "gherkin", "parser" ], - "time": "2016-10-30T11:50:56+00:00" + "time": "2017-08-30T11:04:43+00:00" }, { "name": "codeception/codeception", - "version": "2.3.6", + "version": "2.5.1", "source": { "type": "git", "url": "https://github.com/Codeception/Codeception.git", - "reference": "c3dd3b5d9e0b1ea6c2fcca52457736dc756716f8" + "reference": "e0a658c64e98811a6fd4f6aa7c3222e0609066a9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Codeception/Codeception/zipball/c3dd3b5d9e0b1ea6c2fcca52457736dc756716f8", - "reference": "c3dd3b5d9e0b1ea6c2fcca52457736dc756716f8", + "url": "https://api.github.com/repos/Codeception/Codeception/zipball/e0a658c64e98811a6fd4f6aa7c3222e0609066a9", + "reference": "e0a658c64e98811a6fd4f6aa7c3222e0609066a9", "shasum": "" }, "require": { - "behat/gherkin": "~4.4.0", + "behat/gherkin": "^4.4.0", + "codeception/phpunit-wrapper": "^6.0.9|^7.0.6", + "codeception/stub": "^2.0", + "ext-curl": "*", "ext-json": "*", "ext-mbstring": "*", "facebook/webdriver": ">=1.1.3 <2.0", "guzzlehttp/guzzle": ">=4.1.4 <7.0", "guzzlehttp/psr7": "~1.0", - "php": ">=5.4.0 <8.0", - "phpunit/php-code-coverage": ">=2.2.4 <6.0", - "phpunit/phpunit": ">4.8.20 <7.0", - "phpunit/phpunit-mock-objects": ">2.3 <5.0", - "sebastian/comparator": ">1.1 <3.0", - "sebastian/diff": ">=1.4 <3.0", - "stecman/symfony-console-completion": "^0.7.0", - "symfony/browser-kit": ">=2.7 <4.0", - "symfony/console": ">=2.7 <4.0", - "symfony/css-selector": ">=2.7 <4.0", - "symfony/dom-crawler": ">=2.7.5 <4.0", - "symfony/event-dispatcher": ">=2.7 <4.0", - "symfony/finder": ">=2.7 <4.0", - "symfony/yaml": ">=2.7 <4.0" + "php": ">=5.6.0 <8.0", + "symfony/browser-kit": ">=2.7 <5.0", + "symfony/console": ">=2.7 <5.0", + "symfony/css-selector": ">=2.7 <5.0", + "symfony/dom-crawler": ">=2.7 <5.0", + "symfony/event-dispatcher": ">=2.7 <5.0", + "symfony/finder": ">=2.7 <5.0", + "symfony/yaml": ">=2.7 <5.0" }, "require-dev": { "codeception/specify": "~0.3", "facebook/graph-sdk": "~5.3", "flow/jsonpath": "~0.2", - "league/factory-muffin": "^3.0", - "league/factory-muffin-faker": "^1.0", "monolog/monolog": "~1.8", "pda/pheanstalk": "~3.0", "php-amqplib/php-amqplib": "~2.4", "predis/predis": "^1.0", "squizlabs/php_codesniffer": "~2.0", - "symfony/process": ">=2.7 <4.0", + "symfony/process": ">=2.7 <5.0", "vlucas/phpdotenv": "^2.4.0" }, "suggest": { + "aws/aws-sdk-php": "For using AWS Auth in REST module and Queue module", + "codeception/phpbuiltinserver": "Start and stop PHP built-in web server for your tests", "codeception/specify": "BDD-style code blocks", "codeception/verify": "BDD-style assertions", "flow/jsonpath": "For using JSONPath in REST module", "league/factory-muffin": "For DataFactory module", "league/factory-muffin-faker": "For Faker support in DataFactory module", "phpseclib/phpseclib": "for SFTP option in FTP Module", + "stecman/symfony-console-completion": "For BASH autocompletion", "symfony/phpunit-bridge": "For phpunit-bridge support" }, "bin": [ @@ -5361,7 +7120,7 @@ }, "autoload": { "psr-4": { - "Codeception\\": "src\\Codeception", + "Codeception\\": "src/Codeception", "Codeception\\Extension\\": "ext" } }, @@ -5385,7 +7144,80 @@ "functional testing", "unit testing" ], - "time": "2017-09-28T23:19:49+00:00" + "time": "2018-10-29T21:23:19+00:00" + }, + { + "name": "codeception/phpunit-wrapper", + "version": "7.1.1", + "source": { + "type": "git", + "url": "https://github.com/Codeception/phpunit-wrapper.git", + "reference": "33e8ccf2f7abf5c031eeae9802b821d30ec0f7fc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Codeception/phpunit-wrapper/zipball/33e8ccf2f7abf5c031eeae9802b821d30ec0f7fc", + "reference": "33e8ccf2f7abf5c031eeae9802b821d30ec0f7fc", + "shasum": "" + }, + "require": { + "phpunit/php-code-coverage": "^6.0", + "phpunit/phpunit": "^7.1", + "sebastian/comparator": "^2.0", + "sebastian/diff": "^3.0" + }, + "require-dev": { + "codeception/specify": "*", + "vlucas/phpdotenv": "^2.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "Codeception\\PHPUnit\\": "src\\" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Davert", + "email": "davert.php@resend.cc" + } + ], + "description": "PHPUnit classes used by Codeception", + "time": "2018-04-20T10:17:13+00:00" + }, + { + "name": "codeception/stub", + "version": "2.0.4", + "source": { + "type": "git", + "url": "https://github.com/Codeception/Stub.git", + "reference": "f50bc271f392a2836ff80690ce0c058efe1ae03e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Codeception/Stub/zipball/f50bc271f392a2836ff80690ce0c058efe1ae03e", + "reference": "f50bc271f392a2836ff80690ce0c058efe1ae03e", + "shasum": "" + }, + "require": { + "phpunit/phpunit": ">=4.8 <8.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Codeception\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Flexible Stub wrapper for PHPUnit's Mock Builder", + "time": "2018-07-26T11:55:37+00:00" }, { "name": "facebook/webdriver", @@ -5447,6 +7279,67 @@ ], "time": "2018-05-16T17:37:13+00:00" }, + { + "name": "filp/whoops", + "version": "2.3.1", + "source": { + "type": "git", + "url": "https://github.com/filp/whoops.git", + "reference": "bc0fd11bc455cc20ee4b5edabc63ebbf859324c7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/filp/whoops/zipball/bc0fd11bc455cc20ee4b5edabc63ebbf859324c7", + "reference": "bc0fd11bc455cc20ee4b5edabc63ebbf859324c7", + "shasum": "" + }, + "require": { + "php": "^5.5.9 || ^7.0", + "psr/log": "^1.0.1" + }, + "require-dev": { + "mockery/mockery": "^0.9 || ^1.0", + "phpunit/phpunit": "^4.8.35 || ^5.7", + "symfony/var-dumper": "^2.6 || ^3.0 || ^4.0" + }, + "suggest": { + "symfony/var-dumper": "Pretty print complex values better with var-dumper available", + "whoops/soap": "Formats errors as SOAP responses" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.2-dev" + } + }, + "autoload": { + "psr-4": { + "Whoops\\": "src/Whoops/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Filipe Dobreira", + "homepage": "https://github.com/filp", + "role": "Developer" + } + ], + "description": "php error handling for cool kids", + "homepage": "https://filp.github.io/whoops/", + "keywords": [ + "error", + "exception", + "handling", + "library", + "throwable", + "whoops" + ], + "time": "2018-10-23T09:00:00+00:00" + }, { "name": "fzaninotto/faker", "version": "v1.8.0", @@ -5498,26 +7391,90 @@ "time": "2018-07-12T10:23:15+00:00" }, { - "name": "myclabs/deep-copy", - "version": "1.7.0", + "name": "maximebf/debugbar", + "version": "v1.15.0", "source": { "type": "git", - "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e" + "url": "https://github.com/maximebf/php-debugbar.git", + "reference": "30e7d60937ee5f1320975ca9bc7bcdd44d500f07" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e", - "reference": "3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e", + "url": "https://api.github.com/repos/maximebf/php-debugbar/zipball/30e7d60937ee5f1320975ca9bc7bcdd44d500f07", + "reference": "30e7d60937ee5f1320975ca9bc7bcdd44d500f07", "shasum": "" }, "require": { - "php": "^5.6 || ^7.0" + "php": ">=5.3.0", + "psr/log": "^1.0", + "symfony/var-dumper": "^2.6|^3.0|^4.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.0|^5.0" + }, + "suggest": { + "kriswallsmith/assetic": "The best way to manage assets", + "monolog/monolog": "Log using Monolog", + "predis/predis": "Redis storage" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.14-dev" + } + }, + "autoload": { + "psr-4": { + "DebugBar\\": "src/DebugBar/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Maxime Bouroumeau-Fuseau", + "email": "maxime.bouroumeau@gmail.com", + "homepage": "http://maximebf.com" + }, + { + "name": "Barry vd. Heuvel", + "email": "barryvdh@gmail.com" + } + ], + "description": "Debug bar in the browser for php application", + "homepage": "https://github.com/maximebf/php-debugbar", + "keywords": [ + "debug", + "debugbar" + ], + "time": "2017-12-15T11:13:46+00:00" + }, + { + "name": "myclabs/deep-copy", + "version": "1.8.1", + "source": { + "type": "git", + "url": "https://github.com/myclabs/DeepCopy.git", + "reference": "3e01bdad3e18354c3dce54466b7fbe33a9f9f7f8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3e01bdad3e18354c3dce54466b7fbe33a9f9f7f8", + "reference": "3e01bdad3e18354c3dce54466b7fbe33a9f9f7f8", + "shasum": "" + }, + "require": { + "php": "^7.1" + }, + "replace": { + "myclabs/deep-copy": "self.version" }, "require-dev": { "doctrine/collections": "^1.0", "doctrine/common": "^2.6", - "phpunit/phpunit": "^4.1" + "phpunit/phpunit": "^7.1" }, "type": "library", "autoload": { @@ -5540,44 +7497,146 @@ "object", "object graph" ], - "time": "2017-10-19T19:58:43+00:00" + "time": "2018-06-11T23:09:50+00:00" }, { - "name": "phpunit/php-code-coverage", - "version": "4.0.8", + "name": "phar-io/manifest", + "version": "1.0.1", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "ef7b2f56815df854e66ceaee8ebe9393ae36a40d" + "url": "https://github.com/phar-io/manifest.git", + "reference": "2df402786ab5368a0169091f61a7c1e0eb6852d0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/ef7b2f56815df854e66ceaee8ebe9393ae36a40d", - "reference": "ef7b2f56815df854e66ceaee8ebe9393ae36a40d", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/2df402786ab5368a0169091f61a7c1e0eb6852d0", + "reference": "2df402786ab5368a0169091f61a7c1e0eb6852d0", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-phar": "*", + "phar-io/version": "^1.0.1", + "php": "^5.6 || ^7.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", + "time": "2017-03-05T18:14:27+00:00" + }, + { + "name": "phar-io/version", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/phar-io/version.git", + "reference": "a70c0ced4be299a63d32fa96d9281d03e94041df" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/version/zipball/a70c0ced4be299a63d32fa96d9281d03e94041df", + "reference": "a70c0ced4be299a63d32fa96d9281d03e94041df", + "shasum": "" + }, + "require": { + "php": "^5.6 || ^7.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Library for handling version information and constraints", + "time": "2017-03-05T17:38:23+00:00" + }, + { + "name": "phpunit/php-code-coverage", + "version": "6.0.5", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "4cab20a326d14de7575a8e235c70d879b569a57a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/4cab20a326d14de7575a8e235c70d879b569a57a", + "reference": "4cab20a326d14de7575a8e235c70d879b569a57a", "shasum": "" }, "require": { "ext-dom": "*", "ext-xmlwriter": "*", - "php": "^5.6 || ^7.0", - "phpunit/php-file-iterator": "^1.3", - "phpunit/php-text-template": "^1.2", - "phpunit/php-token-stream": "^1.4.2 || ^2.0", - "sebastian/code-unit-reverse-lookup": "^1.0", - "sebastian/environment": "^1.3.2 || ^2.0", - "sebastian/version": "^1.0 || ^2.0" + "php": "^7.1", + "phpunit/php-file-iterator": "^1.4.2", + "phpunit/php-text-template": "^1.2.1", + "phpunit/php-token-stream": "^3.0", + "sebastian/code-unit-reverse-lookup": "^1.0.1", + "sebastian/environment": "^3.1", + "sebastian/version": "^2.0.1", + "theseer/tokenizer": "^1.1" }, "require-dev": { - "ext-xdebug": "^2.1.4", - "phpunit/phpunit": "^5.7" + "phpunit/phpunit": "^7.0" }, "suggest": { - "ext-xdebug": "^2.5.1" + "ext-xdebug": "^2.6.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0.x-dev" + "dev-master": "6.0-dev" } }, "autoload": { @@ -5592,7 +7651,7 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", + "email": "sebastian@phpunit.de", "role": "lead" } ], @@ -5603,7 +7662,7 @@ "testing", "xunit" ], - "time": "2017-04-02T07:44:40+00:00" + "time": "2018-05-28T11:49:20+00:00" }, { "name": "phpunit/php-file-iterator", @@ -5695,28 +7754,28 @@ }, { "name": "phpunit/php-timer", - "version": "1.0.9", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f" + "reference": "8b8454ea6958c3dee38453d3bd571e023108c91f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", - "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/8b8454ea6958c3dee38453d3bd571e023108c91f", + "reference": "8b8454ea6958c3dee38453d3bd571e023108c91f", "shasum": "" }, "require": { - "php": "^5.3.3 || ^7.0" + "php": "^7.1" }, "require-dev": { - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" + "phpunit/phpunit": "^7.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0-dev" + "dev-master": "2.0-dev" } }, "autoload": { @@ -5731,7 +7790,7 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", + "email": "sebastian@phpunit.de", "role": "lead" } ], @@ -5740,33 +7799,33 @@ "keywords": [ "timer" ], - "time": "2017-02-26T11:10:40+00:00" + "time": "2018-02-01T13:07:23+00:00" }, { "name": "phpunit/php-token-stream", - "version": "1.4.11", + "version": "3.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "e03f8f67534427a787e21a385a67ec3ca6978ea7" + "reference": "c99e3be9d3e85f60646f152f9002d46ed7770d18" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/e03f8f67534427a787e21a385a67ec3ca6978ea7", - "reference": "e03f8f67534427a787e21a385a67ec3ca6978ea7", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/c99e3be9d3e85f60646f152f9002d46ed7770d18", + "reference": "c99e3be9d3e85f60646f152f9002d46ed7770d18", "shasum": "" }, "require": { "ext-tokenizer": "*", - "php": ">=5.3.3" + "php": "^7.1" }, "require-dev": { - "phpunit/phpunit": "~4.2" + "phpunit/phpunit": "^7.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.4-dev" + "dev-master": "3.0-dev" } }, "autoload": { @@ -5789,20 +7848,20 @@ "keywords": [ "tokenizer" ], - "time": "2017-02-27T10:12:30+00:00" + "time": "2018-10-30T05:52:18+00:00" }, { "name": "phpunit/phpunit", - "version": "5.7.27", + "version": "7.1.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "b7803aeca3ccb99ad0a506fa80b64cd6a56bbc0c" + "reference": "6d51299e307dc510149e0b7cd1931dd11770e1cb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/b7803aeca3ccb99ad0a506fa80b64cd6a56bbc0c", - "reference": "b7803aeca3ccb99ad0a506fa80b64cd6a56bbc0c", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/6d51299e307dc510149e0b7cd1931dd11770e1cb", + "reference": "6d51299e307dc510149e0b7cd1931dd11770e1cb", "shasum": "" }, "require": { @@ -5811,33 +7870,31 @@ "ext-libxml": "*", "ext-mbstring": "*", "ext-xml": "*", - "myclabs/deep-copy": "~1.3", - "php": "^5.6 || ^7.0", - "phpspec/prophecy": "^1.6.2", - "phpunit/php-code-coverage": "^4.0.4", - "phpunit/php-file-iterator": "~1.4", - "phpunit/php-text-template": "~1.2", - "phpunit/php-timer": "^1.0.6", - "phpunit/phpunit-mock-objects": "^3.2", - "sebastian/comparator": "^1.2.4", - "sebastian/diff": "^1.4.3", - "sebastian/environment": "^1.3.4 || ^2.0", - "sebastian/exporter": "~2.0", - "sebastian/global-state": "^1.1", - "sebastian/object-enumerator": "~2.0", - "sebastian/resource-operations": "~1.0", - "sebastian/version": "^1.0.6|^2.0.1", - "symfony/yaml": "~2.1|~3.0|~4.0" - }, - "conflict": { - "phpdocumentor/reflection-docblock": "3.0.2" + "myclabs/deep-copy": "^1.6.1", + "phar-io/manifest": "^1.0.1", + "phar-io/version": "^1.0", + "php": "^7.1", + "phpspec/prophecy": "^1.7", + "phpunit/php-code-coverage": "^6.0.1", + "phpunit/php-file-iterator": "^1.4.3", + "phpunit/php-text-template": "^1.2.1", + "phpunit/php-timer": "^2.0", + "phpunit/phpunit-mock-objects": "^6.1.1", + "sebastian/comparator": "^2.1 || ^3.0", + "sebastian/diff": "^3.0", + "sebastian/environment": "^3.1", + "sebastian/exporter": "^3.1", + "sebastian/global-state": "^2.0", + "sebastian/object-enumerator": "^3.0.3", + "sebastian/resource-operations": "^1.0", + "sebastian/version": "^2.0.1" }, "require-dev": { "ext-pdo": "*" }, "suggest": { "ext-xdebug": "*", - "phpunit/php-invoker": "~1.1" + "phpunit/php-invoker": "^2.0" }, "bin": [ "phpunit" @@ -5845,7 +7902,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "5.7.x-dev" + "dev-master": "7.1-dev" } }, "autoload": { @@ -5871,33 +7928,30 @@ "testing", "xunit" ], - "time": "2018-02-01T05:50:59+00:00" + "time": "2018-04-18T13:41:53+00:00" }, { "name": "phpunit/phpunit-mock-objects", - "version": "3.4.4", + "version": "6.1.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", - "reference": "a23b761686d50a560cc56233b9ecf49597cc9118" + "reference": "f9756fd4f43f014cb2dca98deeaaa8ce5500a36e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/a23b761686d50a560cc56233b9ecf49597cc9118", - "reference": "a23b761686d50a560cc56233b9ecf49597cc9118", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/f9756fd4f43f014cb2dca98deeaaa8ce5500a36e", + "reference": "f9756fd4f43f014cb2dca98deeaaa8ce5500a36e", "shasum": "" }, "require": { - "doctrine/instantiator": "^1.0.2", - "php": "^5.6 || ^7.0", - "phpunit/php-text-template": "^1.2", - "sebastian/exporter": "^1.2 || ^2.0" - }, - "conflict": { - "phpunit/phpunit": "<5.4.0" + "doctrine/instantiator": "^1.0.5", + "php": "^7.1", + "phpunit/php-text-template": "^1.2.1", + "sebastian/exporter": "^3.1" }, "require-dev": { - "phpunit/phpunit": "^5.4" + "phpunit/phpunit": "^7.0" }, "suggest": { "ext-soap": "*" @@ -5905,7 +7959,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.2.x-dev" + "dev-master": "6.1-dev" } }, "autoload": { @@ -5920,7 +7974,7 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", + "email": "sebastian@phpunit.de", "role": "lead" } ], @@ -5930,7 +7984,208 @@ "mock", "xunit" ], - "time": "2017-06-30T09:13:00+00:00" + "time": "2018-05-29T13:54:20+00:00" + }, + { + "name": "roave/security-advisories", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/Roave/SecurityAdvisories.git", + "reference": "9fd088ff8176ceb154c7d3cc0d1241af80e5c93e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/9fd088ff8176ceb154c7d3cc0d1241af80e5c93e", + "reference": "9fd088ff8176ceb154c7d3cc0d1241af80e5c93e", + "shasum": "" + }, + "conflict": { + "3f/pygmentize": "<1.2", + "adodb/adodb-php": "<5.20.12", + "alterphp/easyadmin-extension-bundle": ">=1.2,<1.2.11|>=1.3,<1.3.1", + "amphp/artax": "<1.0.6|>=2,<2.0.6", + "amphp/http": "<1.0.1", + "asymmetricrypt/asymmetricrypt": ">=0,<9.9.99", + "aws/aws-sdk-php": ">=3,<3.2.1", + "brightlocal/phpwhois": "<=4.2.5", + "bugsnag/bugsnag-laravel": ">=2,<2.0.2", + "cakephp/cakephp": ">=1.3,<1.3.18|>=2,<2.4.99|>=2.5,<2.5.99|>=2.6,<2.6.12|>=2.7,<2.7.6|>=3,<3.0.15|>=3.1,<3.1.4|>=3.4,<3.4.14|>=3.5,<3.5.17|>=3.6,<3.6.4", + "cart2quote/module-quotation": ">=4.1.6,<=4.4.5|>=5,<5.4.4", + "cartalyst/sentry": "<=2.1.6", + "codeigniter/framework": "<=3.0.6", + "composer/composer": "<=1.0.0-alpha11", + "contao-components/mediaelement": ">=2.14.2,<2.21.1", + "contao/core": ">=2,<3.5.35", + "contao/core-bundle": ">=4,<4.4.18|>=4.5,<4.5.8", + "contao/listing-bundle": ">=4,<4.4.8", + "contao/newsletter-bundle": ">=4,<4.1", + "david-garcia/phpwhois": "<=4.3.1", + "doctrine/annotations": ">=1,<1.2.7", + "doctrine/cache": ">=1,<1.3.2|>=1.4,<1.4.2", + "doctrine/common": ">=2,<2.4.3|>=2.5,<2.5.1", + "doctrine/dbal": ">=2,<2.0.8|>=2.1,<2.1.2", + "doctrine/doctrine-bundle": "<1.5.2", + "doctrine/doctrine-module": "<=0.7.1", + "doctrine/mongodb-odm": ">=1,<1.0.2", + "doctrine/mongodb-odm-bundle": ">=2,<3.0.1", + "doctrine/orm": ">=2,<2.4.8|>=2.5,<2.5.1", + "dompdf/dompdf": ">=0.6,<0.6.2", + "drupal/core": ">=7,<7.60|>=8,<8.5.8|>=8.6,<8.6.2", + "drupal/drupal": ">=7,<7.60|>=8,<8.5.8|>=8.6,<8.6.2", + "erusev/parsedown": "<1.7", + "ezsystems/ezplatform": "<1.7.8.1|>=1.8,<1.13.4.1|>=2,<2.2.3.1|>=2.3,<2.3.2.1", + "ezsystems/ezpublish-kernel": ">=5.3,<5.3.12.1|>=5.4,<5.4.13.1|>=6,<6.7.9.1|>=6.8,<6.13.5.1|>=7,<7.2.4.1|>=7.3,<7.3.2.1", + "ezsystems/ezpublish-legacy": ">=5.3,<5.3.12.6|>=5.4,<5.4.12.3|>=2011,<2017.12.4.3|>=2018.6,<2018.6.1.4|>=2018.9,<2018.9.1.3", + "ezsystems/repository-forms": ">=2.3,<2.3.2.1", + "ezyang/htmlpurifier": "<4.1.1", + "firebase/php-jwt": "<2", + "fooman/tcpdf": "<6.2.22", + "fossar/tcpdf-parser": "<6.2.22", + "friendsofsymfony/rest-bundle": ">=1.2,<1.2.2", + "friendsofsymfony/user-bundle": ">=1.2,<1.3.5", + "fuel/core": "<1.8.1", + "gree/jose": "<=2.2", + "gregwar/rst": "<1.0.3", + "guzzlehttp/guzzle": ">=6,<6.2.1|>=4.0.0-rc2,<4.2.4|>=5,<5.3.1", + "illuminate/auth": ">=4,<4.0.99|>=4.1,<=4.1.31|>=4.2,<=4.2.22|>=5,<=5.0.35|>=5.1,<=5.1.46|>=5.2,<=5.2.45|>=5.3,<=5.3.31|>=5.4,<=5.4.36|>=5.5,<5.5.10", + "illuminate/cookie": ">=4,<=4.0.11|>=4.1,<=4.1.31|>=4.2,<=4.2.22|>=5,<=5.0.35|>=5.1,<=5.1.46|>=5.2,<=5.2.45|>=5.3,<=5.3.31|>=5.4,<=5.4.36|>=5.5,<5.5.42|>=5.6,<5.6.30", + "illuminate/database": ">=4,<4.0.99|>=4.1,<4.1.29", + "illuminate/encryption": ">=4,<=4.0.11|>=4.1,<=4.1.31|>=4.2,<=4.2.22|>=5,<=5.0.35|>=5.1,<=5.1.46|>=5.2,<=5.2.45|>=5.3,<=5.3.31|>=5.4,<=5.4.36|>=5.5,<5.5.40|>=5.6,<5.6.15", + "ivankristianto/phpwhois": "<=4.3", + "james-heinrich/getid3": "<1.9.9", + "joomla/session": "<1.3.1", + "jsmitty12/phpwhois": "<5.1", + "kazist/phpwhois": "<=4.2.6", + "kreait/firebase-php": ">=3.2,<3.8.1", + "la-haute-societe/tcpdf": "<6.2.22", + "laravel/framework": ">=4,<4.0.99|>=4.1,<=4.1.31|>=4.2,<=4.2.22|>=5,<=5.0.35|>=5.1,<=5.1.46|>=5.2,<=5.2.45|>=5.3,<=5.3.31|>=5.4,<=5.4.36|>=5.5,<5.5.42|>=5.6,<5.6.30", + "laravel/socialite": ">=1,<1.0.99|>=2,<2.0.10", + "magento/magento1ce": "<1.9.4", + "magento/magento1ee": ">=1.9,<1.14.4", + "magento/product-community-edition": ">=2,<2.2.7", + "monolog/monolog": ">=1.8,<1.12", + "namshi/jose": "<2.2", + "onelogin/php-saml": "<2.10.4", + "openid/php-openid": "<2.3", + "oro/crm": ">=1.7,<1.7.4", + "oro/platform": ">=1.7,<1.7.4", + "padraic/humbug_get_contents": "<1.1.2", + "pagarme/pagarme-php": ">=0,<3", + "paragonie/random_compat": "<2", + "paypal/merchant-sdk-php": "<3.12", + "phpmailer/phpmailer": ">=5,<5.2.27|>=6,<6.0.6", + "phpoffice/phpexcel": "<=1.8.1", + "phpoffice/phpspreadsheet": "<=1.5", + "phpunit/phpunit": ">=4.8.19,<4.8.28|>=5.0.10,<5.6.3", + "phpwhois/phpwhois": "<=4.2.5", + "phpxmlrpc/extras": "<0.6.1", + "propel/propel": ">=2.0.0-alpha1,<=2.0.0-alpha7", + "propel/propel1": ">=1,<=1.7.1", + "pusher/pusher-php-server": "<2.2.1", + "robrichards/xmlseclibs": ">=1,<3.0.2", + "sabre/dav": ">=1.6,<1.6.99|>=1.7,<1.7.11|>=1.8,<1.8.9", + "sensiolabs/connect": "<4.2.3", + "serluck/phpwhois": "<=4.2.6", + "shopware/shopware": "<5.3.7", + "silverstripe/cms": ">=3,<=3.0.11|>=3.1,<3.1.11", + "silverstripe/forum": "<=0.6.1|>=0.7,<=0.7.3", + "silverstripe/framework": ">=3,<3.3", + "silverstripe/userforms": "<3", + "simple-updates/phpwhois": "<=1", + "simplesamlphp/saml2": "<1.10.6|>=2,<2.3.8|>=3,<3.1.4", + "simplesamlphp/simplesamlphp": "<1.15.2", + "simplesamlphp/simplesamlphp-module-infocard": "<1.0.1", + "slim/slim": "<2.6", + "smarty/smarty": "<3.1.33", + "socalnick/scn-social-auth": "<1.15.2", + "spoonity/tcpdf": "<6.2.22", + "squizlabs/php_codesniffer": ">=1,<2.8.1|>=3,<3.0.1", + "stormpath/sdk": ">=0,<9.9.99", + "swiftmailer/swiftmailer": ">=4,<5.4.5", + "sylius/admin-bundle": ">=1,<1.0.17|>=1.1,<1.1.9|>=1.2,<1.2.2", + "sylius/sylius": ">=1,<1.0.17|>=1.1,<1.1.9|>=1.2,<1.2.2", + "symfony/dependency-injection": ">=2,<2.0.17", + "symfony/form": ">=2.3,<2.3.35|>=2.4,<2.6.12|>=2.7,<2.7.50|>=2.8,<2.8.49|>=3,<3.4.20|>=4,<4.0.15|>=4.1,<4.1.9|>=4.2,<4.2.1", + "symfony/framework-bundle": ">=2,<2.3.18|>=2.4,<2.4.8|>=2.5,<2.5.2", + "symfony/http-foundation": ">=2,<2.7.49|>=2.8,<2.8.44|>=3,<3.3.18|>=3.4,<3.4.14|>=4,<4.0.14|>=4.1,<4.1.3", + "symfony/http-kernel": ">=2,<2.3.29|>=2.4,<2.5.12|>=2.6,<2.6.8", + "symfony/intl": ">=2.7,<2.7.38|>=2.8,<2.8.31|>=3,<3.2.14|>=3.3,<3.3.13", + "symfony/polyfill": ">=1,<1.10", + "symfony/polyfill-php55": ">=1,<1.10", + "symfony/routing": ">=2,<2.0.19", + "symfony/security": ">=2,<2.7.50|>=2.8,<2.8.49|>=3,<3.4.19|>=4,<4.0.15|>=4.1,<4.1.9|>=4.2,<4.2.1", + "symfony/security-bundle": ">=2,<2.7.48|>=2.8,<2.8.41|>=3,<3.3.17|>=3.4,<3.4.11|>=4,<4.0.11", + "symfony/security-core": ">=2.4,<2.6.13|>=2.7,<2.7.9|>=2.7.30,<2.7.32|>=2.8,<2.8.37|>=3,<3.3.17|>=3.4,<3.4.7|>=4,<4.0.7", + "symfony/security-csrf": ">=2.4,<2.7.48|>=2.8,<2.8.41|>=3,<3.3.17|>=3.4,<3.4.11|>=4,<4.0.11", + "symfony/security-guard": ">=2.8,<2.8.41|>=3,<3.3.17|>=3.4,<3.4.11|>=4,<4.0.11", + "symfony/security-http": ">=2.3,<2.3.41|>=2.4,<2.7.50|>=2.8,<2.8.49|>=3,<3.4.20|>=4,<4.0.15|>=4.1,<4.1.9|>=4.2,<4.2.1", + "symfony/serializer": ">=2,<2.0.11", + "symfony/symfony": ">=2,<2.7.50|>=2.8,<2.8.49|>=3,<3.4.20|>=4,<4.0.15|>=4.1,<4.1.9|>=4.2,<4.2.1", + "symfony/translation": ">=2,<2.0.17", + "symfony/validator": ">=2,<2.0.24|>=2.1,<2.1.12|>=2.2,<2.2.5|>=2.3,<2.3.3", + "symfony/web-profiler-bundle": ">=2,<2.3.19|>=2.4,<2.4.9|>=2.5,<2.5.4", + "symfony/yaml": ">=2,<2.0.22|>=2.1,<2.1.7", + "tecnickcom/tcpdf": "<6.2.22", + "thelia/backoffice-default-template": ">=2.1,<2.1.2", + "thelia/thelia": ">=2.1.0-beta1,<2.1.3|>=2.1,<2.1.2", + "theonedemon/phpwhois": "<=4.2.5", + "titon/framework": ">=0,<9.9.99", + "truckersmp/phpwhois": "<=4.3.1", + "twig/twig": "<1.20", + "typo3/cms": ">=6.2,<6.2.30|>=7,<7.6.32|>=8,<8.7.21|>=9,<9.5.2", + "typo3/cms-core": ">=8,<8.7.21|>=9,<9.5.2", + "typo3/flow": ">=1,<1.0.4|>=1.1,<1.1.1|>=2,<2.0.1|>=2.3,<2.3.16|>=3,<3.0.10|>=3.1,<3.1.7|>=3.2,<3.2.7|>=3.3,<3.3.5", + "typo3/neos": ">=1.1,<1.1.3|>=1.2,<1.2.13|>=2,<2.0.4", + "wallabag/tcpdf": "<6.2.22", + "willdurand/js-translation-bundle": "<2.1.1", + "yiisoft/yii": ">=1.1.14,<1.1.15", + "yiisoft/yii2": "<2.0.15", + "yiisoft/yii2-bootstrap": "<2.0.4", + "yiisoft/yii2-dev": "<2.0.15", + "yiisoft/yii2-elasticsearch": "<2.0.5", + "yiisoft/yii2-gii": "<2.0.4", + "yiisoft/yii2-jui": "<2.0.4", + "yiisoft/yii2-redis": "<2.0.8", + "zendframework/zend-cache": ">=2.4,<2.4.8|>=2.5,<2.5.3", + "zendframework/zend-captcha": ">=2,<2.4.9|>=2.5,<2.5.2", + "zendframework/zend-crypt": ">=2,<2.4.9|>=2.5,<2.5.2", + "zendframework/zend-db": ">=2,<2.0.99|>=2.1,<2.1.99|>=2.2,<2.2.10|>=2.3,<2.3.5", + "zendframework/zend-diactoros": ">=1,<1.8.4", + "zendframework/zend-feed": ">=1,<2.10.3", + "zendframework/zend-form": ">=2,<2.2.7|>=2.3,<2.3.1", + "zendframework/zend-http": ">=1,<2.8.1", + "zendframework/zend-json": ">=2.1,<2.1.6|>=2.2,<2.2.6", + "zendframework/zend-ldap": ">=2,<2.0.99|>=2.1,<2.1.99|>=2.2,<2.2.8|>=2.3,<2.3.3", + "zendframework/zend-mail": ">=2,<2.4.11|>=2.5,<2.7.2", + "zendframework/zend-navigation": ">=2,<2.2.7|>=2.3,<2.3.1", + "zendframework/zend-session": ">=2,<2.0.99|>=2.1,<2.1.99|>=2.2,<2.2.9|>=2.3,<2.3.4", + "zendframework/zend-validator": ">=2.3,<2.3.6", + "zendframework/zend-view": ">=2,<2.2.7|>=2.3,<2.3.1", + "zendframework/zend-xmlrpc": ">=2.1,<2.1.6|>=2.2,<2.2.6", + "zendframework/zendframework": "<2.5.1", + "zendframework/zendframework1": "<1.12.20", + "zendframework/zendopenid": ">=2,<2.0.2", + "zendframework/zendxml": ">=1,<1.0.1", + "zetacomponents/mail": "<1.8.2", + "zf-commons/zfc-user": "<1.2.2", + "zfcampus/zf-apigility-doctrine": ">=1,<1.0.3", + "zfr/zfr-oauth2-server-module": "<0.1.2" + }, + "type": "metapackage", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com", + "role": "maintainer" + } + ], + "description": "Prevents installation of composer packages with known security vulnerabilities: no API, simply require it", + "time": "2018-12-11T16:56:18+00:00" }, { "name": "sebastian/code-unit-reverse-lookup", @@ -5979,28 +8234,28 @@ }, { "name": "sebastian/environment", - "version": "2.0.0", + "version": "3.1.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "5795ffe5dc5b02460c3e34222fee8cbe245d8fac" + "reference": "cd0871b3975fb7fc44d11314fd1ee20925fce4f5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/5795ffe5dc5b02460c3e34222fee8cbe245d8fac", - "reference": "5795ffe5dc5b02460c3e34222fee8cbe245d8fac", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/cd0871b3975fb7fc44d11314fd1ee20925fce4f5", + "reference": "cd0871b3975fb7fc44d11314fd1ee20925fce4f5", "shasum": "" }, "require": { - "php": "^5.6 || ^7.0" + "php": "^7.0" }, "require-dev": { - "phpunit/phpunit": "^5.0" + "phpunit/phpunit": "^6.1" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0.x-dev" + "dev-master": "3.1.x-dev" } }, "autoload": { @@ -6025,27 +8280,27 @@ "environment", "hhvm" ], - "time": "2016-11-26T07:53:53+00:00" + "time": "2017-07-01T08:51:00+00:00" }, { "name": "sebastian/global-state", - "version": "1.1.1", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4" + "reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bc37d50fea7d017d3d340f230811c9f1d7280af4", - "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4", + "reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": "^7.0" }, "require-dev": { - "phpunit/phpunit": "~4.2" + "phpunit/phpunit": "^6.0" }, "suggest": { "ext-uopz": "*" @@ -6053,7 +8308,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0-dev" + "dev-master": "2.0-dev" } }, "autoload": { @@ -6076,33 +8331,34 @@ "keywords": [ "global state" ], - "time": "2015-10-12T03:26:01+00:00" + "time": "2017-04-27T15:39:26+00:00" }, { "name": "sebastian/object-enumerator", - "version": "2.0.1", + "version": "3.0.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/object-enumerator.git", - "reference": "1311872ac850040a79c3c058bea3e22d0f09cbb7" + "reference": "7cfd9e65d11ffb5af41198476395774d4c8a84c5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/1311872ac850040a79c3c058bea3e22d0f09cbb7", - "reference": "1311872ac850040a79c3c058bea3e22d0f09cbb7", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/7cfd9e65d11ffb5af41198476395774d4c8a84c5", + "reference": "7cfd9e65d11ffb5af41198476395774d4c8a84c5", "shasum": "" }, "require": { - "php": ">=5.6", - "sebastian/recursion-context": "~2.0" + "php": "^7.0", + "sebastian/object-reflector": "^1.1.1", + "sebastian/recursion-context": "^3.0" }, "require-dev": { - "phpunit/phpunit": "~5" + "phpunit/phpunit": "^6.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0.x-dev" + "dev-master": "3.0.x-dev" } }, "autoload": { @@ -6122,7 +8378,52 @@ ], "description": "Traverses array structures and object graphs to enumerate all referenced objects", "homepage": "https://github.com/sebastianbergmann/object-enumerator/", - "time": "2017-02-18T15:18:39+00:00" + "time": "2017-08-03T12:35:26+00:00" + }, + { + "name": "sebastian/object-reflector", + "version": "1.1.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-reflector.git", + "reference": "773f97c67f28de00d397be301821b06708fca0be" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/773f97c67f28de00d397be301821b06708fca0be", + "reference": "773f97c67f28de00d397be301821b06708fca0be", + "shasum": "" + }, + "require": { + "php": "^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Allows reflection of object attributes, including inherited and non-public ones", + "homepage": "https://github.com/sebastianbergmann/object-reflector/", + "time": "2017-03-29T09:07:27+00:00" }, { "name": "sebastian/resource-operations", @@ -6260,72 +8561,27 @@ ], "time": "2018-09-23T23:08:17+00:00" }, - { - "name": "stecman/symfony-console-completion", - "version": "0.7.0", - "source": { - "type": "git", - "url": "https://github.com/stecman/symfony-console-completion.git", - "reference": "5461d43e53092b3d3b9dbd9d999f2054730f4bbb" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/stecman/symfony-console-completion/zipball/5461d43e53092b3d3b9dbd9d999f2054730f4bbb", - "reference": "5461d43e53092b3d3b9dbd9d999f2054730f4bbb", - "shasum": "" - }, - "require": { - "php": ">=5.3.2", - "symfony/console": "~2.3 || ~3.0" - }, - "require-dev": { - "phpunit/phpunit": "~4.4" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "0.6.x-dev" - } - }, - "autoload": { - "psr-4": { - "Stecman\\Component\\Symfony\\Console\\BashCompletion\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Stephen Holdaway", - "email": "stephen@stecman.co.nz" - } - ], - "description": "Automatic BASH completion for Symfony Console Component based applications.", - "time": "2016-02-24T05:08:54+00:00" - }, { "name": "symfony/browser-kit", - "version": "v3.4.17", + "version": "v4.2.1", "source": { "type": "git", "url": "https://github.com/symfony/browser-kit.git", - "reference": "f6668d1a6182d5a8dec65a1c863a4c1d963816c0" + "reference": "db7e59fec9c82d45e745eb500e6ede2d96f4a6e9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/browser-kit/zipball/f6668d1a6182d5a8dec65a1c863a4c1d963816c0", - "reference": "f6668d1a6182d5a8dec65a1c863a4c1d963816c0", + "url": "https://api.github.com/repos/symfony/browser-kit/zipball/db7e59fec9c82d45e745eb500e6ede2d96f4a6e9", + "reference": "db7e59fec9c82d45e745eb500e6ede2d96f4a6e9", "shasum": "" }, "require": { - "php": "^5.5.9|>=7.0.8", - "symfony/dom-crawler": "~2.8|~3.0|~4.0" + "php": "^7.1.3", + "symfony/dom-crawler": "~3.4|~4.0" }, "require-dev": { - "symfony/css-selector": "~2.8|~3.0|~4.0", - "symfony/process": "~2.8|~3.0|~4.0" + "symfony/css-selector": "~3.4|~4.0", + "symfony/process": "~3.4|~4.0" }, "suggest": { "symfony/process": "" @@ -6333,7 +8589,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-master": "4.2-dev" } }, "autoload": { @@ -6360,28 +8616,29 @@ ], "description": "Symfony BrowserKit Component", "homepage": "https://symfony.com", - "time": "2018-07-26T09:06:28+00:00" + "time": "2018-11-26T11:49:31+00:00" }, { "name": "symfony/dom-crawler", - "version": "v3.1.10", + "version": "v4.0.15", "source": { "type": "git", "url": "https://github.com/symfony/dom-crawler.git", - "reference": "7eede2a901a19928494194f7d1815a77b9a473a0" + "reference": "d370b259c534414fff0be798618235b7f563b26f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/7eede2a901a19928494194f7d1815a77b9a473a0", - "reference": "7eede2a901a19928494194f7d1815a77b9a473a0", + "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/d370b259c534414fff0be798618235b7f563b26f", + "reference": "d370b259c534414fff0be798618235b7f563b26f", "shasum": "" }, "require": { - "php": ">=5.5.9", + "php": "^7.1.3", + "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-mbstring": "~1.0" }, "require-dev": { - "symfony/css-selector": "~2.8|~3.0" + "symfony/css-selector": "~3.4|~4.0" }, "suggest": { "symfony/css-selector": "" @@ -6389,7 +8646,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.1-dev" + "dev-master": "4.0-dev" } }, "autoload": { @@ -6416,24 +8673,24 @@ ], "description": "Symfony DomCrawler Component", "homepage": "https://symfony.com", - "time": "2017-01-21T17:13:55+00:00" + "time": "2018-07-26T11:00:39+00:00" }, { "name": "symfony/yaml", - "version": "v3.4.17", + "version": "v4.2.1", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "640b6c27fed4066d64b64d5903a86043f4a4de7f" + "reference": "c41175c801e3edfda90f32e292619d10c27103d7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/640b6c27fed4066d64b64d5903a86043f4a4de7f", - "reference": "640b6c27fed4066d64b64d5903a86043f4a4de7f", + "url": "https://api.github.com/repos/symfony/yaml/zipball/c41175c801e3edfda90f32e292619d10c27103d7", + "reference": "c41175c801e3edfda90f32e292619d10c27103d7", "shasum": "" }, "require": { - "php": "^5.5.9|>=7.0.8", + "php": "^7.1.3", "symfony/polyfill-ctype": "~1.8" }, "conflict": { @@ -6448,7 +8705,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-master": "4.2-dev" } }, "autoload": { @@ -6475,19 +8732,61 @@ ], "description": "Symfony Yaml Component", "homepage": "https://symfony.com", - "time": "2018-10-02T16:33:53+00:00" + "time": "2018-11-11T19:52:12+00:00" + }, + { + "name": "theseer/tokenizer", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/theseer/tokenizer.git", + "reference": "cb2f008f3f05af2893a87208fe6a6c4985483f8b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/cb2f008f3f05af2893a87208fe6a6c4985483f8b", + "reference": "cb2f008f3f05af2893a87208fe6a6c4985483f8b", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": "^7.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + } + ], + "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", + "time": "2017-04-07T12:08:54+00:00" } ], "aliases": [], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": { + "roave/security-advisories": 20 + }, "prefer-stable": false, "prefer-lowest": false, "platform": { - "php": ">=5.6.4" + "php": ">=7.1.3" }, "platform-dev": [], "platform-overrides": { - "php": "5.6.4" + "php": "7.1.3" } } diff --git a/config/app.php b/config/app.php index 73091160c5..bad512be5f 100755 --- a/config/app.php +++ b/config/app.php @@ -117,54 +117,6 @@ return [ 'cipher' => env('APP_CIPHER', 'AES-256-CBC'), - /* - |-------------------------------------------------------------------------- - | Logging Configuration - |-------------------------------------------------------------------------- - | - | Here you may configure the log settings for your application. Out of - | the box, Laravel uses the Monolog PHP logging library. This gives - | you a variety of powerful log handlers / formatters to utilize. - | - | Available Settings: "single", "daily", "syslog", "errorlog" - | - */ - - 'log' => env('APP_LOG', 'single'), - - /* - |-------------------------------------------------------------------------- - | Logging Max Files - |-------------------------------------------------------------------------- - | - | When using the daily log mode, Laravel will only retain 5 - | days of log files by default. - | - | To change this, set the APP_LOG_MAX_FILES option in your .env. - | - */ - - 'log_max_files' => env('APP_LOG_MAX_FILES', 5), - - /* - |-------------------------------------------------------------------------- - | Logging Detail - |-------------------------------------------------------------------------- - | - | By default, Laravel writes all log levels to storage. However, in your - | production environment, you may wish to configure the minimum severity that - | should be logged by editing your APP_LOG_LEVEL env config. - | - | Laravel will log all levels greater than or equal to the specified severity. - | For example, a default log_level of error will log error, critical, alert, - | and emergency messages. - | - | APP_LOG_LEVEL options are: - | "debug", "info", "notice", "warning", "error", "critical", "alert", "emergency" - | - */ - - 'log_level' => env('APP_LOG_LEVEL', 'error'), /* @@ -243,6 +195,18 @@ return [ 'lock_passwords' => env('APP_LOCKED', false), + /* + |-------------------------------------------------------------------------- + | Minimum PHP version + |-------------------------------------------------------------------------- + | + | Do not change this variable. + | + */ + + 'min_php' => '7.1.3', + + /* |-------------------------------------------------------------------------- | Autoloaded Service Providers @@ -286,12 +250,12 @@ return [ * Package Service Providers... */ - Barryvdh\Debugbar\ServiceProvider::class, + // Barryvdh\Debugbar\ServiceProvider::class, // should be auto-discovered Intervention\Image\ImageServiceProvider::class, Collective\Html\HtmlServiceProvider::class, Spatie\Backup\BackupServiceProvider::class, Fideloper\Proxy\TrustedProxyServiceProvider::class, - PragmaRX\Google2FA\Vendor\Laravel\ServiceProvider::class, + PragmaRX\Google2FALaravel\ServiceProvider::class, Laravel\Passport\PassportServiceProvider::class, Laravel\Tinker\TinkerServiceProvider::class, Unicodeveloper\DumbPassword\DumbPasswordServiceProvider::class, @@ -314,6 +278,7 @@ return [ * Custom service provider */ App\Providers\MacroServiceProvider::class, + App\Providers\LdapServiceProvider::class, ], @@ -366,8 +331,8 @@ return [ 'Input' => Illuminate\Support\Facades\Input::class, 'Form' => Collective\Html\FormFacade::class, 'Html' => Collective\Html\HtmlFacade::class, - 'Google2FA' => PragmaRX\Google2FA\Vendor\Laravel\Facade::class, - 'Debugbar' => Barryvdh\Debugbar\Facade::class, + 'Google2FA' => PragmaRX\Google2FALaravel\Facade::class, + // 'Debugbar' => Barryvdh\Debugbar\Facade::class, //autodiscover should handle this 'Image' => Intervention\Image\ImageManagerStatic::class, 'Carbon' => Carbon\Carbon::class, diff --git a/config/backup.php b/config/backup.php new file mode 100644 index 0000000000..898f467ff2 --- /dev/null +++ b/config/backup.php @@ -0,0 +1,189 @@ + [ + + /* + * I don't know why they call it name - it's used in the path for uploads + */ + 'name' => 'backups', + + 'source' => [ + + 'files' => [ + + /* + * The list of directories and files that will be included in the backup. + */ + 'include' => [ + storage_path('oauth-private.key'), + storage_path('oauth-public.key'), + (env('BACKUP_ENV')=='true') ? base_path('.env') : base_path('.env.example'), + + ], + + /* + * These directories and files will be excluded from the backup. + * + * Directories used by the backup process will automatically be excluded. + */ + 'exclude' => [ + // base_path('vendor'), + // base_path('node_modules'), + ], + + /* + * Determines if symlinks should be followed. + */ + 'followLinks' => false, + ], + + /* + * The names of the connections to the databases that should be backed up + * MySQL, PostgreSQL, SQLite and Mongo databases are supported. + */ + 'databases' => [ + 'mysql', + ], + ], + + /* + * The database dump can be gzipped to decrease diskspace usage. + */ + 'gzip_database_dump' => true, + + 'destination' => [ + + /* + * The filename prefix used for the backup zip file. + */ + 'filename_prefix' => 'snipe-it-backup-', + + /* + * The disk names on which the backups will be stored. + */ + 'disks' => [ + env('FILESYSTEM_DISK'), + ], + ], + ], + + /* + * You can get notified when specific events occur. Out of the box you can use 'mail' and 'slack'. + * For Slack you need to install guzzlehttp/guzzle. + * + * You can also use your own notification classes, just make sure the class is named after one of + * the `Spatie\Backup\Events` classes. + */ + 'notifications' => [ + + 'notifications' => [ + \Spatie\Backup\Notifications\Notifications\BackupHasFailed::class => ['mail'], + \Spatie\Backup\Notifications\Notifications\UnhealthyBackupWasFound::class => ['mail'], + \Spatie\Backup\Notifications\Notifications\CleanupHasFailed::class => ['mail'], + \Spatie\Backup\Notifications\Notifications\BackupWasSuccessful::class => ['mail'], + \Spatie\Backup\Notifications\Notifications\HealthyBackupWasFound::class => ['mail'], + \Spatie\Backup\Notifications\Notifications\CleanupWasSuccessful::class => ['mail'], + ], + + /* + * Here you can specify the notifiable to which the notifications should be sent. The default + * notifiable will use the variables specified in this config file. + */ + 'notifiable' => \Spatie\Backup\Notifications\Notifiable::class, + + 'mail' => [ + 'to' => null, + ], + + 'slack' => [ + 'webhook_url' => '', + + /* + * If this is set to null the default channel of the webhook will be used. + */ + 'channel' => null, + ], + ], + + /* + * Here you can specify which backups should be monitored. + * If a backup does not meet the specified requirements the + * UnHealthyBackupWasFound event will be fired. + */ + 'monitorBackups' => [ + [ + 'name' => env('APP_NAME'), + 'disks' => ['local'], + 'newestBackupsShouldNotBeOlderThanDays' => 1, + 'storageUsedMayNotBeHigherThanMegabytes' => 5000, + ], + + /* + [ + 'name' => 'name of the second app', + 'disks' => ['local', 's3'], + 'newestBackupsShouldNotBeOlderThanDays' => 1, + 'storageUsedMayNotBeHigherThanMegabytes' => 5000, + ], + */ + ], + + 'cleanup' => [ + /* + * The strategy that will be used to cleanup old backups. The default strategy + * will keep all backups for a certain amount of days. After that period only + * a daily backup will be kept. After that period only weekly backups will + * be kept and so on. + * + * No matter how you configure it the default strategy will never + * delete the newest backup. + */ + 'strategy' => \Spatie\Backup\Tasks\Cleanup\Strategies\DefaultStrategy::class, + + 'defaultStrategy' => [ + + /* + * The number of days for which backups must be kept. + */ + 'keepAllBackupsForDays' => 7, + + /* + * The number of days for which daily backups must be kept. + */ + 'keepDailyBackupsForDays' => 16, + + /* + * The number of weeks for which one weekly backup must be kept. + */ + 'keepWeeklyBackupsForWeeks' => 8, + + /* + * The number of months for which one monthly backup must be kept. + */ + 'keepMonthlyBackupsForMonths' => 4, + + /* + * The number of years for which one yearly backup must be kept. + */ + 'keepYearlyBackupsForYears' => 2, + + /* + * After cleaning up the backups remove the oldest backup until + * this amount of megabytes has been reached. + */ + 'deleteOldestBackupsWhenUsingMoreMegabytesThan' => 5000, + ], + ], +]; + diff --git a/config/database.php b/config/database.php index 183d30cf5e..5ae449e758 100755 --- a/config/database.php +++ b/config/database.php @@ -80,7 +80,12 @@ return [ 'strict' => false, 'engine' => 'InnoDB', 'unix_socket' => env('DB_SOCKET',''), - 'dump_command_path' => env('DB_DUMP_PATH', '/usr/local/bin'), // only the path, so without 'mysqldump' + 'dump' => [ + 'dump_binary_path' => env('DB_DUMP_PATH', '/usr/local/bin'), // only the path, so without 'mysqldump' + 'use_single_transaction' => false, + 'timeout' => 60 * 5, // 5 minute timeout + ], + 'dump_command_timeout' => 60 * 5, // 5 minute timeout 'dump_using_single_transaction' => true, // perform dump using a single transaction 'options' => (env('DB_SSL')) ? [ diff --git a/config/filesystems.php b/config/filesystems.php index 568fd1e4ab..c894b6239d 100644 --- a/config/filesystems.php +++ b/config/filesystems.php @@ -1,15 +1,6 @@ 's3', + 'cloud' => env('FILESYSTEM_CLOUD', 's3'), /* |-------------------------------------------------------------------------- @@ -48,47 +37,54 @@ return [ | may even configure multiple disks of the same driver. Defaults have | been setup for each driver as an example of the required options. | + | Supported Drivers: "local", "ftp", "sftp", "s3", "rackspace" + | */ 'disks' => [ 'local' => [ 'driver' => 'local', - 'root' => storage_path('app'), + 'root' => storage_path('app'), ], - 'ftp' => [ - 'driver' => 'ftp', - 'host' => 'ftp.example.com', - 'username' => 'your-username', - 'password' => 'your-password', - - // Optional FTP Settings... - // 'port' => 21, - // 'root' => '', - // 'passive' => true, - // 'ssl' => true, - // 'timeout' => 30, + // This applies the LOCAL public only, not S3/FTP/etc + 'public' => [ + 'driver' => 'local', + 'root' => storage_path('app/public'), + 'url' => env('APP_URL').'/storage', + 'visibility' => 'public', ], 's3' => [ 'driver' => 's3', - 'key' => env('AWS_KEY', null), - 'secret' => env('AWS_SECRET', null), - 'region' => env('AWS_REGION', null), - 'bucket' => env('AWS_BUCKET', null), + 'key' => env('AWS_ACCESS_KEY_ID'), + 'secret' => env('AWS_SECRET_ACCESS_KEY'), + 'region' => env('AWS_DEFAULT_REGION'), + 'bucket' => env('AWS_BUCKET'), + 'url' => env('AWS_URL'), + 'root' => env('AWS_BUCKET_ROOT'), ], 'rackspace' => [ 'driver' => 'rackspace', - 'username' => 'your-username', - 'key' => 'your-key', - 'container' => 'your-container', + 'username' => env('RACKSPACE_USERNAME'), + 'key' => env('RACKSPACE_KEY'), + 'container' => env('RACKSPACE_CONTAINER'), 'endpoint' => 'https://identity.api.rackspacecloud.com/v2.0/', - 'region' => 'IAD', - 'url_type' => 'publicURL', + 'region' => env('RACKSPACE_REGION'), + 'url_type' => env('RACKSPACE_URL_TYPE'), ], ], ]; + +// When you're dealing with local file storage, the paths will be different than S3 +if (env('FILESYSTEM_DISK','local')!='local') +{ + $config['disks']['public'] = $config['disks'][env('FILESYSTEM_DISK')]; + $config['disks']['public']['visibility'] = 'public'; +} + +return $config; diff --git a/config/hashing.php b/config/hashing.php new file mode 100644 index 0000000000..d3c8e2fb22 --- /dev/null +++ b/config/hashing.php @@ -0,0 +1,52 @@ + 'bcrypt', + + /* + |-------------------------------------------------------------------------- + | Bcrypt Options + |-------------------------------------------------------------------------- + | + | Here you may specify the configuration options that should be used when + | passwords are hashed using the Bcrypt algorithm. This will allow you + | to control the amount of time it takes to hash the given password. + | + */ + + 'bcrypt' => [ + 'rounds' => env('BCRYPT_ROUNDS', 10), + ], + + /* + |-------------------------------------------------------------------------- + | Argon Options + |-------------------------------------------------------------------------- + | + | Here you may specify the configuration options that should be used when + | passwords are hashed using the Argon algorithm. These will allow you + | to control the amount of time it takes to hash the given password. + | + */ + + 'argon' => [ + 'memory' => 1024, + 'threads' => 2, + 'time' => 2, + ], + +]; diff --git a/config/laravel-backup.php b/config/laravel-backup.php deleted file mode 100644 index 37250195f5..0000000000 --- a/config/laravel-backup.php +++ /dev/null @@ -1,191 +0,0 @@ - [ - - /* - * The name of this application. You can use this name to monitor - * the backups. - */ - 'name' => 'backups', - - 'source' => [ - - 'files' => [ - - /* - * The list of directories that should be part of the backup. You can - * specify individual files as well. - */ - 'include' => [ - base_path('public/uploads'), - base_path('config'), - base_path('storage/private_uploads'), - base_path('storage/oauth-private.key'), - base_path('storage/oauth-public.key'), - (env('BACKUP_ENV')=='true') ? base_path('.env') : '', - ], - - /* - * These directories will be excluded from the backup. - * You can specify individual files as well. - */ - 'exclude' => [ -// base_path('vendor'), -// base_path('node_modules'), - ], - - /* - * Determines if symlinks should be followed. - */ - 'followLinks' => false, - ], - - /* - * The names of the connections to the databases that should be part of the backup. - * Currently only MySQL- and PostgreSQL-databases are supported. - */ - 'databases' => [ - 'mysql', - ], - ], - - 'destination' => [ - - /* - * The disk names on which the backups will be stored. - */ - 'disks' => [ - 'local', - ], - ], - ], - - 'cleanup' => [ - /* - * The strategy that will be used to cleanup old backups. - * The youngest backup will never be deleted. - */ - 'strategy' => \Spatie\Backup\Tasks\Cleanup\Strategies\DefaultStrategy::class, - - 'defaultStrategy' => [ - - /* - * The amount of days that all daily backups must be kept. - */ - 'keepAllBackupsForDays' => 7, - - /* - * The amount of days that all daily backups must be kept. - */ - 'keepDailyBackupsForDays' => 16, - - /* - * The amount of weeks of which one weekly backup must be kept. - */ - 'keepWeeklyBackupsForWeeks' => 8, - - /* - * The amount of months of which one monthly backup must be kept. - */ - 'keepMonthlyBackupsForMonths' => 4, - - /* - * The amount of years of which one yearly backup must be kept - */ - 'keepYearlyBackupsForYears' => 2, - - /* - * After cleaning up the backups remove the oldest backup until - * this amount of megabytes has been reached. - */ - 'deleteOldestBackupsWhenUsingMoreMegabytesThan' => 5000 - ] - ], - - - /* - * In this array you can specify which backups should be monitored. - * If a backup does not meet the specified requirements the - * UnHealthyBackupWasFound-event will be fired. - */ - 'monitorBackups' => [ - [ - 'name' => 'backups', - 'disks' => ['local'], - 'newestBackupsShouldNotBeOlderThanDays' => 1, - 'storageUsedMayNotBeHigherThanMegabytes' => 5000, - ], - - /* - [ - 'name' => 'name of the second app', - 'disks' => ['local', 's3'], - 'newestBackupsShouldNotBeOlderThanDays' => 1, - 'storageUsedMayNotBeHigherThanMegabytes' => 5000, - ], - */ - ], - - 'notifications' => [ - - /* - * This class will be used to send all notifications. - */ - 'handler' => Spatie\Backup\Notifications\Notifier::class, - - /* - * Here you can specify the ways you want to be notified when certain - * events take place. Possible values are "log", "mail", "slack" and "pushover". - * - * Slack requires the installation of the maknz/slack package. - */ - 'events' => [ - 'whenBackupWasSuccessful' => ['log'], - 'whenCleanupWasSuccessful' => ['log'], - 'whenHealthyBackupWasFound' => ['log'], - 'whenBackupHasFailed' => ['log'], - 'whenCleanupHasFailed' => ['log'], - 'whenUnhealthyBackupWasFound' => ['log'], - ], - - /* - * Here you can specify how emails should be sent. - */ - 'mail' => [ - 'from' => env('MAIL_FROM_ADDR', 'your@email.com'), - 'to' => env('MAIL_FROM_ADDR', 'your@email.com'), - ], - - /* - * Here you can specify how messages should be sent to Slack. - */ - 'slack' => [ - 'channel' => '#backups', - 'username' => 'Backup bot', - 'icon' => ':robot:', - ], - - /* - * Here you can specify how messages should be sent to Pushover. - */ - 'pushover' => [ - 'token' => env('PUSHOVER_APP_TOKEN'), - 'user' => env('PUSHOVER_USER_KEY'), - 'sounds' => [ - 'success' => env('PUSHOVER_SOUND_SUCCESS','pushover'), - 'error' => env('PUSHOVER_SOUND_ERROR','siren'), - ], - ], - ] -]; diff --git a/config/logging.php b/config/logging.php new file mode 100644 index 0000000000..86641787c0 --- /dev/null +++ b/config/logging.php @@ -0,0 +1,81 @@ + env('LOG_CHANNEL', 'stack'), + + /* + |-------------------------------------------------------------------------- + | Log Channels + |-------------------------------------------------------------------------- + | + | Here you may configure the log channels for your application. Out of + | the box, Laravel uses the Monolog PHP logging library. This gives + | you a variety of powerful log handlers / formatters to utilize. + | + | Available Drivers: "single", "daily", "slack", "syslog", + | "errorlog", "monolog", + | "custom", "stack" + | + */ + + 'channels' => [ + 'stack' => [ + 'driver' => 'stack', + 'channels' => ['single'], + ], + + 'single' => [ + 'driver' => 'single', + 'path' => storage_path('logs/laravel.log'), + 'level' => env('APP_LOG_LEVEL', 'error'), + ], + + 'daily' => [ + 'driver' => 'daily', + 'path' => storage_path('logs/laravel.log'), + 'level' => 'debug', + 'days' => env('APP_LOG_MAX_FILES', 5), + ], + + 'slack' => [ + 'driver' => 'slack', + 'url' => env('LOG_SLACK_WEBHOOK_URL'), + 'username' => 'Laravel Log', + 'emoji' => ':boom:', + 'level' => 'critical', + ], + + 'stderr' => [ + 'driver' => 'monolog', + 'handler' => StreamHandler::class, + 'with' => [ + 'stream' => 'php://stderr', + ], + ], + + 'syslog' => [ + 'driver' => 'syslog', + 'level' => env('APP_LOG_LEVEL', 'error'), + ], + + 'errorlog' => [ + 'driver' => 'errorlog', + 'level' => env('APP_LOG_LEVEL', 'error'), + ], + ], + +]; diff --git a/config/mail-auto-embed.php b/config/mail-auto-embed.php new file mode 100644 index 0000000000..bc1d038e0a --- /dev/null +++ b/config/mail-auto-embed.php @@ -0,0 +1,28 @@ + env('MAIL_AUTO_EMBED', true), + + /* + |-------------------------------------------------------------------------- + | Mail embed method + |-------------------------------------------------------------------------- + | + | Supported: "attachment", "base64" + | + */ + + 'method' => env('MAIL_AUTO_EMBED_METHOD', 'base64'), + +]; diff --git a/config/permissions.php b/config/permissions.php index 2950391808..0550886167 100644 --- a/config/permissions.php +++ b/config/permissions.php @@ -578,6 +578,13 @@ return array( 'display' => true, ), + array( + 'permission' => 'self.checkout_assets', + 'label' => 'Self-Checkout', + 'note' => 'This user may check out assets that are marked for self-checkout.', + 'display' => true, + ), + ), diff --git a/config/session.php b/config/session.php index 1d36eb4901..d6710975a6 100644 --- a/config/session.php +++ b/config/session.php @@ -67,7 +67,7 @@ return [ | */ - 'files' => storage_path('framework/sessions'), + 'files' => (env('SESSION_PATH')!='' ? env('SESSION_PATH') : storage_path('framework/sessions')), /* |-------------------------------------------------------------------------- diff --git a/config/trustedproxy.php b/config/trustedproxy.php index fbfdcfbcc4..bde40fc7e8 100644 --- a/config/trustedproxy.php +++ b/config/trustedproxy.php @@ -21,7 +21,7 @@ return [ * within TrustedProxy to trust any proxy * that connects directly to your server, * a requirement when you cannot know the address - * of your proxy (e.g. if using Rackspace balancers). + * of your proxy (e.g. if using ELB or similar). * * The "**" character is syntactic sugar within * TrustedProxy to trust not just any proxy that @@ -33,42 +33,31 @@ return [ * how many proxies that client's request has * subsequently passed through. */ - 'proxies' => env('APP_TRUSTED_PROXIES') !== null ? - explode(',', env('APP_TRUSTED_PROXIES')) : '*', + 'proxies' => null, // [,], '*' + + /* + * To trust one or more specific proxies that connect + * directly to your server, use an array of IP addresses: + */ + # 'proxies' => ['192.168.1.1'], /* * Or, to trust all proxies that connect - * directly to your server, uncomment this: + * directly to your server, use a "*" */ - // 'proxies' => '*', + # 'proxies' => '*', /* - * Or, to trust ALL proxies, including those that - * are in a chain of forwarding, uncomment this: - */ - // 'proxies' => '**', - - /* - * Default Header Names + * Which headers to use to detect proxy related data (For, Host, Proto, Port) * - * Change these if the proxy does - * not send the default header names. + * Options include: * - * Note that headers such as X-Forwarded-For - * are transformed to HTTP_X_FORWARDED_FOR format. + * - Illuminate\Http\Request::HEADER_X_FORWARDED_ALL (use all x-forwarded-* headers to establish trust) + * - Illuminate\Http\Request::HEADER_FORWARDED (use the FORWARDED header to establish trust) * - * The following are Symfony defaults, found in - * \Symfony\Component\HttpFoundation\Request::$trustedHeaders - * - * We may also want to add something like: - * \Illuminate\Http\Request::HEADER_CLIENT_PROTO => 'X_FORWARDED_SCHEME', + * @link https://symfony.com/doc/current/deployment/proxies.html */ - // These are defaults already set in the config: - 'headers' => [ - (defined('Illuminate\Http\Request::HEADER_FORWARDED') ? Illuminate\Http\Request::HEADER_FORWARDED : 'forwarded') => 'FORWARDED', - \Illuminate\Http\Request::HEADER_CLIENT_IP => 'X_FORWARDED_FOR', - \Illuminate\Http\Request::HEADER_CLIENT_HOST => 'X_FORWARDED_HOST', - \Illuminate\Http\Request::HEADER_CLIENT_PROTO => 'X_FORWARDED_PROTO', - \Illuminate\Http\Request::HEADER_CLIENT_PORT => 'X_FORWARDED_PORT', - ] + 'headers' => Illuminate\Http\Request::HEADER_X_FORWARDED_ALL, + + ]; diff --git a/config/version.php b/config/version.php index 2a0b44e79c..1e08ba9b93 100644 --- a/config/version.php +++ b/config/version.php @@ -1,10 +1,10 @@ 'v4.6.9', - 'full_app_version' => 'v4.6.9 - build 3968-gf3c12f38b', - 'build_version' => '3968', + 'app_version' => 'v5.0.0-beta-1.0', + 'full_app_version' => 'v5.0.0-beta-1.0 - build 3866-g3de1de9dc', + 'build_version' => '3866', 'prerelease_version' => '', - 'hash_version' => 'gf3c12f38b', - 'full_hash' => 'v4.6.9-8-gf3c12f38b', - 'branch' => 'master', + 'hash_version' => 'g3de1de9dc', + 'full_hash' => 'v5.0.0--beta-1.0-19-g3de1de9dc', + 'branch' => 'develop', ); diff --git a/database/factories/AccessoryFactory.php b/database/factories/AccessoryFactory.php index 352f0b1540..9e69004862 100644 --- a/database/factories/AccessoryFactory.php +++ b/database/factories/AccessoryFactory.php @@ -21,6 +21,7 @@ $factory->state(App\Models\Accessory::class, 'apple-bt-keyboard', function ($fak return [ 'name' => 'Bluetooth Keyboard', + 'image' => 'bluetooth.jpg', 'category_id' => 8, 'manufacturer_id' => 1, 'qty' => 10, @@ -34,6 +35,7 @@ $factory->state(App\Models\Accessory::class, 'apple-usb-keyboard', function ($fa return [ 'name' => 'USB Keyboard', + 'image' => 'usb-keyboard.jpg', 'category_id' => 8, 'manufacturer_id' => 1, 'qty' => 15, @@ -47,6 +49,7 @@ $factory->state(App\Models\Accessory::class, 'apple-mouse', function ($faker) { return [ 'name' => 'Magic Mouse', + 'image' => 'magic-mouse.jpg', 'category_id' => 9, 'manufacturer_id' => 1, 'qty' => 13, @@ -60,6 +63,7 @@ $factory->state(App\Models\Accessory::class, 'microsoft-mouse', function ($faker return [ 'name' => 'Sculpt Comfort Mouse', + 'image' => 'comfort-mouse.jpg', 'category_id' => 9, 'manufacturer_id' => 2, 'qty' => 13, diff --git a/database/factories/AssetModelFactory.php b/database/factories/AssetModelFactory.php index d634588785..89cb21578c 100644 --- a/database/factories/AssetModelFactory.php +++ b/database/factories/AssetModelFactory.php @@ -33,6 +33,7 @@ $factory->state(App\Models\AssetModel::class, 'mbp-13-model', function ($faker) 'eol' => '36', 'depreciation_id' => 1, 'image' => 'mbp.jpg', + 'fieldset_id' => 2, ]; }); @@ -45,6 +46,7 @@ $factory->state(App\Models\AssetModel::class, 'mbp-air-model', function ($faker) 'eol' => '36', 'depreciation_id' => 1, 'image' => 'macbookair.jpg', + 'fieldset_id' => 2, ]; }); @@ -57,6 +59,7 @@ $factory->state(App\Models\AssetModel::class, 'surface-model', function ($faker) 'eol' => '36', 'depreciation_id' => 1, 'image' => 'surface.jpg', + 'fieldset_id' => 2, ]; }); @@ -69,6 +72,7 @@ $factory->state(App\Models\AssetModel::class, 'xps13-model', function ($faker) { 'eol' => '36', 'depreciation_id' => 1, 'image' => 'xps.jpg', + 'fieldset_id' => 2, ]; }); @@ -81,6 +85,7 @@ $factory->state(App\Models\AssetModel::class, 'zenbook-model', function ($faker) 'eol' => '36', 'depreciation_id' => 1, 'image' => 'zenbook.jpg', + 'fieldset_id' => 2, ]; }); @@ -93,6 +98,7 @@ $factory->state(App\Models\AssetModel::class, 'spectre-model', function ($faker) 'eol' => '36', 'depreciation_id' => 1, 'image' => 'spectre.jpg', + 'fieldset_id' => 2, ]; }); @@ -105,6 +111,7 @@ $factory->state(App\Models\AssetModel::class, 'yoga-model', function ($faker) { 'eol' => '36', 'depreciation_id' => 1, 'image' => 'yoga.png', + 'fieldset_id' => 2, ]; }); @@ -123,6 +130,7 @@ $factory->state(App\Models\AssetModel::class, 'macpro-model', function ($faker) 'eol' => '24', 'depreciation_id' => 1, 'image' => 'imacpro.jpg', + 'fieldset_id' => 2, ]; }); @@ -134,6 +142,7 @@ $factory->state(App\Models\AssetModel::class, 'lenovo-i5-model', function ($fake 'eol' => '24', 'depreciation_id' => 1, 'image' => 'lenovoi5.png', + 'fieldset_id' => 2, ]; }); @@ -146,6 +155,7 @@ $factory->state(App\Models\AssetModel::class, 'optiplex-model', function ($faker 'eol' => '24', 'depreciation_id' => 1, 'image' => 'optiplex.jpg', + 'fieldset_id' => 2, ]; }); @@ -224,6 +234,7 @@ $factory->state(App\Models\AssetModel::class, 'iphone6s-model', function ($faker 'eol' => '12', 'depreciation_id' => 3, 'image' => 'iphone6.jpg', + 'fieldset_id' => 1, ]; }); @@ -235,6 +246,7 @@ $factory->state(App\Models\AssetModel::class, 'iphone7-model', function ($faker) 'eol' => '12', 'depreciation_id' => 1, 'image' => 'iphone7.jpg', + 'fieldset_id' => 1, ]; }); diff --git a/database/factories/CustomFieldsFactory.php b/database/factories/CustomFieldsFactory.php index e6b35df0d1..7840014fd0 100644 --- a/database/factories/CustomFieldsFactory.php +++ b/database/factories/CustomFieldsFactory.php @@ -9,9 +9,40 @@ $factory->define(App\Models\CustomField::class, function (Faker\Generator $faker ]; }); -$factory->define(App\Models\CustomFieldset::class, function (Faker\Generator $faker) { +$factory->state(App\Models\CustomField::class, 'imei', function ($faker) { return [ - 'name' => $faker->catchPhrase, - 'user_id' => Auth::id() + 'name' => 'IMEI', + 'help_text' => 'The IMEI number for this device.', + 'format' => 'regex:/^[0-9]{15}$/', ]; }); + +$factory->state(App\Models\CustomField::class, 'phone', function ($faker) { + return [ + 'name' => 'Phone Number', + 'help_text' => 'Enter the phone number for this device.', + ]; +}); + +$factory->state(App\Models\CustomField::class, 'ram', function ($faker) { + return [ + 'name' => 'RAM', + 'help_text' => 'The amount of RAM this device has.', + ]; +}); + +$factory->state(App\Models\CustomField::class, 'cpu', function ($faker) { + return [ + 'name' => 'CPU', + 'help_text' => 'The speed of the processor on this device.', + ]; +}); + + +$factory->state(App\Models\CustomField::class, 'mac-address', function ($faker) { + return [ + 'name' => 'MAC Address', + 'format' => 'regex:/^([0-9a-fA-F]{2}[:-]){5}[0-9a-fA-F]{2}$/', + ]; +}); + diff --git a/database/factories/CustomFieldsetFactory.php b/database/factories/CustomFieldsetFactory.php new file mode 100644 index 0000000000..bab8cbe58f --- /dev/null +++ b/database/factories/CustomFieldsetFactory.php @@ -0,0 +1,23 @@ +define(App\Models\CustomFieldset::class, function (Faker\Generator $faker) { + return [ + 'name' => $faker->catchPhrase, + ]; +}); + +$factory->state(App\Models\CustomFieldset::class, 'mobile', function ($faker) { + return [ + 'name' => 'Mobile Devices', + ]; +}); + +$factory->state(App\Models\CustomFieldset::class, 'computer', function ($faker) { + return [ + 'name' => 'Laptops and Desktops', + ]; +}); + + + diff --git a/database/factories/ModelFactory.php b/database/factories/ModelFactory.php index 76dd0617b0..ad903e33ba 100644 --- a/database/factories/ModelFactory.php +++ b/database/factories/ModelFactory.php @@ -45,6 +45,11 @@ $factory->define(App\Models\Component::class, function (Faker\Generator $faker) ]; }); +$factory->define(App\Models\Group::class, function (Faker\Generator $faker) { + return [ + 'name' => $faker->name, + ]; +}); $factory->define(App\Models\Location::class, function (Faker\Generator $faker) { return [ diff --git a/database/migrations/2015_09_22_003413_migrate_mac_address.php b/database/migrations/2015_09_22_003413_migrate_mac_address.php index ff31042f9a..6345773ca1 100644 --- a/database/migrations/2015_09_22_003413_migrate_mac_address.php +++ b/database/migrations/2015_09_22_003413_migrate_mac_address.php @@ -21,7 +21,7 @@ class MigrateMacAddress extends Migration { } $macid=DB::table('custom_fields')->insertGetId([ 'name' => "MAC Address", - 'format' => \App\Models\CustomField::$PredefinedFormats['MAC'], + 'format' => \App\Models\CustomField::PREDEFINED_FORMATS['MAC'], 'element'=>'text']); if(!$macid) { throw new Exception("Can't save MAC Custom field: $macid"); diff --git a/database/migrations/2016_12_27_212631_make_asset_assigned_to_polymorphic.php b/database/migrations/2016_12_27_212631_make_asset_assigned_to_polymorphic.php index 3973abbcc3..772bd170a5 100644 --- a/database/migrations/2016_12_27_212631_make_asset_assigned_to_polymorphic.php +++ b/database/migrations/2016_12_27_212631_make_asset_assigned_to_polymorphic.php @@ -18,9 +18,9 @@ class MakeAssetAssignedToPolymorphic extends Migration Schema::table('assets', function (Blueprint $table) { $table->string('assigned_type')->nullable(); }); - - // Prior to this migration, asset's could only be assigned to users. - Asset::whereNotNull('assigned_to')->orWhere('assigned_to', '!=', null)->update(['assigned_type' => User::class]); + if(config('database.default') == 'mysql') { + Asset::whereNotNull('assigned_to')->orWhere('assigned_to', '!=', '')->update(['assigned_type' => User::class]); + } } /** diff --git a/database/migrations/2018_07_28_023826_create_checkout_acceptances_table.php b/database/migrations/2018_07_28_023826_create_checkout_acceptances_table.php new file mode 100644 index 0000000000..67bc3b800a --- /dev/null +++ b/database/migrations/2018_07_28_023826_create_checkout_acceptances_table.php @@ -0,0 +1,41 @@ +increments('id'); + + $table->morphs('checkoutable'); + $table->integer('assigned_to_id')->unsigned(); + + $table->string('signature_filename')->nullable(); + + $table->timestamp('accepted_at')->nullable(); + $table->timestamp('declined_at')->nullable(); + + $table->timestamps(); + $table->softDeletes(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('checkout_acceptances'); + } +} diff --git a/database/migrations/2018_08_20_204842_add_depreciation_option_to_settings.php b/database/migrations/2018_08_20_204842_add_depreciation_option_to_settings.php new file mode 100644 index 0000000000..7678c45d56 --- /dev/null +++ b/database/migrations/2018_08_20_204842_add_depreciation_option_to_settings.php @@ -0,0 +1,32 @@ +char('depreciation_method', 10)->nullable()->default('default'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('settings', function (Blueprint $table) { + $table->dropColumn('depreciation_method'); + }); + } +} diff --git a/database/migrations/2018_09_10_082212_create_checkout_acceptances_for_unaccepted_assets.php b/database/migrations/2018_09_10_082212_create_checkout_acceptances_for_unaccepted_assets.php new file mode 100644 index 0000000000..ddf6949b69 --- /dev/null +++ b/database/migrations/2018_09_10_082212_create_checkout_acceptances_for_unaccepted_assets.php @@ -0,0 +1,43 @@ +where('assigned_type', 'App\Models\User')->where('accepted', 'pending')->get(); + + $acceptances = []; + + foreach($assets as $asset) { + $acceptances[] = [ + 'checkoutable_type' => 'App\Models\Asset', + 'checkoutable_id' => $asset->id, + 'assigned_to_id' => $asset->assigned_to, + ]; + } + + DB::table('checkout_acceptances')->insert($acceptances); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + // + } +} diff --git a/database/migrations/2018_12_05_211936_add_favicon_to_settings.php b/database/migrations/2018_12_05_211936_add_favicon_to_settings.php new file mode 100644 index 0000000000..570eb53926 --- /dev/null +++ b/database/migrations/2018_12_05_211936_add_favicon_to_settings.php @@ -0,0 +1,32 @@ +char('favicon')->nullable()->default(null); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('settings', function (Blueprint $table) { + $table->dropColumn('favicon'); + }); + } +} diff --git a/database/migrations/2018_12_05_212119_add_email_logo_to_settings.php b/database/migrations/2018_12_05_212119_add_email_logo_to_settings.php new file mode 100644 index 0000000000..fd3a89170d --- /dev/null +++ b/database/migrations/2018_12_05_212119_add_email_logo_to_settings.php @@ -0,0 +1,32 @@ +char('email_logo')->nullable()->default(null); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('settings', function (Blueprint $table) { + $table->dropColumn('email_logo'); + }); + } +} diff --git a/database/seeds/AccessorySeeder.php b/database/seeds/AccessorySeeder.php index 9cb9e0aff6..a9041b782c 100644 --- a/database/seeds/AccessorySeeder.php +++ b/database/seeds/AccessorySeeder.php @@ -13,5 +13,31 @@ class AccessorySeeder extends Seeder factory(Accessory::class, 1)->states('apple-bt-keyboard')->create(); factory(Accessory::class, 1)->states('apple-mouse')->create(); factory(Accessory::class, 1)->states('microsoft-mouse')->create(); + + $src = public_path('/img/demo/accessories/'); + $dst = 'accessories'.'/'; + $del_files = Storage::files($dst); + + foreach($del_files as $del_file){ // iterate files + $file_to_delete = str_replace($src,'',$del_file); + \Log::debug('Deleting: '.$file_to_delete); + try { + Storage::disk('public')->delete($dst.$del_file); + } catch (\Exception $e) { + \Log::debug($e); + } + } + + + $add_files = glob($src."/*.*"); + foreach($add_files as $add_file){ + $file_to_copy = str_replace($src,'',$add_file); + \Log::debug('Copying: '.$file_to_copy); + try { + Storage::disk('public')->put($dst.$file_to_copy, file_get_contents($src.$file_to_copy)); + } catch (\Exception $e) { + \Log::debug($e); + } + } } } diff --git a/database/seeds/AssetModelSeeder.php b/database/seeds/AssetModelSeeder.php index fdb1adef0a..03c7fb5095 100755 --- a/database/seeds/AssetModelSeeder.php +++ b/database/seeds/AssetModelSeeder.php @@ -2,6 +2,7 @@ use Illuminate\Database\Seeder; use App\Models\AssetModel; +use Illuminate\Support\Facades\Storage; class AssetModelSeeder extends Seeder { @@ -39,21 +40,30 @@ class AssetModelSeeder extends Seeder factory(AssetModel::class, 1)->states('ultrafine')->create(); // 17 factory(AssetModel::class, 1)->states('ultrasharp')->create(); // 18 - $src = public_path('/img/demo/models'); - $dst = public_path('/uploads/models'); - - $del_files = glob($dst."/*.*"); + $src = public_path('/img/demo/models/'); + $dst = 'assetmodels'.'/'; + $del_files = Storage::files($dst); foreach($del_files as $del_file){ // iterate files - if(is_file($del_file)) - unlink($del_file); // delete file + $file_to_delete = str_replace($src,'',$del_file); + \Log::debug('Deleting: '.$file_to_delete); + try { + Storage::disk('public')->delete($dst.$del_file); + } catch (\Exception $e) { + \Log::debug($e); + } } $add_files = glob($src."/*.*"); foreach($add_files as $add_file){ - $file_to_copy = str_replace($src,$dst,$add_file); - copy($add_file, $file_to_copy); + $file_to_copy = str_replace($src,'',$add_file); + \Log::debug('Copying: '.$file_to_copy); + try { + Storage::disk('public')->put($dst.$file_to_copy, file_get_contents($src.$file_to_copy)); + } catch (\Exception $e) { + \Log::debug($e); + } } diff --git a/database/seeds/AssetSeeder.php b/database/seeds/AssetSeeder.php index 79e47d6113..f9c2f1fc83 100644 --- a/database/seeds/AssetSeeder.php +++ b/database/seeds/AssetSeeder.php @@ -1,7 +1,7 @@ states('ultrasharp')->create(); - $dst = public_path('/uploads/assets'); - - $del_files = glob($dst."/*.*"); - + $del_files = Storage::files('companies'); foreach($del_files as $del_file){ // iterate files - if(is_file($del_file)) - unlink($del_file); // delete file + \Log::debug('Deleting: '.$del_files); + try { + Storage::disk('public')->delete('assets'.'/'.$del_files); + } catch (\Exception $e) { + \Log::debug($e); + } } DB::table('checkout_requests')->truncate(); diff --git a/database/seeds/CompanySeeder.php b/database/seeds/CompanySeeder.php index 3885b939f4..eeae5492b7 100644 --- a/database/seeds/CompanySeeder.php +++ b/database/seeds/CompanySeeder.php @@ -12,26 +12,37 @@ class CompanySeeder extends Seeder */ public function run() { - // + \Log::debug('Seed companies'); Company::truncate(); factory(Company::class, 4)->create(); - $src = public_path('/img/demo/companies'); - $dst = public_path('/uploads/companies'); - $del_files = glob($dst."/*.*"); + $src = public_path('/img/demo/companies/'); + $dst = 'companies'.'/'; + $del_files = Storage::files('companies/'.$dst); foreach($del_files as $del_file){ // iterate files - if(is_file($del_file)) - unlink($del_file); // delete file + $file_to_delete = str_replace($src,'',$del_file); + \Log::debug('Deleting: '.$file_to_delete); + try { + Storage::disk('public')->delete($dst.$del_file); + } catch (\Exception $e) { + \Log::debug($e); + } } $add_files = glob($src."/*.*"); foreach($add_files as $add_file){ - $file_to_copy = str_replace($src,$dst,$add_file); - copy($add_file, $file_to_copy); + $file_to_copy = str_replace($src,'',$add_file); + \Log::debug('Copying: '.$file_to_copy); + try { + Storage::disk('public')->put($dst.$file_to_copy, file_get_contents($src.$file_to_copy)); + } catch (\Exception $e) { + \Log::debug($e); + } } + } } diff --git a/database/seeds/CustomFieldSeeder.php b/database/seeds/CustomFieldSeeder.php index 1186ec86f6..c743b3fc58 100644 --- a/database/seeds/CustomFieldSeeder.php +++ b/database/seeds/CustomFieldSeeder.php @@ -24,7 +24,41 @@ class CustomFieldSeeder extends Seeder CustomField::truncate(); CustomFieldset::truncate(); DB::table('custom_field_custom_fieldset')->truncate(); - factory(CustomField::class, 4)->create(); + + factory(CustomFieldset::class, 1)->states('mobile')->create(); + factory(CustomFieldset::class, 1)->states('computer')->create(); + factory(CustomField::class, 1)->states('imei')->create(); + factory(CustomField::class, 1)->states('phone')->create(); + factory(CustomField::class, 1)->states('ram')->create(); + factory(CustomField::class, 1)->states('cpu')->create(); + factory(CustomField::class, 1)->states('mac-address')->create(); + + DB::table('custom_field_custom_fieldset')->insert([ + [ + 'custom_field_id' => '1', + 'custom_fieldset_id' => '1' + ], + [ + 'custom_field_id' => '2', + 'custom_fieldset_id' => '1' + ], + [ + 'custom_field_id' => '3', + 'custom_fieldset_id' => '2' + ], + [ + 'custom_field_id' => '4', + 'custom_fieldset_id' => '2' + ], + [ + 'custom_field_id' => '5', + 'custom_fieldset_id' => '2' + ], + + ]); + + + } } diff --git a/database/seeds/DatabaseSeeder.php b/database/seeds/DatabaseSeeder.php index 85f3e599ad..030b5f7c5d 100644 --- a/database/seeds/DatabaseSeeder.php +++ b/database/seeds/DatabaseSeeder.php @@ -15,6 +15,12 @@ class DatabaseSeeder extends Seeder { Model::unguard(); + // Only create default settings if they do not exist in the db. + if(!Setting::first()) { + // factory(Setting::class)->create(); + $this->call(SettingsSeeder::class); + } + $this->call(CompanySeeder::class); $this->call(CategorySeeder::class); $this->call(UserSeeder::class); @@ -34,10 +40,7 @@ class DatabaseSeeder extends Seeder $this->call(ActionlogSeeder::class); $this->call(CustomFieldSeeder::class); - // Only create default settings if they do not exist in the db. - if(!Setting::first()) { - factory(Setting::class)->create(); - } + Artisan::call('snipeit:sync-asset-locations', ['--output' => 'all']); $output = Artisan::output(); \Log::info($output); diff --git a/database/seeds/LocationSeeder.php b/database/seeds/LocationSeeder.php index 40d389792f..f7d857f34d 100644 --- a/database/seeds/LocationSeeder.php +++ b/database/seeds/LocationSeeder.php @@ -1,7 +1,7 @@ create(); - $src = public_path('/img/demo/locations'); - $dst = public_path('/uploads/locations'); - - $del_files = glob($dst."/*.*"); + $src = public_path('/img/demo/locations/'); + $dst = 'locations'.'/'; + $del_files = Storage::files($dst); foreach($del_files as $del_file){ // iterate files - if(is_file($del_file)) - unlink($del_file); // delete file + $file_to_delete = str_replace($src,'',$del_file); + \Log::debug('Deleting: '.$file_to_delete); + try { + Storage::disk('public')->delete($dst.$del_file); + } catch (\Exception $e) { + \Log::debug($e); + } } $add_files = glob($src."/*.*"); foreach($add_files as $add_file){ - $file_to_copy = str_replace($src,$dst,$add_file); - copy($add_file, $file_to_copy); + $file_to_copy = str_replace($src,'',$add_file); + \Log::debug('Copying: '.$file_to_copy); + try { + Storage::disk('public')->put($dst.$file_to_copy, file_get_contents($src.$file_to_copy)); + } catch (\Exception $e) { + \Log::debug($e); + } } } diff --git a/database/seeds/ManufacturerSeeder.php b/database/seeds/ManufacturerSeeder.php index f6d9a2451e..a65d12a2e4 100644 --- a/database/seeds/ManufacturerSeeder.php +++ b/database/seeds/ManufacturerSeeder.php @@ -1,6 +1,7 @@ states('avery')->create(); // 10 factory(Manufacturer::class, 1)->states('crucial')->create(); // 10 - $src = public_path('/img/demo/manufacturers'); - $dst = public_path('/uploads/manufacturers'); - - $del_files = glob($dst."/*.*"); + $src = public_path('/img/demo/manufacturers/'); + $dst = 'manufacturers'.'/'; + $del_files = Storage::files($dst); foreach($del_files as $del_file){ // iterate files - if(is_file($del_file)) - unlink($del_file); // delete file + $file_to_delete = str_replace($src,'',$del_file); + \Log::debug('Deleting: '.$file_to_delete); + try { + Storage::disk('public')->delete($dst.$del_file); + } catch (\Exception $e) { + \Log::debug($e); + } } $add_files = glob($src."/*.*"); foreach($add_files as $add_file){ - $file_to_copy = str_replace($src,$dst,$add_file); - copy($add_file, $file_to_copy); + $file_to_copy = str_replace($src,'',$add_file); + \Log::debug('Copying: '.$file_to_copy); + try { + Storage::disk('public')->put($dst.$file_to_copy, file_get_contents($src.$file_to_copy)); + } catch (\Exception $e) { + \Log::debug($e); + } } diff --git a/database/seeds/SettingsSeeder.php b/database/seeds/SettingsSeeder.php new file mode 100644 index 0000000000..f866bea8a0 --- /dev/null +++ b/database/seeds/SettingsSeeder.php @@ -0,0 +1,43 @@ +per_page = 20; + $settings->site_name = 'Snipe-IT Demo'; + $settings->auto_increment_assets = 1; + $settings->logo = 'logo.png'; + $settings->alert_email = 'service@snipe-it.io'; + $settings->header_color = null; + $settings->barcode_type = 'QRCODE'; + $settings->default_currency = 'USD'; + $settings->brand = 3; + $settings->ldap_enabled = 0; + $settings->full_multiple_companies_support = 0; + $settings->alt_barcode = 'C128'; + $settings->skin = ''; + $settings->email_domain = 'example.org'; + $settings->email_format = 'filastname'; + $settings->username_format = 'filastname'; + $settings->date_display_format = 'D M d, Y'; + $settings->time_display_format = 'g:iA'; + $settings->thumbnail_max_h = '30'; + $settings->locale = 'en'; + $settings->version_footer = 'on'; + $settings->support_footer = 'on'; + $settings->pwd_secure_min = '542321'; + $settings->save(); + + if ($user = User::where('username', '=', 'admin')->first()) { + $user->locale = 'en'; + $user->save(); + } + } +} diff --git a/database/seeds/SupplierSeeder.php b/database/seeds/SupplierSeeder.php index 87ca416abd..8dbeac9964 100644 --- a/database/seeds/SupplierSeeder.php +++ b/database/seeds/SupplierSeeder.php @@ -9,22 +9,5 @@ class SupplierSeeder extends Seeder Supplier::truncate(); factory(Supplier::class, 5)->create(); - $src = public_path('/img/demo/suppliers'); - $dst = public_path('/uploads/suppliers'); - - $del_files = glob($dst."/*.*"); - - foreach($del_files as $del_file){ // iterate files - if(is_file($del_file)) - unlink($del_file); // delete file - } - - - $add_files = glob($src."/*.*"); - foreach($add_files as $add_file){ - $file_to_copy = str_replace($src,$dst,$add_file); - copy($add_file, $file_to_copy); - } - } } diff --git a/docker/000-default-2.4.conf b/docker/000-default-2.4.conf new file mode 100644 index 0000000000..62a71adb8b --- /dev/null +++ b/docker/000-default-2.4.conf @@ -0,0 +1,19 @@ + + ServerAdmin webmaster@localhost + + DocumentRoot "/var/www/html/public" + DirectoryIndex index.php index.html + + Options All +MultiViews -ExecCGI -Indexes + + DAV Off + + AllowOverride All + Require all granted + + LogLevel warn + ErrorLog ${APACHE_LOG_DIR}/error.log + CustomLog ${APACHE_LOG_DIR}/access.log combined + + +# vim: syntax=apache ts=4 sw=4 sts=4 sr noet diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh index 171b4f70a3..2a1e489400 100644 --- a/docker/entrypoint.sh +++ b/docker/entrypoint.sh @@ -47,5 +47,5 @@ then cp -ax /var/www/html/vendor/laravel/passport/database/migrations/* /var/www/html/database/migrations/ fi -. /etc/apache2/envvars +. /etc/apache2/envvars exec apache2 -DNO_DETACH < /dev/null diff --git a/docker/entrypoint_alpine.sh b/docker/entrypoint_alpine.sh new file mode 100644 index 0000000000..145ee44157 --- /dev/null +++ b/docker/entrypoint_alpine.sh @@ -0,0 +1,48 @@ +#!/bin/sh + +# fix key if needed +if [ -z "$APP_KEY" ] +then + echo "Please re-run this container with an environment variable \$APP_KEY" + echo "An example APP_KEY you could use is: " + php artisan key:generate --show + exit +fi + +#if [ ! -f /var/lib/snipeit/ssl/snipeit-ssl.crt -o ! -f /var/lib/snipeit/ssl/snipeit-ssl.key ] +#then + # rm /etc/apache2/conf.d/ssl.conf && rm /etc/apache2/conf.d/default-ssl.conf +#fi + +# create data directories +for dir in \ + 'data/private_uploads' \ + 'data/uploads/accessories' \ + 'data/uploads/avatars' \ + 'data/uploads/barcodes' \ + 'data/uploads/categories' \ + 'data/uploads/companies' \ + 'data/uploads/components' \ + 'data/uploads/consumables' \ + 'data/uploads/departments' \ + 'data/uploads/locations' \ + 'data/uploads/manufacturers' \ + 'data/uploads/models' \ + 'data/uploads/suppliers' \ + 'dumps' \ + 'keys' +do + [ ! -d "/var/lib/snipeit/$dir" ] && mkdir -p "/var/lib/snipeit/$dir" +done + +chown -R apache:root /var/lib/snipeit/data/* +chown -R apache:root /var/lib/snipeit/dumps +chown -R apache:root /var/lib/snipeit/keys + +# If the Oauth DB files are not present copy the vendor files over to the db migrations +if [ ! -f "/var/www/html/database/migrations/*create_oauth*" ] +then + cp -a /var/www/html/vendor/laravel/passport/database/migrations/* /var/www/html/database/migrations/ +fi +export APACHE_LOG_DIR=/var/log/apache2 +exec httpd -DNO_DETACH < /dev/null diff --git a/gh-changelog.php b/gh-changelog.php deleted file mode 100644 index 8ca2fd26e9..0000000000 --- a/gh-changelog.php +++ /dev/null @@ -1,61 +0,0 @@ -view •'; - $gitlog .= ' %s \' --reverse | grep -i -E '.escapeshellarg($string).' '; - - if ($omit!=''){ - $gitlog .= ' | grep -i -E -v '.escapeshellarg($omit).''; - } - - $gitlog .= '>> '.escapeshellarg($file); - exec($gitlog); -} diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 1df4cf892e..40fcbcb073 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -2,11 +2,25 @@ "requires": true, "lockfileVersion": 1, "dependencies": { + "@fortawesome/fontawesome-free": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-5.2.0.tgz", + "integrity": "sha512-4pgStJx9UmydKc7wwF6Xjw4dFqzUnQejeuP2aUNHWazayWbmMbrx5rieN9+oob4bUwkf1thS3am0Ko+uhFHpNA==" + }, "@sindresorhus/is": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.7.0.tgz", "integrity": "sha1-mgb08TfuhNffBGDB/bETX/psUP0=" }, + "JSONStream": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.4.tgz", + "integrity": "sha1-YVuyrbDNNMj0xEe19lEvodjxai4=", + "requires": { + "jsonparse": "^1.2.0", + "through": ">=2.2.7 <3" + } + }, "abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", @@ -19,15 +33,14 @@ "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", "dev": true, "requires": { - "mime-types": "2.1.18", + "mime-types": "~2.1.18", "negotiator": "0.6.1" } }, "acorn": { - "version": "5.5.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.5.3.tgz", - "integrity": "sha512-jd5MkIUlbbmb07nXH0DT3y7rDVtkzDi4XZOUVWAer8ajmF/DTSSbl5oNFyDOl/OXA33Bl79+ypHhl2pN20VeOQ==", - "dev": true + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.2.tgz", + "integrity": "sha512-cJrKCNcr2kv8dlDnbw+JPUGjHZzo4myaxOLmpOX8a+rgX94YeTcTMv/LFJUSByRpc+i4GgVnnhLxvMu/2Y+rqw==" }, "acorn-dynamic-import": { "version": "2.0.2", @@ -35,7 +48,7 @@ "integrity": "sha1-x1K9IQvvZ5UBtsbLf8hPj0cVjMQ=", "dev": true, "requires": { - "acorn": "4.0.13" + "acorn": "^4.0.3" }, "dependencies": { "acorn": { @@ -46,19 +59,39 @@ } } }, + "acorn-node": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.5.2.tgz", + "integrity": "sha512-krFKvw/d1F17AN3XZbybIUzEY4YEPNiGo05AfP3dBlfVKrMHETKpgjpuZkSF8qDNt9UkQcqj7am8yJLseklCMg==", + "requires": { + "acorn": "^5.7.1", + "acorn-dynamic-import": "^3.0.0", + "xtend": "^4.0.1" + }, + "dependencies": { + "acorn-dynamic-import": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-3.0.0.tgz", + "integrity": "sha512-zVWV8Z8lislJoOKKqdNMOB+s6+XV5WERty8MnKBeFgwA+19XJjJHs2RP5dzM57FftIs+jQnRToLiWazKr6sSWg==", + "requires": { + "acorn": "^5.0.0" + } + } + } + }, "adjust-sourcemap-loader": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/adjust-sourcemap-loader/-/adjust-sourcemap-loader-1.2.0.tgz", "integrity": "sha1-4z/eleUNufKoAuNkfjEdL8UADGk=", "dev": true, "requires": { - "assert": "1.4.1", - "camelcase": "1.2.1", - "loader-utils": "1.1.0", - "lodash.assign": "4.2.0", - "lodash.defaults": "3.1.2", - "object-path": "0.9.2", - "regex-parser": "2.2.9" + "assert": "^1.3.0", + "camelcase": "^1.2.1", + "loader-utils": "^1.1.0", + "lodash.assign": "^4.0.1", + "lodash.defaults": "^3.1.2", + "object-path": "^0.9.2", + "regex-parser": "^2.2.9" }, "dependencies": { "camelcase": { @@ -73,8 +106,8 @@ "integrity": "sha1-xzCLGNv4vJNy1wGnNJPGEZK9Liw=", "dev": true, "requires": { - "lodash.assign": "3.2.0", - "lodash.restparam": "3.6.1" + "lodash.assign": "^3.0.0", + "lodash.restparam": "^3.0.0" }, "dependencies": { "lodash.assign": { @@ -83,23 +116,100 @@ "integrity": "sha1-POnwI0tLIiPilrj6CsH+6OvKZPo=", "dev": true, "requires": { - "lodash._baseassign": "3.2.0", - "lodash._createassigner": "3.1.1", - "lodash.keys": "3.1.2" + "lodash._baseassign": "^3.0.0", + "lodash._createassigner": "^3.0.0", + "lodash.keys": "^3.0.0" } } } } } }, - "ajv": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", - "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", - "dev": true, + "adler-32": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/adler-32/-/adler-32-1.2.0.tgz", + "integrity": "sha1-aj5r8KY5ALoVZSgIyxXGgT0aXyU=", "requires": { - "co": "4.6.0", - "json-stable-stringify": "1.0.1" + "exit-on-epipe": "~1.0.1", + "printj": "~1.1.0" + } + }, + "admin-lte": { + "version": "2.4.8", + "resolved": "https://registry.npmjs.org/admin-lte/-/admin-lte-2.4.8.tgz", + "integrity": "sha1-Ne2yt4V69/z+1zVcg2SdWr0JpQE=", + "requires": { + "bootstrap": "^3.3.7", + "bootstrap-colorpicker": "^2.5.1", + "bootstrap-datepicker": "^1.7.0", + "bootstrap-daterangepicker": "^2.1.25", + "bootstrap-slider": "^9.8.0", + "bootstrap-timepicker": "^0.5.2", + "chart.js": "1.0.*", + "ckeditor": "^4.7.0", + "datatables.net": "^1.10.15", + "datatables.net-bs": "^1.10.15", + "fastclick": "^1.0.6", + "flot": "^0.8.0-alpha", + "font-awesome": "^4.7.0", + "fullcalendar": "^3.4.0", + "inputmask": "^3.3.7", + "ion-rangeslider": "^2.2.0", + "ionicons": "^3.0.0", + "jquery": "^3.2.1", + "jquery-knob": "^1.2.11", + "jquery-sparkline": "^2.4.0", + "jquery-ui": "^1.12.1", + "jvectormap": "^1.2.2", + "moment": "^2.18.1", + "morris.js": "^0.5.0", + "pace": "0.0.4", + "raphael": "^2.2.7", + "select2": "^4.0.3", + "slimscroll": "^0.9.1" + }, + "dependencies": { + "chart.js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-1.0.2.tgz", + "integrity": "sha1-rVfSIpz9jM9ZVRR+gSG0kR5p3+c=" + } + } + }, + "ajv": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.3.tgz", + "integrity": "sha512-LqZ9wY+fx3UMiiPd741yB2pj3hhil+hQc8taf4o2QGRFpWgZ2V5C8HA165DY9sS3fJwsk7uT7ZlFEyC3Ig3lLg==", + "requires": { + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "dependencies": { + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=" + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + }, + "uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "requires": { + "punycode": "^2.1.0" + } + } } }, "ajv-keywords": { @@ -114,9 +224,9 @@ "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", "dev": true, "requires": { - "kind-of": "3.2.2", - "longest": "1.0.1", - "repeat-string": "1.6.1" + "kind-of": "^3.0.2", + "longest": "^1.0.1", + "repeat-string": "^1.5.2" }, "dependencies": { "kind-of": { @@ -125,7 +235,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "1.1.6" + "is-buffer": "^1.1.5" } } } @@ -147,15 +257,6 @@ "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", "dev": true }, - "ansi-gray": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", - "integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=", - "dev": true, - "requires": { - "ansi-wrap": "0.1.0" - } - }, "ansi-html": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/ansi-html/-/ansi-html-0.0.7.tgz", @@ -174,20 +275,14 @@ "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", "dev": true }, - "ansi-wrap": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", - "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=", - "dev": true - }, "anymatch": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", "integrity": "sha1-vLJLTzeTTZqnrBe0ra+J58du8us=", "dev": true, "requires": { - "micromatch": "3.1.10", - "normalize-path": "2.1.1" + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" } }, "aproba": { @@ -196,31 +291,14 @@ "integrity": "sha1-aALmJk79GMeQobDVF/DyYnvyyUo=", "dev": true }, - "archive-type": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/archive-type/-/archive-type-3.2.0.tgz", - "integrity": "sha1-nNnABpV+vpX62tW9YJiUKoE3N/Y=", - "dev": true, - "requires": { - "file-type": "3.9.0" - }, - "dependencies": { - "file-type": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz", - "integrity": "sha1-JXoHg4TR24CHvESdEH1SpSZyuek=", - "dev": true - } - } - }, "are-we-there-yet": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz", - "integrity": "sha1-u13KOCu5TwXhUZQ3PRb9O6HKEQ0=", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", + "integrity": "sha1-SzXClE8GKov82mZBB2A1D+nd/CE=", "dev": true, "requires": { - "delegates": "1.0.0", - "readable-stream": "2.3.4" + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" } }, "argparse": { @@ -229,7 +307,7 @@ "integrity": "sha1-vNZ5HqWuCXJeF+WtmIE0zUCz2RE=", "dev": true, "requires": { - "sprintf-js": "1.0.3" + "sprintf-js": "~1.0.2" } }, "arr-diff": { @@ -250,11 +328,10 @@ "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", "dev": true }, - "array-differ": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", - "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=", - "dev": true + "array-filter": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/array-filter/-/array-filter-0.0.1.tgz", + "integrity": "sha1-fajPLiZijtcygDWB/SH2fKzS7uw=" }, "array-find-index": { "version": "1.0.2", @@ -274,24 +351,32 @@ "integrity": "sha1-GEtI9i2S10UrsxsyMWXH+L0CJm0=", "dev": true, "requires": { - "define-properties": "1.1.2", - "es-abstract": "1.11.0" + "define-properties": "^1.1.2", + "es-abstract": "^1.7.0" } }, + "array-map": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/array-map/-/array-map-0.0.0.tgz", + "integrity": "sha1-iKK6tz0c97zVwbEYoAP2b2ZfpmI=" + }, + "array-reduce": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/array-reduce/-/array-reduce-0.0.0.tgz", + "integrity": "sha1-FziZ0//Rx9k4PkR5Ul2+J4yrXys=" + }, "array-union": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", - "dev": true, "requires": { - "array-uniq": "1.0.3" + "array-uniq": "^1.0.1" } }, "array-uniq": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", - "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", - "dev": true + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=" }, "array-unique": { "version": "0.3.2", @@ -306,35 +391,35 @@ "optional": true }, "asn1": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", - "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=" + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha1-jSR136tVO7M+d7VOWeiAu4ziMTY=", + "requires": { + "safer-buffer": "~2.1.0" + } }, "asn1.js": { "version": "4.10.1", "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", "integrity": "sha1-ucK/WAXx5kqt7tbfOiv6+1pz9aA=", - "dev": true, "requires": { - "bn.js": "4.11.8", - "inherits": "2.0.3", - "minimalistic-assert": "1.0.1" + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" } }, "assert": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz", "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=", - "dev": true, "requires": { "util": "0.10.3" } }, "assert-plus": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", - "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=", - "dev": true + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" }, "assign-symbols": { "version": "1.0.0", @@ -349,12 +434,20 @@ "dev": true }, "async": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.0.tgz", - "integrity": "sha512-xAfGg1/NTLBBKlHFmnd7PlmUW9KhVQIUuSrYem9xzFUZy13ScvtyGGejaae9iAVRiRq9+Cx7DPFaAAhCpyxyPw==", + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", + "integrity": "sha1-skWiPKcZMAROxT+kaqAKPofGphA=", "dev": true, "requires": { - "lodash": "4.17.5" + "lodash": "^4.17.10" + }, + "dependencies": { + "lodash": { + "version": "4.17.10", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==", + "dev": true + } } }, "async-each": { @@ -363,12 +456,6 @@ "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=", "dev": true }, - "async-each-series": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/async-each-series/-/async-each-series-1.1.0.tgz", - "integrity": "sha1-9C/YFV048hpbjqB8KOBj7RcAsTg=", - "dev": true - }, "async-foreach": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/async-foreach/-/async-foreach-0.1.3.tgz", @@ -381,9 +468,9 @@ "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" }, "atob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.1.tgz", - "integrity": "sha1-ri1acpR38onWDdf5amMUoi3Wwio=", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha1-bZUX654DDSQ2ZmZR6GvZ9vE1M8k=", "dev": true }, "autoprefixer": { @@ -392,18 +479,18 @@ "integrity": "sha1-JWZy+G98c12oScTwfQCKuwVgZ9w=", "dev": true, "requires": { - "browserslist": "2.11.3", - "caniuse-lite": "1.0.30000832", - "normalize-range": "0.1.2", - "num2fraction": "1.2.2", - "postcss": "6.0.19", - "postcss-value-parser": "3.3.0" + "browserslist": "^2.11.3", + "caniuse-lite": "^1.0.30000805", + "normalize-range": "^0.1.2", + "num2fraction": "^1.2.2", + "postcss": "^6.0.17", + "postcss-value-parser": "^3.2.3" } }, "aws-sign2": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", - "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=", + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", "dev": true }, "aws4": { @@ -417,8 +504,8 @@ "integrity": "sha1-uk+S8XFn37q0CYN4VFS5rBScPG0=", "dev": true, "requires": { - "follow-redirects": "1.4.1", - "is-buffer": "1.1.6" + "follow-redirects": "^1.2.3", + "is-buffer": "^1.1.5" } }, "babel-code-frame": { @@ -427,42 +514,42 @@ "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", "dev": true, "requires": { - "chalk": "1.1.3", - "esutils": "2.0.2", - "js-tokens": "3.0.2" + "chalk": "^1.1.3", + "esutils": "^2.0.2", + "js-tokens": "^3.0.2" } }, "babel-core": { "version": "6.26.3", "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.3.tgz", - "integrity": "sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA==", + "integrity": "sha1-suLwnjQtDwyI4vAuBneUEl51wgc=", "dev": true, "requires": { - "babel-code-frame": "6.26.0", - "babel-generator": "6.26.1", - "babel-helpers": "6.24.1", - "babel-messages": "6.23.0", - "babel-register": "6.26.0", - "babel-runtime": "6.26.0", - "babel-template": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0", - "babylon": "6.18.0", - "convert-source-map": "1.5.1", - "debug": "2.6.9", - "json5": "0.5.1", - "lodash": "4.17.5", - "minimatch": "3.0.4", - "path-is-absolute": "1.0.1", - "private": "0.1.8", - "slash": "1.0.0", - "source-map": "0.5.7" + "babel-code-frame": "^6.26.0", + "babel-generator": "^6.26.0", + "babel-helpers": "^6.24.1", + "babel-messages": "^6.23.0", + "babel-register": "^6.26.0", + "babel-runtime": "^6.26.0", + "babel-template": "^6.26.0", + "babel-traverse": "^6.26.0", + "babel-types": "^6.26.0", + "babylon": "^6.18.0", + "convert-source-map": "^1.5.1", + "debug": "^2.6.9", + "json5": "^0.5.1", + "lodash": "^4.17.4", + "minimatch": "^3.0.4", + "path-is-absolute": "^1.0.1", + "private": "^0.1.8", + "slash": "^1.0.0", + "source-map": "^0.5.7" }, "dependencies": { "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", "dev": true, "requires": { "ms": "2.0.0" @@ -476,14 +563,14 @@ "integrity": "sha1-GERAjTuPDTWkBOp6wYDwh6YBvZA=", "dev": true, "requires": { - "babel-messages": "6.23.0", - "babel-runtime": "6.26.0", - "babel-types": "6.26.0", - "detect-indent": "4.0.0", - "jsesc": "1.3.0", - "lodash": "4.17.5", - "source-map": "0.5.7", - "trim-right": "1.0.1" + "babel-messages": "^6.23.0", + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "detect-indent": "^4.0.0", + "jsesc": "^1.3.0", + "lodash": "^4.17.4", + "source-map": "^0.5.7", + "trim-right": "^1.0.1" }, "dependencies": { "jsesc": { @@ -500,9 +587,9 @@ "integrity": "sha1-zORReto1b0IgvK6KAsKzRvmlZmQ=", "dev": true, "requires": { - "babel-helper-explode-assignable-expression": "6.24.1", - "babel-runtime": "6.26.0", - "babel-types": "6.26.0" + "babel-helper-explode-assignable-expression": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" } }, "babel-helper-call-delegate": { @@ -511,10 +598,10 @@ "integrity": "sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340=", "dev": true, "requires": { - "babel-helper-hoist-variables": "6.24.1", - "babel-runtime": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0" + "babel-helper-hoist-variables": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" } }, "babel-helper-define-map": { @@ -523,10 +610,10 @@ "integrity": "sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8=", "dev": true, "requires": { - "babel-helper-function-name": "6.24.1", - "babel-runtime": "6.26.0", - "babel-types": "6.26.0", - "lodash": "4.17.5" + "babel-helper-function-name": "^6.24.1", + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "lodash": "^4.17.4" } }, "babel-helper-explode-assignable-expression": { @@ -535,9 +622,9 @@ "integrity": "sha1-8luCz33BBDPFX3BZLVdGQArCLKo=", "dev": true, "requires": { - "babel-runtime": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0" + "babel-runtime": "^6.22.0", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" } }, "babel-helper-function-name": { @@ -546,11 +633,11 @@ "integrity": "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=", "dev": true, "requires": { - "babel-helper-get-function-arity": "6.24.1", - "babel-runtime": "6.26.0", - "babel-template": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0" + "babel-helper-get-function-arity": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" } }, "babel-helper-get-function-arity": { @@ -559,8 +646,8 @@ "integrity": "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=", "dev": true, "requires": { - "babel-runtime": "6.26.0", - "babel-types": "6.26.0" + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" } }, "babel-helper-hoist-variables": { @@ -569,8 +656,8 @@ "integrity": "sha1-HssnaJydJVE+rbyZFKc/VAi+enY=", "dev": true, "requires": { - "babel-runtime": "6.26.0", - "babel-types": "6.26.0" + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" } }, "babel-helper-optimise-call-expression": { @@ -579,8 +666,8 @@ "integrity": "sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc=", "dev": true, "requires": { - "babel-runtime": "6.26.0", - "babel-types": "6.26.0" + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" } }, "babel-helper-regex": { @@ -589,9 +676,9 @@ "integrity": "sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI=", "dev": true, "requires": { - "babel-runtime": "6.26.0", - "babel-types": "6.26.0", - "lodash": "4.17.5" + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "lodash": "^4.17.4" } }, "babel-helper-remap-async-to-generator": { @@ -600,11 +687,11 @@ "integrity": "sha1-XsWBgnrXI/7N04HxySg5BnbkVRs=", "dev": true, "requires": { - "babel-helper-function-name": "6.24.1", - "babel-runtime": "6.26.0", - "babel-template": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0" + "babel-helper-function-name": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" } }, "babel-helper-replace-supers": { @@ -613,12 +700,12 @@ "integrity": "sha1-v22/5Dk40XNpohPKiov3S2qQqxo=", "dev": true, "requires": { - "babel-helper-optimise-call-expression": "6.24.1", - "babel-messages": "6.23.0", - "babel-runtime": "6.26.0", - "babel-template": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0" + "babel-helper-optimise-call-expression": "^6.24.1", + "babel-messages": "^6.23.0", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" } }, "babel-helpers": { @@ -627,19 +714,19 @@ "integrity": "sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=", "dev": true, "requires": { - "babel-runtime": "6.26.0", - "babel-template": "6.26.0" + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" } }, "babel-loader": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-7.1.4.tgz", - "integrity": "sha512-/hbyEvPzBJuGpk9o80R0ZyTej6heEOr59GoEUtn8qFKbnx4cJm9FWES6J/iv644sYgrtVw9JJQkjaLW/bqb5gw==", + "version": "7.1.5", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-7.1.5.tgz", + "integrity": "sha1-4+4M1zlKpVfgE7AtPkkr/QeqbWg=", "dev": true, "requires": { - "find-cache-dir": "1.0.0", - "loader-utils": "1.1.0", - "mkdirp": "0.5.1" + "find-cache-dir": "^1.0.0", + "loader-utils": "^1.0.2", + "mkdirp": "^0.5.1" } }, "babel-messages": { @@ -648,7 +735,7 @@ "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", "dev": true, "requires": { - "babel-runtime": "6.26.0" + "babel-runtime": "^6.22.0" } }, "babel-plugin-check-es2015-constants": { @@ -657,7 +744,7 @@ "integrity": "sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o=", "dev": true, "requires": { - "babel-runtime": "6.26.0" + "babel-runtime": "^6.22.0" } }, "babel-plugin-syntax-async-functions": { @@ -690,9 +777,9 @@ "integrity": "sha1-ZTbjeK/2yx1VF6wOQOs+n8jQh2E=", "dev": true, "requires": { - "babel-helper-remap-async-to-generator": "6.24.1", - "babel-plugin-syntax-async-functions": "6.13.0", - "babel-runtime": "6.26.0" + "babel-helper-remap-async-to-generator": "^6.24.1", + "babel-plugin-syntax-async-functions": "^6.8.0", + "babel-runtime": "^6.22.0" } }, "babel-plugin-transform-es2015-arrow-functions": { @@ -701,7 +788,7 @@ "integrity": "sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE=", "dev": true, "requires": { - "babel-runtime": "6.26.0" + "babel-runtime": "^6.22.0" } }, "babel-plugin-transform-es2015-block-scoped-functions": { @@ -710,7 +797,7 @@ "integrity": "sha1-u8UbSflk1wy42OC5ToICRs46YUE=", "dev": true, "requires": { - "babel-runtime": "6.26.0" + "babel-runtime": "^6.22.0" } }, "babel-plugin-transform-es2015-block-scoping": { @@ -719,11 +806,11 @@ "integrity": "sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8=", "dev": true, "requires": { - "babel-runtime": "6.26.0", - "babel-template": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0", - "lodash": "4.17.5" + "babel-runtime": "^6.26.0", + "babel-template": "^6.26.0", + "babel-traverse": "^6.26.0", + "babel-types": "^6.26.0", + "lodash": "^4.17.4" } }, "babel-plugin-transform-es2015-classes": { @@ -732,15 +819,15 @@ "integrity": "sha1-WkxYpQyclGHlZLSyo7+ryXolhNs=", "dev": true, "requires": { - "babel-helper-define-map": "6.26.0", - "babel-helper-function-name": "6.24.1", - "babel-helper-optimise-call-expression": "6.24.1", - "babel-helper-replace-supers": "6.24.1", - "babel-messages": "6.23.0", - "babel-runtime": "6.26.0", - "babel-template": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0" + "babel-helper-define-map": "^6.24.1", + "babel-helper-function-name": "^6.24.1", + "babel-helper-optimise-call-expression": "^6.24.1", + "babel-helper-replace-supers": "^6.24.1", + "babel-messages": "^6.23.0", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" } }, "babel-plugin-transform-es2015-computed-properties": { @@ -749,8 +836,8 @@ "integrity": "sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM=", "dev": true, "requires": { - "babel-runtime": "6.26.0", - "babel-template": "6.26.0" + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" } }, "babel-plugin-transform-es2015-destructuring": { @@ -759,7 +846,7 @@ "integrity": "sha1-mXux8auWf2gtKwh2/jWNYOdlxW0=", "dev": true, "requires": { - "babel-runtime": "6.26.0" + "babel-runtime": "^6.22.0" } }, "babel-plugin-transform-es2015-duplicate-keys": { @@ -768,8 +855,8 @@ "integrity": "sha1-c+s9MQypaePvnskcU3QabxV2Qj4=", "dev": true, "requires": { - "babel-runtime": "6.26.0", - "babel-types": "6.26.0" + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" } }, "babel-plugin-transform-es2015-for-of": { @@ -778,7 +865,7 @@ "integrity": "sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE=", "dev": true, "requires": { - "babel-runtime": "6.26.0" + "babel-runtime": "^6.22.0" } }, "babel-plugin-transform-es2015-function-name": { @@ -787,9 +874,9 @@ "integrity": "sha1-g0yJhTvDaxrw86TF26qU/Y6sqos=", "dev": true, "requires": { - "babel-helper-function-name": "6.24.1", - "babel-runtime": "6.26.0", - "babel-types": "6.26.0" + "babel-helper-function-name": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" } }, "babel-plugin-transform-es2015-literals": { @@ -798,7 +885,7 @@ "integrity": "sha1-T1SgLWzWbPkVKAAZox0xklN3yi4=", "dev": true, "requires": { - "babel-runtime": "6.26.0" + "babel-runtime": "^6.22.0" } }, "babel-plugin-transform-es2015-modules-amd": { @@ -807,9 +894,9 @@ "integrity": "sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ=", "dev": true, "requires": { - "babel-plugin-transform-es2015-modules-commonjs": "6.26.0", - "babel-runtime": "6.26.0", - "babel-template": "6.26.0" + "babel-plugin-transform-es2015-modules-commonjs": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" } }, "babel-plugin-transform-es2015-modules-commonjs": { @@ -818,10 +905,10 @@ "integrity": "sha1-DYOUApt9xqvhqX7xgeAHWN0uXYo=", "dev": true, "requires": { - "babel-plugin-transform-strict-mode": "6.24.1", - "babel-runtime": "6.26.0", - "babel-template": "6.26.0", - "babel-types": "6.26.0" + "babel-plugin-transform-strict-mode": "^6.24.1", + "babel-runtime": "^6.26.0", + "babel-template": "^6.26.0", + "babel-types": "^6.26.0" } }, "babel-plugin-transform-es2015-modules-systemjs": { @@ -830,9 +917,9 @@ "integrity": "sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM=", "dev": true, "requires": { - "babel-helper-hoist-variables": "6.24.1", - "babel-runtime": "6.26.0", - "babel-template": "6.26.0" + "babel-helper-hoist-variables": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" } }, "babel-plugin-transform-es2015-modules-umd": { @@ -841,9 +928,9 @@ "integrity": "sha1-rJl+YoXNGO1hdq22B9YCNErThGg=", "dev": true, "requires": { - "babel-plugin-transform-es2015-modules-amd": "6.24.1", - "babel-runtime": "6.26.0", - "babel-template": "6.26.0" + "babel-plugin-transform-es2015-modules-amd": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" } }, "babel-plugin-transform-es2015-object-super": { @@ -852,8 +939,8 @@ "integrity": "sha1-JM72muIcuDp/hgPa0CH1cusnj40=", "dev": true, "requires": { - "babel-helper-replace-supers": "6.24.1", - "babel-runtime": "6.26.0" + "babel-helper-replace-supers": "^6.24.1", + "babel-runtime": "^6.22.0" } }, "babel-plugin-transform-es2015-parameters": { @@ -862,12 +949,12 @@ "integrity": "sha1-V6w1GrScrxSpfNE7CfZv3wpiXys=", "dev": true, "requires": { - "babel-helper-call-delegate": "6.24.1", - "babel-helper-get-function-arity": "6.24.1", - "babel-runtime": "6.26.0", - "babel-template": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0" + "babel-helper-call-delegate": "^6.24.1", + "babel-helper-get-function-arity": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" } }, "babel-plugin-transform-es2015-shorthand-properties": { @@ -876,8 +963,8 @@ "integrity": "sha1-JPh11nIch2YbvZmkYi5R8U3jiqA=", "dev": true, "requires": { - "babel-runtime": "6.26.0", - "babel-types": "6.26.0" + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" } }, "babel-plugin-transform-es2015-spread": { @@ -886,7 +973,7 @@ "integrity": "sha1-1taKmfia7cRTbIGlQujdnxdG+NE=", "dev": true, "requires": { - "babel-runtime": "6.26.0" + "babel-runtime": "^6.22.0" } }, "babel-plugin-transform-es2015-sticky-regex": { @@ -895,9 +982,9 @@ "integrity": "sha1-AMHNsaynERLN8M9hJsLta0V8zbw=", "dev": true, "requires": { - "babel-helper-regex": "6.26.0", - "babel-runtime": "6.26.0", - "babel-types": "6.26.0" + "babel-helper-regex": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" } }, "babel-plugin-transform-es2015-template-literals": { @@ -906,7 +993,7 @@ "integrity": "sha1-qEs0UPfp+PH2g51taH2oS7EjbY0=", "dev": true, "requires": { - "babel-runtime": "6.26.0" + "babel-runtime": "^6.22.0" } }, "babel-plugin-transform-es2015-typeof-symbol": { @@ -915,7 +1002,7 @@ "integrity": "sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I=", "dev": true, "requires": { - "babel-runtime": "6.26.0" + "babel-runtime": "^6.22.0" } }, "babel-plugin-transform-es2015-unicode-regex": { @@ -924,9 +1011,9 @@ "integrity": "sha1-04sS9C6nMj9yk4fxinxa4frrNek=", "dev": true, "requires": { - "babel-helper-regex": "6.26.0", - "babel-runtime": "6.26.0", - "regexpu-core": "2.0.0" + "babel-helper-regex": "^6.24.1", + "babel-runtime": "^6.22.0", + "regexpu-core": "^2.0.0" } }, "babel-plugin-transform-exponentiation-operator": { @@ -935,9 +1022,9 @@ "integrity": "sha1-KrDJx/MJj6SJB3cruBP+QejeOg4=", "dev": true, "requires": { - "babel-helper-builder-binary-assignment-operator-visitor": "6.24.1", - "babel-plugin-syntax-exponentiation-operator": "6.13.0", - "babel-runtime": "6.26.0" + "babel-helper-builder-binary-assignment-operator-visitor": "^6.24.1", + "babel-plugin-syntax-exponentiation-operator": "^6.8.0", + "babel-runtime": "^6.22.0" } }, "babel-plugin-transform-object-rest-spread": { @@ -946,8 +1033,8 @@ "integrity": "sha1-DzZpLVD+9rfi1LOsFHgTepY7ewY=", "dev": true, "requires": { - "babel-plugin-syntax-object-rest-spread": "6.13.0", - "babel-runtime": "6.26.0" + "babel-plugin-syntax-object-rest-spread": "^6.8.0", + "babel-runtime": "^6.26.0" } }, "babel-plugin-transform-regenerator": { @@ -956,7 +1043,7 @@ "integrity": "sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8=", "dev": true, "requires": { - "regenerator-transform": "0.10.1" + "regenerator-transform": "^0.10.0" } }, "babel-plugin-transform-runtime": { @@ -965,7 +1052,7 @@ "integrity": "sha1-iEkNRGUC6puOfvsP4J7E2ZR5se4=", "dev": true, "requires": { - "babel-runtime": "6.26.0" + "babel-runtime": "^6.22.0" } }, "babel-plugin-transform-strict-mode": { @@ -974,46 +1061,58 @@ "integrity": "sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g=", "dev": true, "requires": { - "babel-runtime": "6.26.0", - "babel-types": "6.26.0" + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" } }, "babel-preset-env": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/babel-preset-env/-/babel-preset-env-1.6.1.tgz", - "integrity": "sha512-W6VIyA6Ch9ePMI7VptNn2wBM6dbG0eSz25HEiL40nQXCsXGTGZSTZu1Iap+cj3Q0S5a7T9+529l/5Bkvd+afNA==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/babel-preset-env/-/babel-preset-env-1.7.0.tgz", + "integrity": "sha1-3qefpOvriDzTXasH4mDBycBN93o=", "dev": true, "requires": { - "babel-plugin-check-es2015-constants": "6.22.0", - "babel-plugin-syntax-trailing-function-commas": "6.22.0", - "babel-plugin-transform-async-to-generator": "6.24.1", - "babel-plugin-transform-es2015-arrow-functions": "6.22.0", - "babel-plugin-transform-es2015-block-scoped-functions": "6.22.0", - "babel-plugin-transform-es2015-block-scoping": "6.26.0", - "babel-plugin-transform-es2015-classes": "6.24.1", - "babel-plugin-transform-es2015-computed-properties": "6.24.1", - "babel-plugin-transform-es2015-destructuring": "6.23.0", - "babel-plugin-transform-es2015-duplicate-keys": "6.24.1", - "babel-plugin-transform-es2015-for-of": "6.23.0", - "babel-plugin-transform-es2015-function-name": "6.24.1", - "babel-plugin-transform-es2015-literals": "6.22.0", - "babel-plugin-transform-es2015-modules-amd": "6.24.1", - "babel-plugin-transform-es2015-modules-commonjs": "6.26.0", - "babel-plugin-transform-es2015-modules-systemjs": "6.24.1", - "babel-plugin-transform-es2015-modules-umd": "6.24.1", - "babel-plugin-transform-es2015-object-super": "6.24.1", - "babel-plugin-transform-es2015-parameters": "6.24.1", - "babel-plugin-transform-es2015-shorthand-properties": "6.24.1", - "babel-plugin-transform-es2015-spread": "6.22.0", - "babel-plugin-transform-es2015-sticky-regex": "6.24.1", - "babel-plugin-transform-es2015-template-literals": "6.22.0", - "babel-plugin-transform-es2015-typeof-symbol": "6.23.0", - "babel-plugin-transform-es2015-unicode-regex": "6.24.1", - "babel-plugin-transform-exponentiation-operator": "6.24.1", - "babel-plugin-transform-regenerator": "6.26.0", - "browserslist": "2.11.3", - "invariant": "2.2.3", - "semver": "5.5.0" + "babel-plugin-check-es2015-constants": "^6.22.0", + "babel-plugin-syntax-trailing-function-commas": "^6.22.0", + "babel-plugin-transform-async-to-generator": "^6.22.0", + "babel-plugin-transform-es2015-arrow-functions": "^6.22.0", + "babel-plugin-transform-es2015-block-scoped-functions": "^6.22.0", + "babel-plugin-transform-es2015-block-scoping": "^6.23.0", + "babel-plugin-transform-es2015-classes": "^6.23.0", + "babel-plugin-transform-es2015-computed-properties": "^6.22.0", + "babel-plugin-transform-es2015-destructuring": "^6.23.0", + "babel-plugin-transform-es2015-duplicate-keys": "^6.22.0", + "babel-plugin-transform-es2015-for-of": "^6.23.0", + "babel-plugin-transform-es2015-function-name": "^6.22.0", + "babel-plugin-transform-es2015-literals": "^6.22.0", + "babel-plugin-transform-es2015-modules-amd": "^6.22.0", + "babel-plugin-transform-es2015-modules-commonjs": "^6.23.0", + "babel-plugin-transform-es2015-modules-systemjs": "^6.23.0", + "babel-plugin-transform-es2015-modules-umd": "^6.23.0", + "babel-plugin-transform-es2015-object-super": "^6.22.0", + "babel-plugin-transform-es2015-parameters": "^6.23.0", + "babel-plugin-transform-es2015-shorthand-properties": "^6.22.0", + "babel-plugin-transform-es2015-spread": "^6.22.0", + "babel-plugin-transform-es2015-sticky-regex": "^6.22.0", + "babel-plugin-transform-es2015-template-literals": "^6.22.0", + "babel-plugin-transform-es2015-typeof-symbol": "^6.23.0", + "babel-plugin-transform-es2015-unicode-regex": "^6.22.0", + "babel-plugin-transform-exponentiation-operator": "^6.22.0", + "babel-plugin-transform-regenerator": "^6.22.0", + "browserslist": "^3.2.6", + "invariant": "^2.2.2", + "semver": "^5.3.0" + }, + "dependencies": { + "browserslist": { + "version": "3.2.8", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-3.2.8.tgz", + "integrity": "sha1-sABTYdZHHw9ZUnl6dvyYXx+Xj8Y=", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30000844", + "electron-to-chromium": "^1.3.47" + } + } } }, "babel-preset-es2015": { @@ -1022,30 +1121,30 @@ "integrity": "sha1-1EBQ1rwsn+6nAqrzjXJ6AhBTiTk=", "dev": true, "requires": { - "babel-plugin-check-es2015-constants": "6.22.0", - "babel-plugin-transform-es2015-arrow-functions": "6.22.0", - "babel-plugin-transform-es2015-block-scoped-functions": "6.22.0", - "babel-plugin-transform-es2015-block-scoping": "6.26.0", - "babel-plugin-transform-es2015-classes": "6.24.1", - "babel-plugin-transform-es2015-computed-properties": "6.24.1", - "babel-plugin-transform-es2015-destructuring": "6.23.0", - "babel-plugin-transform-es2015-duplicate-keys": "6.24.1", - "babel-plugin-transform-es2015-for-of": "6.23.0", - "babel-plugin-transform-es2015-function-name": "6.24.1", - "babel-plugin-transform-es2015-literals": "6.22.0", - "babel-plugin-transform-es2015-modules-amd": "6.24.1", - "babel-plugin-transform-es2015-modules-commonjs": "6.26.0", - "babel-plugin-transform-es2015-modules-systemjs": "6.24.1", - "babel-plugin-transform-es2015-modules-umd": "6.24.1", - "babel-plugin-transform-es2015-object-super": "6.24.1", - "babel-plugin-transform-es2015-parameters": "6.24.1", - "babel-plugin-transform-es2015-shorthand-properties": "6.24.1", - "babel-plugin-transform-es2015-spread": "6.22.0", - "babel-plugin-transform-es2015-sticky-regex": "6.24.1", - "babel-plugin-transform-es2015-template-literals": "6.22.0", - "babel-plugin-transform-es2015-typeof-symbol": "6.23.0", - "babel-plugin-transform-es2015-unicode-regex": "6.24.1", - "babel-plugin-transform-regenerator": "6.26.0" + "babel-plugin-check-es2015-constants": "^6.22.0", + "babel-plugin-transform-es2015-arrow-functions": "^6.22.0", + "babel-plugin-transform-es2015-block-scoped-functions": "^6.22.0", + "babel-plugin-transform-es2015-block-scoping": "^6.24.1", + "babel-plugin-transform-es2015-classes": "^6.24.1", + "babel-plugin-transform-es2015-computed-properties": "^6.24.1", + "babel-plugin-transform-es2015-destructuring": "^6.22.0", + "babel-plugin-transform-es2015-duplicate-keys": "^6.24.1", + "babel-plugin-transform-es2015-for-of": "^6.22.0", + "babel-plugin-transform-es2015-function-name": "^6.24.1", + "babel-plugin-transform-es2015-literals": "^6.22.0", + "babel-plugin-transform-es2015-modules-amd": "^6.24.1", + "babel-plugin-transform-es2015-modules-commonjs": "^6.24.1", + "babel-plugin-transform-es2015-modules-systemjs": "^6.24.1", + "babel-plugin-transform-es2015-modules-umd": "^6.24.1", + "babel-plugin-transform-es2015-object-super": "^6.24.1", + "babel-plugin-transform-es2015-parameters": "^6.24.1", + "babel-plugin-transform-es2015-shorthand-properties": "^6.24.1", + "babel-plugin-transform-es2015-spread": "^6.22.0", + "babel-plugin-transform-es2015-sticky-regex": "^6.24.1", + "babel-plugin-transform-es2015-template-literals": "^6.22.0", + "babel-plugin-transform-es2015-typeof-symbol": "^6.22.0", + "babel-plugin-transform-es2015-unicode-regex": "^6.24.1", + "babel-plugin-transform-regenerator": "^6.24.1" } }, "babel-preset-es2016": { @@ -1054,7 +1153,7 @@ "integrity": "sha1-+QC/k+LrwNJ235uKtZck6/2Vn4s=", "dev": true, "requires": { - "babel-plugin-transform-exponentiation-operator": "6.24.1" + "babel-plugin-transform-exponentiation-operator": "^6.24.1" } }, "babel-preset-es2017": { @@ -1063,8 +1162,8 @@ "integrity": "sha1-WXvq37n38gi8/YoS6bKym4svFNE=", "dev": true, "requires": { - "babel-plugin-syntax-trailing-function-commas": "6.22.0", - "babel-plugin-transform-async-to-generator": "6.24.1" + "babel-plugin-syntax-trailing-function-commas": "^6.22.0", + "babel-plugin-transform-async-to-generator": "^6.24.1" } }, "babel-preset-latest": { @@ -1073,9 +1172,9 @@ "integrity": "sha1-Z33gaRVKdIXC0lxXfAL2JLhbheg=", "dev": true, "requires": { - "babel-preset-es2015": "6.24.1", - "babel-preset-es2016": "6.24.1", - "babel-preset-es2017": "6.24.1" + "babel-preset-es2015": "^6.24.1", + "babel-preset-es2016": "^6.24.1", + "babel-preset-es2017": "^6.24.1" } }, "babel-register": { @@ -1084,13 +1183,13 @@ "integrity": "sha1-btAhFz4vy0htestFxgCahW9kcHE=", "dev": true, "requires": { - "babel-core": "6.26.3", - "babel-runtime": "6.26.0", - "core-js": "2.5.3", - "home-or-tmp": "2.0.0", - "lodash": "4.17.5", - "mkdirp": "0.5.1", - "source-map-support": "0.4.18" + "babel-core": "^6.26.0", + "babel-runtime": "^6.26.0", + "core-js": "^2.5.0", + "home-or-tmp": "^2.0.0", + "lodash": "^4.17.4", + "mkdirp": "^0.5.1", + "source-map-support": "^0.4.15" } }, "babel-runtime": { @@ -1099,8 +1198,8 @@ "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", "dev": true, "requires": { - "core-js": "2.5.3", - "regenerator-runtime": "0.11.1" + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" } }, "babel-template": { @@ -1109,11 +1208,11 @@ "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=", "dev": true, "requires": { - "babel-runtime": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0", - "babylon": "6.18.0", - "lodash": "4.17.5" + "babel-runtime": "^6.26.0", + "babel-traverse": "^6.26.0", + "babel-types": "^6.26.0", + "babylon": "^6.18.0", + "lodash": "^4.17.4" } }, "babel-traverse": { @@ -1122,15 +1221,15 @@ "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=", "dev": true, "requires": { - "babel-code-frame": "6.26.0", - "babel-messages": "6.23.0", - "babel-runtime": "6.26.0", - "babel-types": "6.26.0", - "babylon": "6.18.0", - "debug": "2.6.9", - "globals": "9.18.0", - "invariant": "2.2.3", - "lodash": "4.17.5" + "babel-code-frame": "^6.26.0", + "babel-messages": "^6.23.0", + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "babylon": "^6.18.0", + "debug": "^2.6.8", + "globals": "^9.18.0", + "invariant": "^2.2.2", + "lodash": "^4.17.4" }, "dependencies": { "debug": { @@ -1150,10 +1249,10 @@ "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", "dev": true, "requires": { - "babel-runtime": "6.26.0", - "esutils": "2.0.2", - "lodash": "4.17.5", - "to-fast-properties": "1.0.3" + "babel-runtime": "^6.26.0", + "esutils": "^2.0.2", + "lodash": "^4.17.4", + "to-fast-properties": "^1.0.3" } }, "babylon": { @@ -1165,8 +1264,7 @@ "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" }, "base": { "version": "0.11.2", @@ -1174,13 +1272,13 @@ "integrity": "sha1-e95c7RRbbVUakNuH+DxVi060io8=", "dev": true, "requires": { - "cache-base": "1.0.1", - "class-utils": "0.3.6", - "component-emitter": "1.2.1", - "define-property": "1.0.0", - "isobject": "3.0.1", - "mixin-deep": "1.3.1", - "pascalcase": "0.1.1" + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" }, "dependencies": { "define-property": { @@ -1189,7 +1287,7 @@ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", "dev": true, "requires": { - "is-descriptor": "1.0.2" + "is-descriptor": "^1.0.0" } }, "is-accessor-descriptor": { @@ -1198,7 +1296,7 @@ "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=", "dev": true, "requires": { - "kind-of": "6.0.2" + "kind-of": "^6.0.0" } }, "is-data-descriptor": { @@ -1207,7 +1305,7 @@ "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=", "dev": true, "requires": { - "kind-of": "6.0.2" + "kind-of": "^6.0.0" } }, "is-descriptor": { @@ -1216,18 +1314,17 @@ "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=", "dev": true, "requires": { - "is-accessor-descriptor": "1.0.0", - "is-data-descriptor": "1.0.0", - "kind-of": "6.0.2" + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" } } } }, "base64-js": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-0.0.8.tgz", - "integrity": "sha1-EQHpVE9KdrG8OybUUsqW16NeeXg=", - "dev": true + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz", + "integrity": "sha1-yrHmEY8FEJXli1KBrqjBzSK/wOM=" }, "batch": { "version": "0.6.1", @@ -1236,165 +1333,32 @@ "dev": true }, "bcrypt-pbkdf": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", - "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", "optional": true, "requires": { - "tweetnacl": "0.14.5" + "tweetnacl": "^0.14.3" } }, - "beeper": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/beeper/-/beeper-1.1.1.tgz", - "integrity": "sha1-5tXqjF2tABMEpwsiY4RH9pyy+Ak=", - "dev": true - }, "big.js": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz", "integrity": "sha1-pfwpi4G54Nyi5FiCR4S2XFK6WI4=" }, - "bin-build": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/bin-build/-/bin-build-2.2.0.tgz", - "integrity": "sha1-EfjdYfcP/Por3KpbRvXo/t1CIcw=", - "dev": true, - "requires": { - "archive-type": "3.2.0", - "decompress": "3.0.0", - "download": "4.4.3", - "exec-series": "1.0.3", - "rimraf": "2.6.2", - "tempfile": "1.1.1", - "url-regex": "3.2.0" - }, - "dependencies": { - "tempfile": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/tempfile/-/tempfile-1.1.1.tgz", - "integrity": "sha1-W8xOrsxKsscH2LwR2ZzMmiyyh/I=", - "dev": true, - "requires": { - "os-tmpdir": "1.0.2", - "uuid": "2.0.3" - } - }, - "uuid": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.3.tgz", - "integrity": "sha1-Z+LoY3lyFVMN/zGOW/nc6/1Hsho=", - "dev": true - } - } - }, - "bin-check": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/bin-check/-/bin-check-2.0.0.tgz", - "integrity": "sha1-hvjm9CU4k99g3DFpV/WvAqywWTA=", - "dev": true, - "requires": { - "executable": "1.1.0" - } - }, - "bin-version": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/bin-version/-/bin-version-1.0.4.tgz", - "integrity": "sha1-nrSY7m/Xb3q5p8FgQ2+JV5Q1144=", - "dev": true, - "requires": { - "find-versions": "1.2.1" - } - }, - "bin-version-check": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/bin-version-check/-/bin-version-check-2.1.0.tgz", - "integrity": "sha1-5OXfKQuQaffRETJAMe/BP90RpbA=", - "dev": true, - "requires": { - "bin-version": "1.0.4", - "minimist": "1.2.0", - "semver": "4.3.6", - "semver-truncate": "1.1.2" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - }, - "semver": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz", - "integrity": "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=", - "dev": true - } - } - }, - "bin-wrapper": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/bin-wrapper/-/bin-wrapper-3.0.2.tgz", - "integrity": "sha1-Z9MwYmLksaXy+I7iNGT2plVneus=", - "dev": true, - "requires": { - "bin-check": "2.0.0", - "bin-version-check": "2.1.0", - "download": "4.4.3", - "each-async": "1.1.1", - "lazy-req": "1.1.0", - "os-filter-obj": "1.0.3" - } - }, "binary-extensions": { "version": "1.11.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.11.0.tgz", "integrity": "sha1-RqoXUftqL5PuXmibsQh9SxTGwgU=", "dev": true }, - "bl": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.2.tgz", - "integrity": "sha1-oWCRFxcQPAdBDO9j71Gzl8Alr5w=", - "dev": true, - "requires": { - "readable-stream": "2.3.6", - "safe-buffer": "5.1.1" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "2.0.0", - "safe-buffer": "5.1.1", - "string_decoder": "1.1.1", - "util-deprecate": "1.0.2" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "5.1.1" - } - } - } - }, "block-stream": { "version": "0.0.9", "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=", "dev": true, "requires": { - "inherits": "2.0.3" + "inherits": "~2.0.0" } }, "bluebird": { @@ -1434,8 +1398,7 @@ "bn.js": { "version": "4.11.8", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", - "integrity": "sha1-LN4J617jQfSEdGuwMJsyU7GxRC8=", - "dev": true + "integrity": "sha1-LN4J617jQfSEdGuwMJsyU7GxRC8=" }, "body-parser": { "version": "1.18.2", @@ -1444,15 +1407,15 @@ "dev": true, "requires": { "bytes": "3.0.0", - "content-type": "1.0.4", + "content-type": "~1.0.4", "debug": "2.6.9", - "depd": "1.1.2", - "http-errors": "1.6.3", + "depd": "~1.1.1", + "http-errors": "~1.6.2", "iconv-lite": "0.4.19", - "on-finished": "2.3.0", + "on-finished": "~2.3.0", "qs": "6.5.1", "raw-body": "2.3.2", - "type-is": "1.6.16" + "type-is": "~1.6.15" }, "dependencies": { "debug": { @@ -1478,27 +1441,12 @@ "integrity": "sha1-jokKGD2O6aI5OzhExpGkK897yfU=", "dev": true, "requires": { - "array-flatten": "2.1.1", - "deep-equal": "1.0.1", - "dns-equal": "1.0.0", - "dns-txt": "2.0.2", - "multicast-dns": "6.2.3", - "multicast-dns-service-types": "1.1.0" - } - }, - "boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", - "dev": true - }, - "boom": { - "version": "2.10.1", - "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", - "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", - "dev": true, - "requires": { - "hoek": "2.16.3" + "array-flatten": "^2.1.0", + "deep-equal": "^1.0.1", + "dns-equal": "^1.0.0", + "dns-txt": "^2.0.2", + "multicast-dns": "^6.0.1", + "multicast-dns-service-types": "^1.1.0" } }, "bootstrap": { @@ -1511,7 +1459,7 @@ "resolved": "https://registry.npmjs.org/bootstrap-colorpicker/-/bootstrap-colorpicker-2.5.2.tgz", "integrity": "sha1-M7+yBDSF8S3LPfD2CtFxdizDwOQ=", "requires": { - "jquery": "3.3.1" + "jquery": ">=1.10" } }, "bootstrap-datepicker": { @@ -1519,7 +1467,16 @@ "resolved": "https://registry.npmjs.org/bootstrap-datepicker/-/bootstrap-datepicker-1.8.0.tgz", "integrity": "sha1-xjUTkx5vCfFq6fEbYvMtlQ3zlY4=", "requires": { - "jquery": "3.3.1" + "jquery": ">=1.7.1 <4.0.0" + } + }, + "bootstrap-daterangepicker": { + "version": "2.1.30", + "resolved": "https://registry.npmjs.org/bootstrap-daterangepicker/-/bootstrap-daterangepicker-2.1.30.tgz", + "integrity": "sha1-+JPb//Wk19+qt1Rg6OppabuJaJo=", + "requires": { + "jquery": ">=1.10", + "moment": "^2.9.0" } }, "bootstrap-less": { @@ -1527,13 +1484,27 @@ "resolved": "https://registry.npmjs.org/bootstrap-less/-/bootstrap-less-3.3.8.tgz", "integrity": "sha1-cfKd1af//t/onxYFu63+CjONrlM=" }, + "bootstrap-slider": { + "version": "9.10.0", + "resolved": "https://registry.npmjs.org/bootstrap-slider/-/bootstrap-slider-9.10.0.tgz", + "integrity": "sha1-EQPWvADPv6jPyaJZmrUYxVZD2j8=" + }, + "bootstrap-table": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/bootstrap-table/-/bootstrap-table-1.12.1.tgz", + "integrity": "sha1-ycOXMGeEKpN8BdhjnszLAqvWumU=" + }, + "bootstrap-timepicker": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/bootstrap-timepicker/-/bootstrap-timepicker-0.5.2.tgz", + "integrity": "sha1-EO2fKi8LjMrvzeD89qBzi5GaODU=" + }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha1-PH/L9SnYcibz0vUrlm/1Jx60Qd0=", - "dev": true, "requires": { - "balanced-match": "1.0.0", + "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, @@ -1543,16 +1514,16 @@ "integrity": "sha1-WXn9PxTNUxVl5fot8av/8d+u5yk=", "dev": true, "requires": { - "arr-flatten": "1.1.0", - "array-unique": "0.3.2", - "extend-shallow": "2.0.1", - "fill-range": "4.0.0", - "isobject": "3.0.1", - "repeat-element": "1.1.2", - "snapdragon": "0.8.2", - "snapdragon-node": "2.1.1", - "split-string": "3.1.0", - "to-regex": "3.0.2" + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" }, "dependencies": { "extend-shallow": { @@ -1561,7 +1532,7 @@ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-extendable": "0.1.1" + "is-extendable": "^0.1.0" } } } @@ -1569,77 +1540,203 @@ "brorand": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", - "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", - "dev": true + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=" + }, + "browser-pack": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/browser-pack/-/browser-pack-6.1.0.tgz", + "integrity": "sha1-w0uhDQuc4WK1ryJ8cTHJLC7NV3Q=", + "requires": { + "JSONStream": "^1.0.3", + "combine-source-map": "~0.8.0", + "defined": "^1.0.0", + "safe-buffer": "^5.1.1", + "through2": "^2.0.0", + "umd": "^3.0.0" + } + }, + "browser-resolve": { + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.3.tgz", + "integrity": "sha1-m3y7PQ9RDky4a9vXlhJNKLWJCvY=", + "requires": { + "resolve": "1.1.7" + }, + "dependencies": { + "resolve": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=" + } + } + }, + "browserify": { + "version": "16.2.3", + "resolved": "https://registry.npmjs.org/browserify/-/browserify-16.2.3.tgz", + "integrity": "sha1-fubmVLpPkrzmqzWZw0hbHMegrQs=", + "requires": { + "JSONStream": "^1.0.3", + "assert": "^1.4.0", + "browser-pack": "^6.0.1", + "browser-resolve": "^1.11.0", + "browserify-zlib": "~0.2.0", + "buffer": "^5.0.2", + "cached-path-relative": "^1.0.0", + "concat-stream": "^1.6.0", + "console-browserify": "^1.1.0", + "constants-browserify": "~1.0.0", + "crypto-browserify": "^3.0.0", + "defined": "^1.0.0", + "deps-sort": "^2.0.0", + "domain-browser": "^1.2.0", + "duplexer2": "~0.1.2", + "events": "^2.0.0", + "glob": "^7.1.0", + "has": "^1.0.0", + "htmlescape": "^1.1.0", + "https-browserify": "^1.0.0", + "inherits": "~2.0.1", + "insert-module-globals": "^7.0.0", + "labeled-stream-splicer": "^2.0.0", + "mkdirp": "^0.5.0", + "module-deps": "^6.0.0", + "os-browserify": "~0.3.0", + "parents": "^1.0.1", + "path-browserify": "~0.0.0", + "process": "~0.11.0", + "punycode": "^1.3.2", + "querystring-es3": "~0.2.0", + "read-only-stream": "^2.0.0", + "readable-stream": "^2.0.2", + "resolve": "^1.1.4", + "shasum": "^1.0.0", + "shell-quote": "^1.6.1", + "stream-browserify": "^2.0.0", + "stream-http": "^2.0.0", + "string_decoder": "^1.1.1", + "subarg": "^1.0.0", + "syntax-error": "^1.1.1", + "through2": "^2.0.0", + "timers-browserify": "^1.0.1", + "tty-browserify": "0.0.1", + "url": "~0.11.0", + "util": "~0.10.1", + "vm-browserify": "^1.0.0", + "xtend": "^4.0.0" + }, + "dependencies": { + "buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.2.1.tgz", + "integrity": "sha512-c+Ko0loDaFfuPWiL02ls9Xd3GO3cPVmUobQ6t3rXNUk304u6hGq+8N/kFi+QEIKhzK3uwolVhLzszmfLmMLnqg==", + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "events": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/events/-/events-2.1.0.tgz", + "integrity": "sha512-3Zmiobend8P9DjmKAty0Era4jV8oJ0yGYe2nJJAxgymF9+N8F2m0hhZiMoWtcfepExzNKZumFU3ksdQbInGWCg==" + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "timers-browserify": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-1.4.2.tgz", + "integrity": "sha1-ycWLV1voQHN1y14kYtrO50NZ9B0=", + "requires": { + "process": "~0.11.0" + } + }, + "tty-browserify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.1.tgz", + "integrity": "sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw==" + }, + "vm-browserify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.0.tgz", + "integrity": "sha512-iq+S7vZJE60yejDYM0ek6zg308+UZsdtPExWP9VZoCFCz1zkJoXFnAX7aZfd/ZwrkidzdUZL0C/ryW+JwAiIGw==" + } + } }, "browserify-aes": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", "integrity": "sha1-Mmc0ZC9APavDADIJhTu3CtQo70g=", - "dev": true, "requires": { - "buffer-xor": "1.0.3", - "cipher-base": "1.0.4", - "create-hash": "1.2.0", - "evp_bytestokey": "1.0.3", - "inherits": "2.0.3", - "safe-buffer": "5.1.1" + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" } }, "browserify-cipher": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", "integrity": "sha1-jWR0wbhwv9q807z8wZNKEOlPFfA=", - "dev": true, "requires": { - "browserify-aes": "1.2.0", - "browserify-des": "1.0.1", - "evp_bytestokey": "1.0.3" + "browserify-aes": "^1.0.4", + "browserify-des": "^1.0.0", + "evp_bytestokey": "^1.0.0" } }, "browserify-des": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.1.tgz", - "integrity": "sha512-zy0Cobe3hhgpiOM32Tj7KQ3Vl91m0njwsjzZQK1L+JDf11dzP9qIvjreVinsvXrgfjhStXwUWAEpB9D7Gwmayw==", - "dev": true, + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", + "integrity": "sha1-OvTx9Zg5QDVy8cZiBDdfen9wPpw=", "requires": { - "cipher-base": "1.0.4", - "des.js": "1.0.0", - "inherits": "2.0.3" + "cipher-base": "^1.0.1", + "des.js": "^1.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + } } }, "browserify-rsa": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", - "dev": true, "requires": { - "bn.js": "4.11.8", - "randombytes": "2.0.6" + "bn.js": "^4.1.0", + "randombytes": "^2.0.1" } }, "browserify-sign": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", - "dev": true, "requires": { - "bn.js": "4.11.8", - "browserify-rsa": "4.0.1", - "create-hash": "1.2.0", - "create-hmac": "1.1.7", - "elliptic": "6.4.0", - "inherits": "2.0.3", - "parse-asn1": "5.1.1" + "bn.js": "^4.1.1", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.2", + "elliptic": "^6.0.0", + "inherits": "^2.0.1", + "parse-asn1": "^5.0.0" } }, "browserify-zlib": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", "integrity": "sha1-KGlFnZqjviRf6P4sofRuLn9U1z8=", - "dev": true, "requires": { - "pako": "1.0.6" + "pako": "~1.0.5" } }, "browserslist": { @@ -1648,54 +1745,25 @@ "integrity": "sha1-/jYWeu0bvN5IJ+v+cTR6LMcLmbI=", "dev": true, "requires": { - "caniuse-lite": "1.0.30000832", - "electron-to-chromium": "1.3.44" + "caniuse-lite": "^1.0.30000792", + "electron-to-chromium": "^1.3.30" } }, "buffer": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-3.6.0.tgz", - "integrity": "sha1-pyyTb3e5a/UvX357RnGAYoVR3vs=", + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", + "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", "dev": true, "requires": { - "base64-js": "0.0.8", - "ieee754": "1.1.11", - "isarray": "1.0.0" + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" } }, - "buffer-alloc": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.1.0.tgz", - "integrity": "sha1-BVFNM78WVtNUDGhPZbEgLpDsowM=", - "dev": true, - "requires": { - "buffer-alloc-unsafe": "0.1.1", - "buffer-fill": "0.1.1" - } - }, - "buffer-alloc-unsafe": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-0.1.1.tgz", - "integrity": "sha1-/+H2dVHdBVc33iUzN7/oU9+rGmo=", - "dev": true - }, - "buffer-crc32": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", - "dev": true - }, - "buffer-fill": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-0.1.1.tgz", - "integrity": "sha512-YgBMBzdRLEfgxJIGu2wrvI2E03tMCFU1p7d1KhB4BOoMN0VxmTFjSyN5JtKt9z8Z9JajMHruI6SE25W96wNv7Q==", - "dev": true - }, "buffer-from": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.0.0.tgz", - "integrity": "sha512-83apNb8KK0Se60UE1+4Ukbe3HbfELJ6UlI4ldtOGs7So4KD26orJM8hIY9lxdzP+UpItH1Yh/Y8GUvNFWFFRxA==", - "dev": true + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha1-MnE7wCj3XAL9txDXx7zsHyxgcO8=" }, "buffer-indexof": { "version": "1.1.1", @@ -1703,37 +1771,10 @@ "integrity": "sha1-Uvq8xqYG0aADAoAmSO9o9jnaJow=", "dev": true }, - "buffer-to-vinyl": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/buffer-to-vinyl/-/buffer-to-vinyl-1.1.0.tgz", - "integrity": "sha1-APFfruOreh3aLN5tkSG//dB7ImI=", - "dev": true, - "requires": { - "file-type": "3.9.0", - "readable-stream": "2.3.4", - "uuid": "2.0.3", - "vinyl": "1.2.0" - }, - "dependencies": { - "file-type": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz", - "integrity": "sha1-JXoHg4TR24CHvESdEH1SpSZyuek=", - "dev": true - }, - "uuid": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.3.tgz", - "integrity": "sha1-Z+LoY3lyFVMN/zGOW/nc6/1Hsho=", - "dev": true - } - } - }, "buffer-xor": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", - "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", - "dev": true + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=" }, "builtin-modules": { "version": "1.1.1", @@ -1744,8 +1785,7 @@ "builtin-status-codes": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", - "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=", - "dev": true + "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=" }, "bytes": { "version": "3.0.0", @@ -1759,19 +1799,19 @@ "integrity": "sha1-ZFI2eZnv+dQYiu/ZoU6dfGomNGA=", "dev": true, "requires": { - "bluebird": "3.5.1", - "chownr": "1.0.1", - "glob": "7.1.2", - "graceful-fs": "4.1.11", - "lru-cache": "4.1.1", - "mississippi": "2.0.0", - "mkdirp": "0.5.1", - "move-concurrently": "1.0.1", - "promise-inflight": "1.0.1", - "rimraf": "2.6.2", - "ssri": "5.3.0", - "unique-filename": "1.1.0", - "y18n": "4.0.0" + "bluebird": "^3.5.1", + "chownr": "^1.0.1", + "glob": "^7.1.2", + "graceful-fs": "^4.1.11", + "lru-cache": "^4.1.1", + "mississippi": "^2.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.2", + "ssri": "^5.2.4", + "unique-filename": "^1.1.0", + "y18n": "^4.0.0" }, "dependencies": { "y18n": { @@ -1788,15 +1828,15 @@ "integrity": "sha1-Cn9GQWgxyLZi7jb+TnxZ129marI=", "dev": true, "requires": { - "collection-visit": "1.0.0", - "component-emitter": "1.2.1", - "get-value": "2.0.6", - "has-value": "1.0.0", - "isobject": "3.0.1", - "set-value": "2.0.0", - "to-object-path": "0.3.0", - "union-value": "1.0.0", - "unset-value": "1.0.0" + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" } }, "cacheable-request": { @@ -1813,14 +1853,19 @@ "responselike": "1.0.2" } }, + "cached-path-relative": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cached-path-relative/-/cached-path-relative-1.0.1.tgz", + "integrity": "sha1-0JxLUoAKpMB44t2BqGmqyQ0uVOc=" + }, "camel-case": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz", "integrity": "sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M=", "dev": true, "requires": { - "no-case": "2.3.2", - "upper-case": "1.1.3" + "no-case": "^2.2.0", + "upper-case": "^1.1.1" } }, "camelcase": { @@ -1835,8 +1880,8 @@ "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", "dev": true, "requires": { - "camelcase": "2.1.1", - "map-obj": "1.0.1" + "camelcase": "^2.0.0", + "map-obj": "^1.0.0" } }, "caniuse-api": { @@ -1845,10 +1890,10 @@ "integrity": "sha1-tTTnxzTE+B7F++isoq0kNUuWLGw=", "dev": true, "requires": { - "browserslist": "1.7.7", - "caniuse-db": "1.0.30000832", - "lodash.memoize": "4.1.2", - "lodash.uniq": "4.5.0" + "browserslist": "^1.3.6", + "caniuse-db": "^1.0.30000529", + "lodash.memoize": "^4.1.2", + "lodash.uniq": "^4.5.0" }, "dependencies": { "browserslist": { @@ -1857,28 +1902,22 @@ "integrity": "sha1-C9dnBCWL6CmyOYu1Dkti0aFmsLk=", "dev": true, "requires": { - "caniuse-db": "1.0.30000832", - "electron-to-chromium": "1.3.44" + "caniuse-db": "^1.0.30000639", + "electron-to-chromium": "^1.2.7" } } } }, "caniuse-db": { - "version": "1.0.30000832", - "resolved": "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30000832.tgz", - "integrity": "sha1-r+NMn3xiE5/RxgfbKrcwi7tqUVg=", + "version": "1.0.30000880", + "resolved": "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30000880.tgz", + "integrity": "sha512-vkIXVXe+uJt+AL0nvRXgbD4EgbGb+YQ1OhEPEVapOXEhmvAgnpleNx3flmf+qCItmI4I7lyshHU4yCcxTRDaJg==", "dev": true }, "caniuse-lite": { - "version": "1.0.30000832", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000832.tgz", - "integrity": "sha512-WMC2GiGTPxGywFL70h+CnP7GAYo6LM6JSI1sF13vAZfXCzOeunHzl20DpfbDGMdvtT2wpqvabY96MHEp/la+BQ==", - "dev": true - }, - "capture-stack-trace": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/capture-stack-trace/-/capture-stack-trace-1.0.0.tgz", - "integrity": "sha1-Sm+gc5nCa7pH8LJJa00PtAjFVQ0=", + "version": "1.0.30000880", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000880.tgz", + "integrity": "sha512-G2cDhHp0DshhwFJSurN7PByRTXgijs3eA3F9tGd5tf5vnTttDVuRI9bFna0WDMID4VYhGs2ob9U/K1A5+pm8pw==", "dev": true }, "caseless": { @@ -1886,40 +1925,28 @@ "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" }, - "caw": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/caw/-/caw-1.2.0.tgz", - "integrity": "sha1-/7Im/n78VHKI3GLuPpcHPCEtEDQ=", - "dev": true, - "requires": { - "get-proxy": "1.1.0", - "is-obj": "1.0.1", - "object-assign": "3.0.0", - "tunnel-agent": "0.4.3" - }, - "dependencies": { - "object-assign": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", - "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=", - "dev": true - }, - "tunnel-agent": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz", - "integrity": "sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us=", - "dev": true - } - } - }, "center-align": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", "dev": true, "requires": { - "align-text": "0.1.4", - "lazy-cache": "1.0.4" + "align-text": "^0.1.3", + "lazy-cache": "^1.0.3" + } + }, + "cf-blob.js": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/cf-blob.js/-/cf-blob.js-0.0.1.tgz", + "integrity": "sha1-9at+EueYyvCMz4KMaaug8GPYP5k=" + }, + "cfb": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/cfb/-/cfb-1.0.8.tgz", + "integrity": "sha1-d/ITST1pfXVP2cD1UR6rWtctAs8=", + "requires": { + "commander": "^2.14.1", + "printj": "~1.1.2" } }, "chalk": { @@ -1928,11 +1955,11 @@ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { - "ansi-styles": "2.2.1", - "escape-string-regexp": "1.0.5", - "has-ansi": "2.0.0", - "strip-ansi": "3.0.1", - "supports-color": "2.0.0" + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" } }, "charenc": { @@ -1941,24 +1968,63 @@ "integrity": "sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc=", "dev": true }, + "charm": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/charm/-/charm-0.1.2.tgz", + "integrity": "sha1-BsIe7RobBq62dVPNxT4jJ0usIpY=" + }, + "chart.js": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-2.7.3.tgz", + "integrity": "sha512-3+7k/DbR92m6BsMUYP6M0dMsMVZpMnwkUyNSAbqolHKsbIzH2Q4LWVEHHYq7v0fmEV8whXE0DrjANulw9j2K5g==", + "requires": { + "chartjs-color": "^2.1.0", + "moment": "^2.10.2" + } + }, + "chartjs-color": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/chartjs-color/-/chartjs-color-2.2.0.tgz", + "integrity": "sha1-hKL7dVeH7YXDndbdjHsdiEKbrq4=", + "requires": { + "chartjs-color-string": "^0.5.0", + "color-convert": "^0.5.3" + }, + "dependencies": { + "color-convert": { + "version": "0.5.3", + "resolved": "http://registry.npmjs.org/color-convert/-/color-convert-0.5.3.tgz", + "integrity": "sha1-vbbGnOZg+t/+CwAHzER+G59ygr0=" + } + } + }, + "chartjs-color-string": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/chartjs-color-string/-/chartjs-color-string-0.5.0.tgz", + "integrity": "sha512-amWNvCOXlOUYxZVDSa0YOab5K/lmEhbFNKI55PWc4mlv28BDzA7zaoQTGxSBgJMHIW+hGX8YUrvw/FH4LyhwSQ==", + "requires": { + "color-name": "^1.0.0" + } + }, "chokidar": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.3.tgz", - "integrity": "sha512-zW8iXYZtXMx4kux/nuZVXjkLP+CyIK5Al5FHnj1OgTKGZfp4Oy6/ymtMSKFv3GD8DviEmUPmJg9eFdJ/JzudMg==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.4.tgz", + "integrity": "sha1-NW/04rDo5D4yLRijckYLvPOszSY=", "dev": true, "requires": { - "anymatch": "2.0.0", - "async-each": "1.0.1", - "braces": "2.3.2", - "fsevents": "1.2.3", - "glob-parent": "3.1.0", - "inherits": "2.0.3", - "is-binary-path": "1.0.1", - "is-glob": "4.0.0", - "normalize-path": "2.1.1", - "path-is-absolute": "1.0.1", - "readdirp": "2.1.0", - "upath": "1.0.5" + "anymatch": "^2.0.0", + "async-each": "^1.0.0", + "braces": "^2.3.0", + "fsevents": "^1.2.2", + "glob-parent": "^3.1.0", + "inherits": "^2.0.1", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "lodash.debounce": "^4.0.8", + "normalize-path": "^2.1.1", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.0.0", + "upath": "^1.0.5" } }, "chownr": { @@ -1971,19 +2037,23 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", "integrity": "sha1-h2Dk7MJy9MNjUy+SbYdKriwTl94=", - "dev": true, "requires": { - "inherits": "2.0.3", - "safe-buffer": "5.1.1" + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" } }, + "ckeditor": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/ckeditor/-/ckeditor-4.10.1.tgz", + "integrity": "sha1-4CMLBaVHDvBwvpq5ukRP6kGOvHg=" + }, "clap": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/clap/-/clap-1.2.3.tgz", "integrity": "sha1-TzZ0WzIAhJJVf0ZBLWbVDLmbzlE=", "dev": true, "requires": { - "chalk": "1.1.3" + "chalk": "^1.1.3" } }, "class-utils": { @@ -1992,10 +2062,10 @@ "integrity": "sha1-+TNprouafOAv1B+q0MqDAzGQxGM=", "dev": true, "requires": { - "arr-union": "3.1.0", - "define-property": "0.2.5", - "isobject": "3.0.1", - "static-extend": "0.1.2" + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" }, "dependencies": { "define-property": { @@ -2004,18 +2074,31 @@ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { - "is-descriptor": "0.1.6" + "is-descriptor": "^0.1.0" } } } }, + "classie": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/classie/-/classie-1.0.0.tgz", + "integrity": "sha1-/JsptH5k43SiBi+2JNBaYc1wOrI=" + }, "clean-css": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.1.11.tgz", - "integrity": "sha1-Ls3xRaujj1R0DybO/Q/z4D4SXWo=", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.1.tgz", + "integrity": "sha1-LUEe92uFabbQyEBo2r6FsKpeXBc=", "dev": true, "requires": { - "source-map": "0.5.7" + "source-map": "~0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", + "dev": true + } } }, "cliui": { @@ -2024,9 +2107,9 @@ "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", "dev": true, "requires": { - "string-width": "1.0.2", - "strip-ansi": "3.0.1", - "wrap-ansi": "2.1.0" + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" }, "dependencies": { "is-fullwidth-code-point": { @@ -2035,7 +2118,7 @@ "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", "dev": true, "requires": { - "number-is-nan": "1.0.1" + "number-is-nan": "^1.0.0" } }, "string-width": { @@ -2044,9 +2127,9 @@ "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "dev": true, "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "strip-ansi": "3.0.1" + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" } } } @@ -2062,21 +2145,10 @@ "integrity": "sha1-ANs6Hhc2VnMNEYjD1qztbX6pdxM=", "dev": true, "requires": { - "for-own": "1.0.0", - "is-plain-object": "2.0.4", - "kind-of": "6.0.2", - "shallow-clone": "1.0.0" - }, - "dependencies": { - "for-own": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", - "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", - "dev": true, - "requires": { - "for-in": "1.0.2" - } - } + "for-own": "^1.0.0", + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.0", + "shallow-clone": "^1.0.0" } }, "clone-response": { @@ -2084,15 +2156,9 @@ "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", "requires": { - "mimic-response": "1.0.0" + "mimic-response": "^1.0.0" } }, - "clone-stats": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", - "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=", - "dev": true - }, "co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", @@ -2104,7 +2170,7 @@ "integrity": "sha1-qe8VNmDWqGqL3sAomlxoTSF0Mv0=", "dev": true, "requires": { - "q": "1.5.1" + "q": "^1.1.2" } }, "code-point-at": { @@ -2113,14 +2179,30 @@ "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", "dev": true }, + "codepage": { + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/codepage/-/codepage-1.14.0.tgz", + "integrity": "sha1-jL4lSBMjVZ19MHVxsP/5HnodL5k=", + "requires": { + "commander": "~2.14.1", + "exit-on-epipe": "~1.0.1" + }, + "dependencies": { + "commander": { + "version": "2.14.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.14.1.tgz", + "integrity": "sha1-IjUSPjevjKPGXfRbAm29NXsBuao=" + } + } + }, "collection-visit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", "dev": true, "requires": { - "map-visit": "1.0.0", - "object-visit": "1.0.1" + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" } }, "color": { @@ -2129,9 +2211,9 @@ "integrity": "sha1-bXtcdPtl6EHNSHkq0e1eB7kE12Q=", "dev": true, "requires": { - "clone": "1.0.4", - "color-convert": "1.9.1", - "color-string": "0.3.0" + "clone": "^1.0.2", + "color-convert": "^1.3.0", + "color-string": "^0.3.0" }, "dependencies": { "clone": { @@ -2148,14 +2230,13 @@ "integrity": "sha512-mjGanIiwQJskCC18rPR6OmrZ6fm2Lc7PeGFYwCmy5J34wC6F1PzdGL6xeMfmgicfYcNLGuVFA3WzXtIDCQSZxQ==", "dev": true, "requires": { - "color-name": "1.1.3" + "color-name": "^1.1.1" } }, "color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" }, "color-string": { "version": "0.3.0", @@ -2163,24 +2244,18 @@ "integrity": "sha1-J9RvtnAlxcL6JZk7+/V55HhBuZE=", "dev": true, "requires": { - "color-name": "1.1.3" + "color-name": "^1.0.0" } }, - "color-support": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha1-k4NDeaHMmgxh+C9S8NBDIiUb1aI=", - "dev": true - }, "colormin": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/colormin/-/colormin-1.1.2.tgz", "integrity": "sha1-6i90IKcrlogaOKrlnsEkpvcpgTM=", "dev": true, "requires": { - "color": "0.11.4", + "color": "^0.11.0", "css-color-names": "0.0.4", - "has": "1.0.1" + "has": "^1.0.1" } }, "colors": { @@ -2189,19 +2264,41 @@ "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=", "dev": true }, + "combine-source-map": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/combine-source-map/-/combine-source-map-0.8.0.tgz", + "integrity": "sha1-pY0N8ELBhvz4IqjoAV9UUNLXmos=", + "requires": { + "convert-source-map": "~1.1.0", + "inline-source-map": "~0.6.0", + "lodash.memoize": "~3.0.3", + "source-map": "~0.5.3" + }, + "dependencies": { + "convert-source-map": { + "version": "1.1.3", + "resolved": "http://registry.npmjs.org/convert-source-map/-/convert-source-map-1.1.3.tgz", + "integrity": "sha1-SCnId+n+SbMWHzvzZziI4gRpmGA=" + }, + "lodash.memoize": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-3.0.4.tgz", + "integrity": "sha1-LcvSwofLwKVcxCMovQxzYVDVPj8=" + } + } + }, "combined-stream": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", "requires": { - "delayed-stream": "1.0.0" + "delayed-stream": "~1.0.0" } }, "commander": { - "version": "2.15.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", - "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", - "dev": true + "version": "2.17.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz", + "integrity": "sha1-vXerfebelCBc6sxy8XFtKfIKd78=" }, "commondir": { "version": "1.0.1", @@ -2216,56 +2313,68 @@ "dev": true }, "compressible": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.13.tgz", - "integrity": "sha1-DRAgq5JLL9tNYnmHXH1tq6a6p6k=", + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.14.tgz", + "integrity": "sha1-MmxfUH+7BV9UEWeCuWmoG2einac=", "dev": true, "requires": { - "mime-db": "1.33.0" + "mime-db": ">= 1.34.0 < 2" + }, + "dependencies": { + "mime-db": { + "version": "1.36.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.36.0.tgz", + "integrity": "sha512-L+xvyD9MkoYMXb1jAmzI/lWYAxAMCPvIBSWur0PZ5nOf5euahRLVqH//FKW9mWp2lkqUgYiXPgkzfMUFi4zVDw==", + "dev": true + } } }, "compression": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.2.tgz", - "integrity": "sha1-qv+81qr4VLROuygDU9WtFlH1mmk=", + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.3.tgz", + "integrity": "sha1-J+DhdqryYPfywoE8PkQK258Zk9s=", "dev": true, "requires": { - "accepts": "1.3.5", + "accepts": "~1.3.5", "bytes": "3.0.0", - "compressible": "2.0.13", + "compressible": "~2.0.14", "debug": "2.6.9", - "on-headers": "1.0.1", - "safe-buffer": "5.1.1", - "vary": "1.1.2" + "on-headers": "~1.0.1", + "safe-buffer": "5.1.2", + "vary": "~1.1.2" }, "dependencies": { "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", "dev": true, "requires": { "ms": "2.0.0" } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true } } }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, "concat-stream": { "version": "1.6.2", "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", "integrity": "sha1-kEvfGUzTEi/Gdcd/xKw9T/D9GjQ=", - "dev": true, "requires": { - "buffer-from": "1.0.0", - "inherits": "2.0.3", - "readable-stream": "2.3.4", - "typedarray": "0.0.6" + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" } }, "concatenate": { @@ -2274,17 +2383,7 @@ "integrity": "sha1-C0nW6MQQR9dyjNyNYqCGYjOXtJ8=", "dev": true, "requires": { - "globs": "0.1.4" - } - }, - "config-chain": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.11.tgz", - "integrity": "sha1-q6CXR9++TD5w52am5BWG4YWfxvI=", - "dev": true, - "requires": { - "ini": "1.3.5", - "proto-list": "1.2.4" + "globs": "^0.1.2" } }, "connect-history-api-fallback": { @@ -2297,9 +2396,8 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", - "dev": true, "requires": { - "date-now": "0.1.4" + "date-now": "^0.1.4" } }, "console-control-strings": { @@ -2308,26 +2406,19 @@ "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", "dev": true }, - "console-stream": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/console-stream/-/console-stream-0.1.1.tgz", - "integrity": "sha1-oJX+B7IEZZVfL6/Si11yvM2UnUQ=", - "dev": true - }, "consolidate": { "version": "0.14.5", "resolved": "https://registry.npmjs.org/consolidate/-/consolidate-0.14.5.tgz", "integrity": "sha1-WiUEe8dvcwcmZ8jLUsmJiI9JTGM=", "dev": true, "requires": { - "bluebird": "3.5.1" + "bluebird": "^3.1.1" } }, "constants-browserify": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", - "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=", - "dev": true + "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=" }, "content-disposition": { "version": "0.5.2", @@ -2365,12 +2456,12 @@ "integrity": "sha1-kilzmMrjSTf8r9bsgTnBgFHwteA=", "dev": true, "requires": { - "aproba": "1.2.0", - "fs-write-stream-atomic": "1.0.10", - "iferr": "0.1.5", - "mkdirp": "0.5.1", - "rimraf": "2.6.2", - "run-queue": "1.0.3" + "aproba": "^1.1.1", + "fs-write-stream-atomic": "^1.0.8", + "iferr": "^0.1.5", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.0" } }, "copy-descriptor": { @@ -2396,13 +2487,13 @@ "integrity": "sha512-GiNXLwAFPYHy25XmTPpafYvn3CLAkJ8FLsscq78MQd1Kh0OU6Yzhn4eV2MVF4G9WEQZoWEGltatdR+ntGPMl5A==", "dev": true, "requires": { - "is-directory": "0.3.1", - "js-yaml": "3.7.0", - "minimist": "1.2.0", - "object-assign": "4.1.1", - "os-homedir": "1.0.2", - "parse-json": "2.2.0", - "require-from-string": "1.2.1" + "is-directory": "^0.3.1", + "js-yaml": "^3.4.3", + "minimist": "^1.2.0", + "object-assign": "^4.1.0", + "os-homedir": "^1.0.1", + "parse-json": "^2.2.0", + "require-from-string": "^1.1.0" }, "dependencies": { "minimist": { @@ -2413,50 +2504,47 @@ } } }, - "create-ecdh": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.1.tgz", - "integrity": "sha512-iZvCCg8XqHQZ1ioNBTzXS/cQSkqkqcPs8xSX4upNB+DAk9Ht3uzQf2J32uAHNCne8LDmKr29AgZrEs4oIrwLuQ==", - "dev": true, + "crc-32": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.0.tgz", + "integrity": "sha1-yy224puIUI4y2d0OwWk+e0Ghggg=", "requires": { - "bn.js": "4.11.8", - "elliptic": "6.4.0" + "exit-on-epipe": "~1.0.1", + "printj": "~1.1.0" } }, - "create-error-class": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/create-error-class/-/create-error-class-3.0.2.tgz", - "integrity": "sha1-Br56vvlHo/FKMP1hBnHUAbyot7Y=", - "dev": true, + "create-ecdh": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz", + "integrity": "sha1-yREbbzMEXEaX8UR4f5JUzcd8Rf8=", "requires": { - "capture-stack-trace": "1.0.0" + "bn.js": "^4.1.0", + "elliptic": "^6.0.0" } }, "create-hash": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", "integrity": "sha1-iJB4rxGmN1a8+1m9IhmWvjqe8ZY=", - "dev": true, "requires": { - "cipher-base": "1.0.4", - "inherits": "2.0.3", - "md5.js": "1.3.4", - "ripemd160": "2.0.2", - "sha.js": "2.4.11" + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" } }, "create-hmac": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", "integrity": "sha1-aRcMeLOrlXFHsriwRXLkfq0iQ/8=", - "dev": true, "requires": { - "cipher-base": "1.0.4", - "create-hash": "1.2.0", - "inherits": "2.0.3", - "ripemd160": "2.0.2", - "safe-buffer": "5.1.1", - "sha.js": "2.4.11" + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" } }, "cross-env": { @@ -2465,8 +2553,8 @@ "integrity": "sha512-UOokgwvDzCT0mqRSLEkJzUhYXB1vK3E5UgDrD41QiXsm9UetcW2rCGHYz/O3p873lMJ1VZbFCF9Izkwh7nYR5A==", "dev": true, "requires": { - "cross-spawn": "5.1.0", - "is-windows": "1.0.2" + "cross-spawn": "^5.1.0", + "is-windows": "^1.0.0" } }, "cross-spawn": { @@ -2475,9 +2563,9 @@ "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", "dev": true, "requires": { - "lru-cache": "4.1.1", - "shebang-command": "1.2.0", - "which": "1.3.0" + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" } }, "crypt": { @@ -2486,78 +2574,44 @@ "integrity": "sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=", "dev": true }, - "cryptiles": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", - "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=", - "dev": true, - "requires": { - "boom": "2.10.1" - } - }, "crypto-browserify": { "version": "3.12.0", "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", "integrity": "sha1-OWz58xN/A+S45TLFj2mCVOAPgOw=", - "dev": true, "requires": { - "browserify-cipher": "1.0.1", - "browserify-sign": "4.0.4", - "create-ecdh": "4.0.1", - "create-hash": "1.2.0", - "create-hmac": "1.1.7", - "diffie-hellman": "5.0.3", - "inherits": "2.0.3", - "pbkdf2": "3.0.16", - "public-encrypt": "4.0.2", - "randombytes": "2.0.6", - "randomfill": "1.0.4" + "browserify-cipher": "^1.0.0", + "browserify-sign": "^4.0.0", + "create-ecdh": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.0", + "diffie-hellman": "^5.0.0", + "inherits": "^2.0.1", + "pbkdf2": "^3.0.3", + "public-encrypt": "^4.0.0", + "randombytes": "^2.0.0", + "randomfill": "^1.0.3" } }, "css": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/css/-/css-2.2.1.tgz", - "integrity": "sha1-c6TIHehdtmTU7mdPfUcIXjstVdw=", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/css/-/css-2.2.3.tgz", + "integrity": "sha512-0W171WccAjQGGTKLhw4m2nnl0zPHUlTO/I8td4XzJgIB8Hg3ZZx71qT4G4eX8OVsSiaAKiUMy73E3nsbPlg2DQ==", "dev": true, "requires": { - "inherits": "2.0.3", - "source-map": "0.1.43", - "source-map-resolve": "0.3.1", - "urix": "0.1.0" + "inherits": "^2.0.1", + "source-map": "^0.1.38", + "source-map-resolve": "^0.5.1", + "urix": "^0.1.0" }, "dependencies": { - "atob": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/atob/-/atob-1.1.3.tgz", - "integrity": "sha1-lfE2KbEsOlGl0hWr3OKqnzL4B3M=", - "dev": true - }, "source-map": { "version": "0.1.43", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", "dev": true, "requires": { - "amdefine": "1.0.1" + "amdefine": ">=0.0.4" } - }, - "source-map-resolve": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.3.1.tgz", - "integrity": "sha1-YQ9hIqRFuN1RU1oqcbeD38Ekh2E=", - "dev": true, - "requires": { - "atob": "1.1.3", - "resolve-url": "0.2.1", - "source-map-url": "0.3.0", - "urix": "0.1.0" - } - }, - "source-map-url": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.3.0.tgz", - "integrity": "sha1-fsrxO1e80J2opAxdJp2zN5nUqvk=", - "dev": true } } }, @@ -2573,20 +2627,20 @@ "integrity": "sha1-w/mGSnAL4nEbtaJGKyOJsaOS2rc=", "dev": true, "requires": { - "babel-code-frame": "6.26.0", - "css-selector-tokenizer": "0.7.0", - "cssnano": "3.10.0", - "icss-utils": "2.1.0", - "loader-utils": "1.1.0", - "lodash.camelcase": "4.3.0", - "object-assign": "4.1.1", - "postcss": "5.2.18", - "postcss-modules-extract-imports": "1.2.0", - "postcss-modules-local-by-default": "1.2.0", - "postcss-modules-scope": "1.1.0", - "postcss-modules-values": "1.3.0", - "postcss-value-parser": "3.3.0", - "source-list-map": "2.0.0" + "babel-code-frame": "^6.26.0", + "css-selector-tokenizer": "^0.7.0", + "cssnano": "^3.10.0", + "icss-utils": "^2.1.0", + "loader-utils": "^1.0.2", + "lodash.camelcase": "^4.3.0", + "object-assign": "^4.1.1", + "postcss": "^5.0.6", + "postcss-modules-extract-imports": "^1.2.0", + "postcss-modules-local-by-default": "^1.2.0", + "postcss-modules-scope": "^1.1.0", + "postcss-modules-values": "^1.3.0", + "postcss-value-parser": "^3.3.0", + "source-list-map": "^2.0.0" }, "dependencies": { "has-flag": { @@ -2601,10 +2655,10 @@ "integrity": "sha1-ut+hSX1GJE9jkPWLMZgw2RB4U8U=", "dev": true, "requires": { - "chalk": "1.1.3", - "js-base64": "2.4.3", - "source-map": "0.5.7", - "supports-color": "3.2.3" + "chalk": "^1.1.3", + "js-base64": "^2.1.9", + "source-map": "^0.5.6", + "supports-color": "^3.2.3" } }, "supports-color": { @@ -2613,38 +2667,20 @@ "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", "dev": true, "requires": { - "has-flag": "1.0.0" + "has-flag": "^1.0.0" } } } }, - "css-select": { - "version": "1.3.0-rc0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.3.0-rc0.tgz", - "integrity": "sha1-b5MZaqrnN2ZuoQNqjLFKj8t6kjE=", - "dev": true, - "requires": { - "boolbase": "1.0.0", - "css-what": "2.1.0", - "domutils": "1.5.1", - "nth-check": "1.0.1" - } - }, - "css-select-base-adapter": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/css-select-base-adapter/-/css-select-base-adapter-0.1.0.tgz", - "integrity": "sha1-AQKz0UYw34bD65+p9UVicBBs+ZA=", - "dev": true - }, "css-selector-tokenizer": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.7.0.tgz", "integrity": "sha1-5piEdK6MlTR3v15+/s/OzNnPTIY=", "dev": true, "requires": { - "cssesc": "0.1.0", - "fastparse": "1.1.1", - "regexpu-core": "1.0.0" + "cssesc": "^0.1.0", + "fastparse": "^1.1.1", + "regexpu-core": "^1.0.0" }, "dependencies": { "regexpu-core": { @@ -2653,35 +2689,13 @@ "integrity": "sha1-hqdj9Y7k18L2sQLkdkBQ3n7ZDGs=", "dev": true, "requires": { - "regenerate": "1.3.3", - "regjsgen": "0.2.0", - "regjsparser": "0.1.5" + "regenerate": "^1.2.1", + "regjsgen": "^0.2.0", + "regjsparser": "^0.1.4" } } } }, - "css-tree": { - "version": "1.0.0-alpha25", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha25.tgz", - "integrity": "sha1-G7+r+/bu708B2RCP8u3Qvi/jVZc=", - "dev": true, - "requires": { - "mdn-data": "1.1.2", - "source-map": "0.5.7" - } - }, - "css-url-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/css-url-regex/-/css-url-regex-1.1.0.tgz", - "integrity": "sha1-g4NCMMyfdMRX3lnuvRVD/uuDt+w=", - "dev": true - }, - "css-what": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.0.tgz", - "integrity": "sha1-lGfQMsOM+u+58teVASUwYvh/ob0=", - "dev": true - }, "cssesc": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-0.1.0.tgz", @@ -2694,38 +2708,38 @@ "integrity": "sha1-Tzj2zqK5sX+gFJDyPx3GjqZcHDg=", "dev": true, "requires": { - "autoprefixer": "6.7.7", - "decamelize": "1.2.0", - "defined": "1.0.0", - "has": "1.0.1", - "object-assign": "4.1.1", - "postcss": "5.2.18", - "postcss-calc": "5.3.1", - "postcss-colormin": "2.2.2", - "postcss-convert-values": "2.6.1", - "postcss-discard-comments": "2.0.4", - "postcss-discard-duplicates": "2.1.0", - "postcss-discard-empty": "2.1.0", - "postcss-discard-overridden": "0.1.1", - "postcss-discard-unused": "2.2.3", - "postcss-filter-plugins": "2.0.2", - "postcss-merge-idents": "2.1.7", - "postcss-merge-longhand": "2.0.2", - "postcss-merge-rules": "2.1.2", - "postcss-minify-font-values": "1.0.5", - "postcss-minify-gradients": "1.0.5", - "postcss-minify-params": "1.2.2", - "postcss-minify-selectors": "2.1.1", - "postcss-normalize-charset": "1.1.1", - "postcss-normalize-url": "3.0.8", - "postcss-ordered-values": "2.2.3", - "postcss-reduce-idents": "2.4.0", - "postcss-reduce-initial": "1.0.1", - "postcss-reduce-transforms": "1.0.4", - "postcss-svgo": "2.1.6", - "postcss-unique-selectors": "2.0.2", - "postcss-value-parser": "3.3.0", - "postcss-zindex": "2.2.0" + "autoprefixer": "^6.3.1", + "decamelize": "^1.1.2", + "defined": "^1.0.0", + "has": "^1.0.1", + "object-assign": "^4.0.1", + "postcss": "^5.0.14", + "postcss-calc": "^5.2.0", + "postcss-colormin": "^2.1.8", + "postcss-convert-values": "^2.3.4", + "postcss-discard-comments": "^2.0.4", + "postcss-discard-duplicates": "^2.0.1", + "postcss-discard-empty": "^2.0.1", + "postcss-discard-overridden": "^0.1.1", + "postcss-discard-unused": "^2.2.1", + "postcss-filter-plugins": "^2.0.0", + "postcss-merge-idents": "^2.1.5", + "postcss-merge-longhand": "^2.0.1", + "postcss-merge-rules": "^2.0.3", + "postcss-minify-font-values": "^1.0.2", + "postcss-minify-gradients": "^1.0.1", + "postcss-minify-params": "^1.0.4", + "postcss-minify-selectors": "^2.0.4", + "postcss-normalize-charset": "^1.1.0", + "postcss-normalize-url": "^3.0.7", + "postcss-ordered-values": "^2.1.0", + "postcss-reduce-idents": "^2.2.2", + "postcss-reduce-initial": "^1.0.0", + "postcss-reduce-transforms": "^1.0.3", + "postcss-svgo": "^2.1.1", + "postcss-unique-selectors": "^2.0.2", + "postcss-value-parser": "^3.2.3", + "postcss-zindex": "^2.0.1" }, "dependencies": { "autoprefixer": { @@ -2734,12 +2748,12 @@ "integrity": "sha1-Hb0cg1ZY41zj+ZhAmdsAWFx4IBQ=", "dev": true, "requires": { - "browserslist": "1.7.7", - "caniuse-db": "1.0.30000832", - "normalize-range": "0.1.2", - "num2fraction": "1.2.2", - "postcss": "5.2.18", - "postcss-value-parser": "3.3.0" + "browserslist": "^1.7.6", + "caniuse-db": "^1.0.30000634", + "normalize-range": "^0.1.2", + "num2fraction": "^1.2.2", + "postcss": "^5.2.16", + "postcss-value-parser": "^3.2.3" } }, "browserslist": { @@ -2748,8 +2762,8 @@ "integrity": "sha1-C9dnBCWL6CmyOYu1Dkti0aFmsLk=", "dev": true, "requires": { - "caniuse-db": "1.0.30000832", - "electron-to-chromium": "1.3.44" + "caniuse-db": "^1.0.30000639", + "electron-to-chromium": "^1.2.7" } }, "has-flag": { @@ -2764,10 +2778,10 @@ "integrity": "sha1-ut+hSX1GJE9jkPWLMZgw2RB4U8U=", "dev": true, "requires": { - "chalk": "1.1.3", - "js-base64": "2.4.3", - "source-map": "0.5.7", - "supports-color": "3.2.3" + "chalk": "^1.1.3", + "js-base64": "^2.1.9", + "source-map": "^0.5.6", + "supports-color": "^3.2.3" } }, "supports-color": { @@ -2776,7 +2790,7 @@ "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", "dev": true, "requires": { - "has-flag": "1.0.0" + "has-flag": "^1.0.0" } } } @@ -2787,8 +2801,8 @@ "integrity": "sha1-3dUsWHAz9J6Utx/FVWnyUuj/X4U=", "dev": true, "requires": { - "clap": "1.2.3", - "source-map": "0.5.7" + "clap": "^1.0.9", + "source-map": "^0.5.3" } }, "currently-unhandled": { @@ -2797,7 +2811,7 @@ "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", "dev": true, "requires": { - "array-find-index": "1.0.2" + "array-find-index": "^1.0.1" } }, "cyclist": { @@ -2812,7 +2826,7 @@ "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", "dev": true, "requires": { - "es5-ext": "0.10.42" + "es5-ext": "^0.10.9" } }, "dashdash": { @@ -2820,27 +2834,30 @@ "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", "requires": { - "assert-plus": "1.0.0" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" - } + "assert-plus": "^1.0.0" + } + }, + "datatables.net": { + "version": "1.10.19", + "resolved": "https://registry.npmjs.org/datatables.net/-/datatables.net-1.10.19.tgz", + "integrity": "sha1-l6HtQcheYtYQQGA0gbWXkKFy3R8=", + "requires": { + "jquery": ">=1.7" + } + }, + "datatables.net-bs": { + "version": "1.10.19", + "resolved": "https://registry.npmjs.org/datatables.net-bs/-/datatables.net-bs-1.10.19.tgz", + "integrity": "sha1-CHY7Tk0M7xpCfQGdwV5xfH7Wek0=", + "requires": { + "datatables.net": "1.10.19", + "jquery": ">=1.7" } }, "date-now": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", - "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=", - "dev": true - }, - "dateformat": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-2.2.0.tgz", - "integrity": "sha1-QGXiATz5+5Ft39gu+1Bq1MZ2kGI=", - "dev": true + "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=" }, "de-indent": { "version": "1.0.2", @@ -2868,171 +2885,12 @@ "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" }, - "decompress": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/decompress/-/decompress-3.0.0.tgz", - "integrity": "sha1-rx3VDQbjv8QyRh033hGzjA2ZG+0=", - "dev": true, - "requires": { - "buffer-to-vinyl": "1.1.0", - "concat-stream": "1.6.2", - "decompress-tar": "3.1.0", - "decompress-tarbz2": "3.1.0", - "decompress-targz": "3.1.0", - "decompress-unzip": "3.4.0", - "stream-combiner2": "1.1.1", - "vinyl-assign": "1.2.1", - "vinyl-fs": "2.4.4" - } - }, "decompress-response": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", "requires": { - "mimic-response": "1.0.0" - } - }, - "decompress-tar": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/decompress-tar/-/decompress-tar-3.1.0.tgz", - "integrity": "sha1-IXx4n5uURQ76rcXF5TeXj8MzxGY=", - "dev": true, - "requires": { - "is-tar": "1.0.0", - "object-assign": "2.1.1", - "strip-dirs": "1.1.1", - "tar-stream": "1.6.0", - "through2": "0.6.5", - "vinyl": "0.4.6" - }, - "dependencies": { - "clone": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", - "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", - "dev": true - }, - "object-assign": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-2.1.1.tgz", - "integrity": "sha1-Q8NuXVaf+OSBbE76i+AtJpZ8GKo=", - "dev": true - }, - "vinyl": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", - "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", - "dev": true, - "requires": { - "clone": "0.2.0", - "clone-stats": "0.0.1" - } - } - } - }, - "decompress-tarbz2": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/decompress-tarbz2/-/decompress-tarbz2-3.1.0.tgz", - "integrity": "sha1-iyOTVoE1X58YnYclag+L3ZbZZm0=", - "dev": true, - "requires": { - "is-bzip2": "1.0.0", - "object-assign": "2.1.1", - "seek-bzip": "1.0.5", - "strip-dirs": "1.1.1", - "tar-stream": "1.6.0", - "through2": "0.6.5", - "vinyl": "0.4.6" - }, - "dependencies": { - "clone": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", - "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", - "dev": true - }, - "object-assign": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-2.1.1.tgz", - "integrity": "sha1-Q8NuXVaf+OSBbE76i+AtJpZ8GKo=", - "dev": true - }, - "vinyl": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", - "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", - "dev": true, - "requires": { - "clone": "0.2.0", - "clone-stats": "0.0.1" - } - } - } - }, - "decompress-targz": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/decompress-targz/-/decompress-targz-3.1.0.tgz", - "integrity": "sha1-ssE9+YFmJomRtxXWRH9kLpaW9aA=", - "dev": true, - "requires": { - "is-gzip": "1.0.0", - "object-assign": "2.1.1", - "strip-dirs": "1.1.1", - "tar-stream": "1.6.0", - "through2": "0.6.5", - "vinyl": "0.4.6" - }, - "dependencies": { - "clone": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", - "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", - "dev": true - }, - "object-assign": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-2.1.1.tgz", - "integrity": "sha1-Q8NuXVaf+OSBbE76i+AtJpZ8GKo=", - "dev": true - }, - "vinyl": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", - "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", - "dev": true, - "requires": { - "clone": "0.2.0", - "clone-stats": "0.0.1" - } - } - } - }, - "decompress-unzip": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/decompress-unzip/-/decompress-unzip-3.4.0.tgz", - "integrity": "sha1-YUdbQVIGa74/7hL51inRX+ZHjus=", - "dev": true, - "requires": { - "is-zip": "1.0.0", - "read-all-stream": "3.1.0", - "stat-mode": "0.2.2", - "strip-dirs": "1.1.1", - "through2": "2.0.3", - "vinyl": "1.2.0", - "yauzl": "2.9.1" - }, - "dependencies": { - "through2": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", - "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", - "dev": true, - "requires": { - "readable-stream": "2.3.4", - "xtend": "4.0.1" - } - } + "mimic-response": "^1.0.0" } }, "deep-equal": { @@ -3041,20 +2899,13 @@ "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=", "dev": true }, - "deep-extend": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.5.1.tgz", - "integrity": "sha512-N8vBdOa+DF7zkRrDCsaOXoCs/E2fJfx9B9MrKnnSiHNh4ws7eSys6YQE4KvT1cecKmOASYQBhbKjeuDD9lT81w==", - "dev": true - }, "define-properties": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.2.tgz", - "integrity": "sha1-g6c/L+pWmJj7c3GTyPhzyvbUXJQ=", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha1-z4jabL7ib+bbcJT2HYcMvYTO6fE=", "dev": true, "requires": { - "foreach": "2.0.5", - "object-keys": "1.0.11" + "object-keys": "^1.0.12" } }, "define-property": { @@ -3063,8 +2914,8 @@ "integrity": "sha1-1Flono1lS6d+AqgX+HENcCyxbp0=", "dev": true, "requires": { - "is-descriptor": "1.0.2", - "isobject": "3.0.1" + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" }, "dependencies": { "is-accessor-descriptor": { @@ -3073,7 +2924,7 @@ "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=", "dev": true, "requires": { - "kind-of": "6.0.2" + "kind-of": "^6.0.0" } }, "is-data-descriptor": { @@ -3082,7 +2933,7 @@ "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=", "dev": true, "requires": { - "kind-of": "6.0.2" + "kind-of": "^6.0.0" } }, "is-descriptor": { @@ -3091,9 +2942,9 @@ "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=", "dev": true, "requires": { - "is-accessor-descriptor": "1.0.0", - "is-data-descriptor": "1.0.0", - "kind-of": "6.0.2" + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" } } } @@ -3101,8 +2952,7 @@ "defined": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", - "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", - "dev": true + "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=" }, "del": { "version": "3.0.0", @@ -3110,12 +2960,12 @@ "integrity": "sha1-U+z2mf/LyzljdpGrE7rxYIGXZuU=", "dev": true, "requires": { - "globby": "6.1.0", - "is-path-cwd": "1.0.0", - "is-path-in-cwd": "1.0.1", - "p-map": "1.2.0", - "pify": "3.0.0", - "rimraf": "2.6.2" + "globby": "^6.1.0", + "is-path-cwd": "^1.0.0", + "is-path-in-cwd": "^1.0.0", + "p-map": "^1.1.1", + "pify": "^3.0.0", + "rimraf": "^2.2.8" } }, "delayed-stream": { @@ -3135,14 +2985,24 @@ "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", "dev": true }, + "deps-sort": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/deps-sort/-/deps-sort-2.0.0.tgz", + "integrity": "sha1-CRckkC6EZYJg65EHSMzNGvbiH7U=", + "requires": { + "JSONStream": "^1.0.3", + "shasum": "^1.0.0", + "subarg": "^1.0.0", + "through2": "^2.0.0" + } + }, "des.js": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=", - "dev": true, "requires": { - "inherits": "2.0.3", - "minimalistic-assert": "1.0.1" + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" } }, "destroy": { @@ -3157,7 +3017,7 @@ "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=", "dev": true, "requires": { - "repeating": "2.0.1" + "repeating": "^2.0.0" } }, "detect-node": { @@ -3166,15 +3026,31 @@ "integrity": "sha1-ogM8CcyOFY03dI+951B4Mr1s4Sc=", "dev": true }, + "detective": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/detective/-/detective-5.1.0.tgz", + "integrity": "sha1-eiDYkjbXszHM6mWDLnEjtVUbt8s=", + "requires": { + "acorn-node": "^1.3.0", + "defined": "^1.0.0", + "minimist": "^1.1.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + } + } + }, "diffie-hellman": { "version": "5.0.3", "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", "integrity": "sha1-QOjumPVaIUlgcUaSHGPhrl89KHU=", - "dev": true, "requires": { - "bn.js": "4.11.8", - "miller-rabin": "4.0.1", - "randombytes": "2.0.6" + "bn.js": "^4.1.0", + "miller-rabin": "^4.0.0", + "randombytes": "^2.0.0" } }, "dns-equal": { @@ -3189,8 +3065,8 @@ "integrity": "sha1-EqpCaYEHW+UAuRDu3NC0fdfe2lo=", "dev": true, "requires": { - "ip": "1.1.5", - "safe-buffer": "5.1.1" + "ip": "^1.1.0", + "safe-buffer": "^5.0.1" } }, "dns-txt": { @@ -3199,47 +3075,22 @@ "integrity": "sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY=", "dev": true, "requires": { - "buffer-indexof": "1.1.1" - } - }, - "dom-serializer": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz", - "integrity": "sha1-BzxpdUbOB4DOI75KKOKT5AvDDII=", - "dev": true, - "requires": { - "domelementtype": "1.1.3", - "entities": "1.1.1" - }, - "dependencies": { - "domelementtype": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz", - "integrity": "sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs=", - "dev": true - } + "buffer-indexof": "^1.0.0" } }, "domain-browser": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", - "integrity": "sha1-PTH1AZGmdJ3RN1p/Ui6CPULlTto=", - "dev": true + "integrity": "sha1-PTH1AZGmdJ3RN1p/Ui6CPULlTto=" }, - "domelementtype": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz", - "integrity": "sha1-sXrtguirWeUt2cGbF1bg/BhyBMI=", - "dev": true - }, - "domutils": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", - "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", - "dev": true, + "domhelper": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/domhelper/-/domhelper-0.9.1.tgz", + "integrity": "sha1-JlVOW6wsnpWF3KUAl431Bn1kvQA=", "requires": { - "dom-serializer": "0.1.0", - "domelementtype": "1.3.0" + "browserify": ">=3.46.0", + "classie": ">=0.0.1", + "util-extend": "^1.0.1" } }, "dotenv": { @@ -3254,82 +3105,12 @@ "integrity": "sha1-3vHxyl1gWdJKdm5YeULCEQbOEnU=", "dev": true }, - "download": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/download/-/download-4.4.3.tgz", - "integrity": "sha1-qlX9rTktldS2jowr4D4MKqIbqaw=", - "dev": true, - "requires": { - "caw": "1.2.0", - "concat-stream": "1.6.2", - "each-async": "1.1.1", - "filenamify": "1.2.1", - "got": "5.7.1", - "gulp-decompress": "1.2.0", - "gulp-rename": "1.2.2", - "is-url": "1.2.4", - "object-assign": "4.1.1", - "read-all-stream": "3.1.0", - "readable-stream": "2.3.4", - "stream-combiner2": "1.1.1", - "vinyl": "1.2.0", - "vinyl-fs": "2.4.4", - "ware": "1.3.0" - }, - "dependencies": { - "got": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/got/-/got-5.7.1.tgz", - "integrity": "sha1-X4FjWmHkplifGAVp6k44FoClHzU=", - "dev": true, - "requires": { - "create-error-class": "3.0.2", - "duplexer2": "0.1.4", - "is-redirect": "1.0.0", - "is-retry-allowed": "1.1.0", - "is-stream": "1.1.0", - "lowercase-keys": "1.0.0", - "node-status-codes": "1.0.0", - "object-assign": "4.1.1", - "parse-json": "2.2.0", - "pinkie-promise": "2.0.1", - "read-all-stream": "3.1.0", - "readable-stream": "2.3.4", - "timed-out": "3.1.3", - "unzip-response": "1.0.2", - "url-parse-lax": "1.0.0" - } - }, - "prepend-http": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", - "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=", - "dev": true - }, - "timed-out": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-3.1.3.tgz", - "integrity": "sha1-lYYL/MXHbCd/j4Mm/Q9bLiDrohc=", - "dev": true - }, - "url-parse-lax": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz", - "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=", - "dev": true, - "requires": { - "prepend-http": "1.0.4" - } - } - } - }, "duplexer2": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", - "dev": true, "requires": { - "readable-stream": "2.3.4" + "readable-stream": "^2.0.2" } }, "duplexer3": { @@ -3338,34 +3119,25 @@ "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=" }, "duplexify": { - "version": "3.5.4", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.5.4.tgz", - "integrity": "sha512-JzYSLYMhoVVBe8+mbHQ4KgpvHpm0DZpJuL8PY93Vyv1fW7jYJ90LoXa1di/CVbJM+TgMs91rbDapE/RNIfnJsA==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.6.0.tgz", + "integrity": "sha1-WSkD9dgLONA3IgVBJk1poZj7NBA=", "dev": true, "requires": { - "end-of-stream": "1.4.1", - "inherits": "2.0.3", - "readable-stream": "2.3.4", - "stream-shift": "1.0.0" - } - }, - "each-async": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/each-async/-/each-async-1.1.1.tgz", - "integrity": "sha1-3uUim98KtrogEqOV4bhpq/iBNHM=", - "dev": true, - "requires": { - "onetime": "1.1.0", - "set-immediate-shim": "1.0.1" + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" } }, "ecc-jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", - "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", "optional": true, "requires": { - "jsbn": "0.1.1" + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" } }, "ee-first": { @@ -3380,24 +3152,23 @@ "integrity": "sha1-+/zZ35Oo0c2/h3CtyMBaqsTST1Y=" }, "electron-to-chromium": { - "version": "1.3.44", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.44.tgz", - "integrity": "sha1-72sVCmDVIwgjiMra2ICF7NL9RoQ=", + "version": "1.3.61", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.61.tgz", + "integrity": "sha512-XjTdsm6x71Y48lF9EEvGciwXD70b20g0t+3YbrE+0fPFutqV08DSNrZXkoXAp3QuzX7TpL/OW+/VsNoR9GkuNg==", "dev": true }, "elliptic": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.0.tgz", - "integrity": "sha1-ysmvh2LIWDYYcAPI3+GT5eLq5d8=", - "dev": true, + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.1.tgz", + "integrity": "sha1-wtC3d2kRuGcixjLDwGxg8vgZk5o=", "requires": { - "bn.js": "4.11.8", - "brorand": "1.1.0", - "hash.js": "1.1.3", - "hmac-drbg": "1.0.1", - "inherits": "2.0.3", - "minimalistic-assert": "1.0.1", - "minimalistic-crypto-utils": "1.0.1" + "bn.js": "^4.4.0", + "brorand": "^1.0.1", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.0" } }, "emojis-list": { @@ -3417,7 +3188,7 @@ "integrity": "sha1-7SljTRm6ukY7bOa4CjchPqtx7EM=", "dev": true, "requires": { - "once": "1.4.0" + "once": "^1.4.0" } }, "enhanced-resolve": { @@ -3426,24 +3197,18 @@ "integrity": "sha1-BCHjOf1xQZs9oT0Smzl5BAIwR24=", "dev": true, "requires": { - "graceful-fs": "4.1.11", - "memory-fs": "0.4.1", - "object-assign": "4.1.1", - "tapable": "0.2.8" + "graceful-fs": "^4.1.2", + "memory-fs": "^0.4.0", + "object-assign": "^4.0.1", + "tapable": "^0.2.7" } }, - "entities": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz", - "integrity": "sha1-blwtClYhtdra7O+AuQ7ftc13cvA=", - "dev": true - }, "errno": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", "integrity": "sha1-RoTXF3mtOa8Xfj8AeZb3xnyFJhg=", "requires": { - "prr": "1.0.1" + "prr": "~1.0.1" } }, "error-ex": { @@ -3452,29 +3217,29 @@ "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=", "dev": true, "requires": { - "is-arrayish": "0.2.1" + "is-arrayish": "^0.2.1" } }, "error-stack-parser": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.0.1.tgz", - "integrity": "sha1-oyArj7AxFKqbQKDjZp5IsrZaAQo=", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.0.2.tgz", + "integrity": "sha1-Sujbqiv5CotFBwe5FJ3KvKE1Ug0=", "dev": true, "requires": { - "stackframe": "1.0.4" + "stackframe": "^1.0.4" } }, "es-abstract": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.11.0.tgz", - "integrity": "sha512-ZnQrE/lXTTQ39ulXZ+J1DTFazV9qBy61x2bY071B+qGco8Z8q1QddsLdt/EF8Ai9hcWH72dWS0kFqXLxOxqslA==", + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.12.0.tgz", + "integrity": "sha1-nbvdJ8aFbwABQhyhh4LXhr+KYWU=", "dev": true, "requires": { - "es-to-primitive": "1.1.1", - "function-bind": "1.1.1", - "has": "1.0.1", - "is-callable": "1.1.3", - "is-regex": "1.0.4" + "es-to-primitive": "^1.1.1", + "function-bind": "^1.1.1", + "has": "^1.0.1", + "is-callable": "^1.1.3", + "is-regex": "^1.0.4" } }, "es-to-primitive": { @@ -3483,20 +3248,20 @@ "integrity": "sha1-RTVSSKiJeQNLZ5Lhm7gfK3l13Q0=", "dev": true, "requires": { - "is-callable": "1.1.3", - "is-date-object": "1.0.1", - "is-symbol": "1.0.1" + "is-callable": "^1.1.1", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.1" } }, "es5-ext": { - "version": "0.10.42", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.42.tgz", - "integrity": "sha1-jAfdM68E1dzRMQtc7xO+pjqJuo0=", + "version": "0.10.46", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.46.tgz", + "integrity": "sha1-79mfZ8Wn7Hibqj2qf3mHA4j39XI=", "dev": true, "requires": { - "es6-iterator": "2.0.3", - "es6-symbol": "3.1.1", - "next-tick": "1.0.0" + "es6-iterator": "~2.0.3", + "es6-symbol": "~3.1.1", + "next-tick": "1" } }, "es6-iterator": { @@ -3505,9 +3270,9 @@ "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", "dev": true, "requires": { - "d": "1.0.0", - "es5-ext": "0.10.42", - "es6-symbol": "3.1.1" + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" } }, "es6-map": { @@ -3516,12 +3281,12 @@ "integrity": "sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA=", "dev": true, "requires": { - "d": "1.0.0", - "es5-ext": "0.10.42", - "es6-iterator": "2.0.3", - "es6-set": "0.1.5", - "es6-symbol": "3.1.1", - "event-emitter": "0.3.5" + "d": "1", + "es5-ext": "~0.10.14", + "es6-iterator": "~2.0.1", + "es6-set": "~0.1.5", + "es6-symbol": "~3.1.1", + "event-emitter": "~0.3.5" } }, "es6-set": { @@ -3530,11 +3295,11 @@ "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=", "dev": true, "requires": { - "d": "1.0.0", - "es5-ext": "0.10.42", - "es6-iterator": "2.0.3", + "d": "1", + "es5-ext": "~0.10.14", + "es6-iterator": "~2.0.1", "es6-symbol": "3.1.1", - "event-emitter": "0.3.5" + "event-emitter": "~0.3.5" } }, "es6-symbol": { @@ -3543,8 +3308,8 @@ "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", "dev": true, "requires": { - "d": "1.0.0", - "es5-ext": "0.10.42" + "d": "1", + "es5-ext": "~0.10.14" } }, "es6-templates": { @@ -3553,8 +3318,8 @@ "integrity": "sha1-XLmsn7He1usSOTQrgdeSu7QHjuQ=", "dev": true, "requires": { - "recast": "0.11.23", - "through": "2.3.8" + "recast": "~0.11.12", + "through": "~2.3.6" } }, "es6-weak-map": { @@ -3563,10 +3328,10 @@ "integrity": "sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8=", "dev": true, "requires": { - "d": "1.0.0", - "es5-ext": "0.10.42", - "es6-iterator": "2.0.3", - "es6-symbol": "3.1.1" + "d": "1", + "es5-ext": "^0.10.14", + "es6-iterator": "^2.0.1", + "es6-symbol": "^3.1.1" } }, "escape-html": { @@ -3587,10 +3352,10 @@ "integrity": "sha1-4Bl16BJ4GhY6ba392AOY3GTIicM=", "dev": true, "requires": { - "es6-map": "0.1.5", - "es6-weak-map": "2.0.2", - "esrecurse": "4.2.1", - "estraverse": "4.2.0" + "es6-map": "^0.1.3", + "es6-weak-map": "^2.0.1", + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" } }, "esprima": { @@ -3605,7 +3370,7 @@ "integrity": "sha1-AHo7n9vCs7uH5IeeoZyS/b05Qs8=", "dev": true, "requires": { - "estraverse": "4.2.0" + "estraverse": "^4.1.0" } }, "estraverse": { @@ -3626,14 +3391,19 @@ "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", "dev": true }, + "eve-raphael": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/eve-raphael/-/eve-raphael-0.5.0.tgz", + "integrity": "sha1-F8dUt5K+7z+maE15z1pHxjxM2jA=" + }, "event-emitter": { "version": "0.3.5", "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", "dev": true, "requires": { - "d": "1.0.0", - "es5-ext": "0.10.42" + "d": "1", + "es5-ext": "~0.10.14" } }, "eventemitter3": { @@ -3654,40 +3424,16 @@ "integrity": "sha1-Cs7ehJ7X3RzMMsgRuxG5RNTykjI=", "dev": true, "requires": { - "original": "1.0.0" + "original": ">=0.0.5" } }, "evp_bytestokey": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", "integrity": "sha1-f8vbGY3HGVlDLv4ThCaE4FJaywI=", - "dev": true, "requires": { - "md5.js": "1.3.4", - "safe-buffer": "5.1.1" - } - }, - "exec-buffer": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/exec-buffer/-/exec-buffer-3.2.0.tgz", - "integrity": "sha1-sWhtvZBMfPmC5lLB9aebHlVzCCs=", - "dev": true, - "requires": { - "execa": "0.7.0", - "p-finally": "1.0.0", - "pify": "3.0.0", - "rimraf": "2.6.2", - "tempfile": "2.0.0" - } - }, - "exec-series": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/exec-series/-/exec-series-1.0.3.tgz", - "integrity": "sha1-bSV6m+rEgqhyx3g7yGFYOfx3FDo=", - "dev": true, - "requires": { - "async-each-series": "1.1.0", - "object-assign": "4.1.1" + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" } }, "execa": { @@ -3696,23 +3442,19 @@ "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", "dev": true, "requires": { - "cross-spawn": "5.1.0", - "get-stream": "3.0.0", - "is-stream": "1.1.0", - "npm-run-path": "2.0.2", - "p-finally": "1.0.0", - "signal-exit": "3.0.2", - "strip-eof": "1.0.0" + "cross-spawn": "^5.0.1", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" } }, - "executable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/executable/-/executable-1.1.0.tgz", - "integrity": "sha1-h3mA6REvM5EGbaNyZd562ENKtNk=", - "dev": true, - "requires": { - "meow": "3.7.0" - } + "exit-on-epipe": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/exit-on-epipe/-/exit-on-epipe-1.0.1.tgz", + "integrity": "sha1-C92S6H1ShdJn2qgXHQ6wYVlolpI=" }, "expand-brackets": { "version": "2.1.4", @@ -3720,13 +3462,13 @@ "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", "dev": true, "requires": { - "debug": "2.6.9", - "define-property": "0.2.5", - "extend-shallow": "2.0.1", - "posix-character-classes": "0.1.1", - "regex-not": "1.0.2", - "snapdragon": "0.8.2", - "to-regex": "3.0.2" + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" }, "dependencies": { "debug": { @@ -3744,7 +3486,7 @@ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { - "is-descriptor": "0.1.6" + "is-descriptor": "^0.1.0" } }, "extend-shallow": { @@ -3753,7 +3495,7 @@ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-extendable": "0.1.1" + "is-extendable": "^0.1.0" } } } @@ -3764,20 +3506,20 @@ "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", "dev": true, "requires": { - "fill-range": "2.2.3" + "fill-range": "^2.1.0" }, "dependencies": { "fill-range": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz", - "integrity": "sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM=", + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.4.tgz", + "integrity": "sha1-6x53OrsFbc2N8r/favWbizqTZWU=", "dev": true, "requires": { - "is-number": "2.1.0", - "isobject": "2.1.0", - "randomatic": "1.1.7", - "repeat-element": "1.1.2", - "repeat-string": "1.6.1" + "is-number": "^2.1.0", + "isobject": "^2.0.0", + "randomatic": "^3.0.0", + "repeat-element": "^1.1.2", + "repeat-string": "^1.5.2" } }, "is-number": { @@ -3786,7 +3528,7 @@ "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", "dev": true, "requires": { - "kind-of": "3.2.2" + "kind-of": "^3.0.2" } }, "isobject": { @@ -3804,7 +3546,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "1.1.6" + "is-buffer": "^1.1.5" } } } @@ -3815,36 +3557,36 @@ "integrity": "sha1-avilAjUNsyRuzEvs9rWjTSL37VM=", "dev": true, "requires": { - "accepts": "1.3.5", + "accepts": "~1.3.5", "array-flatten": "1.1.1", "body-parser": "1.18.2", "content-disposition": "0.5.2", - "content-type": "1.0.4", + "content-type": "~1.0.4", "cookie": "0.3.1", "cookie-signature": "1.0.6", "debug": "2.6.9", - "depd": "1.1.2", - "encodeurl": "1.0.2", - "escape-html": "1.0.3", - "etag": "1.8.1", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", "finalhandler": "1.1.1", "fresh": "0.5.2", "merge-descriptors": "1.0.1", - "methods": "1.1.2", - "on-finished": "2.3.0", - "parseurl": "1.3.2", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.2", "path-to-regexp": "0.1.7", - "proxy-addr": "2.0.3", + "proxy-addr": "~2.0.3", "qs": "6.5.1", - "range-parser": "1.2.0", + "range-parser": "~1.2.0", "safe-buffer": "5.1.1", "send": "0.16.2", "serve-static": "1.13.2", "setprototypeof": "1.1.0", - "statuses": "1.4.0", - "type-is": "1.6.16", + "statuses": "~1.4.0", + "type-is": "~1.6.16", "utils-merge": "1.0.1", - "vary": "1.1.2" + "vary": "~1.1.2" }, "dependencies": { "array-flatten": { @@ -3870,25 +3612,6 @@ } } }, - "ext-list": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/ext-list/-/ext-list-2.2.2.tgz", - "integrity": "sha1-C5jmTtgvWs8PKTG6v2khLvUt3Tc=", - "dev": true, - "requires": { - "mime-db": "1.33.0" - } - }, - "ext-name": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ext-name/-/ext-name-5.0.0.tgz", - "integrity": "sha1-cHgZgdGD7hXROZPIgiBFxQbI8KY=", - "dev": true, - "requires": { - "ext-list": "2.2.2", - "sort-keys-length": "1.0.1" - } - }, "extend": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", @@ -3900,8 +3623,8 @@ "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", "dev": true, "requires": { - "assign-symbols": "1.0.0", - "is-extendable": "1.0.1" + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" }, "dependencies": { "is-extendable": { @@ -3910,7 +3633,7 @@ "integrity": "sha1-p0cPnkJnM9gb2B4RVSZOOjUHyrQ=", "dev": true, "requires": { - "is-plain-object": "2.0.4" + "is-plain-object": "^2.0.4" } } } @@ -3921,14 +3644,14 @@ "integrity": "sha1-rQD+TcYSqSMuhxhxHcXLWrAoVUM=", "dev": true, "requires": { - "array-unique": "0.3.2", - "define-property": "1.0.0", - "expand-brackets": "2.1.4", - "extend-shallow": "2.0.1", - "fragment-cache": "0.2.1", - "regex-not": "1.0.2", - "snapdragon": "0.8.2", - "to-regex": "3.0.2" + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" }, "dependencies": { "define-property": { @@ -3937,7 +3660,7 @@ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", "dev": true, "requires": { - "is-descriptor": "1.0.2" + "is-descriptor": "^1.0.0" } }, "extend-shallow": { @@ -3946,7 +3669,7 @@ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-extendable": "0.1.1" + "is-extendable": "^0.1.0" } }, "is-accessor-descriptor": { @@ -3955,7 +3678,7 @@ "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=", "dev": true, "requires": { - "kind-of": "6.0.2" + "kind-of": "^6.0.0" } }, "is-data-descriptor": { @@ -3964,7 +3687,7 @@ "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=", "dev": true, "requires": { - "kind-of": "6.0.2" + "kind-of": "^6.0.0" } }, "is-descriptor": { @@ -3973,9 +3696,9 @@ "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=", "dev": true, "requires": { - "is-accessor-descriptor": "1.0.0", - "is-data-descriptor": "1.0.0", - "kind-of": "6.0.2" + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" } } } @@ -3986,10 +3709,10 @@ "integrity": "sha1-XwQ+qgL5dQqSWLeMCm4NwUCPsvc=", "dev": true, "requires": { - "async": "2.6.0", - "loader-utils": "1.1.0", - "schema-utils": "0.3.0", - "webpack-sources": "1.1.0" + "async": "^2.4.1", + "loader-utils": "^1.1.0", + "schema-utils": "^0.3.0", + "webpack-sources": "^1.0.1" } }, "extsprintf": { @@ -3997,17 +3720,6 @@ "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" }, - "fancy-log": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.2.tgz", - "integrity": "sha1-9BEl49hPLn2JpD0G2VjI94vha+E=", - "dev": true, - "requires": { - "ansi-gray": "0.1.1", - "color-support": "1.1.3", - "time-stamp": "1.1.0" - } - }, "fast-deep-equal": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", @@ -4018,6 +3730,11 @@ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" }, + "fastclick": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/fastclick/-/fastclick-1.0.6.tgz", + "integrity": "sha1-FhYlsnsaWAZAWTa9qaLBkm0Gvmo=" + }, "fastparse": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.1.tgz", @@ -4030,26 +3747,7 @@ "integrity": "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=", "dev": true, "requires": { - "websocket-driver": "0.7.0" - } - }, - "fd-slicer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.0.1.tgz", - "integrity": "sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU=", - "dev": true, - "requires": { - "pend": "1.2.0" - } - }, - "figures": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", - "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", - "dev": true, - "requires": { - "escape-string-regexp": "1.0.5", - "object-assign": "4.1.1" + "websocket-driver": ">=0.5.1" } }, "file-loader": { @@ -4058,14 +3756,18 @@ "integrity": "sha1-T/HfKK84cZpgmAk7iMgscdF5SjQ=", "dev": true, "requires": { - "loader-utils": "1.1.0" + "loader-utils": "^1.0.2" } }, + "file-saver": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/file-saver/-/file-saver-1.3.8.tgz", + "integrity": "sha1-zdTETTqiZOrC9o7BZbx5HDSvEjI=" + }, "file-type": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/file-type/-/file-type-4.4.0.tgz", - "integrity": "sha1-G2AOX8ofvcboDApwxxyNul95BsU=", - "dev": true + "integrity": "sha1-G2AOX8ofvcboDApwxxyNul95BsU=" }, "filename-regex": { "version": "2.0.1", @@ -4073,33 +3775,16 @@ "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", "dev": true }, - "filename-reserved-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-1.0.0.tgz", - "integrity": "sha1-5hz4BfDeHJhFZ9A4bcXfUO5a9+Q=", - "dev": true - }, - "filenamify": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-1.2.1.tgz", - "integrity": "sha1-qfL/0RxQO+0wABUCknI3jx8TZaU=", - "dev": true, - "requires": { - "filename-reserved-regex": "1.0.0", - "strip-outer": "1.0.1", - "trim-repeated": "1.0.0" - } - }, "fill-range": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", "dev": true, "requires": { - "extend-shallow": "2.0.1", - "is-number": "3.0.0", - "repeat-string": "1.6.1", - "to-regex-range": "2.1.1" + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" }, "dependencies": { "extend-shallow": { @@ -4108,7 +3793,7 @@ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-extendable": "0.1.1" + "is-extendable": "^0.1.0" } } } @@ -4120,12 +3805,12 @@ "dev": true, "requires": { "debug": "2.6.9", - "encodeurl": "1.0.2", - "escape-html": "1.0.3", - "on-finished": "2.3.0", - "parseurl": "1.3.2", - "statuses": "1.4.0", - "unpipe": "1.0.0" + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.2", + "statuses": "~1.4.0", + "unpipe": "~1.0.0" }, "dependencies": { "debug": { @@ -4145,9 +3830,9 @@ "integrity": "sha1-kojj6ePMN0hxfTnq3hfPcfww7m8=", "dev": true, "requires": { - "commondir": "1.0.1", - "make-dir": "1.2.0", - "pkg-dir": "2.0.0" + "commondir": "^1.0.1", + "make-dir": "^1.0.0", + "pkg-dir": "^2.0.0" } }, "find-up": { @@ -4156,41 +3841,28 @@ "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", "dev": true, "requires": { - "locate-path": "2.0.0" + "locate-path": "^2.0.0" } }, - "find-versions": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/find-versions/-/find-versions-1.2.1.tgz", - "integrity": "sha1-y96fEuOFdaCvG+G5osXV/Y8Ya2I=", - "dev": true, - "requires": { - "array-uniq": "1.0.3", - "get-stdin": "4.0.1", - "meow": "3.7.0", - "semver-regex": "1.0.0" - } - }, - "first-chunk-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz", - "integrity": "sha1-Wb+1DNkF9g18OUzT2ayqtOatk04=", - "dev": true - }, "flatten": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/flatten/-/flatten-1.0.2.tgz", "integrity": "sha1-2uRqnXj74lKSJYzB54CkHZXAN4I=", "dev": true }, + "flot": { + "version": "0.8.0-alpha", + "resolved": "https://registry.npmjs.org/flot/-/flot-0.8.0-alpha.tgz", + "integrity": "sha1-nLvHFHwQpH0lSduQvSmH7BunhLo=" + }, "flush-write-stream": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.0.3.tgz", "integrity": "sha1-xdWG7zivYJdlC0m8QbVfq7GfNb0=", "dev": true, "requires": { - "inherits": "2.0.3", - "readable-stream": "2.3.4" + "inherits": "^2.0.1", + "readable-stream": "^2.0.4" } }, "follow-redirects": { @@ -4199,7 +3871,7 @@ "integrity": "sha1-2BIPRRgZD1Wqxlu2/HuF/NZm1qo=", "dev": true, "requires": { - "debug": "3.1.0" + "debug": "^3.1.0" } }, "font-awesome": { @@ -4214,34 +3886,28 @@ "dev": true }, "for-own": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", - "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", + "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", "dev": true, "requires": { - "for-in": "1.0.2" + "for-in": "^1.0.1" } }, - "foreach": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", - "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=", - "dev": true - }, "forever-agent": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" }, "form-data": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz", - "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz", + "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", "dev": true, "requires": { - "asynckit": "0.4.0", + "asynckit": "^0.4.0", "combined-stream": "1.0.6", - "mime-types": "2.1.18" + "mime-types": "^2.1.12" } }, "forwarded": { @@ -4250,13 +3916,18 @@ "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=", "dev": true }, + "frac": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/frac/-/frac-1.1.2.tgz", + "integrity": "sha1-PXT39keMiKG1AgMG10fcYxPHTQs=" + }, "fragment-cache": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", "dev": true, "requires": { - "map-cache": "0.2.2" + "map-cache": "^0.2.2" } }, "fresh": { @@ -4271,9 +3942,9 @@ "integrity": "sha1-78hsu4FiJFZYYaG+ep2E0Kr+oTY=", "dev": true, "requires": { - "chalk": "1.1.3", - "error-stack-parser": "2.0.1", - "string-width": "2.1.1" + "chalk": "^1.1.3", + "error-stack-parser": "^2.0.0", + "string-width": "^2.0.0" } }, "from2": { @@ -4281,25 +3952,19 @@ "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", "requires": { - "inherits": "2.0.3", - "readable-stream": "2.3.4" + "inherits": "^2.0.1", + "readable-stream": "^2.0.0" } }, - "fs-constants": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", - "integrity": "sha1-a+Dem+mYzhavivwkSXue6bfM2a0=", - "dev": true - }, "fs-extra": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-3.0.1.tgz", "integrity": "sha1-N5TzeMWLNC6n27sjCVEJxLO2IpE=", "dev": true, "requires": { - "graceful-fs": "4.1.11", - "jsonfile": "3.0.1", - "universalify": "0.1.1" + "graceful-fs": "^4.1.2", + "jsonfile": "^3.0.0", + "universalify": "^0.1.0" } }, "fs-write-stream-atomic": { @@ -4308,27 +3973,26 @@ "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=", "dev": true, "requires": { - "graceful-fs": "4.1.11", - "iferr": "0.1.5", - "imurmurhash": "0.1.4", - "readable-stream": "2.3.4" + "graceful-fs": "^4.1.2", + "iferr": "^0.1.5", + "imurmurhash": "^0.1.4", + "readable-stream": "1 || 2" } }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, "fsevents": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.3.tgz", - "integrity": "sha512-X+57O5YkDTiEQGiw8i7wYc2nQgweIekqkepI8Q3y4wVlurgBt2SuwxTeYUYMZIGpLZH3r/TsMjczCMXE5ZOt7Q==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.4.tgz", + "integrity": "sha1-9B3LGvJYKvNpLaNvxVy9jhBBxCY=", "dev": true, "optional": true, "requires": { - "nan": "2.10.0", - "node-pre-gyp": "0.9.1" + "nan": "^2.9.2", + "node-pre-gyp": "^0.10.0" }, "dependencies": { "abbrev": { @@ -4354,8 +4018,8 @@ "dev": true, "optional": true, "requires": { - "delegates": "1.0.0", - "readable-stream": "2.3.6" + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" } }, "balanced-match": { @@ -4368,7 +4032,7 @@ "bundled": true, "dev": true, "requires": { - "balanced-match": "1.0.0", + "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, @@ -4409,7 +4073,7 @@ } }, "deep-extend": { - "version": "0.4.2", + "version": "0.5.1", "bundled": true, "dev": true, "optional": true @@ -4432,7 +4096,7 @@ "dev": true, "optional": true, "requires": { - "minipass": "2.2.4" + "minipass": "^2.2.1" } }, "fs.realpath": { @@ -4447,14 +4111,14 @@ "dev": true, "optional": true, "requires": { - "aproba": "1.2.0", - "console-control-strings": "1.1.0", - "has-unicode": "2.0.1", - "object-assign": "4.1.1", - "signal-exit": "3.0.2", - "string-width": "1.0.2", - "strip-ansi": "3.0.1", - "wide-align": "1.1.2" + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" } }, "glob": { @@ -4463,12 +4127,12 @@ "dev": true, "optional": true, "requires": { - "fs.realpath": "1.0.0", - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" } }, "has-unicode": { @@ -4483,7 +4147,7 @@ "dev": true, "optional": true, "requires": { - "safer-buffer": "2.1.2" + "safer-buffer": "^2.1.0" } }, "ignore-walk": { @@ -4492,7 +4156,7 @@ "dev": true, "optional": true, "requires": { - "minimatch": "3.0.4" + "minimatch": "^3.0.4" } }, "inflight": { @@ -4501,8 +4165,8 @@ "dev": true, "optional": true, "requires": { - "once": "1.4.0", - "wrappy": "1.0.2" + "once": "^1.3.0", + "wrappy": "1" } }, "inherits": { @@ -4521,7 +4185,7 @@ "bundled": true, "dev": true, "requires": { - "number-is-nan": "1.0.1" + "number-is-nan": "^1.0.0" } }, "isarray": { @@ -4535,7 +4199,7 @@ "bundled": true, "dev": true, "requires": { - "brace-expansion": "1.1.11" + "brace-expansion": "^1.1.7" } }, "minimist": { @@ -4548,8 +4212,8 @@ "bundled": true, "dev": true, "requires": { - "safe-buffer": "5.1.1", - "yallist": "3.0.2" + "safe-buffer": "^5.1.1", + "yallist": "^3.0.0" } }, "minizlib": { @@ -4558,7 +4222,7 @@ "dev": true, "optional": true, "requires": { - "minipass": "2.2.4" + "minipass": "^2.2.1" } }, "mkdirp": { @@ -4581,27 +4245,27 @@ "dev": true, "optional": true, "requires": { - "debug": "2.6.9", - "iconv-lite": "0.4.21", - "sax": "1.2.4" + "debug": "^2.1.2", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" } }, "node-pre-gyp": { - "version": "0.9.1", + "version": "0.10.0", "bundled": true, "dev": true, "optional": true, "requires": { - "detect-libc": "1.0.3", - "mkdirp": "0.5.1", - "needle": "2.2.0", - "nopt": "4.0.1", - "npm-packlist": "1.1.10", - "npmlog": "4.1.2", - "rc": "1.2.6", - "rimraf": "2.6.2", - "semver": "5.5.0", - "tar": "4.4.1" + "detect-libc": "^1.0.2", + "mkdirp": "^0.5.1", + "needle": "^2.2.0", + "nopt": "^4.0.1", + "npm-packlist": "^1.1.6", + "npmlog": "^4.0.2", + "rc": "^1.1.7", + "rimraf": "^2.6.1", + "semver": "^5.3.0", + "tar": "^4" } }, "nopt": { @@ -4610,8 +4274,8 @@ "dev": true, "optional": true, "requires": { - "abbrev": "1.1.1", - "osenv": "0.1.5" + "abbrev": "1", + "osenv": "^0.1.4" } }, "npm-bundled": { @@ -4626,8 +4290,8 @@ "dev": true, "optional": true, "requires": { - "ignore-walk": "3.0.1", - "npm-bundled": "1.0.3" + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1" } }, "npmlog": { @@ -4636,10 +4300,10 @@ "dev": true, "optional": true, "requires": { - "are-we-there-yet": "1.1.4", - "console-control-strings": "1.1.0", - "gauge": "2.7.4", - "set-blocking": "2.0.0" + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" } }, "number-is-nan": { @@ -4658,7 +4322,7 @@ "bundled": true, "dev": true, "requires": { - "wrappy": "1.0.2" + "wrappy": "1" } }, "os-homedir": { @@ -4679,8 +4343,8 @@ "dev": true, "optional": true, "requires": { - "os-homedir": "1.0.2", - "os-tmpdir": "1.0.2" + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" } }, "path-is-absolute": { @@ -4696,15 +4360,15 @@ "optional": true }, "rc": { - "version": "1.2.6", + "version": "1.2.7", "bundled": true, "dev": true, "optional": true, "requires": { - "deep-extend": "0.4.2", - "ini": "1.3.5", - "minimist": "1.2.0", - "strip-json-comments": "2.0.1" + "deep-extend": "^0.5.1", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" }, "dependencies": { "minimist": { @@ -4721,13 +4385,13 @@ "dev": true, "optional": true, "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "2.0.0", - "safe-buffer": "5.1.1", - "string_decoder": "1.1.1", - "util-deprecate": "1.0.2" + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" } }, "rimraf": { @@ -4736,7 +4400,7 @@ "dev": true, "optional": true, "requires": { - "glob": "7.1.2" + "glob": "^7.0.5" } }, "safe-buffer": { @@ -4779,9 +4443,9 @@ "bundled": true, "dev": true, "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "strip-ansi": "3.0.1" + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" } }, "string_decoder": { @@ -4790,7 +4454,7 @@ "dev": true, "optional": true, "requires": { - "safe-buffer": "5.1.1" + "safe-buffer": "~5.1.0" } }, "strip-ansi": { @@ -4798,7 +4462,7 @@ "bundled": true, "dev": true, "requires": { - "ansi-regex": "2.1.1" + "ansi-regex": "^2.0.0" } }, "strip-json-comments": { @@ -4813,13 +4477,13 @@ "dev": true, "optional": true, "requires": { - "chownr": "1.0.1", - "fs-minipass": "1.2.5", - "minipass": "2.2.4", - "minizlib": "1.1.0", - "mkdirp": "0.5.1", - "safe-buffer": "5.1.1", - "yallist": "3.0.2" + "chownr": "^1.0.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.2.4", + "minizlib": "^1.1.0", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.1", + "yallist": "^3.0.2" } }, "util-deprecate": { @@ -4834,7 +4498,7 @@ "dev": true, "optional": true, "requires": { - "string-width": "1.0.2" + "string-width": "^1.0.2" } }, "wrappy": { @@ -4855,17 +4519,25 @@ "integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=", "dev": true, "requires": { - "graceful-fs": "4.1.11", - "inherits": "2.0.3", - "mkdirp": "0.5.1", - "rimraf": "2.6.2" + "graceful-fs": "^4.1.2", + "inherits": "~2.0.0", + "mkdirp": ">=0.5 0", + "rimraf": "2" + } + }, + "fullcalendar": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/fullcalendar/-/fullcalendar-3.9.0.tgz", + "integrity": "sha1-tgipmJ80FvCx1SbGvf7q8qx57aU=", + "requires": { + "jquery": "2 - 3", + "moment": "^2.20.1" } }, "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha1-pWiZ0+o8m6uHS7l3O3xe3pL0iV0=", - "dev": true + "integrity": "sha1-pWiZ0+o8m6uHS7l3O3xe3pL0iV0=" }, "gauge": { "version": "2.7.4", @@ -4873,14 +4545,14 @@ "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", "dev": true, "requires": { - "aproba": "1.2.0", - "console-control-strings": "1.1.0", - "has-unicode": "2.0.1", - "object-assign": "4.1.1", - "signal-exit": "3.0.2", - "string-width": "1.0.2", - "strip-ansi": "3.0.1", - "wide-align": "1.1.2" + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" }, "dependencies": { "is-fullwidth-code-point": { @@ -4889,7 +4561,7 @@ "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", "dev": true, "requires": { - "number-is-nan": "1.0.1" + "number-is-nan": "^1.0.0" } }, "string-width": { @@ -4898,52 +4570,33 @@ "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "dev": true, "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "strip-ansi": "3.0.1" + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" } } } }, "gaze": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.2.tgz", - "integrity": "sha1-hHIkZ3rbiHDWeSV+0ziP22HkAQU=", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.3.tgz", + "integrity": "sha1-xEFzPhO5J6yMD/C0w7Az8ogSkko=", "dev": true, "requires": { - "globule": "1.2.0" + "globule": "^1.0.0" } }, - "generate-function": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz", - "integrity": "sha1-aFj+fAlpt9TpCTM3ZHrHn2DfvnQ=", - "dev": true - }, - "generate-object-property": { + "get-assigned-identifiers": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", - "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", - "dev": true, - "requires": { - "is-property": "1.0.2" - } + "resolved": "https://registry.npmjs.org/get-assigned-identifiers/-/get-assigned-identifiers-1.2.0.tgz", + "integrity": "sha1-bb9BHeZIy6+NkWnrsNLVdhkeL/E=" }, "get-caller-file": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz", - "integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", + "integrity": "sha1-+Xj6TJDR3+f/LWvtoqUV5xO9z0o=", "dev": true }, - "get-proxy": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/get-proxy/-/get-proxy-1.1.0.tgz", - "integrity": "sha1-iUhUSRvFkbDxR9euVw9cZ4tyVus=", - "dev": true, - "requires": { - "rc": "1.2.7" - } - }, "get-stdin": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", @@ -4966,39 +4619,20 @@ "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", "requires": { - "assert-plus": "1.0.0" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" - } - } - }, - "gifsicle": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/gifsicle/-/gifsicle-3.0.4.tgz", - "integrity": "sha1-9Fy17RAWW2ZdySng6TKLbIId+js=", - "dev": true, - "requires": { - "bin-build": "2.2.0", - "bin-wrapper": "3.0.2", - "logalot": "2.1.0" + "assert-plus": "^1.0.0" } }, "glob": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", - "dev": true, + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha1-OWCDLT8VdBCDQtr9OmezMsCWnfE=", "requires": { - "fs.realpath": "1.0.0", - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" } }, "glob-base": { @@ -5007,8 +4641,8 @@ "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", "dev": true, "requires": { - "glob-parent": "2.0.0", - "is-glob": "2.0.1" + "glob-parent": "^2.0.0", + "is-glob": "^2.0.0" }, "dependencies": { "glob-parent": { @@ -5017,7 +4651,7 @@ "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", "dev": true, "requires": { - "is-glob": "2.0.1" + "is-glob": "^2.0.0" } }, "is-extglob": { @@ -5032,7 +4666,7 @@ "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", "dev": true, "requires": { - "is-extglob": "1.0.0" + "is-extglob": "^1.0.0" } } } @@ -5043,8 +4677,8 @@ "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", "dev": true, "requires": { - "is-glob": "3.1.0", - "path-dirname": "1.0.2" + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" }, "dependencies": { "is-glob": { @@ -5053,127 +4687,7 @@ "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", "dev": true, "requires": { - "is-extglob": "2.1.1" - } - } - } - }, - "glob-stream": { - "version": "5.3.5", - "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-5.3.5.tgz", - "integrity": "sha1-pVZlqajM3EGRWofHAeMtTgFvrSI=", - "dev": true, - "requires": { - "extend": "3.0.1", - "glob": "5.0.15", - "glob-parent": "3.1.0", - "micromatch": "2.3.11", - "ordered-read-streams": "0.3.0", - "through2": "0.6.5", - "to-absolute-glob": "0.1.1", - "unique-stream": "2.2.1" - }, - "dependencies": { - "arr-diff": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", - "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", - "dev": true, - "requires": { - "arr-flatten": "1.1.0" - } - }, - "array-unique": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", - "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", - "dev": true - }, - "braces": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", - "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", - "dev": true, - "requires": { - "expand-range": "1.8.2", - "preserve": "0.2.0", - "repeat-element": "1.1.2" - } - }, - "expand-brackets": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", - "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", - "dev": true, - "requires": { - "is-posix-bracket": "0.1.1" - } - }, - "extglob": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", - "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", - "dev": true, - "requires": { - "is-extglob": "1.0.0" - } - }, - "glob": { - "version": "5.0.15", - "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", - "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", - "dev": true, - "requires": { - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" - } - }, - "is-extglob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true - }, - "is-glob": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "dev": true, - "requires": { - "is-extglob": "1.0.0" - } - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "1.1.6" - } - }, - "micromatch": { - "version": "2.3.11", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", - "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", - "dev": true, - "requires": { - "arr-diff": "2.0.0", - "array-unique": "0.2.1", - "braces": "1.8.5", - "expand-brackets": "0.1.5", - "extglob": "0.3.2", - "filename-regex": "2.0.1", - "is-extglob": "1.0.0", - "is-glob": "2.0.1", - "kind-of": "3.2.2", - "normalize-path": "2.1.1", - "object.omit": "2.0.1", - "parse-glob": "3.0.4", - "regex-cache": "0.4.4" + "is-extglob": "^2.1.0" } } } @@ -5188,20 +4702,18 @@ "version": "6.1.0", "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", - "dev": true, "requires": { - "array-union": "1.0.2", - "glob": "7.1.2", - "object-assign": "4.1.1", - "pify": "2.3.0", - "pinkie-promise": "2.0.1" + "array-union": "^1.0.1", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" }, "dependencies": { "pify": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" } } }, @@ -5211,27 +4723,26 @@ "integrity": "sha1-HRNjn2F05K5zp/k22n2aB59lfBw=", "dev": true, "requires": { - "glob": "7.1.2" + "glob": "^7.1.1" } }, "globule": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/globule/-/globule-1.2.0.tgz", - "integrity": "sha1-HcScaCLdnoovoAuiopUAboZkvQk=", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/globule/-/globule-1.2.1.tgz", + "integrity": "sha1-Xf+xsZHyLSB5epNptJ6rTpg5aW0=", "dev": true, "requires": { - "glob": "7.1.2", - "lodash": "4.17.5", - "minimatch": "3.0.4" - } - }, - "glogg": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.1.tgz", - "integrity": "sha1-3PdY5EeJzD89MsHzVio2duajSBA=", - "dev": true, - "requires": { - "sparkles": "1.0.0" + "glob": "~7.1.1", + "lodash": "~4.17.10", + "minimatch": "~3.0.2" + }, + "dependencies": { + "lodash": { + "version": "4.17.10", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==", + "dev": true + } } }, "got": { @@ -5239,23 +4750,23 @@ "resolved": "https://registry.npmjs.org/got/-/got-8.3.0.tgz", "integrity": "sha512-kBNy/S2CGwrYgDSec5KTWGKUvupwkkTVAjIsVFF2shXO13xpZdFP4d4kxa//CLX2tN/rV0aYwK8vY6UKWGn2vQ==", "requires": { - "@sindresorhus/is": "0.7.0", - "cacheable-request": "2.1.4", - "decompress-response": "3.3.0", - "duplexer3": "0.1.4", - "get-stream": "3.0.0", - "into-stream": "3.1.0", - "is-retry-allowed": "1.1.0", - "isurl": "1.0.0", - "lowercase-keys": "1.0.0", - "mimic-response": "1.0.0", - "p-cancelable": "0.4.1", - "p-timeout": "2.0.1", - "pify": "3.0.0", - "safe-buffer": "5.1.1", - "timed-out": "4.0.1", - "url-parse-lax": "3.0.0", - "url-to-options": "1.0.1" + "@sindresorhus/is": "^0.7.0", + "cacheable-request": "^2.1.1", + "decompress-response": "^3.3.0", + "duplexer3": "^0.1.4", + "get-stream": "^3.0.0", + "into-stream": "^3.1.0", + "is-retry-allowed": "^1.1.0", + "isurl": "^1.0.0-alpha5", + "lowercase-keys": "^1.0.0", + "mimic-response": "^1.0.0", + "p-cancelable": "^0.4.0", + "p-timeout": "^2.0.1", + "pify": "^3.0.0", + "safe-buffer": "^5.1.1", + "timed-out": "^4.0.1", + "url-parse-lax": "^3.0.0", + "url-to-options": "^1.0.1" }, "dependencies": { "p-cancelable": { @@ -5270,143 +4781,12 @@ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" }, - "graceful-readlink": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", - "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", - "dev": true - }, "growly": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/growly/-/growly-1.3.0.tgz", "integrity": "sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=", "dev": true }, - "gulp-decompress": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/gulp-decompress/-/gulp-decompress-1.2.0.tgz", - "integrity": "sha1-jutlpeAV+O2FMsr+KEVJYGJvDcc=", - "dev": true, - "requires": { - "archive-type": "3.2.0", - "decompress": "3.0.0", - "gulp-util": "3.0.8", - "readable-stream": "2.3.4" - } - }, - "gulp-rename": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/gulp-rename/-/gulp-rename-1.2.2.tgz", - "integrity": "sha1-OtRCh2PwXidk3sHGfYaNsnVoeBc=", - "dev": true - }, - "gulp-sourcemaps": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/gulp-sourcemaps/-/gulp-sourcemaps-1.6.0.tgz", - "integrity": "sha1-uG/zSdgBzrVuHZ59x7vLS33uYAw=", - "dev": true, - "requires": { - "convert-source-map": "1.5.1", - "graceful-fs": "4.1.11", - "strip-bom": "2.0.0", - "through2": "2.0.3", - "vinyl": "1.2.0" - }, - "dependencies": { - "through2": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", - "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", - "dev": true, - "requires": { - "readable-stream": "2.3.4", - "xtend": "4.0.1" - } - } - } - }, - "gulp-util": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", - "integrity": "sha1-AFTh50RQLifATBh8PsxQXdVLu08=", - "dev": true, - "requires": { - "array-differ": "1.0.0", - "array-uniq": "1.0.3", - "beeper": "1.1.1", - "chalk": "1.1.3", - "dateformat": "2.2.0", - "fancy-log": "1.3.2", - "gulplog": "1.0.0", - "has-gulplog": "0.1.0", - "lodash._reescape": "3.0.0", - "lodash._reevaluate": "3.0.0", - "lodash._reinterpolate": "3.0.0", - "lodash.template": "3.6.2", - "minimist": "1.2.0", - "multipipe": "0.1.2", - "object-assign": "3.0.0", - "replace-ext": "0.0.1", - "through2": "2.0.3", - "vinyl": "0.5.3" - }, - "dependencies": { - "clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", - "dev": true - }, - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - }, - "object-assign": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", - "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=", - "dev": true - }, - "replace-ext": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", - "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", - "dev": true - }, - "through2": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", - "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", - "dev": true, - "requires": { - "readable-stream": "2.3.4", - "xtend": "4.0.1" - } - }, - "vinyl": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz", - "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=", - "dev": true, - "requires": { - "clone": "1.0.4", - "clone-stats": "0.0.1", - "replace-ext": "0.0.1" - } - } - } - }, - "gulplog": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", - "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", - "dev": true, - "requires": { - "glogg": "1.0.1" - } - }, "handle-thing": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-1.2.5.tgz", @@ -5414,28 +4794,41 @@ "dev": true }, "har-schema": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-1.0.5.tgz", - "integrity": "sha1-0mMTX0MwfALGAq/I/pWXDAFRNp4=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", "dev": true }, "har-validator": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-4.2.1.tgz", - "integrity": "sha1-M0gdDxu/9gDdID11gSpqX7oALio=", + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz", + "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", "dev": true, "requires": { - "ajv": "4.11.8", - "har-schema": "1.0.5" + "ajv": "^5.1.0", + "har-schema": "^2.0.0" + }, + "dependencies": { + "ajv": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "dev": true, + "requires": { + "co": "^4.6.0", + "fast-deep-equal": "^1.0.0", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.3.0" + } + } } }, "has": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.1.tgz", - "integrity": "sha1-hGFzP1OLCDfJNh45qauelwTcLyg=", - "dev": true, + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha1-ci18v8H2qoJB8W3YFOAR4fQeh5Y=", "requires": { - "function-bind": "1.1.1" + "function-bind": "^1.1.1" } }, "has-ansi": { @@ -5444,7 +4837,7 @@ "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", "dev": true, "requires": { - "ansi-regex": "2.1.1" + "ansi-regex": "^2.0.0" } }, "has-flag": { @@ -5453,15 +4846,6 @@ "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", "dev": true }, - "has-gulplog": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz", - "integrity": "sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4=", - "dev": true, - "requires": { - "sparkles": "1.0.0" - } - }, "has-symbol-support-x": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz", @@ -5472,7 +4856,7 @@ "resolved": "https://registry.npmjs.org/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz", "integrity": "sha1-oEWrOD17SyASoAFIqwql8pAETU0=", "requires": { - "has-symbol-support-x": "1.4.2" + "has-symbol-support-x": "^1.4.1" } }, "has-unicode": { @@ -5487,9 +4871,9 @@ "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", "dev": true, "requires": { - "get-value": "2.0.6", - "has-values": "1.0.0", - "isobject": "3.0.1" + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" } }, "has-values": { @@ -5498,8 +4882,8 @@ "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", "dev": true, "requires": { - "is-number": "3.0.0", - "kind-of": "4.0.0" + "is-number": "^3.0.0", + "kind-of": "^4.0.0" }, "dependencies": { "kind-of": { @@ -5508,7 +4892,7 @@ "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", "dev": true, "requires": { - "is-buffer": "1.1.6" + "is-buffer": "^1.1.5" } } } @@ -5517,10 +4901,9 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", - "dev": true, "requires": { - "inherits": "2.0.3", - "safe-buffer": "5.1.1" + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" } }, "hash-sum": { @@ -5530,25 +4913,12 @@ "dev": true }, "hash.js": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", - "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", - "dev": true, + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.5.tgz", + "integrity": "sha1-44q0uF37HgxA/pJlwOm1SFTCOBI=", "requires": { - "inherits": "2.0.3", - "minimalistic-assert": "1.0.1" - } - }, - "hawk": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", - "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=", - "dev": true, - "requires": { - "boom": "2.10.1", - "cryptiles": "2.0.5", - "hoek": "2.16.3", - "sntp": "1.0.9" + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" } }, "he": { @@ -5561,33 +4931,26 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", - "dev": true, "requires": { - "hash.js": "1.1.3", - "minimalistic-assert": "1.0.1", - "minimalistic-crypto-utils": "1.0.1" + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" } }, - "hoek": { - "version": "2.16.3", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", - "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=", - "dev": true - }, "home-or-tmp": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz", "integrity": "sha1-42w/LSyufXRqhX440Y1fMqeILbg=", "dev": true, "requires": { - "os-homedir": "1.0.2", - "os-tmpdir": "1.0.2" + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.1" } }, "hosted-git-info": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.6.0.tgz", - "integrity": "sha512-lIbgIIQA3lz5XaB6vxakj6sDHADJiZadYEJB+FgA+C4nubM1NwcuvUr9EJPmnH1skZqpqUzWborWo8EIUi0Sdw==", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz", + "integrity": "sha1-l/I2l3vW4SVAiTD/bePuxigewEc=", "dev": true }, "hpack.js": { @@ -5596,10 +4959,10 @@ "integrity": "sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI=", "dev": true, "requires": { - "inherits": "2.0.3", - "obuf": "1.1.2", - "readable-stream": "2.3.4", - "wbuf": "1.7.3" + "inherits": "^2.0.1", + "obuf": "^1.0.0", + "readable-stream": "^2.0.1", + "wbuf": "^1.1.0" } }, "html-comment-regex": { @@ -5620,46 +4983,56 @@ "integrity": "sha1-X7zYfNY6XEmn/OL+VvQl4Fcpxow=", "dev": true, "requires": { - "es6-templates": "0.2.3", - "fastparse": "1.1.1", - "html-minifier": "3.5.15", - "loader-utils": "1.1.0", - "object-assign": "4.1.1" + "es6-templates": "^0.2.2", + "fastparse": "^1.1.1", + "html-minifier": "^3.0.1", + "loader-utils": "^1.0.2", + "object-assign": "^4.1.0" } }, "html-minifier": { - "version": "3.5.15", - "resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-3.5.15.tgz", - "integrity": "sha512-OZa4rfb6tZOZ3Z8Xf0jKxXkiDcFWldQePGYFDcgKqES2sXeWaEv9y6QQvWUtX3ySI3feApQi5uCsHLINQ6NoAw==", + "version": "3.5.20", + "resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-3.5.20.tgz", + "integrity": "sha1-exn9PKoMt5983l7lw6vfjsqmuxQ=", "dev": true, "requires": { - "camel-case": "3.0.0", - "clean-css": "4.1.11", - "commander": "2.15.1", - "he": "1.1.1", - "param-case": "2.1.1", - "relateurl": "0.2.7", - "uglify-js": "3.3.23" + "camel-case": "3.0.x", + "clean-css": "4.2.x", + "commander": "2.17.x", + "he": "1.1.x", + "param-case": "2.1.x", + "relateurl": "0.2.x", + "uglify-js": "3.4.x" }, "dependencies": { "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", "dev": true }, "uglify-js": { - "version": "3.3.23", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.3.23.tgz", - "integrity": "sha512-Ks+KqLGDsYn4z+pU7JsKCzC0T3mPYl+rU+VcPZiQOazjE4Uqi4UCRY3qPMDbJi7ze37n1lDXj3biz1ik93vqvw==", + "version": "3.4.8", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.8.tgz", + "integrity": "sha512-WatYTD84gP/867bELqI2F/2xC9PQBETn/L+7RGq9MQOA/7yFBNvY1UwXqvtILeE6n0ITwBXxp34M0/o70dzj6A==", "dev": true, "requires": { - "commander": "2.15.1", - "source-map": "0.6.1" + "commander": "~2.17.1", + "source-map": "~0.6.1" } } } }, + "html2canvas": { + "version": "0.5.0-beta4", + "resolved": "https://registry.npmjs.org/html2canvas/-/html2canvas-0.5.0-beta4.tgz", + "integrity": "sha1-goLGKsX9eBaPVwK15IdxV8qT854=" + }, + "htmlescape": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/htmlescape/-/htmlescape-1.1.1.tgz", + "integrity": "sha1-OgPtwiFLyjtmQko+eVk0lQnLA1E=" + }, "http-cache-semantics": { "version": "3.8.1", "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz", @@ -5677,16 +5050,16 @@ "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", "dev": true, "requires": { - "depd": "1.1.2", + "depd": "~1.1.2", "inherits": "2.0.3", "setprototypeof": "1.1.0", - "statuses": "1.4.0" + "statuses": ">= 1.4.0 < 2" } }, "http-parser-js": { - "version": "0.4.12", - "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.4.12.tgz", - "integrity": "sha1-uc+/Sizybw/DSxDKFImid3HjR08=", + "version": "0.4.13", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.4.13.tgz", + "integrity": "sha1-O9bW/ebjFyyTNMOzO2wZPYD+ETc=", "dev": true }, "http-proxy": { @@ -5695,9 +5068,9 @@ "integrity": "sha1-etOElGWPhGBeL220Q230EPTlvpo=", "dev": true, "requires": { - "eventemitter3": "3.1.0", - "follow-redirects": "1.4.1", - "requires-port": "1.0.0" + "eventemitter3": "^3.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" } }, "http-proxy-middleware": { @@ -5706,10 +5079,10 @@ "integrity": "sha1-ZC6ISIUdZvCdTxJJEoRtuutBuDM=", "dev": true, "requires": { - "http-proxy": "1.17.0", - "is-glob": "3.1.0", - "lodash": "4.17.5", - "micromatch": "2.3.11" + "http-proxy": "^1.16.2", + "is-glob": "^3.1.0", + "lodash": "^4.17.2", + "micromatch": "^2.3.11" }, "dependencies": { "arr-diff": { @@ -5718,7 +5091,7 @@ "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", "dev": true, "requires": { - "arr-flatten": "1.1.0" + "arr-flatten": "^1.0.1" } }, "array-unique": { @@ -5733,9 +5106,9 @@ "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", "dev": true, "requires": { - "expand-range": "1.8.2", - "preserve": "0.2.0", - "repeat-element": "1.1.2" + "expand-range": "^1.8.1", + "preserve": "^0.2.0", + "repeat-element": "^1.1.2" } }, "expand-brackets": { @@ -5744,7 +5117,7 @@ "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", "dev": true, "requires": { - "is-posix-bracket": "0.1.1" + "is-posix-bracket": "^0.1.0" } }, "extglob": { @@ -5753,7 +5126,7 @@ "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", "dev": true, "requires": { - "is-extglob": "1.0.0" + "is-extglob": "^1.0.0" }, "dependencies": { "is-extglob": { @@ -5770,7 +5143,7 @@ "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", "dev": true, "requires": { - "is-extglob": "2.1.1" + "is-extglob": "^2.1.0" } }, "kind-of": { @@ -5779,7 +5152,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "1.1.6" + "is-buffer": "^1.1.5" } }, "micromatch": { @@ -5788,19 +5161,19 @@ "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", "dev": true, "requires": { - "arr-diff": "2.0.0", - "array-unique": "0.2.1", - "braces": "1.8.5", - "expand-brackets": "0.1.5", - "extglob": "0.3.2", - "filename-regex": "2.0.1", - "is-extglob": "1.0.0", - "is-glob": "2.0.1", - "kind-of": "3.2.2", - "normalize-path": "2.1.1", - "object.omit": "2.0.1", - "parse-glob": "3.0.4", - "regex-cache": "0.4.4" + "arr-diff": "^2.0.0", + "array-unique": "^0.2.1", + "braces": "^1.8.2", + "expand-brackets": "^0.1.4", + "extglob": "^0.3.1", + "filename-regex": "^2.0.0", + "is-extglob": "^1.0.0", + "is-glob": "^2.0.1", + "kind-of": "^3.0.2", + "normalize-path": "^2.0.1", + "object.omit": "^2.0.0", + "parse-glob": "^3.0.4", + "regex-cache": "^0.4.2" }, "dependencies": { "is-extglob": { @@ -5815,7 +5188,7 @@ "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", "dev": true, "requires": { - "is-extglob": "1.0.0" + "is-extglob": "^1.0.0" } } } @@ -5823,21 +5196,20 @@ } }, "http-signature": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", - "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", "dev": true, "requires": { - "assert-plus": "0.2.0", - "jsprim": "1.4.1", - "sshpk": "1.13.1" + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" } }, "https-browserify": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", - "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=", - "dev": true + "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=" }, "icheck": { "version": "1.0.2", @@ -5862,14 +5234,13 @@ "integrity": "sha1-g/Cg7DeL8yRheLbCrZE28TWxyWI=", "dev": true, "requires": { - "postcss": "6.0.19" + "postcss": "^6.0.1" } }, "ieee754": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.11.tgz", - "integrity": "sha512-VhDzCKN7K8ufStx/CLj5/PDTMgph+qwN5Pkd5i0sGnVwk56zJ0lkT8Qzi1xqWLS0Wp29DgDtNeS7v8/wMoZeHg==", - "dev": true + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.12.tgz", + "integrity": "sha1-UL8k5bnIu5ivSWTJQc2wkY2ntgs=" }, "iferr": { "version": "0.1.5", @@ -5887,216 +5258,47 @@ "version": "5.3.1", "resolved": "https://registry.npmjs.org/imagemin/-/imagemin-5.3.1.tgz", "integrity": "sha1-8Zwu7h5xumxlWMUV+fyWaAGJptQ=", - "dev": true, "requires": { - "file-type": "4.4.0", - "globby": "6.1.0", - "make-dir": "1.2.0", - "p-pipe": "1.2.0", - "pify": "2.3.0", - "replace-ext": "1.0.0" + "file-type": "^4.1.0", + "globby": "^6.1.0", + "make-dir": "^1.0.0", + "p-pipe": "^1.1.0", + "pify": "^2.3.0", + "replace-ext": "^1.0.0" }, "dependencies": { "pify": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - } - } - }, - "imagemin-gifsicle": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/imagemin-gifsicle/-/imagemin-gifsicle-5.2.0.tgz", - "integrity": "sha1-N4FSTEV2Eu8EkWrzQkGitCv8tAo=", - "dev": true, - "requires": { - "exec-buffer": "3.2.0", - "gifsicle": "3.0.4", - "is-gif": "1.0.0" - } - }, - "imagemin-mozjpeg": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/imagemin-mozjpeg/-/imagemin-mozjpeg-7.0.0.tgz", - "integrity": "sha1-2SZHf8bvXzp2ikIi97LYCNPrpWg=", - "dev": true, - "requires": { - "execa": "0.8.0", - "is-jpg": "1.0.1", - "mozjpeg": "5.0.0" - }, - "dependencies": { - "execa": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.8.0.tgz", - "integrity": "sha1-2NdrvBtVIX7RkP1t1J08d07PyNo=", - "dev": true, - "requires": { - "cross-spawn": "5.1.0", - "get-stream": "3.0.0", - "is-stream": "1.1.0", - "npm-run-path": "2.0.2", - "p-finally": "1.0.0", - "signal-exit": "3.0.2", - "strip-eof": "1.0.0" - } - } - } - }, - "imagemin-optipng": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/imagemin-optipng/-/imagemin-optipng-5.2.1.tgz", - "integrity": "sha1-0i2kEsCfX/AKQzmWC5ioix2+hpU=", - "dev": true, - "requires": { - "exec-buffer": "3.2.0", - "is-png": "1.1.0", - "optipng-bin": "3.1.4" - } - }, - "imagemin-pngquant": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/imagemin-pngquant/-/imagemin-pngquant-5.1.0.tgz", - "integrity": "sha1-uetWPZ5qOHb2JIvgBhuhsO8mnAc=", - "dev": true, - "requires": { - "execa": "0.10.0", - "is-png": "1.1.0", - "is-stream": "1.1.0", - "pngquant-bin": "4.0.0" - }, - "dependencies": { - "cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "dev": true, - "requires": { - "nice-try": "1.0.4", - "path-key": "2.0.1", - "semver": "5.5.0", - "shebang-command": "1.2.0", - "which": "1.3.0" - } - }, - "execa": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.10.0.tgz", - "integrity": "sha1-/0Vqj1P5D47MxxqW0Rvfx/CCy1A=", - "dev": true, - "requires": { - "cross-spawn": "6.0.5", - "get-stream": "3.0.0", - "is-stream": "1.1.0", - "npm-run-path": "2.0.2", - "p-finally": "1.0.0", - "signal-exit": "3.0.2", - "strip-eof": "1.0.0" - } - } - } - }, - "imagemin-svgo": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/imagemin-svgo/-/imagemin-svgo-6.0.0.tgz", - "integrity": "sha1-LdjIKUa+Qqjiy8rjxb8Ae8K4ueg=", - "dev": true, - "requires": { - "buffer-from": "0.1.2", - "is-svg": "2.1.0", - "svgo": "1.0.5" - }, - "dependencies": { - "buffer-from": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-0.1.2.tgz", - "integrity": "sha1-FfS5vO8BIETfMRQsFDM8r24CYNA=", - "dev": true - }, - "coa": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/coa/-/coa-2.0.1.tgz", - "integrity": "sha1-8/iwsVBz411wJj+xBCyywCPbOK8=", - "dev": true, - "requires": { - "q": "1.5.1" - } - }, - "csso": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/csso/-/csso-3.5.0.tgz", - "integrity": "sha512-WtJjFP3ZsSdWhiZr4/k1B9uHPgYjFYnDxfbaJxk1hz5PDLIJ5BCRWkJqaztZ0DbP8d2ZIVwUPIJb2YmCwkPaMw==", - "dev": true, - "requires": { - "css-tree": "1.0.0-alpha.27" - }, - "dependencies": { - "css-tree": { - "version": "1.0.0-alpha.27", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.27.tgz", - "integrity": "sha512-BAYp9FyN4jLXjfvRpTDchBllDptqlK9I7OsagXCG9Am5C+5jc8eRZHgqb9x500W2OKS14MMlpQc/nmh/aA7TEQ==", - "dev": true, - "requires": { - "mdn-data": "1.1.2", - "source-map": "0.5.7" - } - } - } - }, - "esprima": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", - "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==", - "dev": true - }, - "js-yaml": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.10.0.tgz", - "integrity": "sha1-LnhEFka9RoLpY/IrbpKCPDCcYtw=", - "dev": true, - "requires": { - "argparse": "1.0.10", - "esprima": "4.0.0" - } - }, - "svgo": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/svgo/-/svgo-1.0.5.tgz", - "integrity": "sha1-cEA2TAYqBTirrP9EAc6momp6OJo=", - "dev": true, - "requires": { - "coa": "2.0.1", - "colors": "1.1.2", - "css-select": "1.3.0-rc0", - "css-select-base-adapter": "0.1.0", - "css-tree": "1.0.0-alpha25", - "css-url-regex": "1.1.0", - "csso": "3.5.0", - "js-yaml": "3.10.0", - "mkdirp": "0.5.1", - "object.values": "1.0.4", - "sax": "1.2.4", - "stable": "0.1.8", - "unquote": "1.1.1", - "util.promisify": "1.0.0" - } + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" } } }, "img-loader": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/img-loader/-/img-loader-2.0.1.tgz", - "integrity": "sha1-3o+Aql4yIvoetMjDvD1B5djdfHg=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/img-loader/-/img-loader-3.0.0.tgz", + "integrity": "sha1-FUPO2Amx7JtNXnfSWEFZKC8cTdY=", "dev": true, "requires": { - "imagemin": "5.3.1", - "imagemin-gifsicle": "5.2.0", - "imagemin-mozjpeg": "7.0.0", - "imagemin-optipng": "5.2.1", - "imagemin-pngquant": "5.1.0", - "imagemin-svgo": "6.0.0", - "loader-utils": "1.1.0" + "loader-utils": "^1.1.0" + } + }, + "import-cwd": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-cwd/-/import-cwd-2.1.0.tgz", + "integrity": "sha1-qmzzbnInYShcs3HsZRn1PiQ1sKk=", + "dev": true, + "requires": { + "import-from": "^2.1.0" + } + }, + "import-from": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-from/-/import-from-2.1.0.tgz", + "integrity": "sha1-M1238qev/VOqpHHUuAId7ja387E=", + "dev": true, + "requires": { + "resolve-from": "^3.0.0" } }, "import-local": { @@ -6105,8 +5307,8 @@ "integrity": "sha1-Xk/9wD9P5sAJxnKb6yljHC+CJ7w=", "dev": true, "requires": { - "pkg-dir": "2.0.0", - "resolve-cwd": "2.0.0" + "pkg-dir": "^2.0.0", + "resolve-cwd": "^2.0.0" } }, "imurmurhash": { @@ -6127,7 +5329,7 @@ "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", "dev": true, "requires": { - "repeating": "2.0.1" + "repeating": "^2.0.0" } }, "indexes-of": { @@ -6146,10 +5348,9 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, "requires": { - "once": "1.4.0", - "wrappy": "1.0.2" + "once": "^1.3.0", + "wrappy": "1" } }, "inherits": { @@ -6157,11 +5358,35 @@ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" }, - "ini": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", - "integrity": "sha1-7uJfVtscnsYIXgwid4CD9Zar+Sc=", - "dev": true + "inline-source-map": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/inline-source-map/-/inline-source-map-0.6.2.tgz", + "integrity": "sha1-+Tk0ccGKedFyT4Y/o4tYY3Ct4qU=", + "requires": { + "source-map": "~0.5.3" + } + }, + "inputmask": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/inputmask/-/inputmask-3.3.11.tgz", + "integrity": "sha1-FCHJSuKMPc0bTSYze1CLs0mY4tg=" + }, + "insert-module-globals": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/insert-module-globals/-/insert-module-globals-7.2.0.tgz", + "integrity": "sha1-7IfltCcoR54ye9XFxxYR3ftHUro=", + "requires": { + "JSONStream": "^1.0.3", + "acorn-node": "^1.5.2", + "combine-source-map": "^0.8.0", + "concat-stream": "^1.6.1", + "is-buffer": "^1.1.0", + "path-is-absolute": "^1.0.1", + "process": "~0.11.0", + "through2": "^2.0.0", + "undeclared-identifiers": "^1.1.2", + "xtend": "^4.0.0" + } }, "internal-ip": { "version": "1.2.0", @@ -6169,7 +5394,7 @@ "integrity": "sha1-rp+/k7mEh4eF1QqN4bNWlWBYz1w=", "dev": true, "requires": { - "meow": "3.7.0" + "meow": "^3.3.0" } }, "interpret": { @@ -6183,8 +5408,8 @@ "resolved": "https://registry.npmjs.org/into-stream/-/into-stream-3.1.0.tgz", "integrity": "sha1-lvsKk2wSur1v8XUqF9BWFqvQlMY=", "requires": { - "from2": "2.3.0", - "p-is-promise": "1.1.0" + "from2": "^2.1.1", + "p-is-promise": "^1.1.0" } }, "invariant": { @@ -6193,7 +5418,7 @@ "integrity": "sha512-7Z5PPegwDTyjbaeCnV0efcyS6vdKAU51kpEmS7QFib3P4822l8ICYyMn7qvJnc+WzLoDsuI9gPMKbJ8pCu8XtA==", "dev": true, "requires": { - "loose-envify": "1.3.1" + "loose-envify": "^1.0.0" } }, "invert-kv": { @@ -6202,33 +5427,31 @@ "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", "dev": true }, + "ion-rangeslider": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ion-rangeslider/-/ion-rangeslider-2.2.0.tgz", + "integrity": "sha1-OI8SzXBZOmGzNo+tbE8wpdqLl8k=", + "requires": { + "jquery": ">=1.8" + } + }, + "ionicons": { + "version": "3.0.0", + "resolved": "http://registry.npmjs.org/ionicons/-/ionicons-3.0.0.tgz", + "integrity": "sha1-QLja9P16MRUL0AIWD2ZJbiKpjDw=" + }, "ip": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", "dev": true }, - "ip-regex": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-1.0.3.tgz", - "integrity": "sha1-3FiQdvZZ9BnCIgOaMzFvHHOH7/0=", - "dev": true - }, "ipaddr.js": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.6.0.tgz", - "integrity": "sha1-4/o1e3c9phnybpXwSdBVxyeW+Gs=", + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.8.0.tgz", + "integrity": "sha1-6qM9bd16zo9/b+DJygRA5wZzix4=", "dev": true }, - "is-absolute": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-0.1.7.tgz", - "integrity": "sha1-hHSREZ/MtftDYhfMc39/qtUPYD8=", - "dev": true, - "requires": { - "is-relative": "0.1.3" - } - }, "is-absolute-url": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-2.1.0.tgz", @@ -6241,7 +5464,7 @@ "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", "dev": true, "requires": { - "kind-of": "3.2.2" + "kind-of": "^3.0.2" }, "dependencies": { "kind-of": { @@ -6250,7 +5473,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "1.1.6" + "is-buffer": "^1.1.5" } } } @@ -6267,14 +5490,13 @@ "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", "dev": true, "requires": { - "binary-extensions": "1.11.0" + "binary-extensions": "^1.0.0" } }, "is-buffer": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha1-76ouqdqg16suoTqXsritUf776L4=", - "dev": true + "integrity": "sha1-76ouqdqg16suoTqXsritUf776L4=" }, "is-builtin-module": { "version": "1.0.0", @@ -6282,19 +5504,13 @@ "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", "dev": true, "requires": { - "builtin-modules": "1.1.1" + "builtin-modules": "^1.0.0" } }, - "is-bzip2": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-bzip2/-/is-bzip2-1.0.0.tgz", - "integrity": "sha1-XuWOqlounIDiFAe+3yOuWsCRs/w=", - "dev": true - }, "is-callable": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.3.tgz", - "integrity": "sha1-hut1OSgF3cM69xySoO7fdO52BLI=", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", + "integrity": "sha1-HhrfIZ4e62hNaR+dagX/DTCiTXU=", "dev": true }, "is-data-descriptor": { @@ -6303,7 +5519,7 @@ "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", "dev": true, "requires": { - "kind-of": "3.2.2" + "kind-of": "^3.0.2" }, "dependencies": { "kind-of": { @@ -6312,7 +5528,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "1.1.6" + "is-buffer": "^1.1.5" } } } @@ -6329,9 +5545,9 @@ "integrity": "sha1-Nm2CQN3kh8pRgjsaufB6EKeCUco=", "dev": true, "requires": { - "is-accessor-descriptor": "0.1.6", - "is-data-descriptor": "0.1.4", - "kind-of": "5.1.0" + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" }, "dependencies": { "kind-of": { @@ -6360,7 +5576,7 @@ "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", "dev": true, "requires": { - "is-primitive": "2.0.0" + "is-primitive": "^2.0.0" } }, "is-extendable": { @@ -6381,7 +5597,7 @@ "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", "dev": true, "requires": { - "number-is-nan": "1.0.1" + "number-is-nan": "^1.0.0" } }, "is-fullwidth-code-point": { @@ -6390,65 +5606,22 @@ "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", "dev": true }, - "is-gif": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-gif/-/is-gif-1.0.0.tgz", - "integrity": "sha1-ptKumIkwB7/6l6HYwB1jIFgyCX4=", - "dev": true - }, "is-glob": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", "dev": true, "requires": { - "is-extglob": "2.1.1" + "is-extglob": "^2.1.1" } }, - "is-gzip": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-gzip/-/is-gzip-1.0.0.tgz", - "integrity": "sha1-bKiwe5nHeZgCWQDlVc7Y7YCHmoM=", - "dev": true - }, - "is-jpg": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-jpg/-/is-jpg-1.0.1.tgz", - "integrity": "sha1-KW1X/dmc4BBDSnKD40armhA16XU=", - "dev": true - }, - "is-my-ip-valid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-my-ip-valid/-/is-my-ip-valid-1.0.0.tgz", - "integrity": "sha512-gmh/eWXROncUzRnIa1Ubrt5b8ep/MGSnfAUI3aRp+sqTCs1tv1Isl8d8F6JmkN3dXKc3ehZMrtiPN9eL03NuaQ==", - "dev": true - }, - "is-my-json-valid": { - "version": "2.17.2", - "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.17.2.tgz", - "integrity": "sha512-IBhBslgngMQN8DDSppmgDv7RNrlFotuuDsKcrCP3+HbFaVivIBU7u9oiiErw8sH4ynx3+gOGQ3q2otkgiSi6kg==", - "dev": true, - "requires": { - "generate-function": "2.0.0", - "generate-object-property": "1.2.0", - "is-my-ip-valid": "1.0.0", - "jsonpointer": "4.0.1", - "xtend": "4.0.1" - } - }, - "is-natural-number": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-natural-number/-/is-natural-number-2.1.1.tgz", - "integrity": "sha1-fUxXKDd+84bD4ZSpkRv1fG3DNec=", - "dev": true - }, "is-number": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", "dev": true, "requires": { - "kind-of": "3.2.2" + "kind-of": "^3.0.2" }, "dependencies": { "kind-of": { @@ -6457,39 +5630,16 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "1.1.6" + "is-buffer": "^1.1.5" } } } }, - "is-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", - "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", - "dev": true - }, "is-object": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.1.tgz", "integrity": "sha1-iVJojF7C/9awPsyF52ngKQMINHA=" }, - "is-odd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-odd/-/is-odd-2.0.0.tgz", - "integrity": "sha512-OTiixgpZAT1M4NHgS5IguFp/Vz2VI3U7Goh4/HA1adtwyLtSBrxYlcSYkhpAE07s4fKEcjrFxyvtQBND4vFQyQ==", - "dev": true, - "requires": { - "is-number": "4.0.0" - }, - "dependencies": { - "is-number": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", - "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", - "dev": true - } - } - }, "is-path-cwd": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", @@ -6502,7 +5652,7 @@ "integrity": "sha1-WsSLNF72dTOb1sekipEhELJBz1I=", "dev": true, "requires": { - "is-path-inside": "1.0.1" + "is-path-inside": "^1.0.0" } }, "is-path-inside": { @@ -6511,7 +5661,7 @@ "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", "dev": true, "requires": { - "path-is-inside": "1.0.2" + "path-is-inside": "^1.0.1" } }, "is-plain-obj": { @@ -6525,15 +5675,9 @@ "integrity": "sha1-LBY7P6+xtgbZ0Xko8FwqHDjgdnc=", "dev": true, "requires": { - "isobject": "3.0.1" + "isobject": "^3.0.1" } }, - "is-png": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-png/-/is-png-1.1.0.tgz", - "integrity": "sha1-1XSxK/J1wDUEVVcLDltXqwYgd84=", - "dev": true - }, "is-posix-bracket": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", @@ -6546,33 +5690,15 @@ "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", "dev": true }, - "is-property": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", - "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=", - "dev": true - }, - "is-redirect": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-redirect/-/is-redirect-1.0.0.tgz", - "integrity": "sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ=", - "dev": true - }, "is-regex": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", "dev": true, "requires": { - "has": "1.0.1" + "has": "^1.0.1" } }, - "is-relative": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-0.1.3.tgz", - "integrity": "sha1-kF/uiuhvRbPsYUvDwVyGnfCHboI=", - "dev": true - }, "is-retry-allowed": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz", @@ -6590,7 +5716,7 @@ "integrity": "sha1-z2EJDaDZ77yrhyLeum8DIgjbsOk=", "dev": true, "requires": { - "html-comment-regex": "1.1.1" + "html-comment-regex": "^1.1.0" } }, "is-symbol": { @@ -6599,35 +5725,17 @@ "integrity": "sha1-PMWfAAJRlLarLjjbrmaJJWtmBXI=", "dev": true }, - "is-tar": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-tar/-/is-tar-1.0.0.tgz", - "integrity": "sha1-L2suF5LB9bs2UZrKqdZcDSb+hT0=", - "dev": true - }, "is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" }, - "is-url": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz", - "integrity": "sha1-BKTfRtKMTP89c9Af8Gq+sxihqlI=", - "dev": true - }, "is-utf8": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", "dev": true }, - "is-valid-glob": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-0.3.0.tgz", - "integrity": "sha1-1LVcafUYhvm2XHDWwmItN+KfSP4=", - "dev": true - }, "is-windows": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", @@ -6640,12 +5748,6 @@ "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", "dev": true }, - "is-zip": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-zip/-/is-zip-1.0.0.tgz", - "integrity": "sha1-R7Co/004p2QxzP2ZqOFaTIa6IyU=", - "dev": true - }, "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", @@ -6673,8 +5775,8 @@ "resolved": "https://registry.npmjs.org/isurl/-/isurl-1.0.0.tgz", "integrity": "sha1-sn9PSfPNqj6kSgpbfzRi5u3DnWc=", "requires": { - "has-to-string-tag-x": "1.4.1", - "is-object": "1.0.1" + "has-to-string-tag-x": "^1.2.0", + "is-object": "^1.0.1" } }, "jquery": { @@ -6682,6 +5784,11 @@ "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.3.1.tgz", "integrity": "sha1-lYzinoHJeQ8xvneS311NlfxX+8o=" }, + "jquery-knob": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/jquery-knob/-/jquery-knob-1.2.11.tgz", + "integrity": "sha1-83w528HHpqbBLNsu1Pa/+2g/ENY=" + }, "jquery-mousewheel": { "version": "3.1.13", "resolved": "https://registry.npmjs.org/jquery-mousewheel/-/jquery-mousewheel-3.1.13.tgz", @@ -6692,18 +5799,23 @@ "resolved": "https://registry.npmjs.org/jquery-slimscroll/-/jquery-slimscroll-1.3.8.tgz", "integrity": "sha1-hIHETnpHaHZTkIoo9/cK7WTITjY=", "requires": { - "jquery": "3.3.1" + "jquery": ">= 1.7" } }, + "jquery-sparkline": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/jquery-sparkline/-/jquery-sparkline-2.4.0.tgz", + "integrity": "sha1-G+i3twTdOFcVJwiu+x1KSzpp+zM=" + }, "jquery-ui": { "version": "1.12.1", "resolved": "https://registry.npmjs.org/jquery-ui/-/jquery-ui-1.12.1.tgz", "integrity": "sha1-vLQEXI3QU5wTS8FIjN0+dop6nlE=" }, - "jquery-ui-bundle": { + "jquery-ui-dist": { "version": "1.12.1", - "resolved": "https://registry.npmjs.org/jquery-ui-bundle/-/jquery-ui-bundle-1.12.1.tgz", - "integrity": "sha1-1r4uTDd0lOI3ixyuKSCpHRGC2MQ=" + "resolved": "https://registry.npmjs.org/jquery-ui-dist/-/jquery-ui-dist-1.12.1.tgz", + "integrity": "sha1-XAgV08xvkP9fqvWyaKbiO0ypBPo=" }, "jquery.iframe-transport": { "version": "1.0.0", @@ -6711,9 +5823,9 @@ "integrity": "sha1-mKuuhb6s4cw2JkXnqHNg/5QYF18=" }, "js-base64": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.4.3.tgz", - "integrity": "sha512-H7ErYLM34CvDMto3GbD6xD0JLUGYXR3QTcH6B/tr4Hi/QpSThnCsIp+Sy5FRTw3B0d6py4HcNkW7nO/wdtGWEw==", + "version": "2.4.9", + "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.4.9.tgz", + "integrity": "sha1-dIkR+wT0imDEdxs3XKxFqA3xHAM=", "dev": true }, "js-tokens": { @@ -6728,8 +5840,8 @@ "integrity": "sha1-XJZ93YN6m/3KXy3oQlOr6KHAO4A=", "dev": true, "requires": { - "argparse": "1.0.10", - "esprima": "2.7.3" + "argparse": "^1.0.7", + "esprima": "^2.6.0" } }, "jsbn": { @@ -6755,6 +5867,12 @@ "integrity": "sha1-3KFKcCNf+C8KyaOr62DTN6NlGF0=", "dev": true }, + "json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha1-u4Z8+zRQ5pEHwTHRxRS6s9yLyqk=", + "dev": true + }, "json-schema": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", @@ -6766,12 +5884,11 @@ "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=" }, "json-stable-stringify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", - "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", - "dev": true, + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-0.0.1.tgz", + "integrity": "sha1-YRwj6BTbN1Un34URk9tZ3Sryf0U=", "requires": { - "jsonify": "0.0.0" + "jsonify": "~0.0.0" } }, "json-stringify-safe": { @@ -6796,20 +5913,18 @@ "integrity": "sha1-pezG9l9T9mLEQVx2daAzHQmS7GY=", "dev": true, "requires": { - "graceful-fs": "4.1.11" + "graceful-fs": "^4.1.6" } }, "jsonify": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", - "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", - "dev": true + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=" }, - "jsonpointer": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz", - "integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=", - "dev": true + "jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=" }, "jsprim": { "version": "1.4.1", @@ -6829,6 +5944,14 @@ } } }, + "jvectormap": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/jvectormap/-/jvectormap-1.2.2.tgz", + "integrity": "sha1-LkQIskpgRz/xBsHnJD43WuXKhdo=", + "requires": { + "jquery": ">=1.5" + } + }, "keyv": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.0.0.tgz", @@ -6849,58 +5972,75 @@ "integrity": "sha1-ARRrNqYhjmTljzqNZt5df8b20FE=", "dev": true }, + "labeled-stream-splicer": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/labeled-stream-splicer/-/labeled-stream-splicer-2.0.1.tgz", + "integrity": "sha1-nP+jL9meFhL9HYao25YkFtUpKSY=", + "requires": { + "inherits": "^2.0.1", + "isarray": "^2.0.4", + "stream-splicer": "^2.0.0" + }, + "dependencies": { + "isarray": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.4.tgz", + "integrity": "sha1-OOe8uw87obeTPIa6GJTd/DeBu7c=" + } + } + }, "laravel-mix": { - "version": "2.1.11", - "resolved": "https://registry.npmjs.org/laravel-mix/-/laravel-mix-2.1.11.tgz", - "integrity": "sha1-N0G94hRYb4wXFkGZDJpIfuzlNn0=", + "version": "2.1.14", + "resolved": "https://registry.npmjs.org/laravel-mix/-/laravel-mix-2.1.14.tgz", + "integrity": "sha1-XDx3i4iOIRIKqdiQDDGEEdouyRE=", "dev": true, "requires": { - "autoprefixer": "7.2.6", - "babel-core": "6.26.3", - "babel-loader": "7.1.4", - "babel-plugin-transform-object-rest-spread": "6.26.0", - "babel-plugin-transform-runtime": "6.23.0", - "babel-preset-env": "1.6.1", - "chokidar": "2.0.3", - "clean-css": "4.1.11", + "autoprefixer": "^7.2.6", + "babel-core": "^6.24.1", + "babel-loader": "^7.1.1", + "babel-plugin-transform-object-rest-spread": "^6.26.0", + "babel-plugin-transform-runtime": "^6.23.0", + "babel-preset-env": "^1.5.1", + "chokidar": "^2.0.3", + "clean-css": "^4.1.3", "concatenate": "0.0.2", - "css-loader": "0.28.11", - "dotenv": "4.0.0", - "dotenv-expand": "4.2.0", - "extract-text-webpack-plugin": "3.0.2", - "file-loader": "0.11.2", - "friendly-errors-webpack-plugin": "1.7.0", - "fs-extra": "3.0.1", - "glob": "7.1.2", - "html-loader": "0.4.5", - "img-loader": "2.0.1", - "lodash": "4.17.5", - "md5": "2.2.1", - "node-sass": "4.9.0", - "postcss-loader": "2.1.4", - "resolve-url-loader": "2.3.0", - "sass-loader": "6.0.7", - "style-loader": "0.18.2", - "uglify-js": "2.8.29", - "uglifyjs-webpack-plugin": "1.2.5", - "vue-loader": "13.7.1", - "vue-template-compiler": "2.5.16", - "webpack": "3.11.0", - "webpack-chunk-hash": "0.4.0", - "webpack-dev-server": "2.11.2", - "webpack-merge": "4.1.2", - "webpack-notifier": "1.6.0", - "yargs": "8.0.2" + "css-loader": "^0.28.9", + "dotenv": "^4.0.0", + "dotenv-expand": "^4.2.0", + "extract-text-webpack-plugin": "^3.0.2", + "file-loader": "^0.11.2", + "friendly-errors-webpack-plugin": "^1.6.1", + "fs-extra": "^3.0.1", + "glob": "^7.1.2", + "html-loader": "^0.4.5", + "img-loader": "^3.0.0", + "lodash": "^4.17.5", + "md5": "^2.2.1", + "node-sass": "^4.9.0", + "postcss-loader": "^2.1.0", + "resolve-url-loader": "^2.2.1", + "sass-loader": "^6.0.5", + "style-loader": "^0.18.2", + "uglify-js": "^2.8.29", + "uglifyjs-webpack-plugin": "^1.1.8", + "vue-loader": "^13.7.1", + "vue-template-compiler": "^2.5.13", + "webpack": "^3.11.0", + "webpack-chunk-hash": "^0.4.0", + "webpack-dev-server": "^2.11.1", + "webpack-merge": "^4.1.0", + "webpack-notifier": "^1.5.1", + "yargs": "^8.0.2" }, "dependencies": { "vue-template-compiler": { - "version": "2.5.16", - "resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.5.16.tgz", - "integrity": "sha1-k7SFcOVscgzfPwUcwVKHwm+9BMs=", + "version": "2.5.17", + "resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.5.17.tgz", + "integrity": "sha1-UqSgeMMn3rk3SCpQmuhcBvNGw8s=", "dev": true, "requires": { - "de-indent": "1.0.2", - "he": "1.1.1" + "de-indent": "^1.0.2", + "he": "^1.1.0" } } } @@ -6911,41 +6051,27 @@ "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", "dev": true }, - "lazy-req": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/lazy-req/-/lazy-req-1.1.0.tgz", - "integrity": "sha1-va6+rTD42CQDnODOFJ1Nqge6H6w=", - "dev": true - }, - "lazystream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", - "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", - "dev": true, - "requires": { - "readable-stream": "2.3.4" - } - }, "lcid": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", "dev": true, "requires": { - "invert-kv": "1.0.0" + "invert-kv": "^1.0.0" } }, "less": { "version": "github:less/less.js#efa6eb5306f28a7ef7e235d79ce854b780345591", + "from": "less@github:less/less.js#efa6eb5306f28a7ef7e235d79ce854b780345591", "requires": { - "errno": "0.1.7", - "graceful-fs": "4.1.11", - "image-size": "0.5.5", - "mime": "1.6.0", - "mkdirp": "0.5.1", - "promise": "7.3.1", - "request": "2.85.0", - "source-map": "0.5.7" + "errno": "^0.1.1", + "graceful-fs": "^4.1.2", + "image-size": "~0.5.0", + "mime": "^1.4.1", + "mkdirp": "^0.5.0", + "promise": "^7.1.1", + "request": "^2.83.0", + "source-map": "^0.5.3" }, "dependencies": { "ajv": { @@ -6954,10 +6080,10 @@ "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", "optional": true, "requires": { - "co": "4.6.0", - "fast-deep-equal": "1.1.0", - "fast-json-stable-stringify": "2.0.0", - "json-schema-traverse": "0.3.1" + "co": "^4.6.0", + "fast-deep-equal": "^1.0.0", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.3.0" } }, "assert-plus": { @@ -6978,7 +6104,7 @@ "integrity": "sha1-T4owBctKfjiJ90kDD9JbluAdLjE=", "optional": true, "requires": { - "hoek": "4.2.1" + "hoek": "4.x.x" } }, "cryptiles": { @@ -6987,7 +6113,7 @@ "integrity": "sha1-qJ+7Ig9c4l7FboxKqKT9e1sNKf4=", "optional": true, "requires": { - "boom": "5.2.0" + "boom": "5.x.x" }, "dependencies": { "boom": { @@ -6996,7 +6122,7 @@ "integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==", "optional": true, "requires": { - "hoek": "4.2.1" + "hoek": "4.x.x" } } } @@ -7007,9 +6133,9 @@ "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", "optional": true, "requires": { - "asynckit": "0.4.0", + "asynckit": "^0.4.0", "combined-stream": "1.0.6", - "mime-types": "2.1.18" + "mime-types": "^2.1.12" } }, "har-schema": { @@ -7024,8 +6150,8 @@ "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", "optional": true, "requires": { - "ajv": "5.5.2", - "har-schema": "2.0.0" + "ajv": "^5.1.0", + "har-schema": "^2.0.0" } }, "hawk": { @@ -7034,10 +6160,10 @@ "integrity": "sha512-miowhl2+U7Qle4vdLqDdPt9m09K6yZhkLDTWGoUiUzrQCn+mHHSmfJgAyGaLRZbPmTqfFFjRV1QWCW0VWUJBbQ==", "optional": true, "requires": { - "boom": "4.3.1", - "cryptiles": "3.1.2", - "hoek": "4.2.1", - "sntp": "2.1.0" + "boom": "4.x.x", + "cryptiles": "3.x.x", + "hoek": "4.x.x", + "sntp": "2.x.x" } }, "hoek": { @@ -7051,9 +6177,9 @@ "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", "optional": true, "requires": { - "assert-plus": "1.0.0", - "jsprim": "1.4.1", - "sshpk": "1.13.1" + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" } }, "performance-now": { @@ -7074,28 +6200,28 @@ "integrity": "sha512-8H7Ehijd4js+s6wuVPLjwORxD4zeuyjYugprdOXlPSqaApmL/QOy+EB/beICHVCHkGMKNh5rvihb5ov+IDw4mg==", "optional": true, "requires": { - "aws-sign2": "0.7.0", - "aws4": "1.6.0", - "caseless": "0.12.0", - "combined-stream": "1.0.6", - "extend": "3.0.1", - "forever-agent": "0.6.1", - "form-data": "2.3.2", - "har-validator": "5.0.3", - "hawk": "6.0.2", - "http-signature": "1.2.0", - "is-typedarray": "1.0.0", - "isstream": "0.1.2", - "json-stringify-safe": "5.0.1", - "mime-types": "2.1.18", - "oauth-sign": "0.8.2", - "performance-now": "2.1.0", - "qs": "6.5.1", - "safe-buffer": "5.1.1", - "stringstream": "0.0.5", - "tough-cookie": "2.3.4", - "tunnel-agent": "0.6.0", - "uuid": "3.2.1" + "aws-sign2": "~0.7.0", + "aws4": "^1.6.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.5", + "extend": "~3.0.1", + "forever-agent": "~0.6.1", + "form-data": "~2.3.1", + "har-validator": "~5.0.3", + "hawk": "~6.0.2", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.17", + "oauth-sign": "~0.8.2", + "performance-now": "^2.1.0", + "qs": "~6.5.1", + "safe-buffer": "^5.1.1", + "stringstream": "~0.0.5", + "tough-cookie": "~2.3.3", + "tunnel-agent": "^0.6.0", + "uuid": "^3.1.0" } }, "sntp": { @@ -7104,7 +6230,7 @@ "integrity": "sha512-FL1b58BDrqS3A11lJ0zEdnJ3UOKqVxawAkF3k7F0CVN7VQ34aZrV+G8BZ1WC9ZL7NyrwsW0oviwsWDgRuVYtJg==", "optional": true, "requires": { - "hoek": "4.2.1" + "hoek": "4.x.x" } } } @@ -7114,9 +6240,9 @@ "resolved": "https://registry.npmjs.org/less-loader/-/less-loader-4.1.0.tgz", "integrity": "sha1-LBNSxbCaT4QQFJAnT9UWdN5BNj4=", "requires": { - "clone": "2.1.1", - "loader-utils": "1.1.0", - "pify": "3.0.0" + "clone": "^2.1.1", + "loader-utils": "^1.1.0", + "pify": "^3.0.0" } }, "load-json-file": { @@ -7125,11 +6251,11 @@ "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", "dev": true, "requires": { - "graceful-fs": "4.1.11", - "parse-json": "2.2.0", - "pify": "2.3.0", - "pinkie-promise": "2.0.1", - "strip-bom": "2.0.0" + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" }, "dependencies": { "pify": { @@ -7151,9 +6277,9 @@ "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz", "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=", "requires": { - "big.js": "3.2.0", - "emojis-list": "2.1.0", - "json5": "0.5.1" + "big.js": "^3.1.3", + "emojis-list": "^2.0.0", + "json5": "^0.5.0" } }, "locate-path": { @@ -7162,8 +6288,8 @@ "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", "dev": true, "requires": { - "p-locate": "2.0.0", - "path-exists": "3.0.0" + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" } }, "lodash": { @@ -7178,8 +6304,8 @@ "integrity": "sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4=", "dev": true, "requires": { - "lodash._basecopy": "3.0.1", - "lodash.keys": "3.1.2" + "lodash._basecopy": "^3.0.0", + "lodash.keys": "^3.0.0" } }, "lodash._basecopy": { @@ -7188,18 +6314,6 @@ "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=", "dev": true }, - "lodash._basetostring": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz", - "integrity": "sha1-0YYdh3+CSlL2aYMtyvPuFVZqB9U=", - "dev": true - }, - "lodash._basevalues": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz", - "integrity": "sha1-W3dXYoAr3j0yl1A+JjAIIP32Ybc=", - "dev": true - }, "lodash._bindcallback": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/lodash._bindcallback/-/lodash._bindcallback-3.0.1.tgz", @@ -7212,9 +6326,9 @@ "integrity": "sha1-g4pbri/aymOsIt7o4Z+k5taXCxE=", "dev": true, "requires": { - "lodash._bindcallback": "3.0.1", - "lodash._isiterateecall": "3.0.9", - "lodash.restparam": "3.6.1" + "lodash._bindcallback": "^3.0.0", + "lodash._isiterateecall": "^3.0.0", + "lodash.restparam": "^3.0.0" } }, "lodash._getnative": { @@ -7229,30 +6343,6 @@ "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=", "dev": true }, - "lodash._reescape": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._reescape/-/lodash._reescape-3.0.0.tgz", - "integrity": "sha1-Kx1vXf4HyKNVdT5fJ/rH8c3hYWo=", - "dev": true - }, - "lodash._reevaluate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz", - "integrity": "sha1-WLx0xAZklTrgsSTYBpltrKQx4u0=", - "dev": true - }, - "lodash._reinterpolate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", - "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=", - "dev": true - }, - "lodash._root": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash._root/-/lodash._root-3.0.1.tgz", - "integrity": "sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI=", - "dev": true - }, "lodash.assign": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz", @@ -7271,21 +6361,18 @@ "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", "dev": true }, + "lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=", + "dev": true + }, "lodash.defaults": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=", "dev": true }, - "lodash.escape": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz", - "integrity": "sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg=", - "dev": true, - "requires": { - "lodash._root": "3.0.1" - } - }, "lodash.isarguments": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", @@ -7298,21 +6385,15 @@ "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=", "dev": true }, - "lodash.isequal": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", - "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=", - "dev": true - }, "lodash.keys": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", "dev": true, "requires": { - "lodash._getnative": "3.9.1", - "lodash.isarguments": "3.1.0", - "lodash.isarray": "3.0.4" + "lodash._getnative": "^3.0.0", + "lodash.isarguments": "^3.0.0", + "lodash.isarray": "^3.0.0" } }, "lodash.memoize": { @@ -7339,49 +6420,12 @@ "integrity": "sha1-0jM6NtnncXyK0vfKyv7HwytERmQ=", "dev": true }, - "lodash.template": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz", - "integrity": "sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8=", - "dev": true, - "requires": { - "lodash._basecopy": "3.0.1", - "lodash._basetostring": "3.0.1", - "lodash._basevalues": "3.0.0", - "lodash._isiterateecall": "3.0.9", - "lodash._reinterpolate": "3.0.0", - "lodash.escape": "3.2.0", - "lodash.keys": "3.1.2", - "lodash.restparam": "3.6.1", - "lodash.templatesettings": "3.1.1" - } - }, - "lodash.templatesettings": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz", - "integrity": "sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU=", - "dev": true, - "requires": { - "lodash._reinterpolate": "3.0.0", - "lodash.escape": "3.2.0" - } - }, "lodash.uniq": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=", "dev": true }, - "logalot": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/logalot/-/logalot-2.1.0.tgz", - "integrity": "sha1-X46MkNME7fElMJUaVVSruMXj9VI=", - "dev": true, - "requires": { - "figures": "1.7.0", - "squeak": "1.3.0" - } - }, "loglevel": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.6.1.tgz", @@ -7400,7 +6444,7 @@ "integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg=", "dev": true, "requires": { - "js-tokens": "3.0.2" + "js-tokens": "^3.0.0" } }, "loud-rejection": { @@ -7409,8 +6453,8 @@ "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", "dev": true, "requires": { - "currently-unhandled": "0.4.1", - "signal-exit": "3.0.2" + "currently-unhandled": "^0.4.1", + "signal-exit": "^3.0.0" } }, "lower-case": { @@ -7424,41 +6468,22 @@ "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.0.tgz", "integrity": "sha1-TjNms55/VFfjXxMkvfb4jQv8cwY=" }, - "lpad-align": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/lpad-align/-/lpad-align-1.1.2.tgz", - "integrity": "sha1-IfYArBwwlcPG5JfuZyce4ISB/p4=", - "dev": true, - "requires": { - "get-stdin": "4.0.1", - "indent-string": "2.1.0", - "longest": "1.0.1", - "meow": "3.7.0" - } - }, "lru-cache": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz", "integrity": "sha512-q4spe4KTfsAS1SUHLO0wz8Qiyf1+vMIAgpRYioFYDMNqKfHQbg+AVDH3i4fvpl71/P1L0dBl+fQi+P37UYf0ew==", "dev": true, "requires": { - "pseudomap": "1.0.2", - "yallist": "2.1.2" + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" } }, - "macaddress": { - "version": "0.2.8", - "resolved": "https://registry.npmjs.org/macaddress/-/macaddress-0.2.8.tgz", - "integrity": "sha1-WQTcU3w57G2+/q6QIycTX6hRHxI=", - "dev": true - }, "make-dir": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.2.0.tgz", - "integrity": "sha512-aNUAa4UMg/UougV25bbrU4ZaaKNjJ/3/xnvg/twpmKROPdKZPZ9wGgI0opdZzO8q/zUFawoUuixuOv33eZ61Iw==", - "dev": true, + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", + "integrity": "sha1-ecEDO4BRW9bSTsmTPoYMp17ifww=", "requires": { - "pify": "3.0.0" + "pify": "^3.0.0" } }, "map-cache": { @@ -7479,7 +6504,7 @@ "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", "dev": true, "requires": { - "object-visit": "1.0.1" + "object-visit": "^1.0.0" } }, "math-expression-evaluator": { @@ -7488,33 +6513,32 @@ "integrity": "sha1-3oGf282E3M2PrlnGrreWFbnSZqw=", "dev": true }, + "math-random": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.1.tgz", + "integrity": "sha1-izqsWIuKZuSXXjzepn97sylgH6w=", + "dev": true + }, "md5": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/md5/-/md5-2.2.1.tgz", "integrity": "sha1-U6s41f48iJG6RlMp6iP6wFQBJvk=", "dev": true, "requires": { - "charenc": "0.0.2", - "crypt": "0.0.2", - "is-buffer": "1.1.6" + "charenc": "~0.0.1", + "crypt": "~0.0.1", + "is-buffer": "~1.1.1" } }, "md5.js": { "version": "1.3.4", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.4.tgz", "integrity": "sha1-6b296UogpawYsENA/Fdk1bCdkB0=", - "dev": true, "requires": { - "hash-base": "3.0.4", - "inherits": "2.0.3" + "hash-base": "^3.0.0", + "inherits": "^2.0.1" } }, - "mdn-data": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-1.1.2.tgz", - "integrity": "sha512-HUqqf4U+XdKomJXe2Chw+b1zPXFRUZ3bfUbrGLQ2TGwMOBRULuTHI9geusGqRL4WzsusnLLxYAxV4f/F/8wV+g==", - "dev": true - }, "media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -7527,7 +6551,7 @@ "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", "dev": true, "requires": { - "mimic-fn": "1.2.0" + "mimic-fn": "^1.0.0" } }, "memory-fs": { @@ -7536,8 +6560,8 @@ "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", "dev": true, "requires": { - "errno": "0.1.7", - "readable-stream": "2.3.4" + "errno": "^0.1.3", + "readable-stream": "^2.0.1" } }, "meow": { @@ -7546,16 +6570,16 @@ "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", "dev": true, "requires": { - "camelcase-keys": "2.1.0", - "decamelize": "1.2.0", - "loud-rejection": "1.6.0", - "map-obj": "1.0.1", - "minimist": "1.2.0", - "normalize-package-data": "2.4.0", - "object-assign": "4.1.1", - "read-pkg-up": "1.0.1", - "redent": "1.0.0", - "trim-newlines": "1.0.0" + "camelcase-keys": "^2.0.0", + "decamelize": "^1.1.2", + "loud-rejection": "^1.0.0", + "map-obj": "^1.0.1", + "minimist": "^1.1.3", + "normalize-package-data": "^2.3.4", + "object-assign": "^4.0.1", + "read-pkg-up": "^1.0.1", + "redent": "^1.0.0", + "trim-newlines": "^1.0.0" }, "dependencies": { "minimist": { @@ -7572,15 +6596,6 @@ "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", "dev": true }, - "merge-stream": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-1.0.1.tgz", - "integrity": "sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE=", - "dev": true, - "requires": { - "readable-stream": "2.3.4" - } - }, "methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", @@ -7593,35 +6608,34 @@ "integrity": "sha1-cIWbyVyYQJUvNZoGij/En57PrCM=", "dev": true, "requires": { - "arr-diff": "4.0.0", - "array-unique": "0.3.2", - "braces": "2.3.2", - "define-property": "2.0.2", - "extend-shallow": "3.0.2", - "extglob": "2.0.4", - "fragment-cache": "0.2.1", - "kind-of": "6.0.2", - "nanomatch": "1.2.9", - "object.pick": "1.3.0", - "regex-not": "1.0.2", - "snapdragon": "0.8.2", - "to-regex": "3.0.2" + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" } }, "miller-rabin": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", "integrity": "sha1-8IA1HIZbDcViqEYpZtqlNUPHik0=", - "dev": true, "requires": { - "bn.js": "4.11.8", - "brorand": "1.1.0" + "bn.js": "^4.0.0", + "brorand": "^1.0.1" } }, "mime": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" + "integrity": "sha1-Ms2eXGRVO9WNGaVor0Uqz/BJgbE=" }, "mime-db": { "version": "1.33.0", @@ -7633,7 +6647,7 @@ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", "integrity": "sha1-bzI/YKg9ERRvgx/xH9ZuL+VQO7g=", "requires": { - "mime-db": "1.33.0" + "mime-db": "~1.33.0" } }, "mimic-fn": { @@ -7650,22 +6664,19 @@ "minimalistic-assert": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha1-LhlN4ERibUoQ5/f7wAznPoPk1cc=", - "dev": true + "integrity": "sha1-LhlN4ERibUoQ5/f7wAznPoPk1cc=" }, "minimalistic-crypto-utils": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", - "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", - "dev": true + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=" }, "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", - "dev": true, "requires": { - "brace-expansion": "1.1.11" + "brace-expansion": "^1.1.7" } }, "minimist": { @@ -7679,28 +6690,16 @@ "integrity": "sha1-NEKlCPr8KFAEhv7qmUCWduTuWm8=", "dev": true, "requires": { - "concat-stream": "1.6.2", - "duplexify": "3.5.4", - "end-of-stream": "1.4.1", - "flush-write-stream": "1.0.3", - "from2": "2.3.0", - "parallel-transform": "1.1.0", - "pump": "2.0.1", - "pumpify": "1.4.0", - "stream-each": "1.2.2", - "through2": "2.0.3" - }, - "dependencies": { - "through2": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", - "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", - "dev": true, - "requires": { - "readable-stream": "2.3.4", - "xtend": "4.0.1" - } - } + "concat-stream": "^1.5.0", + "duplexify": "^3.4.2", + "end-of-stream": "^1.1.0", + "flush-write-stream": "^1.0.0", + "from2": "^2.1.0", + "parallel-transform": "^1.1.0", + "pump": "^2.0.1", + "pumpify": "^1.3.3", + "stream-each": "^1.1.0", + "through2": "^2.0.0" } }, "mixin-deep": { @@ -7709,8 +6708,8 @@ "integrity": "sha1-pJ5yaNzhoNlpjkUybFYm3zVD0P4=", "dev": true, "requires": { - "for-in": "1.0.2", - "is-extendable": "1.0.1" + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" }, "dependencies": { "is-extendable": { @@ -7719,7 +6718,7 @@ "integrity": "sha1-p0cPnkJnM9gb2B4RVSZOOjUHyrQ=", "dev": true, "requires": { - "is-plain-object": "2.0.4" + "is-plain-object": "^2.0.4" } } } @@ -7730,8 +6729,8 @@ "integrity": "sha1-T7lJRB2rGCVA8f4DW6YOGUel5X4=", "dev": true, "requires": { - "for-in": "0.1.8", - "is-extendable": "0.1.1" + "for-in": "^0.1.3", + "is-extendable": "^0.1.1" }, "dependencies": { "for-in": { @@ -7750,29 +6749,50 @@ "minimist": "0.0.8" } }, + "module-deps": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/module-deps/-/module-deps-6.1.0.tgz", + "integrity": "sha1-0eHvxIHGiGJp9xEsUsMjYYjhZHk=", + "requires": { + "JSONStream": "^1.0.3", + "browser-resolve": "^1.7.0", + "cached-path-relative": "^1.0.0", + "concat-stream": "~1.6.0", + "defined": "^1.0.0", + "detective": "^5.0.2", + "duplexer2": "^0.1.2", + "inherits": "^2.0.1", + "parents": "^1.0.0", + "readable-stream": "^2.0.2", + "resolve": "^1.4.0", + "stream-combiner2": "^1.1.1", + "subarg": "^1.0.0", + "through2": "^2.0.0", + "xtend": "^4.0.0" + } + }, + "moment": { + "version": "2.22.2", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.22.2.tgz", + "integrity": "sha1-PCV/mDn8DpP/UxSWMiOeuQeD/2Y=" + }, + "morris.js": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/morris.js/-/morris.js-0.5.0.tgz", + "integrity": "sha1-cldnE1z64Fmq51mZuyzmocXRtEs=" + }, "move-concurrently": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=", "dev": true, "requires": { - "aproba": "1.2.0", - "copy-concurrently": "1.0.5", - "fs-write-stream-atomic": "1.0.10", - "mkdirp": "0.5.1", - "rimraf": "2.6.2", - "run-queue": "1.0.3" - } - }, - "mozjpeg": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/mozjpeg/-/mozjpeg-5.0.0.tgz", - "integrity": "sha1-uGccSSRWijY94AP/L9OXq4P3UsU=", - "dev": true, - "requires": { - "bin-build": "2.2.0", - "bin-wrapper": "3.0.2", - "logalot": "2.1.0" + "aproba": "^1.1.1", + "copy-concurrently": "^1.0.0", + "fs-write-stream-atomic": "^1.0.8", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.3" } }, "ms": { @@ -7787,8 +6807,8 @@ "integrity": "sha1-oOx72QVcQoL3kMPIL04o2zsxsik=", "dev": true, "requires": { - "dns-packet": "1.3.1", - "thunky": "1.0.2" + "dns-packet": "^1.3.1", + "thunky": "^1.0.2" } }, "multicast-dns-service-types": { @@ -7797,74 +6817,29 @@ "integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=", "dev": true }, - "multipipe": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz", - "integrity": "sha1-Ko8t33Du1WTf8tV/HhoTfZ8FB4s=", - "dev": true, - "requires": { - "duplexer2": "0.0.2" - }, - "dependencies": { - "duplexer2": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", - "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", - "dev": true, - "requires": { - "readable-stream": "1.1.14" - } - }, - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - } - } - }, "nan": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.10.0.tgz", - "integrity": "sha1-ltDNYQ69WNS03pzAxoKM2pnHVI8=", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.11.0.tgz", + "integrity": "sha512-F4miItu2rGnV2ySkXOQoA8FKz/SR2Q2sWP0sbTxNxz/tuokeC8WxOhPMcwi0qIyGtVn/rrSeLbvVkznqCdwYnw==", "dev": true }, "nanomatch": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.9.tgz", - "integrity": "sha512-n8R9bS8yQ6eSXaV6jHUpKzD8gLsin02w1HSFiegwrs9E098Ylhw5jdyKPaYqvHknHaSCKTPp7C8dGCQ0q9koXA==", + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha1-uHqKpPwN6P5r6IiVs4mD/yZb0Rk=", "dev": true, "requires": { - "arr-diff": "4.0.0", - "array-unique": "0.3.2", - "define-property": "2.0.2", - "extend-shallow": "3.0.2", - "fragment-cache": "0.2.1", - "is-odd": "2.0.0", - "is-windows": "1.0.2", - "kind-of": "6.0.2", - "object.pick": "1.3.0", - "regex-not": "1.0.2", - "snapdragon": "0.8.2", - "to-regex": "3.0.2" + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" } }, "negotiator": { @@ -7874,9 +6849,9 @@ "dev": true }, "neo-async": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.5.1.tgz", - "integrity": "sha1-rLkJ4yex6H7J7xX0G4omlRKtQe4=", + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.5.2.tgz", + "integrity": "sha1-SJEFznvFTnCdc2sZX4ITUEjFD8w=", "dev": true }, "next-tick": { @@ -7885,46 +6860,39 @@ "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", "dev": true }, - "nice-try": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.4.tgz", - "integrity": "sha1-2Tli9sUvLBVYwPvabVEoGfHv4cQ=", - "dev": true - }, "no-case": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz", "integrity": "sha1-YLgTOWvjmz8SiKTB7V0efSi0ZKw=", "dev": true, "requires": { - "lower-case": "1.1.4" + "lower-case": "^1.1.1" } }, "node-forge": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.7.1.tgz", - "integrity": "sha1-naYR6giYL0uUIGs760zJZl8gwwA=", + "version": "0.7.5", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.7.5.tgz", + "integrity": "sha1-bBUsNFzhHFL0ZcKr2VfoY5zWdN8=", "dev": true }, "node-gyp": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-3.6.2.tgz", - "integrity": "sha1-m/vlRWIoYoSDjnUOrAUpWFP6HGA=", + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-3.8.0.tgz", + "integrity": "sha1-VAMEJhwzDoDQ1e3OJTpoyzlkIYw=", "dev": true, "requires": { - "fstream": "1.0.11", - "glob": "7.1.2", - "graceful-fs": "4.1.11", - "minimatch": "3.0.4", - "mkdirp": "0.5.1", - "nopt": "3.0.6", - "npmlog": "4.1.2", - "osenv": "0.1.5", - "request": "2.81.0", - "rimraf": "2.6.2", - "semver": "5.3.0", - "tar": "2.2.1", - "which": "1.3.0" + "fstream": "^1.0.0", + "glob": "^7.0.3", + "graceful-fs": "^4.1.2", + "mkdirp": "^0.5.0", + "nopt": "2 || 3", + "npmlog": "0 || 1 || 2 || 3 || 4", + "osenv": "0", + "request": "^2.87.0", + "rimraf": "2", + "semver": "~5.3.0", + "tar": "^2.0.0", + "which": "1" }, "dependencies": { "semver": { @@ -7941,48 +6909,29 @@ "integrity": "sha1-X5QmPUBPbkR2fXJpAf/wVHjWAN8=", "dev": true, "requires": { - "assert": "1.4.1", - "browserify-zlib": "0.2.0", - "buffer": "4.9.1", - "console-browserify": "1.1.0", - "constants-browserify": "1.0.0", - "crypto-browserify": "3.12.0", - "domain-browser": "1.2.0", - "events": "1.1.1", - "https-browserify": "1.0.0", - "os-browserify": "0.3.0", + "assert": "^1.1.1", + "browserify-zlib": "^0.2.0", + "buffer": "^4.3.0", + "console-browserify": "^1.1.0", + "constants-browserify": "^1.0.0", + "crypto-browserify": "^3.11.0", + "domain-browser": "^1.1.1", + "events": "^1.0.0", + "https-browserify": "^1.0.0", + "os-browserify": "^0.3.0", "path-browserify": "0.0.0", - "process": "0.11.10", - "punycode": "1.4.1", - "querystring-es3": "0.2.1", - "readable-stream": "2.3.4", - "stream-browserify": "2.0.1", - "stream-http": "2.8.1", - "string_decoder": "1.0.3", - "timers-browserify": "2.0.10", + "process": "^0.11.10", + "punycode": "^1.2.4", + "querystring-es3": "^0.2.0", + "readable-stream": "^2.3.3", + "stream-browserify": "^2.0.1", + "stream-http": "^2.7.2", + "string_decoder": "^1.0.0", + "timers-browserify": "^2.0.4", "tty-browserify": "0.0.0", - "url": "0.11.0", - "util": "0.10.3", + "url": "^0.11.0", + "util": "^0.10.3", "vm-browserify": "0.0.4" - }, - "dependencies": { - "base64-js": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz", - "integrity": "sha1-yrHmEY8FEJXli1KBrqjBzSK/wOM=", - "dev": true - }, - "buffer": { - "version": "4.9.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", - "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", - "dev": true, - "requires": { - "base64-js": "1.3.0", - "ieee754": "1.1.11", - "isarray": "1.0.0" - } - } } }, "node-notifier": { @@ -7991,122 +6940,58 @@ "integrity": "sha1-+jE90I9VF9sOJQLldY1mSsafneo=", "dev": true, "requires": { - "growly": "1.3.0", - "semver": "5.5.0", - "shellwords": "0.1.1", - "which": "1.3.0" + "growly": "^1.3.0", + "semver": "^5.4.1", + "shellwords": "^0.1.1", + "which": "^1.3.0" } }, "node-sass": { - "version": "4.9.0", - "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.9.0.tgz", - "integrity": "sha512-QFHfrZl6lqRU3csypwviz2XLgGNOoWQbo2GOvtsfQqOfL4cy1BtWnhx/XUeAO9LT3ahBzSRXcEO6DdvAH9DzSg==", + "version": "4.9.3", + "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.9.3.tgz", + "integrity": "sha1-9AfPPWb3gwi7HjRrJPpChwMZYiQ=", "dev": true, "requires": { - "async-foreach": "0.1.3", - "chalk": "1.1.3", - "cross-spawn": "3.0.1", - "gaze": "1.1.2", - "get-stdin": "4.0.1", - "glob": "7.1.2", - "in-publish": "2.0.0", - "lodash.assign": "4.2.0", - "lodash.clonedeep": "4.5.0", - "lodash.mergewith": "4.6.1", - "meow": "3.7.0", - "mkdirp": "0.5.1", - "nan": "2.10.0", - "node-gyp": "3.6.2", - "npmlog": "4.1.2", - "request": "2.79.0", - "sass-graph": "2.2.4", - "stdout-stream": "1.4.0", - "true-case-path": "1.0.2" + "async-foreach": "^0.1.3", + "chalk": "^1.1.1", + "cross-spawn": "^3.0.0", + "gaze": "^1.0.0", + "get-stdin": "^4.0.1", + "glob": "^7.0.3", + "in-publish": "^2.0.0", + "lodash.assign": "^4.2.0", + "lodash.clonedeep": "^4.3.2", + "lodash.mergewith": "^4.6.0", + "meow": "^3.7.0", + "mkdirp": "^0.5.1", + "nan": "^2.10.0", + "node-gyp": "^3.8.0", + "npmlog": "^4.0.0", + "request": "2.87.0", + "sass-graph": "^2.2.4", + "stdout-stream": "^1.4.0", + "true-case-path": "^1.0.2" }, "dependencies": { - "caseless": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz", - "integrity": "sha1-cVuW6phBWTzDMGeSP17GDr2k99c=", - "dev": true - }, "cross-spawn": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-3.0.1.tgz", "integrity": "sha1-ElYDfsufDF9549bvE14wdwGEuYI=", "dev": true, "requires": { - "lru-cache": "4.1.1", - "which": "1.3.0" + "lru-cache": "^4.0.1", + "which": "^1.2.9" } - }, - "har-validator": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz", - "integrity": "sha1-zcvAgYgmWtEZtqWnyKtw7s+10n0=", - "dev": true, - "requires": { - "chalk": "1.1.3", - "commander": "2.15.1", - "is-my-json-valid": "2.17.2", - "pinkie-promise": "2.0.1" - } - }, - "qs": { - "version": "6.3.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.3.2.tgz", - "integrity": "sha1-51vV9uJoEioqDgvaYwslUMFmUCw=", - "dev": true - }, - "request": { - "version": "2.79.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.79.0.tgz", - "integrity": "sha1-Tf5b9r6LjNw3/Pk+BLZVd3InEN4=", - "dev": true, - "requires": { - "aws-sign2": "0.6.0", - "aws4": "1.6.0", - "caseless": "0.11.0", - "combined-stream": "1.0.6", - "extend": "3.0.1", - "forever-agent": "0.6.1", - "form-data": "2.1.4", - "har-validator": "2.0.6", - "hawk": "3.1.3", - "http-signature": "1.1.1", - "is-typedarray": "1.0.0", - "isstream": "0.1.2", - "json-stringify-safe": "5.0.1", - "mime-types": "2.1.18", - "oauth-sign": "0.8.2", - "qs": "6.3.2", - "stringstream": "0.0.5", - "tough-cookie": "2.3.4", - "tunnel-agent": "0.4.3", - "uuid": "3.2.1" - } - }, - "tunnel-agent": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz", - "integrity": "sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us=", - "dev": true } } }, - "node-status-codes": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/node-status-codes/-/node-status-codes-1.0.0.tgz", - "integrity": "sha1-WuVUHQJGRdMqWPzdyc7s6nrjrC8=", - "dev": true - }, "nopt": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", "dev": true, "requires": { - "abbrev": "1.1.1" + "abbrev": "1" } }, "normalize-package-data": { @@ -8115,10 +7000,10 @@ "integrity": "sha1-EvlaMH1YNSB1oEkHuErIvpisAS8=", "dev": true, "requires": { - "hosted-git-info": "2.6.0", - "is-builtin-module": "1.0.0", - "semver": "5.5.0", - "validate-npm-package-license": "3.0.3" + "hosted-git-info": "^2.1.4", + "is-builtin-module": "^1.0.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" } }, "normalize-path": { @@ -8127,7 +7012,7 @@ "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", "dev": true, "requires": { - "remove-trailing-separator": "1.1.0" + "remove-trailing-separator": "^1.0.1" } }, "normalize-range": { @@ -8139,21 +7024,11 @@ "normalize-url": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-2.0.1.tgz", - "integrity": "sha512-D6MUW4K/VzoJ4rJ01JFKxDrtY1v9wrgzCX5f2qj/lzH1m/lW6MhUZFKerVsnyjOhOsYzI9Kqqak+10l4LvLpMw==", + "integrity": "sha1-g1qdoVUfom9w6SMpBpojqmV01+Y=", "requires": { - "prepend-http": "2.0.0", - "query-string": "5.1.1", - "sort-keys": "2.0.0" - } - }, - "npm-conf": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/npm-conf/-/npm-conf-1.1.3.tgz", - "integrity": "sha1-JWzEe9DiGMJZxOlVC/QTvCGSr/k=", - "dev": true, - "requires": { - "config-chain": "1.1.11", - "pify": "3.0.0" + "prepend-http": "^2.0.0", + "query-string": "^5.0.1", + "sort-keys": "^2.0.0" } }, "npm-run-path": { @@ -8162,7 +7037,7 @@ "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", "dev": true, "requires": { - "path-key": "2.0.1" + "path-key": "^2.0.0" } }, "npmlog": { @@ -8171,19 +7046,10 @@ "integrity": "sha1-CKfyqL9zRgR3mp76StXMcXq7lUs=", "dev": true, "requires": { - "are-we-there-yet": "1.1.4", - "console-control-strings": "1.1.0", - "gauge": "2.7.4", - "set-blocking": "2.0.0" - } - }, - "nth-check": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.1.tgz", - "integrity": "sha1-mSms32KPwsQQmN6rgqxYDPFJquQ=", - "dev": true, - "requires": { - "boolbase": "1.0.0" + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" } }, "num2fraction": { @@ -8214,9 +7080,9 @@ "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", "dev": true, "requires": { - "copy-descriptor": "0.1.1", - "define-property": "0.2.5", - "kind-of": "3.2.2" + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" }, "dependencies": { "define-property": { @@ -8225,7 +7091,7 @@ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { - "is-descriptor": "0.1.6" + "is-descriptor": "^0.1.0" } }, "kind-of": { @@ -8234,15 +7100,15 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "1.1.6" + "is-buffer": "^1.1.5" } } } }, "object-keys": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.11.tgz", - "integrity": "sha1-xUYBd4rVYPEULODgG8yotW0TQm0=", + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.12.tgz", + "integrity": "sha1-CcU4VTd1dTEMymL1W7M0q/97PtI=", "dev": true }, "object-path": { @@ -8257,17 +7123,7 @@ "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", "dev": true, "requires": { - "isobject": "3.0.1" - } - }, - "object.getownpropertydescriptors": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz", - "integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=", - "dev": true, - "requires": { - "define-properties": "1.1.2", - "es-abstract": "1.11.0" + "isobject": "^3.0.0" } }, "object.omit": { @@ -8276,8 +7132,19 @@ "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", "dev": true, "requires": { - "for-own": "0.1.5", - "is-extendable": "0.1.1" + "for-own": "^0.1.4", + "is-extendable": "^0.1.1" + }, + "dependencies": { + "for-own": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", + "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", + "dev": true, + "requires": { + "for-in": "^1.0.1" + } + } } }, "object.pick": { @@ -8286,19 +7153,7 @@ "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", "dev": true, "requires": { - "isobject": "3.0.1" - } - }, - "object.values": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.0.4.tgz", - "integrity": "sha1-5STaCbT2b/Bd9FdUbscqyZ8TBpo=", - "dev": true, - "requires": { - "define-properties": "1.1.2", - "es-abstract": "1.11.0", - "function-bind": "1.1.1", - "has": "1.0.1" + "isobject": "^3.0.1" } }, "obuf": { @@ -8326,79 +7181,32 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, "requires": { - "wrappy": "1.0.2" + "wrappy": "1" } }, - "onetime": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", - "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", - "dev": true - }, "opn": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/opn/-/opn-5.3.0.tgz", - "integrity": "sha1-ZIcVZchjh18FLP31PT48ta21Oxw=", + "integrity": "sha512-bYJHo/LOmoTd+pfiYhfZDnf9zekVJrY+cnS2a5F2x+w5ppvTqObojTP7WiFG+kVZs9Inw+qQ/lw7TroWwhdd2g==", "dev": true, "requires": { - "is-wsl": "1.1.0" - } - }, - "optipng-bin": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/optipng-bin/-/optipng-bin-3.1.4.tgz", - "integrity": "sha1-ldNPLEiHBPb9cGBr/qDGWfHZXYQ=", - "dev": true, - "requires": { - "bin-build": "2.2.0", - "bin-wrapper": "3.0.2", - "logalot": "2.1.0" - } - }, - "ordered-read-streams": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.3.0.tgz", - "integrity": "sha1-cTfmmzKYuzQiR6G77jiByA4v14s=", - "dev": true, - "requires": { - "is-stream": "1.1.0", - "readable-stream": "2.3.4" + "is-wsl": "^1.1.0" } }, "original": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/original/-/original-1.0.0.tgz", - "integrity": "sha1-kUf5P6FpbQS+YeAb1QuurKZWvTs=", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/original/-/original-1.0.2.tgz", + "integrity": "sha1-5EKmHP/hxf0gpl8yYcJmY7MD8l8=", "dev": true, "requires": { - "url-parse": "1.0.5" - }, - "dependencies": { - "url-parse": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.0.5.tgz", - "integrity": "sha1-CFSGBCKv3P7+tsllxmLUgAFpkns=", - "dev": true, - "requires": { - "querystringify": "0.0.4", - "requires-port": "1.0.0" - } - } + "url-parse": "^1.4.3" } }, "os-browserify": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", - "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=", - "dev": true - }, - "os-filter-obj": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/os-filter-obj/-/os-filter-obj-1.0.3.tgz", - "integrity": "sha1-WRUzDZDs7VV9LZOKMcbdIU2cY60=", - "dev": true + "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=" }, "os-homedir": { "version": "1.0.2", @@ -8412,7 +7220,7 @@ "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", "dev": true, "requires": { - "lcid": "1.0.0" + "lcid": "^1.0.0" } }, "os-tmpdir": { @@ -8427,34 +7235,8 @@ "integrity": "sha1-hc36+uso6Gd/QW4odZK18/SepBA=", "dev": true, "requires": { - "os-homedir": "1.0.2", - "os-tmpdir": "1.0.2" - } - }, - "p-cancelable": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-0.3.0.tgz", - "integrity": "sha1-ueEjgAvOu3rBOkeb4ZW1B7mNMPo=", - "dev": true - }, - "p-event": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-event/-/p-event-1.3.0.tgz", - "integrity": "sha1-jmtPT2XHK8W2/ii3XtqHT5akoIU=", - "dev": true, - "requires": { - "p-timeout": "1.2.1" - }, - "dependencies": { - "p-timeout": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-1.2.1.tgz", - "integrity": "sha1-XrOzU7f86Z8QGhA4iAuwVOu+o4Y=", - "dev": true, - "requires": { - "p-finally": "1.0.0" - } - } + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" } }, "p-finally": { @@ -8468,12 +7250,12 @@ "integrity": "sha1-nJRWmJ6fZYgBewQ01WCXZ1w9oF4=" }, "p-limit": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.2.0.tgz", - "integrity": "sha512-Y/OtIaXtUPr4/YpMv1pCL5L5ed0rumAaAeBSj12F+bSlMdys7i8oQF/GUJmfpTS/QoaRrS/k6pma29haJpsMng==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha1-uGvV8MJWkJEcdZD8v8IBDVSzzLg=", "dev": true, "requires": { - "p-try": "1.0.0" + "p-try": "^1.0.0" } }, "p-locate": { @@ -8482,7 +7264,7 @@ "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", "dev": true, "requires": { - "p-limit": "1.2.0" + "p-limit": "^1.1.0" } }, "p-map": { @@ -8491,33 +7273,17 @@ "integrity": "sha1-5OlPMR6rvIYzoeeZCBZfyiYkG2s=", "dev": true }, - "p-map-series": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-map-series/-/p-map-series-1.0.0.tgz", - "integrity": "sha1-v5j+V1cFZYqeE1G++4WuTB8Hvco=", - "dev": true, - "requires": { - "p-reduce": "1.0.0" - } - }, "p-pipe": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/p-pipe/-/p-pipe-1.2.0.tgz", - "integrity": "sha1-SxoROZoRUgpneQ7loMHViB1r7+k=", - "dev": true - }, - "p-reduce": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-reduce/-/p-reduce-1.0.0.tgz", - "integrity": "sha1-GMKw3ZNqRpClKfgjH1ig/bakffo=", - "dev": true + "integrity": "sha1-SxoROZoRUgpneQ7loMHViB1r7+k=" }, "p-timeout": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-2.0.1.tgz", - "integrity": "sha512-88em58dDVB/KzPEx1X0N3LwFfYZPyDc4B6eF38M1rk9VTZMbxXXgjugz8mmwpS9Ox4BDZ+t6t3QP5+/gazweIA==", + "integrity": "sha1-2N0ZeVldLcATnh/ka4tkbLPN8Dg=", "requires": { - "p-finally": "1.0.0" + "p-finally": "^1.0.0" } }, "p-try": { @@ -8526,11 +7292,18 @@ "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", "dev": true }, + "pace": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/pace/-/pace-0.0.4.tgz", + "integrity": "sha1-1mQF1fW8EtJUQabibIeNvGnnenc=", + "requires": { + "charm": "~0.1.0" + } + }, "pako": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.6.tgz", - "integrity": "sha1-AQEhG6pwxLykoPY/Igbpe3368lg=", - "dev": true + "integrity": "sha1-AQEhG6pwxLykoPY/Igbpe3368lg=" }, "papaparse": { "version": "4.4.0", @@ -8543,9 +7316,9 @@ "integrity": "sha1-1BDwZbBdojCB/NEPKIVMKb2jOwY=", "dev": true, "requires": { - "cyclist": "0.2.2", - "inherits": "2.0.3", - "readable-stream": "2.3.4" + "cyclist": "~0.2.2", + "inherits": "^2.0.3", + "readable-stream": "^2.1.5" } }, "param-case": { @@ -8554,20 +7327,27 @@ "integrity": "sha1-35T9jPZTHs915r75oIWPvHK+Ikc=", "dev": true, "requires": { - "no-case": "2.3.2" + "no-case": "^2.2.0" + } + }, + "parents": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parents/-/parents-1.0.1.tgz", + "integrity": "sha1-/t1NK/GTp3dF/nHjcdc8MwfZx1E=", + "requires": { + "path-platform": "~0.11.15" } }, "parse-asn1": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.1.tgz", "integrity": "sha1-9r8pOBgzK9DatU77Fgh3JHRebKg=", - "dev": true, "requires": { - "asn1.js": "4.10.1", - "browserify-aes": "1.2.0", - "create-hash": "1.2.0", - "evp_bytestokey": "1.0.3", - "pbkdf2": "3.0.16" + "asn1.js": "^4.0.0", + "browserify-aes": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.0", + "pbkdf2": "^3.0.3" } }, "parse-glob": { @@ -8576,10 +7356,10 @@ "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", "dev": true, "requires": { - "glob-base": "0.3.0", - "is-dotfile": "1.0.3", - "is-extglob": "1.0.0", - "is-glob": "2.0.1" + "glob-base": "^0.3.0", + "is-dotfile": "^1.0.0", + "is-extglob": "^1.0.0", + "is-glob": "^2.0.0" }, "dependencies": { "is-extglob": { @@ -8594,7 +7374,7 @@ "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", "dev": true, "requires": { - "is-extglob": "1.0.0" + "is-extglob": "^1.0.0" } } } @@ -8605,7 +7385,7 @@ "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", "dev": true, "requires": { - "error-ex": "1.3.1" + "error-ex": "^1.2.0" } }, "parseurl": { @@ -8623,8 +7403,7 @@ "path-browserify": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz", - "integrity": "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo=", - "dev": true + "integrity": "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo=" }, "path-dirname": { "version": "1.0.2", @@ -8641,8 +7420,7 @@ "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" }, "path-is-inside": { "version": "1.0.2", @@ -8659,8 +7437,12 @@ "path-parse": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", - "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=", - "dev": true + "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=" + }, + "path-platform": { + "version": "0.11.15", + "resolved": "https://registry.npmjs.org/path-platform/-/path-platform-0.11.15.tgz", + "integrity": "sha1-6GQhf3TDaFDwhSt43Hv31KVyG/I=" }, "path-to-regexp": { "version": "0.1.7", @@ -8674,9 +7456,9 @@ "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", "dev": true, "requires": { - "graceful-fs": "4.1.11", - "pify": "2.3.0", - "pinkie-promise": "2.0.1" + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" }, "dependencies": { "pify": { @@ -8690,26 +7472,19 @@ "pbkdf2": { "version": "3.0.16", "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.16.tgz", - "integrity": "sha1-dAQgjsawG2LYW/g4U6gGT42cKlw=", - "dev": true, + "integrity": "sha512-y4CXP3thSxqf7c0qmOF+9UeOTrifiVTIM+u7NWlq+PRsHbr7r7dpCmvzrZxa96JJUNi0Y5w9VqG5ZNeCVMoDcA==", "requires": { - "create-hash": "1.2.0", - "create-hmac": "1.1.7", - "ripemd160": "2.0.2", - "safe-buffer": "5.1.1", - "sha.js": "2.4.11" + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" } }, - "pend": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", - "dev": true - }, "performance-now": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-0.2.0.tgz", - "integrity": "sha1-M+8wxcd9TqIcWlOGnZG1bY8lVeU=", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", "dev": true }, "pify": { @@ -8720,16 +7495,14 @@ "pinkie": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", - "dev": true + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=" }, "pinkie-promise": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "dev": true, "requires": { - "pinkie": "2.0.4" + "pinkie": "^2.0.0" } }, "pkg-dir": { @@ -8738,345 +7511,18 @@ "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", "dev": true, "requires": { - "find-up": "2.1.0" - } - }, - "pngquant-bin": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/pngquant-bin/-/pngquant-bin-4.0.0.tgz", - "integrity": "sha1-RorfcDb1D64JycJk72K20QwC9cI=", - "dev": true, - "requires": { - "bin-build": "3.0.0", - "bin-wrapper": "3.0.2", - "execa": "0.10.0", - "logalot": "2.1.0" - }, - "dependencies": { - "bin-build": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bin-build/-/bin-build-3.0.0.tgz", - "integrity": "sha1-xXgKJaip+WbYJEIX5sH1CCoUOGE=", - "dev": true, - "requires": { - "decompress": "4.2.0", - "download": "6.2.5", - "execa": "0.7.0", - "p-map-series": "1.0.0", - "tempfile": "2.0.0" - }, - "dependencies": { - "execa": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", - "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", - "dev": true, - "requires": { - "cross-spawn": "5.1.0", - "get-stream": "3.0.0", - "is-stream": "1.1.0", - "npm-run-path": "2.0.2", - "p-finally": "1.0.0", - "signal-exit": "3.0.2", - "strip-eof": "1.0.0" - } - }, - "get-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", - "dev": true - } - } - }, - "caw": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/caw/-/caw-2.0.1.tgz", - "integrity": "sha1-bDygcfwZRyCIPC3F2psHS/x+npU=", - "dev": true, - "requires": { - "get-proxy": "2.1.0", - "isurl": "1.0.0", - "tunnel-agent": "0.6.0", - "url-to-options": "1.0.1" - } - }, - "decompress": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/decompress/-/decompress-4.2.0.tgz", - "integrity": "sha1-eu3YVCflqS2s/lVnSnxQXpbQH50=", - "dev": true, - "requires": { - "decompress-tar": "4.1.1", - "decompress-tarbz2": "4.1.1", - "decompress-targz": "4.1.1", - "decompress-unzip": "4.0.1", - "graceful-fs": "4.1.11", - "make-dir": "1.2.0", - "pify": "2.3.0", - "strip-dirs": "2.1.0" - } - }, - "decompress-tar": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/decompress-tar/-/decompress-tar-4.1.1.tgz", - "integrity": "sha1-cYy9P8sWIJcW5womuE57pFkuWvE=", - "dev": true, - "requires": { - "file-type": "5.2.0", - "is-stream": "1.1.0", - "tar-stream": "1.6.0" - } - }, - "decompress-tarbz2": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/decompress-tarbz2/-/decompress-tarbz2-4.1.1.tgz", - "integrity": "sha1-MIKluIDqQEOBY0nzeLVsUWvho5s=", - "dev": true, - "requires": { - "decompress-tar": "4.1.1", - "file-type": "6.2.0", - "is-stream": "1.1.0", - "seek-bzip": "1.0.5", - "unbzip2-stream": "1.2.5" - }, - "dependencies": { - "file-type": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-6.2.0.tgz", - "integrity": "sha1-5QzXXTVv/tTjBtxPW89Sp5kDqRk=", - "dev": true - } - } - }, - "decompress-targz": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/decompress-targz/-/decompress-targz-4.1.1.tgz", - "integrity": "sha1-wJvDXE0R894J8tLaU+neI+fOHu4=", - "dev": true, - "requires": { - "decompress-tar": "4.1.1", - "file-type": "5.2.0", - "is-stream": "1.1.0" - } - }, - "decompress-unzip": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/decompress-unzip/-/decompress-unzip-4.0.1.tgz", - "integrity": "sha1-3qrM39FK6vhVePczroIQ+bSEj2k=", - "dev": true, - "requires": { - "file-type": "3.9.0", - "get-stream": "2.3.1", - "pify": "2.3.0", - "yauzl": "2.9.1" - }, - "dependencies": { - "file-type": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz", - "integrity": "sha1-JXoHg4TR24CHvESdEH1SpSZyuek=", - "dev": true - } - } - }, - "download": { - "version": "6.2.5", - "resolved": "https://registry.npmjs.org/download/-/download-6.2.5.tgz", - "integrity": "sha1-rNalQuTNC7Qspwz8mMnkOwcDlxQ=", - "dev": true, - "requires": { - "caw": "2.0.1", - "content-disposition": "0.5.2", - "decompress": "4.2.0", - "ext-name": "5.0.0", - "file-type": "5.2.0", - "filenamify": "2.0.0", - "get-stream": "3.0.0", - "got": "7.1.0", - "make-dir": "1.2.0", - "p-event": "1.3.0", - "pify": "3.0.0" - }, - "dependencies": { - "get-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", - "dev": true - }, - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true - } - } - }, - "execa": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.10.0.tgz", - "integrity": "sha1-/0Vqj1P5D47MxxqW0Rvfx/CCy1A=", - "dev": true, - "requires": { - "cross-spawn": "6.0.5", - "get-stream": "3.0.0", - "is-stream": "1.1.0", - "npm-run-path": "2.0.2", - "p-finally": "1.0.0", - "signal-exit": "3.0.2", - "strip-eof": "1.0.0" - }, - "dependencies": { - "cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha1-Sl7Hxk364iw6FBJNus3uhG2Ay8Q=", - "dev": true, - "requires": { - "nice-try": "1.0.4", - "path-key": "2.0.1", - "semver": "5.5.0", - "shebang-command": "1.2.0", - "which": "1.3.0" - } - }, - "get-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", - "dev": true - } - } - }, - "file-type": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-5.2.0.tgz", - "integrity": "sha1-LdvqfHP/42No365J3DOMBYwritY=", - "dev": true - }, - "filename-reserved-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz", - "integrity": "sha1-q/c9+rc10EVECr/qLZHzieu/oik=", - "dev": true - }, - "filenamify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-2.0.0.tgz", - "integrity": "sha1-vRYiYsC26Uv7zc8Zo7uzdk94VpU=", - "dev": true, - "requires": { - "filename-reserved-regex": "2.0.0", - "strip-outer": "1.0.1", - "trim-repeated": "1.0.0" - } - }, - "get-proxy": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/get-proxy/-/get-proxy-2.1.0.tgz", - "integrity": "sha1-NJ8rTZHUTE1NTpy6KtkBQ/rF75M=", - "dev": true, - "requires": { - "npm-conf": "1.1.3" - } - }, - "get-stream": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-2.3.1.tgz", - "integrity": "sha1-Xzj5PzRgCWZu4BUKBUFn+Rvdld4=", - "dev": true, - "requires": { - "object-assign": "4.1.1", - "pinkie-promise": "2.0.1" - } - }, - "got": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/got/-/got-7.1.0.tgz", - "integrity": "sha1-BUUP2ECU5rvqVvRRpDqcKJFmOFo=", - "dev": true, - "requires": { - "decompress-response": "3.3.0", - "duplexer3": "0.1.4", - "get-stream": "3.0.0", - "is-plain-obj": "1.1.0", - "is-retry-allowed": "1.1.0", - "is-stream": "1.1.0", - "isurl": "1.0.0", - "lowercase-keys": "1.0.0", - "p-cancelable": "0.3.0", - "p-timeout": "1.2.1", - "safe-buffer": "5.1.1", - "timed-out": "4.0.1", - "url-parse-lax": "1.0.0", - "url-to-options": "1.0.1" - }, - "dependencies": { - "get-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", - "dev": true - } - } - }, - "is-natural-number": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-natural-number/-/is-natural-number-4.0.1.tgz", - "integrity": "sha1-q5124dtM7VHjXeDHLr7PCfc0zeg=", - "dev": true - }, - "p-timeout": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-1.2.1.tgz", - "integrity": "sha1-XrOzU7f86Z8QGhA4iAuwVOu+o4Y=", - "dev": true, - "requires": { - "p-finally": "1.0.0" - } - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - }, - "prepend-http": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", - "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=", - "dev": true - }, - "strip-dirs": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/strip-dirs/-/strip-dirs-2.1.0.tgz", - "integrity": "sha1-SYdzYmT8NEzyD2w0rKnRPR1O1sU=", - "dev": true, - "requires": { - "is-natural-number": "4.0.1" - } - }, - "url-parse-lax": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz", - "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=", - "dev": true, - "requires": { - "prepend-http": "1.0.4" - } - } + "find-up": "^2.1.0" } }, "portfinder": { - "version": "1.0.13", - "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.13.tgz", - "integrity": "sha1-uzLs2HwnEErm7kS1o8y/Drsa7ek=", + "version": "1.0.17", + "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.17.tgz", + "integrity": "sha1-qKFpEUPkbEc17e/PT7zM7a0mRWo=", "dev": true, "requires": { - "async": "1.5.2", - "debug": "2.6.9", - "mkdirp": "0.5.1" + "async": "^1.5.2", + "debug": "^2.2.0", + "mkdirp": "0.5.x" }, "dependencies": { "async": { @@ -9108,18 +7554,18 @@ "integrity": "sha512-f13HRz0HtVwVaEuW6J6cOUCBLFtymhgyLPV7t4QEk2UD3twRI9IluDcQNdzQdBpiixkXj2OmzejhhTbSbDxNTg==", "dev": true, "requires": { - "chalk": "2.3.2", - "source-map": "0.6.1", - "supports-color": "5.3.0" + "chalk": "^2.3.1", + "source-map": "^0.6.1", + "supports-color": "^5.2.0" }, "dependencies": { "ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "integrity": "sha1-QfuyAkPlCxK+DwS43tvwdSDOhB0=", "dev": true, "requires": { - "color-convert": "1.9.1" + "color-convert": "^1.9.0" } }, "chalk": { @@ -9128,15 +7574,15 @@ "integrity": "sha512-ZM4j2/ld/YZDc3Ma8PgN7gyAk+kHMMMyzLNryCPGhWrsfAuDVeuid5bpRFTDgMH9JBK2lA4dyyAkkZYF/WcqDQ==", "dev": true, "requires": { - "ansi-styles": "3.2.1", - "escape-string-regexp": "1.0.5", - "supports-color": "5.3.0" + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" } }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", "dev": true }, "supports-color": { @@ -9145,7 +7591,7 @@ "integrity": "sha512-0aP01LLIskjKs3lq52EC0aGBAJhLq7B2Rd8HC/DR/PtNNpcLilNmHC12O+hu0usQpo7wtHNRqtrhBwtDb0+dNg==", "dev": true, "requires": { - "has-flag": "3.0.0" + "has-flag": "^3.0.0" } } } @@ -9156,9 +7602,9 @@ "integrity": "sha1-d7rnypKK2FcW4v2kLyYb98HWW14=", "dev": true, "requires": { - "postcss": "5.2.18", - "postcss-message-helpers": "2.0.0", - "reduce-css-calc": "1.3.0" + "postcss": "^5.0.2", + "postcss-message-helpers": "^2.0.0", + "reduce-css-calc": "^1.2.6" }, "dependencies": { "has-flag": { @@ -9173,10 +7619,10 @@ "integrity": "sha1-ut+hSX1GJE9jkPWLMZgw2RB4U8U=", "dev": true, "requires": { - "chalk": "1.1.3", - "js-base64": "2.4.3", - "source-map": "0.5.7", - "supports-color": "3.2.3" + "chalk": "^1.1.3", + "js-base64": "^2.1.9", + "source-map": "^0.5.6", + "supports-color": "^3.2.3" } }, "supports-color": { @@ -9185,7 +7631,7 @@ "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", "dev": true, "requires": { - "has-flag": "1.0.0" + "has-flag": "^1.0.0" } } } @@ -9196,9 +7642,9 @@ "integrity": "sha1-ZjFBfV8OkJo9fsJrJMio0eT5bks=", "dev": true, "requires": { - "colormin": "1.1.2", - "postcss": "5.2.18", - "postcss-value-parser": "3.3.0" + "colormin": "^1.0.5", + "postcss": "^5.0.13", + "postcss-value-parser": "^3.2.3" }, "dependencies": { "has-flag": { @@ -9213,10 +7659,10 @@ "integrity": "sha1-ut+hSX1GJE9jkPWLMZgw2RB4U8U=", "dev": true, "requires": { - "chalk": "1.1.3", - "js-base64": "2.4.3", - "source-map": "0.5.7", - "supports-color": "3.2.3" + "chalk": "^1.1.3", + "js-base64": "^2.1.9", + "source-map": "^0.5.6", + "supports-color": "^3.2.3" } }, "supports-color": { @@ -9225,7 +7671,7 @@ "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", "dev": true, "requires": { - "has-flag": "1.0.0" + "has-flag": "^1.0.0" } } } @@ -9236,8 +7682,8 @@ "integrity": "sha1-u9hZPFwf0uPRwyK7kl3K6Nrk1i0=", "dev": true, "requires": { - "postcss": "5.2.18", - "postcss-value-parser": "3.3.0" + "postcss": "^5.0.11", + "postcss-value-parser": "^3.1.2" }, "dependencies": { "has-flag": { @@ -9252,10 +7698,10 @@ "integrity": "sha1-ut+hSX1GJE9jkPWLMZgw2RB4U8U=", "dev": true, "requires": { - "chalk": "1.1.3", - "js-base64": "2.4.3", - "source-map": "0.5.7", - "supports-color": "3.2.3" + "chalk": "^1.1.3", + "js-base64": "^2.1.9", + "source-map": "^0.5.6", + "supports-color": "^3.2.3" } }, "supports-color": { @@ -9264,7 +7710,7 @@ "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", "dev": true, "requires": { - "has-flag": "1.0.0" + "has-flag": "^1.0.0" } } } @@ -9275,7 +7721,7 @@ "integrity": "sha1-vv6J+v1bPazlzM5Rt2uBUUvgDj0=", "dev": true, "requires": { - "postcss": "5.2.18" + "postcss": "^5.0.14" }, "dependencies": { "has-flag": { @@ -9290,10 +7736,10 @@ "integrity": "sha1-ut+hSX1GJE9jkPWLMZgw2RB4U8U=", "dev": true, "requires": { - "chalk": "1.1.3", - "js-base64": "2.4.3", - "source-map": "0.5.7", - "supports-color": "3.2.3" + "chalk": "^1.1.3", + "js-base64": "^2.1.9", + "source-map": "^0.5.6", + "supports-color": "^3.2.3" } }, "supports-color": { @@ -9302,7 +7748,7 @@ "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", "dev": true, "requires": { - "has-flag": "1.0.0" + "has-flag": "^1.0.0" } } } @@ -9313,7 +7759,7 @@ "integrity": "sha1-uavye4isGIFYpesSq8riAmO5GTI=", "dev": true, "requires": { - "postcss": "5.2.18" + "postcss": "^5.0.4" }, "dependencies": { "has-flag": { @@ -9328,10 +7774,10 @@ "integrity": "sha1-ut+hSX1GJE9jkPWLMZgw2RB4U8U=", "dev": true, "requires": { - "chalk": "1.1.3", - "js-base64": "2.4.3", - "source-map": "0.5.7", - "supports-color": "3.2.3" + "chalk": "^1.1.3", + "js-base64": "^2.1.9", + "source-map": "^0.5.6", + "supports-color": "^3.2.3" } }, "supports-color": { @@ -9340,7 +7786,7 @@ "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", "dev": true, "requires": { - "has-flag": "1.0.0" + "has-flag": "^1.0.0" } } } @@ -9351,7 +7797,7 @@ "integrity": "sha1-0rS9nVztXr2Nyt52QMfXzX9PkrU=", "dev": true, "requires": { - "postcss": "5.2.18" + "postcss": "^5.0.14" }, "dependencies": { "has-flag": { @@ -9366,10 +7812,10 @@ "integrity": "sha1-ut+hSX1GJE9jkPWLMZgw2RB4U8U=", "dev": true, "requires": { - "chalk": "1.1.3", - "js-base64": "2.4.3", - "source-map": "0.5.7", - "supports-color": "3.2.3" + "chalk": "^1.1.3", + "js-base64": "^2.1.9", + "source-map": "^0.5.6", + "supports-color": "^3.2.3" } }, "supports-color": { @@ -9378,7 +7824,7 @@ "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", "dev": true, "requires": { - "has-flag": "1.0.0" + "has-flag": "^1.0.0" } } } @@ -9389,7 +7835,7 @@ "integrity": "sha1-ix6vVU9ob7KIzYdMVWZ7CqNmjVg=", "dev": true, "requires": { - "postcss": "5.2.18" + "postcss": "^5.0.16" }, "dependencies": { "has-flag": { @@ -9404,10 +7850,10 @@ "integrity": "sha1-ut+hSX1GJE9jkPWLMZgw2RB4U8U=", "dev": true, "requires": { - "chalk": "1.1.3", - "js-base64": "2.4.3", - "source-map": "0.5.7", - "supports-color": "3.2.3" + "chalk": "^1.1.3", + "js-base64": "^2.1.9", + "source-map": "^0.5.6", + "supports-color": "^3.2.3" } }, "supports-color": { @@ -9416,7 +7862,7 @@ "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", "dev": true, "requires": { - "has-flag": "1.0.0" + "has-flag": "^1.0.0" } } } @@ -9427,8 +7873,8 @@ "integrity": "sha1-vOMLLMWR/8Y0Mitfs0ZLbZNPRDM=", "dev": true, "requires": { - "postcss": "5.2.18", - "uniqs": "2.0.0" + "postcss": "^5.0.14", + "uniqs": "^2.0.0" }, "dependencies": { "has-flag": { @@ -9443,10 +7889,10 @@ "integrity": "sha1-ut+hSX1GJE9jkPWLMZgw2RB4U8U=", "dev": true, "requires": { - "chalk": "1.1.3", - "js-base64": "2.4.3", - "source-map": "0.5.7", - "supports-color": "3.2.3" + "chalk": "^1.1.3", + "js-base64": "^2.1.9", + "source-map": "^0.5.6", + "supports-color": "^3.2.3" } }, "supports-color": { @@ -9455,19 +7901,18 @@ "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", "dev": true, "requires": { - "has-flag": "1.0.0" + "has-flag": "^1.0.0" } } } }, "postcss-filter-plugins": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/postcss-filter-plugins/-/postcss-filter-plugins-2.0.2.tgz", - "integrity": "sha1-bYWGJTTXNaxCDkqFgG4fXUKG2Ew=", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/postcss-filter-plugins/-/postcss-filter-plugins-2.0.3.tgz", + "integrity": "sha1-giRf34IzcEFkXkdxFNjlk6oYuOw=", "dev": true, "requires": { - "postcss": "5.2.18", - "uniqid": "4.1.1" + "postcss": "^5.0.4" }, "dependencies": { "has-flag": { @@ -9479,13 +7924,13 @@ "postcss": { "version": "5.2.18", "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", + "integrity": "sha1-ut+hSX1GJE9jkPWLMZgw2RB4U8U=", "dev": true, "requires": { - "chalk": "1.1.3", - "js-base64": "2.4.3", - "source-map": "0.5.7", - "supports-color": "3.2.3" + "chalk": "^1.1.3", + "js-base64": "^2.1.9", + "source-map": "^0.5.6", + "supports-color": "^3.2.3" } }, "supports-color": { @@ -9494,7 +7939,7 @@ "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", "dev": true, "requires": { - "has-flag": "1.0.0" + "has-flag": "^1.0.0" } } } @@ -9505,10 +7950,10 @@ "integrity": "sha1-U56a/J3chiASHr+djDZz4M5Q0oo=", "dev": true, "requires": { - "cosmiconfig": "2.2.2", - "object-assign": "4.1.1", - "postcss-load-options": "1.2.0", - "postcss-load-plugins": "2.3.0" + "cosmiconfig": "^2.1.0", + "object-assign": "^4.1.0", + "postcss-load-options": "^1.2.0", + "postcss-load-plugins": "^2.3.0" } }, "postcss-load-options": { @@ -9517,8 +7962,8 @@ "integrity": "sha1-sJixVZ3awt8EvAuzdfmaXP4rbYw=", "dev": true, "requires": { - "cosmiconfig": "2.2.2", - "object-assign": "4.1.1" + "cosmiconfig": "^2.1.0", + "object-assign": "^4.1.0" } }, "postcss-load-plugins": { @@ -9527,42 +7972,84 @@ "integrity": "sha1-dFdoEWWZrKLwCfrUJrABdQSdjZI=", "dev": true, "requires": { - "cosmiconfig": "2.2.2", - "object-assign": "4.1.1" + "cosmiconfig": "^2.1.1", + "object-assign": "^4.1.0" } }, "postcss-loader": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-2.1.4.tgz", - "integrity": "sha512-L2p654oK945B/gDFUGgOhh7uzj19RWoY1SVMeJVoKno1H2MdbQ0RppR/28JGju4pMb22iRC7BJ9aDzbxXSLf4A==", + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-2.1.6.tgz", + "integrity": "sha1-HX3XsXxrojS5vtWvE+C+pApC10A=", "dev": true, "requires": { - "loader-utils": "1.1.0", - "postcss": "6.0.19", - "postcss-load-config": "1.2.0", - "schema-utils": "0.4.5" + "loader-utils": "^1.1.0", + "postcss": "^6.0.0", + "postcss-load-config": "^2.0.0", + "schema-utils": "^0.4.0" }, "dependencies": { - "ajv": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.4.0.tgz", - "integrity": "sha1-06/3jpJ3VJdx2vAWTP9ISCt1T8Y=", + "cosmiconfig": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-4.0.0.tgz", + "integrity": "sha512-6e5vDdrXZD+t5v0L8CrurPeybg4Fmf+FCSYxXKYVAqLUtyCSbuyqE059d0kDthTNRzKVjL7QMgNpEUlsoYH3iQ==", "dev": true, "requires": { - "fast-deep-equal": "1.1.0", - "fast-json-stable-stringify": "2.0.0", - "json-schema-traverse": "0.3.1", - "uri-js": "3.0.2" + "is-directory": "^0.3.1", + "js-yaml": "^3.9.0", + "parse-json": "^4.0.0", + "require-from-string": "^2.0.1" } }, - "schema-utils": { - "version": "0.4.5", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.4.5.tgz", - "integrity": "sha512-yYrjb9TX2k/J1Y5UNy3KYdZq10xhYcF8nMpAW6o3hy6Q8WSIEf9lJHG/ePnOBfziPM3fvQwfOwa13U/Fh8qTfA==", + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "js-yaml": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz", + "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==", "dev": true, "requires": { - "ajv": "6.4.0", - "ajv-keywords": "3.2.0" + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "postcss-load-config": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-2.0.0.tgz", + "integrity": "sha512-V5JBLzw406BB8UIfsAWSK2KSwIJ5yoEIVFb4gVkXci0QdKgA24jLmHZ/ghe/GgX0lJ0/D1uUK1ejhzEY94MChQ==", + "dev": true, + "requires": { + "cosmiconfig": "^4.0.0", + "import-cwd": "^2.0.0" + } + }, + "require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true + }, + "schema-utils": { + "version": "0.4.7", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.4.7.tgz", + "integrity": "sha1-unT1l9K+LqiAExdG7hfQoJPGgYc=", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-keywords": "^3.1.0" } } } @@ -9573,9 +8060,9 @@ "integrity": "sha1-TFUwMTwI4dWzu/PSu8dH4njuonA=", "dev": true, "requires": { - "has": "1.0.1", - "postcss": "5.2.18", - "postcss-value-parser": "3.3.0" + "has": "^1.0.1", + "postcss": "^5.0.10", + "postcss-value-parser": "^3.1.1" }, "dependencies": { "has-flag": { @@ -9590,10 +8077,10 @@ "integrity": "sha1-ut+hSX1GJE9jkPWLMZgw2RB4U8U=", "dev": true, "requires": { - "chalk": "1.1.3", - "js-base64": "2.4.3", - "source-map": "0.5.7", - "supports-color": "3.2.3" + "chalk": "^1.1.3", + "js-base64": "^2.1.9", + "source-map": "^0.5.6", + "supports-color": "^3.2.3" } }, "supports-color": { @@ -9602,7 +8089,7 @@ "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", "dev": true, "requires": { - "has-flag": "1.0.0" + "has-flag": "^1.0.0" } } } @@ -9613,7 +8100,7 @@ "integrity": "sha1-I9kM0Sewp3mUkVMyc5A0oaTz1lg=", "dev": true, "requires": { - "postcss": "5.2.18" + "postcss": "^5.0.4" }, "dependencies": { "has-flag": { @@ -9628,10 +8115,10 @@ "integrity": "sha1-ut+hSX1GJE9jkPWLMZgw2RB4U8U=", "dev": true, "requires": { - "chalk": "1.1.3", - "js-base64": "2.4.3", - "source-map": "0.5.7", - "supports-color": "3.2.3" + "chalk": "^1.1.3", + "js-base64": "^2.1.9", + "source-map": "^0.5.6", + "supports-color": "^3.2.3" } }, "supports-color": { @@ -9640,7 +8127,7 @@ "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", "dev": true, "requires": { - "has-flag": "1.0.0" + "has-flag": "^1.0.0" } } } @@ -9651,11 +8138,11 @@ "integrity": "sha1-0d9d+qexrMO+VT8OnhDofGG19yE=", "dev": true, "requires": { - "browserslist": "1.7.7", - "caniuse-api": "1.6.1", - "postcss": "5.2.18", - "postcss-selector-parser": "2.2.3", - "vendors": "1.0.2" + "browserslist": "^1.5.2", + "caniuse-api": "^1.5.2", + "postcss": "^5.0.4", + "postcss-selector-parser": "^2.2.2", + "vendors": "^1.0.0" }, "dependencies": { "browserslist": { @@ -9664,8 +8151,8 @@ "integrity": "sha1-C9dnBCWL6CmyOYu1Dkti0aFmsLk=", "dev": true, "requires": { - "caniuse-db": "1.0.30000832", - "electron-to-chromium": "1.3.44" + "caniuse-db": "^1.0.30000639", + "electron-to-chromium": "^1.2.7" } }, "has-flag": { @@ -9680,10 +8167,10 @@ "integrity": "sha1-ut+hSX1GJE9jkPWLMZgw2RB4U8U=", "dev": true, "requires": { - "chalk": "1.1.3", - "js-base64": "2.4.3", - "source-map": "0.5.7", - "supports-color": "3.2.3" + "chalk": "^1.1.3", + "js-base64": "^2.1.9", + "source-map": "^0.5.6", + "supports-color": "^3.2.3" } }, "supports-color": { @@ -9692,7 +8179,7 @@ "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", "dev": true, "requires": { - "has-flag": "1.0.0" + "has-flag": "^1.0.0" } } } @@ -9709,9 +8196,9 @@ "integrity": "sha1-S1jttWZB66fIR0qzUmyv17vey2k=", "dev": true, "requires": { - "object-assign": "4.1.1", - "postcss": "5.2.18", - "postcss-value-parser": "3.3.0" + "object-assign": "^4.0.1", + "postcss": "^5.0.4", + "postcss-value-parser": "^3.0.2" }, "dependencies": { "has-flag": { @@ -9726,10 +8213,10 @@ "integrity": "sha1-ut+hSX1GJE9jkPWLMZgw2RB4U8U=", "dev": true, "requires": { - "chalk": "1.1.3", - "js-base64": "2.4.3", - "source-map": "0.5.7", - "supports-color": "3.2.3" + "chalk": "^1.1.3", + "js-base64": "^2.1.9", + "source-map": "^0.5.6", + "supports-color": "^3.2.3" } }, "supports-color": { @@ -9738,7 +8225,7 @@ "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", "dev": true, "requires": { - "has-flag": "1.0.0" + "has-flag": "^1.0.0" } } } @@ -9749,8 +8236,8 @@ "integrity": "sha1-Xb2hE3NwP4PPtKPqOIHY11/15uE=", "dev": true, "requires": { - "postcss": "5.2.18", - "postcss-value-parser": "3.3.0" + "postcss": "^5.0.12", + "postcss-value-parser": "^3.3.0" }, "dependencies": { "has-flag": { @@ -9765,10 +8252,10 @@ "integrity": "sha1-ut+hSX1GJE9jkPWLMZgw2RB4U8U=", "dev": true, "requires": { - "chalk": "1.1.3", - "js-base64": "2.4.3", - "source-map": "0.5.7", - "supports-color": "3.2.3" + "chalk": "^1.1.3", + "js-base64": "^2.1.9", + "source-map": "^0.5.6", + "supports-color": "^3.2.3" } }, "supports-color": { @@ -9777,7 +8264,7 @@ "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", "dev": true, "requires": { - "has-flag": "1.0.0" + "has-flag": "^1.0.0" } } } @@ -9788,10 +8275,10 @@ "integrity": "sha1-rSzgcTc7lDs9kwo/pZo1jCjW8fM=", "dev": true, "requires": { - "alphanum-sort": "1.0.2", - "postcss": "5.2.18", - "postcss-value-parser": "3.3.0", - "uniqs": "2.0.0" + "alphanum-sort": "^1.0.1", + "postcss": "^5.0.2", + "postcss-value-parser": "^3.0.2", + "uniqs": "^2.0.0" }, "dependencies": { "has-flag": { @@ -9806,10 +8293,10 @@ "integrity": "sha1-ut+hSX1GJE9jkPWLMZgw2RB4U8U=", "dev": true, "requires": { - "chalk": "1.1.3", - "js-base64": "2.4.3", - "source-map": "0.5.7", - "supports-color": "3.2.3" + "chalk": "^1.1.3", + "js-base64": "^2.1.9", + "source-map": "^0.5.6", + "supports-color": "^3.2.3" } }, "supports-color": { @@ -9818,7 +8305,7 @@ "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", "dev": true, "requires": { - "has-flag": "1.0.0" + "has-flag": "^1.0.0" } } } @@ -9829,10 +8316,10 @@ "integrity": "sha1-ssapjAByz5G5MtGkllCBFDEXNb8=", "dev": true, "requires": { - "alphanum-sort": "1.0.2", - "has": "1.0.1", - "postcss": "5.2.18", - "postcss-selector-parser": "2.2.3" + "alphanum-sort": "^1.0.2", + "has": "^1.0.1", + "postcss": "^5.0.14", + "postcss-selector-parser": "^2.0.0" }, "dependencies": { "has-flag": { @@ -9847,10 +8334,10 @@ "integrity": "sha1-ut+hSX1GJE9jkPWLMZgw2RB4U8U=", "dev": true, "requires": { - "chalk": "1.1.3", - "js-base64": "2.4.3", - "source-map": "0.5.7", - "supports-color": "3.2.3" + "chalk": "^1.1.3", + "js-base64": "^2.1.9", + "source-map": "^0.5.6", + "supports-color": "^3.2.3" } }, "supports-color": { @@ -9859,7 +8346,7 @@ "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", "dev": true, "requires": { - "has-flag": "1.0.0" + "has-flag": "^1.0.0" } } } @@ -9870,7 +8357,7 @@ "integrity": "sha1-ZhQOzs447wa/DT41XWm/WdFB6oU=", "dev": true, "requires": { - "postcss": "6.0.19" + "postcss": "^6.0.1" } }, "postcss-modules-local-by-default": { @@ -9879,8 +8366,8 @@ "integrity": "sha1-99gMOYxaOT+nlkRmvRlQCn1hwGk=", "dev": true, "requires": { - "css-selector-tokenizer": "0.7.0", - "postcss": "6.0.19" + "css-selector-tokenizer": "^0.7.0", + "postcss": "^6.0.1" } }, "postcss-modules-scope": { @@ -9889,8 +8376,8 @@ "integrity": "sha1-1upkmUx5+XtipytCb75gVqGUu5A=", "dev": true, "requires": { - "css-selector-tokenizer": "0.7.0", - "postcss": "6.0.19" + "css-selector-tokenizer": "^0.7.0", + "postcss": "^6.0.1" } }, "postcss-modules-values": { @@ -9899,8 +8386,8 @@ "integrity": "sha1-7P+p1+GSUYOJ9CrQ6D9yrsRW6iA=", "dev": true, "requires": { - "icss-replace-symbols": "1.1.0", - "postcss": "6.0.19" + "icss-replace-symbols": "^1.1.0", + "postcss": "^6.0.1" } }, "postcss-normalize-charset": { @@ -9909,7 +8396,7 @@ "integrity": "sha1-757nEhLX/nWceO0WL2HtYrXLk/E=", "dev": true, "requires": { - "postcss": "5.2.18" + "postcss": "^5.0.5" }, "dependencies": { "has-flag": { @@ -9924,10 +8411,10 @@ "integrity": "sha1-ut+hSX1GJE9jkPWLMZgw2RB4U8U=", "dev": true, "requires": { - "chalk": "1.1.3", - "js-base64": "2.4.3", - "source-map": "0.5.7", - "supports-color": "3.2.3" + "chalk": "^1.1.3", + "js-base64": "^2.1.9", + "source-map": "^0.5.6", + "supports-color": "^3.2.3" } }, "supports-color": { @@ -9936,7 +8423,7 @@ "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", "dev": true, "requires": { - "has-flag": "1.0.0" + "has-flag": "^1.0.0" } } } @@ -9947,10 +8434,10 @@ "integrity": "sha1-EI90s/L82viRov+j6kWSJ5/HgiI=", "dev": true, "requires": { - "is-absolute-url": "2.1.0", - "normalize-url": "1.9.1", - "postcss": "5.2.18", - "postcss-value-parser": "3.3.0" + "is-absolute-url": "^2.0.0", + "normalize-url": "^1.4.0", + "postcss": "^5.0.14", + "postcss-value-parser": "^3.2.3" }, "dependencies": { "has-flag": { @@ -9965,10 +8452,10 @@ "integrity": "sha1-LMDWazHqIwNkWENuNiDYWVTGbDw=", "dev": true, "requires": { - "object-assign": "4.1.1", - "prepend-http": "1.0.4", - "query-string": "4.3.4", - "sort-keys": "1.1.2" + "object-assign": "^4.0.1", + "prepend-http": "^1.0.0", + "query-string": "^4.1.0", + "sort-keys": "^1.0.0" } }, "postcss": { @@ -9977,10 +8464,10 @@ "integrity": "sha1-ut+hSX1GJE9jkPWLMZgw2RB4U8U=", "dev": true, "requires": { - "chalk": "1.1.3", - "js-base64": "2.4.3", - "source-map": "0.5.7", - "supports-color": "3.2.3" + "chalk": "^1.1.3", + "js-base64": "^2.1.9", + "source-map": "^0.5.6", + "supports-color": "^3.2.3" } }, "prepend-http": { @@ -9995,8 +8482,8 @@ "integrity": "sha1-u7aTucqRXCMlFbIosaArYJBD2+s=", "dev": true, "requires": { - "object-assign": "4.1.1", - "strict-uri-encode": "1.1.0" + "object-assign": "^4.1.0", + "strict-uri-encode": "^1.0.0" } }, "sort-keys": { @@ -10005,7 +8492,7 @@ "integrity": "sha1-RBttTTRnmPG05J6JIK37oOVD+a0=", "dev": true, "requires": { - "is-plain-obj": "1.1.0" + "is-plain-obj": "^1.0.0" } }, "supports-color": { @@ -10014,7 +8501,7 @@ "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", "dev": true, "requires": { - "has-flag": "1.0.0" + "has-flag": "^1.0.0" } } } @@ -10025,8 +8512,8 @@ "integrity": "sha1-7sbCpntsQSqNsgQud/6NpD+VwR0=", "dev": true, "requires": { - "postcss": "5.2.18", - "postcss-value-parser": "3.3.0" + "postcss": "^5.0.4", + "postcss-value-parser": "^3.0.1" }, "dependencies": { "has-flag": { @@ -10041,10 +8528,10 @@ "integrity": "sha1-ut+hSX1GJE9jkPWLMZgw2RB4U8U=", "dev": true, "requires": { - "chalk": "1.1.3", - "js-base64": "2.4.3", - "source-map": "0.5.7", - "supports-color": "3.2.3" + "chalk": "^1.1.3", + "js-base64": "^2.1.9", + "source-map": "^0.5.6", + "supports-color": "^3.2.3" } }, "supports-color": { @@ -10053,7 +8540,7 @@ "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", "dev": true, "requires": { - "has-flag": "1.0.0" + "has-flag": "^1.0.0" } } } @@ -10064,8 +8551,8 @@ "integrity": "sha1-wsbSDMlYKE9qv75j92Cb9AkFmtM=", "dev": true, "requires": { - "postcss": "5.2.18", - "postcss-value-parser": "3.3.0" + "postcss": "^5.0.4", + "postcss-value-parser": "^3.0.2" }, "dependencies": { "has-flag": { @@ -10080,10 +8567,10 @@ "integrity": "sha1-ut+hSX1GJE9jkPWLMZgw2RB4U8U=", "dev": true, "requires": { - "chalk": "1.1.3", - "js-base64": "2.4.3", - "source-map": "0.5.7", - "supports-color": "3.2.3" + "chalk": "^1.1.3", + "js-base64": "^2.1.9", + "source-map": "^0.5.6", + "supports-color": "^3.2.3" } }, "supports-color": { @@ -10092,7 +8579,7 @@ "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", "dev": true, "requires": { - "has-flag": "1.0.0" + "has-flag": "^1.0.0" } } } @@ -10103,7 +8590,7 @@ "integrity": "sha1-aPgGlfBF0IJjqHmtJA343WT2ROo=", "dev": true, "requires": { - "postcss": "5.2.18" + "postcss": "^5.0.4" }, "dependencies": { "has-flag": { @@ -10118,10 +8605,10 @@ "integrity": "sha1-ut+hSX1GJE9jkPWLMZgw2RB4U8U=", "dev": true, "requires": { - "chalk": "1.1.3", - "js-base64": "2.4.3", - "source-map": "0.5.7", - "supports-color": "3.2.3" + "chalk": "^1.1.3", + "js-base64": "^2.1.9", + "source-map": "^0.5.6", + "supports-color": "^3.2.3" } }, "supports-color": { @@ -10130,7 +8617,7 @@ "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", "dev": true, "requires": { - "has-flag": "1.0.0" + "has-flag": "^1.0.0" } } } @@ -10141,9 +8628,9 @@ "integrity": "sha1-/3b02CEkN7McKYpC0uFEQCV3GuE=", "dev": true, "requires": { - "has": "1.0.1", - "postcss": "5.2.18", - "postcss-value-parser": "3.3.0" + "has": "^1.0.1", + "postcss": "^5.0.8", + "postcss-value-parser": "^3.0.1" }, "dependencies": { "has-flag": { @@ -10158,10 +8645,10 @@ "integrity": "sha1-ut+hSX1GJE9jkPWLMZgw2RB4U8U=", "dev": true, "requires": { - "chalk": "1.1.3", - "js-base64": "2.4.3", - "source-map": "0.5.7", - "supports-color": "3.2.3" + "chalk": "^1.1.3", + "js-base64": "^2.1.9", + "source-map": "^0.5.6", + "supports-color": "^3.2.3" } }, "supports-color": { @@ -10170,7 +8657,7 @@ "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", "dev": true, "requires": { - "has-flag": "1.0.0" + "has-flag": "^1.0.0" } } } @@ -10181,9 +8668,9 @@ "integrity": "sha1-+UN3iGBsPJrO4W/+jYsWKX8nu5A=", "dev": true, "requires": { - "flatten": "1.0.2", - "indexes-of": "1.0.1", - "uniq": "1.0.1" + "flatten": "^1.0.2", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" } }, "postcss-svgo": { @@ -10192,10 +8679,10 @@ "integrity": "sha1-tt8YqmE7Zm4TPwittSGcJoSsEI0=", "dev": true, "requires": { - "is-svg": "2.1.0", - "postcss": "5.2.18", - "postcss-value-parser": "3.3.0", - "svgo": "0.7.2" + "is-svg": "^2.0.0", + "postcss": "^5.0.14", + "postcss-value-parser": "^3.2.3", + "svgo": "^0.7.0" }, "dependencies": { "has-flag": { @@ -10210,10 +8697,10 @@ "integrity": "sha1-ut+hSX1GJE9jkPWLMZgw2RB4U8U=", "dev": true, "requires": { - "chalk": "1.1.3", - "js-base64": "2.4.3", - "source-map": "0.5.7", - "supports-color": "3.2.3" + "chalk": "^1.1.3", + "js-base64": "^2.1.9", + "source-map": "^0.5.6", + "supports-color": "^3.2.3" } }, "supports-color": { @@ -10222,7 +8709,7 @@ "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", "dev": true, "requires": { - "has-flag": "1.0.0" + "has-flag": "^1.0.0" } } } @@ -10233,9 +8720,9 @@ "integrity": "sha1-mB1X0p3csz57Hf4f1DuGSfkzyh0=", "dev": true, "requires": { - "alphanum-sort": "1.0.2", - "postcss": "5.2.18", - "uniqs": "2.0.0" + "alphanum-sort": "^1.0.1", + "postcss": "^5.0.4", + "uniqs": "^2.0.0" }, "dependencies": { "has-flag": { @@ -10250,10 +8737,10 @@ "integrity": "sha1-ut+hSX1GJE9jkPWLMZgw2RB4U8U=", "dev": true, "requires": { - "chalk": "1.1.3", - "js-base64": "2.4.3", - "source-map": "0.5.7", - "supports-color": "3.2.3" + "chalk": "^1.1.3", + "js-base64": "^2.1.9", + "source-map": "^0.5.6", + "supports-color": "^3.2.3" } }, "supports-color": { @@ -10262,7 +8749,7 @@ "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", "dev": true, "requires": { - "has-flag": "1.0.0" + "has-flag": "^1.0.0" } } } @@ -10279,9 +8766,9 @@ "integrity": "sha1-0hCd3AVbka9n/EyzsCWUZjnSryI=", "dev": true, "requires": { - "has": "1.0.1", - "postcss": "5.2.18", - "uniqs": "2.0.0" + "has": "^1.0.1", + "postcss": "^5.0.4", + "uniqs": "^2.0.0" }, "dependencies": { "has-flag": { @@ -10296,10 +8783,10 @@ "integrity": "sha1-ut+hSX1GJE9jkPWLMZgw2RB4U8U=", "dev": true, "requires": { - "chalk": "1.1.3", - "js-base64": "2.4.3", - "source-map": "0.5.7", - "supports-color": "3.2.3" + "chalk": "^1.1.3", + "js-base64": "^2.1.9", + "source-map": "^0.5.6", + "supports-color": "^3.2.3" } }, "supports-color": { @@ -10308,7 +8795,7 @@ "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", "dev": true, "requires": { - "has-flag": "1.0.0" + "has-flag": "^1.0.0" } } } @@ -10330,6 +8817,11 @@ "integrity": "sha512-T/KD65Ot0PB97xTrG8afQ46x3oiVhnfGjGESSI9NWYcG92+OUPZKkwHqGWXH2t9jK1crnQjubECW0FuOth+hxw==", "dev": true }, + "printj": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/printj/-/printj-1.1.2.tgz", + "integrity": "sha1-2Q3rKXWoufYA+zoclOP0xTx4oiI=" + }, "private": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", @@ -10339,8 +8831,7 @@ "process": { "version": "0.11.10", "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", - "dev": true + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=" }, "process-nextick-args": { "version": "2.0.0", @@ -10353,7 +8844,7 @@ "integrity": "sha1-BktyYCsY+Q8pGSuLG8QY/9Hr078=", "optional": true, "requires": { - "asap": "2.0.6" + "asap": "~2.0.3" } }, "promise-inflight": { @@ -10362,20 +8853,14 @@ "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", "dev": true }, - "proto-list": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", - "integrity": "sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=", - "dev": true - }, "proxy-addr": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.3.tgz", - "integrity": "sha1-NV8mJQWmIWRrMTCnKOtkfiIFU0E=", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.4.tgz", + "integrity": "sha1-7PxzO/Iv+Mb0B/onUye5q2fki5M=", "dev": true, "requires": { - "forwarded": "0.1.2", - "ipaddr.js": "1.6.0" + "forwarded": "~0.1.2", + "ipaddr.js": "1.8.0" } }, "prr": { @@ -10392,14 +8877,13 @@ "public-encrypt": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.2.tgz", - "integrity": "sha1-RuuRByBr9zSJ+LhbadkTNMZhCZQ=", - "dev": true, + "integrity": "sha512-4kJ5Esocg8X3h8YgJsKAuoesBgB7mqH3eowiDzMUPKiRDDE7E/BqqZD1hnTByIaAFiwAw246YEltSq7tdrOH0Q==", "requires": { - "bn.js": "4.11.8", - "browserify-rsa": "4.0.1", - "create-hash": "1.2.0", - "parse-asn1": "5.1.1", - "randombytes": "2.0.6" + "bn.js": "^4.1.0", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "parse-asn1": "^5.0.0", + "randombytes": "^2.0.1" } }, "pump": { @@ -10408,19 +8892,19 @@ "integrity": "sha1-Ejma3W5M91Jtlzy8i1zi4pCLOQk=", "dev": true, "requires": { - "end-of-stream": "1.4.1", - "once": "1.4.0" + "end-of-stream": "^1.1.0", + "once": "^1.3.1" } }, "pumpify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.4.0.tgz", - "integrity": "sha512-2kmNR9ry+Pf45opRVirpNuIFotsxUGLaYqxIwuR77AYrYRMuFCz9eryHBS52L360O+NcR383CL4QYlMKPq4zYA==", + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", + "integrity": "sha1-NlE74karJ1cLGjdKXOJ4v9dDcM4=", "dev": true, "requires": { - "duplexify": "3.5.4", - "inherits": "2.0.3", - "pump": "2.0.1" + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" } }, "punycode": { @@ -10435,57 +8919,53 @@ "dev": true }, "qs": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz", - "integrity": "sha1-E+JtKK1rD/qpExLNO/cI7TUecjM=", + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha1-yzroBuh0BERYTvFUzo7pjUA/PjY=", "dev": true }, "query-string": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", - "integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==", + "integrity": "sha1-p4wBK3HBfgXy4/ojGd0zBoLvs8s=", "requires": { - "decode-uri-component": "0.2.0", - "object-assign": "4.1.1", - "strict-uri-encode": "1.1.0" + "decode-uri-component": "^0.2.0", + "object-assign": "^4.1.0", + "strict-uri-encode": "^1.0.0" } }, "querystring": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", - "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", - "dev": true + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=" }, "querystring-es3": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", - "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", - "dev": true + "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=" }, "querystringify": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-0.0.4.tgz", - "integrity": "sha1-DPf4T5Rj/wrlHExLFC2VvjdyTZw=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.0.0.tgz", + "integrity": "sha1-+j7W5o6xUVlFfImze8ZHKDMZV1U=", "dev": true }, "randomatic": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz", - "integrity": "sha512-D5JUjPyJbaJDkuAazpVnSfVkLlpeO3wDlPROTMLGKG1zMFNFRgrciKo1ltz/AzNTkqE0HzDx655QOL51N06how==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.1.0.tgz", + "integrity": "sha1-NvLKcI6eVn9e0uwBlJAm1QqhARY=", "dev": true, "requires": { - "is-number": "3.0.0", - "kind-of": "4.0.0" + "is-number": "^4.0.0", + "kind-of": "^6.0.0", + "math-random": "^1.0.1" }, "dependencies": { - "kind-of": { + "is-number": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "dev": true, - "requires": { - "is-buffer": "1.1.6" - } + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha1-ACbjf1RU1z41bf5lZGmYZ8an8P8=", + "dev": true } } }, @@ -10493,19 +8973,17 @@ "version": "2.0.6", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.6.tgz", "integrity": "sha1-0wLFIpSFiISKjTAMkytEwkIx2oA=", - "dev": true, "requires": { - "safe-buffer": "5.1.1" + "safe-buffer": "^5.1.0" } }, "randomfill": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", "integrity": "sha1-ySGW/IarQr6YPxvzF3giSTHWFFg=", - "dev": true, "requires": { - "randombytes": "2.0.6", - "safe-buffer": "5.1.1" + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" } }, "range-parser": { @@ -10514,6 +8992,14 @@ "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=", "dev": true }, + "raphael": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/raphael/-/raphael-2.2.7.tgz", + "integrity": "sha1-IxsZFB+NCGmG2PrOtm+LVi7iyBA=", + "requires": { + "eve-raphael": "0.5.0" + } + }, "raw-body": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz", @@ -10541,7 +9027,7 @@ "depd": "1.1.1", "inherits": "2.0.3", "setprototypeof": "1.0.3", - "statuses": "1.4.0" + "statuses": ">= 1.3.1 < 2" } }, "setprototypeof": { @@ -10552,34 +9038,12 @@ } } }, - "rc": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.7.tgz", - "integrity": "sha512-LdLD8xD4zzLsAT5xyushXDNscEjB7+2ulnl8+r1pnESlYtlJtVSoCMBGr30eDRJ3+2Gq89jK9P9e4tCEH1+ywA==", - "dev": true, + "read-only-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-only-stream/-/read-only-stream-2.0.0.tgz", + "integrity": "sha1-JyT9aoET1zdkrCiNQ4YnDB2/F/A=", "requires": { - "deep-extend": "0.5.1", - "ini": "1.3.5", - "minimist": "1.2.0", - "strip-json-comments": "2.0.1" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - } - } - }, - "read-all-stream": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/read-all-stream/-/read-all-stream-3.1.0.tgz", - "integrity": "sha1-NcPhd/IHjveJ7kv6+kNzB06u9Po=", - "dev": true, - "requires": { - "pinkie-promise": "2.0.1", - "readable-stream": "2.3.4" + "readable-stream": "^2.0.2" } }, "read-pkg": { @@ -10588,9 +9052,9 @@ "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", "dev": true, "requires": { - "load-json-file": "1.1.0", - "normalize-package-data": "2.4.0", - "path-type": "1.1.0" + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.0" } }, "read-pkg-up": { @@ -10599,8 +9063,8 @@ "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", "dev": true, "requires": { - "find-up": "1.1.2", - "read-pkg": "1.1.0" + "find-up": "^1.0.0", + "read-pkg": "^1.0.0" }, "dependencies": { "find-up": { @@ -10609,8 +9073,8 @@ "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", "dev": true, "requires": { - "path-exists": "2.1.0", - "pinkie-promise": "2.0.1" + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" } }, "path-exists": { @@ -10619,7 +9083,7 @@ "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", "dev": true, "requires": { - "pinkie-promise": "2.0.1" + "pinkie-promise": "^2.0.0" } } } @@ -10629,13 +9093,13 @@ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.4.tgz", "integrity": "sha512-vuYxeWYM+fde14+rajzqgeohAI7YoJcHE7kXDAc4Nk0EbuKnJfqtY9YtRkLo/tqkuF7MsBQRhPnPeyjYITp3ZQ==", "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "2.0.0", - "safe-buffer": "5.1.1", - "string_decoder": "1.0.3", - "util-deprecate": "1.0.2" + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.0.3", + "util-deprecate": "~1.0.1" } }, "readdirp": { @@ -10644,10 +9108,10 @@ "integrity": "sha1-TtCtBg3zBzMAxIRANz9y0cxkLXg=", "dev": true, "requires": { - "graceful-fs": "4.1.11", - "minimatch": "3.0.4", - "readable-stream": "2.3.4", - "set-immediate-shim": "1.0.1" + "graceful-fs": "^4.1.2", + "minimatch": "^3.0.2", + "readable-stream": "^2.0.2", + "set-immediate-shim": "^1.0.1" } }, "recast": { @@ -10657,9 +9121,9 @@ "dev": true, "requires": { "ast-types": "0.9.6", - "esprima": "3.1.3", - "private": "0.1.8", - "source-map": "0.5.7" + "esprima": "~3.1.0", + "private": "~0.1.5", + "source-map": "~0.5.0" }, "dependencies": { "esprima": { @@ -10676,8 +9140,8 @@ "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", "dev": true, "requires": { - "indent-string": "2.1.0", - "strip-indent": "1.0.1" + "indent-string": "^2.1.0", + "strip-indent": "^1.0.1" } }, "reduce-css-calc": { @@ -10686,9 +9150,9 @@ "integrity": "sha1-dHyRTgSWFKTJz7umKYca0dKSdxY=", "dev": true, "requires": { - "balanced-match": "0.4.2", - "math-expression-evaluator": "1.2.17", - "reduce-function-call": "1.0.2" + "balanced-match": "^0.4.2", + "math-expression-evaluator": "^1.2.14", + "reduce-function-call": "^1.0.1" }, "dependencies": { "balanced-match": { @@ -10705,7 +9169,7 @@ "integrity": "sha1-WiAL+S4ON3UXUv5FsKszD9S2vpk=", "dev": true, "requires": { - "balanced-match": "0.4.2" + "balanced-match": "^0.4.2" }, "dependencies": { "balanced-match": { @@ -10734,9 +9198,9 @@ "integrity": "sha1-HkmWg3Ix2ot/PPQRTXG1aRoGgN0=", "dev": true, "requires": { - "babel-runtime": "6.26.0", - "babel-types": "6.26.0", - "private": "0.1.8" + "babel-runtime": "^6.18.0", + "babel-types": "^6.19.0", + "private": "^0.1.6" } }, "regex-cache": { @@ -10745,7 +9209,7 @@ "integrity": "sha1-db3FiioUls7EihKDW8VMjVYjNt0=", "dev": true, "requires": { - "is-equal-shallow": "0.1.3" + "is-equal-shallow": "^0.1.3" } }, "regex-not": { @@ -10754,8 +9218,8 @@ "integrity": "sha1-H07OJ+ALC2XgJHpoEOaoXYOldSw=", "dev": true, "requires": { - "extend-shallow": "3.0.2", - "safe-regex": "1.1.0" + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" } }, "regex-parser": { @@ -10770,9 +9234,9 @@ "integrity": "sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA=", "dev": true, "requires": { - "regenerate": "1.3.3", - "regjsgen": "0.2.0", - "regjsparser": "0.1.5" + "regenerate": "^1.2.1", + "regjsgen": "^0.2.0", + "regjsparser": "^0.1.4" } }, "regjsgen": { @@ -10787,7 +9251,7 @@ "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", "dev": true, "requires": { - "jsesc": "0.5.0" + "jsesc": "~0.5.0" } }, "relateurl": { @@ -10803,9 +9267,9 @@ "dev": true }, "repeat-element": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", - "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", + "integrity": "sha1-eC4NglwMWjuzlzH4Tv7mt0Lmsc4=", "dev": true }, "repeat-string": { @@ -10820,43 +9284,40 @@ "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", "dev": true, "requires": { - "is-finite": "1.0.2" + "is-finite": "^1.0.0" } }, "replace-ext": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", - "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", - "dev": true + "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=" }, "request": { - "version": "2.81.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.81.0.tgz", - "integrity": "sha1-xpKJRqDgbF+Nb4qTM0af/aRimKA=", + "version": "2.87.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.87.0.tgz", + "integrity": "sha512-fcogkm7Az5bsS6Sl0sibkbhcKsnyon/jV1kF3ajGmF0c8HrttdKTPRT9hieOaQHA5HEq6r8OyWOo/o781C1tNw==", "dev": true, "requires": { - "aws-sign2": "0.6.0", - "aws4": "1.6.0", - "caseless": "0.12.0", - "combined-stream": "1.0.6", - "extend": "3.0.1", - "forever-agent": "0.6.1", - "form-data": "2.1.4", - "har-validator": "4.2.1", - "hawk": "3.1.3", - "http-signature": "1.1.1", - "is-typedarray": "1.0.0", - "isstream": "0.1.2", - "json-stringify-safe": "5.0.1", - "mime-types": "2.1.18", - "oauth-sign": "0.8.2", - "performance-now": "0.2.0", - "qs": "6.4.0", - "safe-buffer": "5.1.1", - "stringstream": "0.0.5", - "tough-cookie": "2.3.4", - "tunnel-agent": "0.6.0", - "uuid": "3.2.1" + "aws-sign2": "~0.7.0", + "aws4": "^1.6.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.5", + "extend": "~3.0.1", + "forever-agent": "~0.6.1", + "form-data": "~2.3.1", + "har-validator": "~5.0.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.17", + "oauth-sign": "~0.8.2", + "performance-now": "^2.1.0", + "qs": "~6.5.1", + "safe-buffer": "^5.1.1", + "tough-cookie": "~2.3.3", + "tunnel-agent": "^0.6.0", + "uuid": "^3.1.0" } }, "require-directory": { @@ -10887,9 +9348,8 @@ "version": "1.5.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz", "integrity": "sha512-hgoSGrc3pjzAPHNBg+KnFcK2HwlHTs/YrAGUr6qgTVUZmXv1UEXXl0bZNBKMA9fud6lRYFdPGz0xXxycPzmmiw==", - "dev": true, "requires": { - "path-parse": "1.0.5" + "path-parse": "^1.0.5" } }, "resolve-cwd": { @@ -10898,7 +9358,7 @@ "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", "dev": true, "requires": { - "resolve-from": "3.0.0" + "resolve-from": "^3.0.0" } }, "resolve-from": { @@ -10916,18 +9376,18 @@ "resolve-url-loader": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/resolve-url-loader/-/resolve-url-loader-2.3.0.tgz", - "integrity": "sha1-4bNwNNSPIvjPufBMAm+qoHD9ryY=", + "integrity": "sha512-RaEUWgF/B6aTg9VKaOv2o6dfm5f75/lGh8S+SQwoMcBm48WkA2nhLR+V7KEawkxXjU4lLB16IVeHCe7F69nyVw==", "dev": true, "requires": { - "adjust-sourcemap-loader": "1.2.0", - "camelcase": "4.1.0", - "convert-source-map": "1.5.1", - "loader-utils": "1.1.0", - "lodash.defaults": "4.2.0", - "rework": "1.0.1", - "rework-visit": "1.0.0", - "source-map": "0.5.7", - "urix": "0.1.0" + "adjust-sourcemap-loader": "^1.1.0", + "camelcase": "^4.1.0", + "convert-source-map": "^1.5.1", + "loader-utils": "^1.1.0", + "lodash.defaults": "^4.0.0", + "rework": "^1.0.1", + "rework-visit": "^1.0.0", + "source-map": "^0.5.7", + "urix": "^0.1.0" }, "dependencies": { "camelcase": { @@ -10943,7 +9403,7 @@ "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", "requires": { - "lowercase-keys": "1.0.0" + "lowercase-keys": "^1.0.0" } }, "ret": { @@ -10958,8 +9418,8 @@ "integrity": "sha1-MIBqhBNCtUUQqkEQhQzUhTQUSqc=", "dev": true, "requires": { - "convert-source-map": "0.3.5", - "css": "2.2.1" + "convert-source-map": "^0.3.3", + "css": "^2.0.0" }, "dependencies": { "convert-source-map": { @@ -10982,7 +9442,7 @@ "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", "dev": true, "requires": { - "align-text": "0.1.4" + "align-text": "^0.1.1" } }, "rimraf": { @@ -10991,17 +9451,16 @@ "integrity": "sha1-LtgVDSShbqhlHm1u8PR8QVjOejY=", "dev": true, "requires": { - "glob": "7.1.2" + "glob": "^7.0.5" } }, "ripemd160": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", "integrity": "sha1-ocGm9iR1FXe6XQeRTLyShQWFiQw=", - "dev": true, "requires": { - "hash-base": "3.0.4", - "inherits": "2.0.3" + "hash-base": "^3.0.0", + "inherits": "^2.0.1" } }, "run-queue": { @@ -11010,7 +9469,7 @@ "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=", "dev": true, "requires": { - "aproba": "1.2.0" + "aproba": "^1.1.1" } }, "safe-buffer": { @@ -11024,19 +9483,24 @@ "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", "dev": true, "requires": { - "ret": "0.1.15" + "ret": "~0.1.10" } }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha1-RPoWGwGHuVSd2Eu5GAL5vYOFzWo=" + }, "sass-graph": { "version": "2.2.4", "resolved": "https://registry.npmjs.org/sass-graph/-/sass-graph-2.2.4.tgz", "integrity": "sha1-E/vWPNHK8JCLn9k0dq1DpR0eC0k=", "dev": true, "requires": { - "glob": "7.1.2", - "lodash": "4.17.5", - "scss-tokenizer": "0.2.3", - "yargs": "7.1.0" + "glob": "^7.0.0", + "lodash": "^4.0.0", + "scss-tokenizer": "^0.2.3", + "yargs": "^7.0.0" }, "dependencies": { "camelcase": { @@ -11051,7 +9515,7 @@ "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", "dev": true, "requires": { - "number-is-nan": "1.0.1" + "number-is-nan": "^1.0.0" } }, "string-width": { @@ -11060,9 +9524,9 @@ "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "dev": true, "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "strip-ansi": "3.0.1" + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" } }, "yargs": { @@ -11071,19 +9535,19 @@ "integrity": "sha1-a6MY6xaWFyf10oT46gA+jWFU0Mg=", "dev": true, "requires": { - "camelcase": "3.0.0", - "cliui": "3.2.0", - "decamelize": "1.2.0", - "get-caller-file": "1.0.2", - "os-locale": "1.4.0", - "read-pkg-up": "1.0.1", - "require-directory": "2.1.1", - "require-main-filename": "1.0.1", - "set-blocking": "2.0.0", - "string-width": "1.0.2", - "which-module": "1.0.0", - "y18n": "3.2.1", - "yargs-parser": "5.0.0" + "camelcase": "^3.0.0", + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "os-locale": "^1.4.0", + "read-pkg-up": "^1.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^1.0.2", + "which-module": "^1.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^5.0.0" } } } @@ -11094,11 +9558,11 @@ "integrity": "sha1-3S/bPn7v9KU/NbpqxAhxVIg1PQA=", "dev": true, "requires": { - "clone-deep": "2.0.2", - "loader-utils": "1.1.0", - "lodash.tail": "4.1.1", - "neo-async": "2.5.1", - "pify": "3.0.0" + "clone-deep": "^2.0.1", + "loader-utils": "^1.0.1", + "lodash.tail": "^4.1.1", + "neo-async": "^2.5.0", + "pify": "^3.0.0" } }, "sax": { @@ -11113,7 +9577,7 @@ "integrity": "sha1-9YdyIs4+kx7a4DnxfrNxbnE3+M8=", "dev": true, "requires": { - "ajv": "5.5.2" + "ajv": "^5.0.0" }, "dependencies": { "ajv": { @@ -11122,10 +9586,10 @@ "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", "dev": true, "requires": { - "co": "4.6.0", - "fast-deep-equal": "1.1.0", - "fast-json-stable-stringify": "2.0.0", - "json-schema-traverse": "0.3.1" + "co": "^4.6.0", + "fast-deep-equal": "^1.0.0", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.3.0" } } } @@ -11136,8 +9600,8 @@ "integrity": "sha1-jrBtualyMzOCTT9VMGQRSYR85dE=", "dev": true, "requires": { - "js-base64": "2.4.3", - "source-map": "0.4.4" + "js-base64": "^2.1.8", + "source-map": "^0.4.2" }, "dependencies": { "source-map": { @@ -11146,27 +9610,7 @@ "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", "dev": true, "requires": { - "amdefine": "1.0.1" - } - } - } - }, - "seek-bzip": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/seek-bzip/-/seek-bzip-1.0.5.tgz", - "integrity": "sha1-z+kXyz0nS8/6x5J1ivUxc+sfq9w=", - "dev": true, - "requires": { - "commander": "2.8.1" - }, - "dependencies": { - "commander": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.8.1.tgz", - "integrity": "sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ=", - "dev": true, - "requires": { - "graceful-readlink": "1.0.1" + "amdefine": ">=0.0.4" } } } @@ -11182,40 +9626,25 @@ "resolved": "https://registry.npmjs.org/select2/-/select2-4.0.5.tgz", "integrity": "sha1-eqxQaSVhmFs007guxV4ib4lg1Ao=", "requires": { - "almond": "0.3.3", - "jquery-mousewheel": "3.1.13" + "almond": "~0.3.1", + "jquery-mousewheel": "~3.1.13" } }, "selfsigned": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.2.tgz", - "integrity": "sha1-tESVgNmZKbZbEKSDiTAaZZIIh1g=", + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.3.tgz", + "integrity": "sha1-1ijs+eNzX4TouvupNrPPhb6kOCM=", "dev": true, "requires": { - "node-forge": "0.7.1" + "node-forge": "0.7.5" } }, "semver": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", - "integrity": "sha1-3Eu8emyp2Rbe5dQ1FvAJK1j3uKs=", + "version": "5.5.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.1.tgz", + "integrity": "sha1-ff3YgUvbfKvHvg+x1zTPtmyUBHc=", "dev": true }, - "semver-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-1.0.0.tgz", - "integrity": "sha1-kqSWkGX5xwxpR1PVUkj8aPj2Usk=", - "dev": true - }, - "semver-truncate": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/semver-truncate/-/semver-truncate-1.1.2.tgz", - "integrity": "sha1-V/Qd5pcHpicJp+AQS6IRcQnqR+g=", - "dev": true, - "requires": { - "semver": "5.5.0" - } - }, "send": { "version": "0.16.2", "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", @@ -11223,18 +9652,18 @@ "dev": true, "requires": { "debug": "2.6.9", - "depd": "1.1.2", - "destroy": "1.0.4", - "encodeurl": "1.0.2", - "escape-html": "1.0.3", - "etag": "1.8.1", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", "fresh": "0.5.2", - "http-errors": "1.6.3", + "http-errors": "~1.6.2", "mime": "1.4.1", "ms": "2.0.0", - "on-finished": "2.3.0", - "range-parser": "1.2.0", - "statuses": "1.4.0" + "on-finished": "~2.3.0", + "range-parser": "~1.2.0", + "statuses": "~1.4.0" }, "dependencies": { "debug": { @@ -11249,7 +9678,7 @@ "mime": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", - "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==", + "integrity": "sha1-Eh+evEnjdm8xGnbh+hyAA8SwOqY=", "dev": true } } @@ -11266,13 +9695,13 @@ "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=", "dev": true, "requires": { - "accepts": "1.3.5", + "accepts": "~1.3.4", "batch": "0.6.1", "debug": "2.6.9", - "escape-html": "1.0.3", - "http-errors": "1.6.3", - "mime-types": "2.1.18", - "parseurl": "1.3.2" + "escape-html": "~1.0.3", + "http-errors": "~1.6.2", + "mime-types": "~2.1.17", + "parseurl": "~1.3.2" }, "dependencies": { "debug": { @@ -11292,9 +9721,9 @@ "integrity": "sha1-CV6Ecv1bRiN9tQzkhqQ/S4bGzsE=", "dev": true, "requires": { - "encodeurl": "1.0.2", - "escape-html": "1.0.3", - "parseurl": "1.3.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.2", "send": "0.16.2" } }, @@ -11316,10 +9745,10 @@ "integrity": "sha1-ca5KiPD+77v1LR6mBPP7MV67YnQ=", "dev": true, "requires": { - "extend-shallow": "2.0.1", - "is-extendable": "0.1.1", - "is-plain-object": "2.0.4", - "split-string": "3.1.0" + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" }, "dependencies": { "extend-shallow": { @@ -11328,7 +9757,7 @@ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-extendable": "0.1.1" + "is-extendable": "^0.1.0" } } } @@ -11349,10 +9778,9 @@ "version": "2.4.11", "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", "integrity": "sha1-N6XPC4HsvGlD3hCbopYNGyZYSuc=", - "dev": true, "requires": { - "inherits": "2.0.3", - "safe-buffer": "5.1.1" + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" } }, "shallow-clone": { @@ -11361,9 +9789,9 @@ "integrity": "sha1-RIDNBuiC72iyrYij6lSDLixItXE=", "dev": true, "requires": { - "is-extendable": "0.1.1", - "kind-of": "5.1.0", - "mixin-object": "2.0.1" + "is-extendable": "^0.1.1", + "kind-of": "^5.0.0", + "mixin-object": "^2.0.1" }, "dependencies": { "kind-of": { @@ -11374,13 +9802,22 @@ } } }, + "shasum": { + "version": "1.0.2", + "resolved": "http://registry.npmjs.org/shasum/-/shasum-1.0.2.tgz", + "integrity": "sha1-5wEjENj0F/TetXEhUOVni4euVl8=", + "requires": { + "json-stable-stringify": "~0.0.0", + "sha.js": "~2.4.4" + } + }, "shebang-command": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", "dev": true, "requires": { - "shebang-regex": "1.0.0" + "shebang-regex": "^1.0.0" } }, "shebang-regex": { @@ -11389,6 +9826,17 @@ "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", "dev": true }, + "shell-quote": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.6.1.tgz", + "integrity": "sha1-9HgZSczkAmlxJ0MOo7PFR29IF2c=", + "requires": { + "array-filter": "~0.0.0", + "array-map": "~0.0.0", + "array-reduce": "~0.0.0", + "jsonify": "~0.0.0" + } + }, "shellwords": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/shellwords/-/shellwords-0.1.1.tgz", @@ -11401,26 +9849,42 @@ "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", "dev": true }, + "simple-concat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.0.tgz", + "integrity": "sha1-c0TLuLbib7J9ZrL8hvn21Zl1IcY=" + }, "slash": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", "dev": true }, + "slimscroll": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/slimscroll/-/slimscroll-0.9.1.tgz", + "integrity": "sha1-9nXNxgHYCtog8WAE0ifRVv0Rh7I=", + "requires": { + "browserify": ">=3.46.0", + "classie": ">=0.0.1", + "domhelper": "~0.9.0", + "util-extend": "^1.0.1" + } + }, "snapdragon": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", "integrity": "sha1-ZJIufFZbDhQgS6GqfWlkJ40lGC0=", "dev": true, "requires": { - "base": "0.11.2", - "debug": "2.6.9", - "define-property": "0.2.5", - "extend-shallow": "2.0.1", - "map-cache": "0.2.2", - "source-map": "0.5.7", - "source-map-resolve": "0.5.1", - "use": "3.1.0" + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.0" }, "dependencies": { "debug": { @@ -11438,7 +9902,7 @@ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { - "is-descriptor": "0.1.6" + "is-descriptor": "^0.1.0" } }, "extend-shallow": { @@ -11447,7 +9911,7 @@ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-extendable": "0.1.1" + "is-extendable": "^0.1.0" } } } @@ -11458,9 +9922,9 @@ "integrity": "sha1-bBdfhv8UvbByRWPo88GwIaKGhTs=", "dev": true, "requires": { - "define-property": "1.0.0", - "isobject": "3.0.1", - "snapdragon-util": "3.0.1" + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" }, "dependencies": { "define-property": { @@ -11469,7 +9933,7 @@ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", "dev": true, "requires": { - "is-descriptor": "1.0.2" + "is-descriptor": "^1.0.0" } }, "is-accessor-descriptor": { @@ -11478,7 +9942,7 @@ "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=", "dev": true, "requires": { - "kind-of": "6.0.2" + "kind-of": "^6.0.0" } }, "is-data-descriptor": { @@ -11487,7 +9951,7 @@ "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=", "dev": true, "requires": { - "kind-of": "6.0.2" + "kind-of": "^6.0.0" } }, "is-descriptor": { @@ -11496,9 +9960,9 @@ "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=", "dev": true, "requires": { - "is-accessor-descriptor": "1.0.0", - "is-data-descriptor": "1.0.0", - "kind-of": "6.0.2" + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" } } } @@ -11509,7 +9973,7 @@ "integrity": "sha1-+VZHlIbyrNeXAGk/b3uAXkWrVuI=", "dev": true, "requires": { - "kind-of": "3.2.2" + "kind-of": "^3.2.0" }, "dependencies": { "kind-of": { @@ -11518,42 +9982,33 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "1.1.6" + "is-buffer": "^1.1.5" } } } }, - "sntp": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", - "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=", - "dev": true, - "requires": { - "hoek": "2.16.3" - } - }, "sockjs": { "version": "0.3.19", "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.19.tgz", "integrity": "sha1-2Xa76ACve9IK4IWY1YI5NQiZPA0=", "dev": true, "requires": { - "faye-websocket": "0.10.0", - "uuid": "3.2.1" + "faye-websocket": "^0.10.0", + "uuid": "^3.0.1" } }, "sockjs-client": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/sockjs-client/-/sockjs-client-1.1.4.tgz", - "integrity": "sha1-W6vjhrd15M8U51IJEUUmVAFsixI=", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/sockjs-client/-/sockjs-client-1.1.5.tgz", + "integrity": "sha1-G7fA9yIsQPQq3xT0RCy9Eml3GoM=", "dev": true, "requires": { - "debug": "2.6.9", + "debug": "^2.6.6", "eventsource": "0.1.6", - "faye-websocket": "0.11.1", - "inherits": "2.0.3", - "json3": "3.3.2", - "url-parse": "1.4.0" + "faye-websocket": "~0.11.0", + "inherits": "^2.0.1", + "json3": "^3.3.2", + "url-parse": "^1.1.8" }, "dependencies": { "debug": { @@ -11571,7 +10026,7 @@ "integrity": "sha1-8O/hjE9W5PQK/H4Gxxn9XuYYjzg=", "dev": true, "requires": { - "websocket-driver": "0.7.0" + "websocket-driver": ">=0.5.1" } } } @@ -11581,27 +10036,7 @@ "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-2.0.0.tgz", "integrity": "sha1-ZYU1WEhh7JfXMNbPQYIuH1ZoQSg=", "requires": { - "is-plain-obj": "1.1.0" - } - }, - "sort-keys-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/sort-keys-length/-/sort-keys-length-1.0.1.tgz", - "integrity": "sha1-nLb09OnkgVWmqgZx7dM2/xR5oYg=", - "dev": true, - "requires": { - "sort-keys": "1.1.2" - }, - "dependencies": { - "sort-keys": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz", - "integrity": "sha1-RBttTTRnmPG05J6JIK37oOVD+a0=", - "dev": true, - "requires": { - "is-plain-obj": "1.1.0" - } - } + "is-plain-obj": "^1.0.0" } }, "source-list-map": { @@ -11616,16 +10051,16 @@ "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" }, "source-map-resolve": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.1.tgz", - "integrity": "sha512-0KW2wvzfxm8NCTb30z0LMNyPqWCdDGE2viwzUaucqJdkTRXtZiSY3I+2A6nVAjmdOy0I4gU8DwnVVGsk9jvP2A==", + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", + "integrity": "sha1-cuLMNAlVQ+Q7LGKyxMENSpBU8lk=", "dev": true, "requires": { - "atob": "2.1.1", - "decode-uri-component": "0.2.0", - "resolve-url": "0.2.1", - "source-map-url": "0.4.0", - "urix": "0.1.0" + "atob": "^2.1.1", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" } }, "source-map-support": { @@ -11634,7 +10069,7 @@ "integrity": "sha1-Aoam3ovkJkEzhZTpfM6nXwosWF8=", "dev": true, "requires": { - "source-map": "0.5.7" + "source-map": "^0.5.6" } }, "source-map-url": { @@ -11643,26 +10078,20 @@ "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", "dev": true }, - "sparkles": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.0.tgz", - "integrity": "sha1-Gsu/tZJDbRC76PeFt8xvgoFQEsM=", - "dev": true - }, "spdx-correct": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.0.tgz", - "integrity": "sha1-BaW01xU6GVvJLDxCW2nzsqlSTII=", + "integrity": "sha512-N19o9z5cEyc8yQQPukRCZ9EUmb4HUpnrmaL/fxS2pBo2jbfcFRVuFZ/oFC+vZz0MNNk0h80iMn5/S6qGZOL5+g==", "dev": true, "requires": { - "spdx-expression-parse": "3.0.0", - "spdx-license-ids": "3.0.0" + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" } }, "spdx-exceptions": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz", - "integrity": "sha1-LHrmEFbHFKW5ubKyr30xHvXHj+k=", + "integrity": "sha512-4K1NsmrlCU1JJgUrtgEeTVyfx8VaYea9J9LvARxhbHtVtohPs/gFGG5yy49beySjlIMhhXZ4QqujIZEfS4l6Cg==", "dev": true }, "spdx-expression-parse": { @@ -11671,14 +10100,14 @@ "integrity": "sha1-meEZt6XaAOBUkcn6M4t5BII7QdA=", "dev": true, "requires": { - "spdx-exceptions": "2.1.0", - "spdx-license-ids": "3.0.0" + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" } }, "spdx-license-ids": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.0.tgz", - "integrity": "sha1-enzShHDMbToc/m1miG9rxDDTrIc=", + "integrity": "sha512-2+EPwgbnmOIl8HjGBXXMd9NAu02vLjOO1nWw4kmeRDFyHn+M/ETfHxQUK0oXg8ctgVnl9t3rosNVsZ1jG61nDA==", "dev": true }, "spdy": { @@ -11687,12 +10116,12 @@ "integrity": "sha1-Qv9B7OXMD5mjpsKKq7c/XDsDrLw=", "dev": true, "requires": { - "debug": "2.6.9", - "handle-thing": "1.2.5", - "http-deceiver": "1.2.7", - "safe-buffer": "5.1.1", - "select-hose": "2.0.0", - "spdy-transport": "2.1.0" + "debug": "^2.6.8", + "handle-thing": "^1.2.5", + "http-deceiver": "^1.2.7", + "safe-buffer": "^5.0.1", + "select-hose": "^2.0.0", + "spdy-transport": "^2.0.18" }, "dependencies": { "debug": { @@ -11712,13 +10141,13 @@ "integrity": "sha1-S7sVqv/tC+791WrWHb3Iuj4st6E=", "dev": true, "requires": { - "debug": "2.6.9", - "detect-node": "2.0.3", - "hpack.js": "2.1.6", - "obuf": "1.1.2", - "readable-stream": "2.3.4", - "safe-buffer": "5.1.1", - "wbuf": "1.7.3" + "debug": "^2.6.8", + "detect-node": "^2.0.3", + "hpack.js": "^2.1.6", + "obuf": "^1.1.1", + "readable-stream": "^2.2.9", + "safe-buffer": "^5.0.1", + "wbuf": "^1.7.2" }, "dependencies": { "debug": { @@ -11738,7 +10167,7 @@ "integrity": "sha1-fLCd2jqGWFcFxks5pkZgOGguj+I=", "dev": true, "requires": { - "extend-shallow": "3.0.2" + "extend-shallow": "^3.0.0" } }, "sprintf-js": { @@ -11747,37 +10176,28 @@ "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", "dev": true }, - "squeak": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/squeak/-/squeak-1.3.0.tgz", - "integrity": "sha1-MwRQN7ZDiLVnZ0uEMiplIQc5FsM=", - "dev": true, + "ssf": { + "version": "0.10.2", + "resolved": "https://registry.npmjs.org/ssf/-/ssf-0.10.2.tgz", + "integrity": "sha1-ZbK0/N/ZZ7yOg4OkE0kAmJMRWXY=", "requires": { - "chalk": "1.1.3", - "console-stream": "0.1.1", - "lpad-align": "1.1.2" + "frac": "~1.1.2" } }, "sshpk": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz", - "integrity": "sha1-US322mKHFEMW3EwY/hzx2UBzm+M=", + "version": "1.14.2", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.2.tgz", + "integrity": "sha1-xvxhZIo9nE52T9P8306hBeSSupg=", "requires": { - "asn1": "0.2.3", - "assert-plus": "1.0.0", - "bcrypt-pbkdf": "1.0.1", - "dashdash": "1.14.1", - "ecc-jsbn": "0.1.1", - "getpass": "0.1.7", - "jsbn": "0.1.1", - "tweetnacl": "0.14.5" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" - } + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" } }, "ssri": { @@ -11786,35 +10206,23 @@ "integrity": "sha1-ujhyycbTOgcEp9cf8EXl7EiZnQY=", "dev": true, "requires": { - "safe-buffer": "5.1.1" + "safe-buffer": "^5.1.1" } }, - "stable": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", - "integrity": "sha1-g26zyDgv4pNv6vVEYxAXzn1Ho88=", - "dev": true - }, "stackframe": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.0.4.tgz", "integrity": "sha1-NXskqZL5Qny6a1RdlqFO0svKGHs=", "dev": true }, - "stat-mode": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/stat-mode/-/stat-mode-0.2.2.tgz", - "integrity": "sha1-5sgLYjEj19gM8TLOU480YokHJQI=", - "dev": true - }, "static-extend": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", "dev": true, "requires": { - "define-property": "0.2.5", - "object-copy": "0.1.0" + "define-property": "^0.2.5", + "object-copy": "^0.1.0" }, "dependencies": { "define-property": { @@ -11823,7 +10231,7 @@ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { - "is-descriptor": "0.1.6" + "is-descriptor": "^0.1.0" } } } @@ -11835,55 +10243,76 @@ "dev": true }, "stdout-stream": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/stdout-stream/-/stdout-stream-1.4.0.tgz", - "integrity": "sha1-osfIWH5U2UJ+qe2zrD8s1SLfN4s=", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/stdout-stream/-/stdout-stream-1.4.1.tgz", + "integrity": "sha1-WsF0zdXNcmEEqgwLK9g4FdjVNd4=", "dev": true, "requires": { - "readable-stream": "2.3.4" + "readable-stream": "^2.0.1" } }, "stream-browserify": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz", "integrity": "sha1-ZiZu5fm9uZQKTkUUyvtDu3Hlyds=", - "dev": true, "requires": { - "inherits": "2.0.3", - "readable-stream": "2.3.4" + "inherits": "~2.0.1", + "readable-stream": "^2.0.2" } }, "stream-combiner2": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.1.1.tgz", "integrity": "sha1-+02KFCDqNidk4hrUeAOXvry0HL4=", - "dev": true, "requires": { - "duplexer2": "0.1.4", - "readable-stream": "2.3.4" + "duplexer2": "~0.1.0", + "readable-stream": "^2.0.2" } }, "stream-each": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.2.tgz", - "integrity": "sha1-joxGP5HaiZF3h2WHP+TZYNj2Fr0=", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz", + "integrity": "sha1-6+J6DDibBPvMIzZClS4Qcxr6m64=", "dev": true, "requires": { - "end-of-stream": "1.4.1", - "stream-shift": "1.0.0" + "end-of-stream": "^1.1.0", + "stream-shift": "^1.0.0" } }, "stream-http": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.1.tgz", - "integrity": "sha512-cQ0jo17BLca2r0GfRdZKYAGLU6JRoIWxqSOakUMuKOT6MOK7AAlE856L33QuDmAy/eeOrhLee3dZKX0Uadu93A==", - "dev": true, + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz", + "integrity": "sha1-stJCRpKIpaJ+xP6JM6z2I95lFPw=", "requires": { - "builtin-status-codes": "3.0.0", - "inherits": "2.0.3", - "readable-stream": "2.3.4", - "to-arraybuffer": "1.0.1", - "xtend": "4.0.1" + "builtin-status-codes": "^3.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.3.6", + "to-arraybuffer": "^1.0.0", + "xtend": "^4.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + } } }, "stream-shift": { @@ -11892,6 +10321,15 @@ "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=", "dev": true }, + "stream-splicer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/stream-splicer/-/stream-splicer-2.0.0.tgz", + "integrity": "sha1-G2O+Q4oTPktnHMGTUZdgAXWRDYM=", + "requires": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.2" + } + }, "strict-uri-encode": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", @@ -11903,8 +10341,8 @@ "integrity": "sha1-q5Pyeo3BPSjKyBXEYhQ6bZASrp4=", "dev": true, "requires": { - "is-fullwidth-code-point": "2.0.0", - "strip-ansi": "4.0.0" + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" }, "dependencies": { "ansi-regex": { @@ -11919,7 +10357,7 @@ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", "dev": true, "requires": { - "ansi-regex": "3.0.0" + "ansi-regex": "^3.0.0" } } } @@ -11929,13 +10367,14 @@ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", "requires": { - "safe-buffer": "5.1.1" + "safe-buffer": "~5.1.0" } }, "stringstream": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", - "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=" + "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=", + "optional": true }, "strip-ansi": { "version": "3.0.1", @@ -11943,7 +10382,7 @@ "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, "requires": { - "ansi-regex": "2.1.1" + "ansi-regex": "^2.0.0" } }, "strip-bom": { @@ -11952,39 +10391,7 @@ "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", "dev": true, "requires": { - "is-utf8": "0.2.1" - } - }, - "strip-bom-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-bom-stream/-/strip-bom-stream-1.0.0.tgz", - "integrity": "sha1-5xRDmFd9Uaa+0PoZlPoF9D/ZiO4=", - "dev": true, - "requires": { - "first-chunk-stream": "1.0.0", - "strip-bom": "2.0.0" - } - }, - "strip-dirs": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/strip-dirs/-/strip-dirs-1.1.1.tgz", - "integrity": "sha1-lgu9EoeETzl1pFWKoQOoJV4kVqA=", - "dev": true, - "requires": { - "chalk": "1.1.3", - "get-stdin": "4.0.1", - "is-absolute": "0.1.7", - "is-natural-number": "2.1.1", - "minimist": "1.2.0", - "sum-up": "1.0.3" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - } + "is-utf8": "^0.2.0" } }, "strip-eof": { @@ -11999,22 +10406,7 @@ "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", "dev": true, "requires": { - "get-stdin": "4.0.1" - } - }, - "strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", - "dev": true - }, - "strip-outer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.1.tgz", - "integrity": "sha1-sv0qv2YEudHmATBXGV34Nrip1jE=", - "dev": true, - "requires": { - "escape-string-regexp": "1.0.5" + "get-stdin": "^4.0.1" } }, "style-loader": { @@ -12023,17 +10415,23 @@ "integrity": "sha1-zDFFmvvNbYC3Ig7lSykan9Zv9es=", "dev": true, "requires": { - "loader-utils": "1.1.0", - "schema-utils": "0.3.0" + "loader-utils": "^1.0.2", + "schema-utils": "^0.3.0" } }, - "sum-up": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sum-up/-/sum-up-1.0.3.tgz", - "integrity": "sha1-HGYfZnBX9jvLeHWqFDi8FiUlFW4=", - "dev": true, + "subarg": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/subarg/-/subarg-1.0.0.tgz", + "integrity": "sha1-9izxdYHplrSPyWVpn1TAauJouNI=", "requires": { - "chalk": "1.1.3" + "minimist": "^1.1.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + } } }, "supports-color": { @@ -12048,13 +10446,72 @@ "integrity": "sha1-n1dyQTlSE1xv779Ar+ak+qiLS7U=", "dev": true, "requires": { - "coa": "1.0.4", - "colors": "1.1.2", - "csso": "2.3.2", - "js-yaml": "3.7.0", - "mkdirp": "0.5.1", - "sax": "1.2.4", - "whet.extend": "0.9.9" + "coa": "~1.0.1", + "colors": "~1.1.2", + "csso": "~2.3.1", + "js-yaml": "~3.7.0", + "mkdirp": "~0.5.1", + "sax": "~1.2.1", + "whet.extend": "~0.9.9" + } + }, + "syntax-error": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/syntax-error/-/syntax-error-1.4.0.tgz", + "integrity": "sha1-LZ1P9cBkrLcRWUo+O5UFStUdkHw=", + "requires": { + "acorn-node": "^1.2.0" + } + }, + "tableexport.jquery.plugin": { + "version": "1.9.15", + "resolved": "https://registry.npmjs.org/tableexport.jquery.plugin/-/tableexport.jquery.plugin-1.9.15.tgz", + "integrity": "sha512-qBErGTf0x6YRkl+Jf5fSXdQI1oEKGYNthFEl9wy2KkfxWseJ0CEg5C5rtCOEGdqXNeWosUVMnXznpO6hutudlA==", + "requires": { + "file-saver": ">=1.2.0", + "html2canvas": ">=0.5.0-beta4", + "jquery": ">=1.9.1", + "jspdf": "1.3.2 - 1.3.4", + "jspdf-autotable": "2.0.14 || 2.0.17", + "xlsx": ">=0.12.5" + }, + "dependencies": { + "adler32cs": { + "version": "github:chick307/adler32cs.js#7fd00ffa24bf173a1eeb987ce7a21ae214eff658", + "from": "github:chick307/adler32cs.js#7fd00ffa24bf173a1eeb987ce7a21ae214eff658" + }, + "filesaver.js": { + "version": "github:andyinabox/FileSaver.js#973b433b8fbaee9a11d53b9ae423b046742cfe32", + "from": "github:andyinabox/FileSaver.js#973b433b8fbaee9a11d53b9ae423b046742cfe32" + }, + "jspdf": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/jspdf/-/jspdf-1.3.4.tgz", + "integrity": "sha1-j0uu3Rj1wkYPAQdijHiYxgarKW8=", + "requires": { + "adler32cs": "github:chick307/adler32cs.js#7fd00ffa24bf173a1eeb987ce7a21ae214eff658", + "cf-blob.js": "0.0.1", + "filesaver.js": "github:andyinabox/FileSaver.js#973b433b8fbaee9a11d53b9ae423b046742cfe32" + }, + "dependencies": { + "adler32cs": { + "version": "github:chick307/adler32cs.js#7fd00ffa24bf173a1eeb987ce7a21ae214eff658", + "from": "github:chick307/adler32cs.js" + }, + "filesaver.js": { + "version": "github:andyinabox/FileSaver.js#973b433b8fbaee9a11d53b9ae423b046742cfe32", + "from": "github:andyinabox/FileSaver.js" + } + } + }, + "jspdf-autotable": { + "version": "2.0.17", + "resolved": "https://registry.npmjs.org/jspdf-autotable/-/jspdf-autotable-2.0.17.tgz", + "integrity": "sha1-usPRFK4S1E4NeXVjTROZ+GZxbHc=", + "requires": { + "jspdf": "^1.0.272" + } + } } }, "tapable": { @@ -12069,40 +10526,9 @@ "integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=", "dev": true, "requires": { - "block-stream": "0.0.9", - "fstream": "1.0.11", - "inherits": "2.0.3" - } - }, - "tar-stream": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.0.tgz", - "integrity": "sha512-lh2iAPG/BHNmN6WB9Ybdynk9rEJ5GD/dy4zscHmVlwa1dq2tpE+BH78i5vjYwYVWEaOXGBjzxr89aVACF17Cpw==", - "dev": true, - "requires": { - "bl": "1.2.2", - "buffer-alloc": "1.1.0", - "end-of-stream": "1.4.1", - "fs-constants": "1.0.0", - "readable-stream": "2.3.4", - "to-buffer": "1.1.1", - "xtend": "4.0.1" - } - }, - "temp-dir": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-1.0.0.tgz", - "integrity": "sha1-CnwOom06Oa+n4OvqnB/AvE2qAR0=", - "dev": true - }, - "tempfile": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/tempfile/-/tempfile-2.0.0.tgz", - "integrity": "sha1-awRGhWqbERTRhW/8vlCczLCXcmU=", - "dev": true, - "requires": { - "temp-dir": "1.0.0", - "uuid": "3.2.1" + "block-stream": "*", + "fstream": "^1.0.2", + "inherits": "2" } }, "tether": { @@ -12113,65 +10539,15 @@ "through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", - "dev": true + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" }, "through2": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", - "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", - "dev": true, + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", "requires": { - "readable-stream": "1.0.34", - "xtend": "4.0.1" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - } - } - }, - "through2-filter": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-2.0.0.tgz", - "integrity": "sha1-YLxVoNrLdghdsfna6Zq0P4PWIuw=", - "dev": true, - "requires": { - "through2": "2.0.3", - "xtend": "4.0.1" - }, - "dependencies": { - "through2": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", - "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", - "dev": true, - "requires": { - "readable-stream": "2.3.4", - "xtend": "4.0.1" - } - } + "readable-stream": "^2.1.5", + "xtend": "~4.0.1" } }, "thunky": { @@ -12181,9 +10557,9 @@ "dev": true }, "time-stamp": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", - "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-2.1.0.tgz", + "integrity": "sha1-bFwLK8g1okRharz934HOE6GXXJ8=", "dev": true }, "timed-out": { @@ -12194,43 +10570,16 @@ "timers-browserify": { "version": "2.0.10", "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.10.tgz", - "integrity": "sha1-HSjj0qrfHVpZlsTp+VYBzQU0gK4=", + "integrity": "sha512-YvC1SV1XdOUaL6gx5CoGroT3Gu49pK9+TZ38ErPldOWW4j49GI1HKs9DV+KGq/w6y+LZ72W1c8cKz2vzY+qpzg==", "dev": true, "requires": { - "setimmediate": "1.0.5" - } - }, - "to-absolute-glob": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-0.1.1.tgz", - "integrity": "sha1-HN+kcqnvUMI57maZm2YsoOs5k38=", - "dev": true, - "requires": { - "extend-shallow": "2.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "0.1.1" - } - } + "setimmediate": "^1.0.4" } }, "to-arraybuffer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", - "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=", - "dev": true - }, - "to-buffer": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz", - "integrity": "sha1-STvUj2LXxD/N7TE6A9ytsuEhOoA=", - "dev": true + "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=" }, "to-fast-properties": { "version": "1.0.3", @@ -12244,7 +10593,7 @@ "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", "dev": true, "requires": { - "kind-of": "3.2.2" + "kind-of": "^3.0.2" }, "dependencies": { "kind-of": { @@ -12253,7 +10602,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "1.1.6" + "is-buffer": "^1.1.5" } } } @@ -12264,10 +10613,10 @@ "integrity": "sha1-E8/dmzNlUvMLUfM6iuG0Knp1mc4=", "dev": true, "requires": { - "define-property": "2.0.2", - "extend-shallow": "3.0.2", - "regex-not": "1.0.2", - "safe-regex": "1.1.0" + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" } }, "to-regex-range": { @@ -12276,8 +10625,8 @@ "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", "dev": true, "requires": { - "is-number": "3.0.0", - "repeat-string": "1.6.1" + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" } }, "tough-cookie": { @@ -12285,7 +10634,7 @@ "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz", "integrity": "sha1-7GDO44rGdQY//JelwYlwV47oNlU=", "requires": { - "punycode": "1.4.1" + "punycode": "^1.4.1" } }, "trim-newlines": { @@ -12294,15 +10643,6 @@ "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", "dev": true }, - "trim-repeated": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz", - "integrity": "sha1-42RqLqTokTEr9+rObPsFOAvAHCE=", - "dev": true, - "requires": { - "escape-string-regexp": "1.0.5" - } - }, "trim-right": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", @@ -12310,27 +10650,12 @@ "dev": true }, "true-case-path": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/true-case-path/-/true-case-path-1.0.2.tgz", - "integrity": "sha1-fskRMJJHZsf1c74wIMNPj9/QDWI=", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/true-case-path/-/true-case-path-1.0.3.tgz", + "integrity": "sha1-+BO1qMhrQNpZYGcisUTjIleZ9H0=", "dev": true, "requires": { - "glob": "6.0.4" - }, - "dependencies": { - "glob": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/glob/-/glob-6.0.4.tgz", - "integrity": "sha1-DwiGD2oVUSey+t1PnOJLGqtuTSI=", - "dev": true, - "requires": { - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" - } - } + "glob": "^7.1.2" } }, "tty-browserify": { @@ -12344,7 +10669,7 @@ "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", "requires": { - "safe-buffer": "5.1.1" + "safe-buffer": "^5.0.1" } }, "tweetnacl": { @@ -12360,14 +10685,13 @@ "dev": true, "requires": { "media-typer": "0.3.0", - "mime-types": "2.1.18" + "mime-types": "~2.1.18" } }, "typedarray": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", - "dev": true + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" }, "uglify-js": { "version": "2.8.29", @@ -12375,9 +10699,9 @@ "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", "dev": true, "requires": { - "source-map": "0.5.7", - "uglify-to-browserify": "1.0.2", - "yargs": "3.10.0" + "source-map": "~0.5.1", + "uglify-to-browserify": "~1.0.0", + "yargs": "~3.10.0" }, "dependencies": { "camelcase": { @@ -12392,8 +10716,8 @@ "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", "dev": true, "requires": { - "center-align": "0.1.3", - "right-align": "0.1.3", + "center-align": "^0.1.1", + "right-align": "^0.1.1", "wordwrap": "0.0.2" } }, @@ -12403,9 +10727,9 @@ "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", "dev": true, "requires": { - "camelcase": "1.2.1", - "cliui": "2.1.0", - "decamelize": "1.2.0", + "camelcase": "^1.0.2", + "cliui": "^2.1.0", + "decamelize": "^1.0.0", "window-size": "0.1.0" } } @@ -12419,75 +10743,69 @@ "optional": true }, "uglifyjs-webpack-plugin": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-1.2.5.tgz", - "integrity": "sha512-hIQJ1yxAPhEA2yW/i7Fr+SXZVMp+VEI3d42RTHBgQd2yhp/1UdBcR3QEWPV5ahBxlqQDMEMTuTEvDHSFINfwSw==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-1.3.0.tgz", + "integrity": "sha1-dfVIFghYFjoIZD4IbV/v4YpdZ94=", "dev": true, "requires": { - "cacache": "10.0.4", - "find-cache-dir": "1.0.0", - "schema-utils": "0.4.5", - "serialize-javascript": "1.5.0", - "source-map": "0.6.1", - "uglify-es": "3.3.9", - "webpack-sources": "1.1.0", - "worker-farm": "1.6.0" + "cacache": "^10.0.4", + "find-cache-dir": "^1.0.0", + "schema-utils": "^0.4.5", + "serialize-javascript": "^1.4.0", + "source-map": "^0.6.1", + "uglify-es": "^3.3.4", + "webpack-sources": "^1.1.0", + "worker-farm": "^1.5.2" }, "dependencies": { - "ajv": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.4.0.tgz", - "integrity": "sha1-06/3jpJ3VJdx2vAWTP9ISCt1T8Y=", - "dev": true, - "requires": { - "fast-deep-equal": "1.1.0", - "fast-json-stable-stringify": "2.0.0", - "json-schema-traverse": "0.3.1", - "uri-js": "3.0.2" - } - }, "commander": { "version": "2.13.0", "resolved": "https://registry.npmjs.org/commander/-/commander-2.13.0.tgz", - "integrity": "sha512-MVuS359B+YzaWqjCL/c+22gfryv+mCBPHAv3zyVI2GN8EY6IRP8VwtasXn8jyyhvvq84R4ImN1OKRtcbIasjYA==", + "integrity": "sha1-aWS8pnaF33wfFDDFhPB9dZeIW5w=", "dev": true }, "schema-utils": { - "version": "0.4.5", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.4.5.tgz", - "integrity": "sha512-yYrjb9TX2k/J1Y5UNy3KYdZq10xhYcF8nMpAW6o3hy6Q8WSIEf9lJHG/ePnOBfziPM3fvQwfOwa13U/Fh8qTfA==", + "version": "0.4.7", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.4.7.tgz", + "integrity": "sha1-unT1l9K+LqiAExdG7hfQoJPGgYc=", "dev": true, "requires": { - "ajv": "6.4.0", - "ajv-keywords": "3.2.0" + "ajv": "^6.1.0", + "ajv-keywords": "^3.1.0" } }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", "dev": true }, "uglify-es": { "version": "3.3.9", "resolved": "https://registry.npmjs.org/uglify-es/-/uglify-es-3.3.9.tgz", - "integrity": "sha512-r+MU0rfv4L/0eeW3xZrd16t4NZfK8Ld4SWVglYBb7ez5uXFWHuVRs6xCTrf1yirs9a4j4Y27nn7SRfO6v67XsQ==", + "integrity": "sha1-DBxPBwC+2NvBJM2zBNJZLKID5nc=", "dev": true, "requires": { - "commander": "2.13.0", - "source-map": "0.6.1" + "commander": "~2.13.0", + "source-map": "~0.6.1" } } } }, - "unbzip2-stream": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.2.5.tgz", - "integrity": "sha1-c6AzpWe7veWWVLGTxE1Ip+T0PEc=", - "dev": true, + "umd": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/umd/-/umd-3.0.3.tgz", + "integrity": "sha1-qp/mU8QrkJdnhInAEACstp8LJs8=" + }, + "undeclared-identifiers": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/undeclared-identifiers/-/undeclared-identifiers-1.1.2.tgz", + "integrity": "sha1-fYUKmIh8/0vQv2SZnAFNCO1tGsw=", "requires": { - "buffer": "3.6.0", - "through": "2.3.8" + "acorn-node": "^1.3.0", + "get-assigned-identifiers": "^1.2.0", + "simple-concat": "^1.0.0", + "xtend": "^4.0.1" } }, "union-value": { @@ -12496,10 +10814,10 @@ "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", "dev": true, "requires": { - "arr-union": "3.1.0", - "get-value": "2.0.6", - "is-extendable": "0.1.1", - "set-value": "0.4.3" + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^0.4.3" }, "dependencies": { "extend-shallow": { @@ -12508,7 +10826,7 @@ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-extendable": "0.1.1" + "is-extendable": "^0.1.0" } }, "set-value": { @@ -12517,10 +10835,10 @@ "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", "dev": true, "requires": { - "extend-shallow": "2.0.1", - "is-extendable": "0.1.1", - "is-plain-object": "2.0.4", - "to-object-path": "0.3.0" + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.1", + "to-object-path": "^0.3.0" } } } @@ -12531,15 +10849,6 @@ "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=", "dev": true }, - "uniqid": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/uniqid/-/uniqid-4.1.1.tgz", - "integrity": "sha1-iSIN32t1GuUrX3JISGNShZa7hME=", - "dev": true, - "requires": { - "macaddress": "0.2.8" - } - }, "uniqs": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/uniqs/-/uniqs-2.0.0.tgz", @@ -12552,7 +10861,7 @@ "integrity": "sha1-0F8v5AMlYIcfMOk8vnNe6iAVFPM=", "dev": true, "requires": { - "unique-slug": "2.0.0" + "unique-slug": "^2.0.0" } }, "unique-slug": { @@ -12561,23 +10870,13 @@ "integrity": "sha1-22Z258fMBimHj/GWCXx4hVrp9Ks=", "dev": true, "requires": { - "imurmurhash": "0.1.4" - } - }, - "unique-stream": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.2.1.tgz", - "integrity": "sha1-WqADz76Uxf+GbE59ZouxxNuts2k=", - "dev": true, - "requires": { - "json-stable-stringify": "1.0.1", - "through2-filter": "2.0.0" + "imurmurhash": "^0.1.4" } }, "universalify": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.1.tgz", - "integrity": "sha1-+nG63UQ3r0wUiEHjs7Fl+enlkLc=", + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha1-tkb2m+OULavOzJ1mOcgNwQXvqmY=", "dev": true }, "unpipe": { @@ -12586,20 +10885,14 @@ "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", "dev": true }, - "unquote": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/unquote/-/unquote-1.1.1.tgz", - "integrity": "sha1-j97XMk7G6IoP+LkF58CYzcCG1UQ=", - "dev": true - }, "unset-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", "dev": true, "requires": { - "has-value": "0.3.1", - "isobject": "3.0.1" + "has-value": "^0.3.1", + "isobject": "^3.0.0" }, "dependencies": { "has-value": { @@ -12608,9 +10901,9 @@ "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", "dev": true, "requires": { - "get-value": "2.0.6", - "has-values": "0.1.4", - "isobject": "2.1.0" + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" }, "dependencies": { "isobject": { @@ -12632,16 +10925,10 @@ } } }, - "unzip-response": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/unzip-response/-/unzip-response-1.0.2.tgz", - "integrity": "sha1-uYTwh3/AqJwsdzzB73tbIytbBv4=", - "dev": true - }, "upath": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/upath/-/upath-1.0.5.tgz", - "integrity": "sha512-qbKn90aDQ0YEwvXoLqj0oiuUYroLX2lVHZ+b+xwjozFasAOC4GneDq5+OaIG5Zj+jFmbz/uO+f7a9qxjktJQww==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.1.0.tgz", + "integrity": "sha1-NSVll+RqWB20eT0M5H+prr/J+r0=", "dev": true }, "upper-case": { @@ -12650,23 +10937,6 @@ "integrity": "sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg=", "dev": true }, - "uri-js": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-3.0.2.tgz", - "integrity": "sha1-+QuFhQf4HepNz7s8TD2/orVX+qo=", - "dev": true, - "requires": { - "punycode": "2.1.0" - }, - "dependencies": { - "punycode": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.0.tgz", - "integrity": "sha1-X4Y+3Im5bbCQdLrXlHvwkFbKTn0=", - "dev": true - } - } - }, "urix": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", @@ -12677,7 +10947,6 @@ "version": "0.11.0", "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", - "dev": true, "requires": { "punycode": "1.3.2", "querystring": "0.2.0" @@ -12686,27 +10955,18 @@ "punycode": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", - "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", - "dev": true + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=" } } }, "url-parse": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.0.tgz", - "integrity": "sha512-ERuGxDiQ6Xw/agN4tuoCRbmwRuZP0cJ1lJxJubXr5Q/5cDa78+Dc4wfvtxzhzhkm5VvmW6Mf8EVj9SPGN4l8Lg==", + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.3.tgz", + "integrity": "sha1-v67kVciJAjIZ11fgRfpqaE7DbBU=", "dev": true, "requires": { - "querystringify": "2.0.0", - "requires-port": "1.0.0" - }, - "dependencies": { - "querystringify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.0.0.tgz", - "integrity": "sha512-eTPo5t/4bgaMNZxyjWx6N2a6AuE0mq51KWvpc7nU/MAqixcI6v6KrGUKES0HaomdnolQBBXU/++X6/QQ9KL4tw==", - "dev": true - } + "querystringify": "^2.0.0", + "requires-port": "^1.0.0" } }, "url-parse-lax": { @@ -12714,16 +10974,7 @@ "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", "requires": { - "prepend-http": "2.0.0" - } - }, - "url-regex": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/url-regex/-/url-regex-3.2.0.tgz", - "integrity": "sha1-260eDJ4p4QXdCx8J9oYvf9tIJyQ=", - "dev": true, - "requires": { - "ip-regex": "1.0.3" + "prepend-http": "^2.0.0" } }, "url-to-options": { @@ -12732,19 +10983,15 @@ "integrity": "sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k=" }, "use": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/use/-/use-3.1.0.tgz", - "integrity": "sha512-6UJEQM/L+mzC3ZJNM56Q4DFGLX/evKGRg15UJHGB9X5j5Z3AFbgZvjUh2yq/UJUY4U5dh7Fal++XbNg1uzpRAw==", - "dev": true, - "requires": { - "kind-of": "6.0.2" - } + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", + "integrity": "sha1-1QyMrHmhn7wg8pEfVuuXP04QBw8=", + "dev": true }, "util": { "version": "0.10.3", "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", - "dev": true, "requires": { "inherits": "2.0.1" }, @@ -12752,8 +10999,7 @@ "inherits": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", - "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", - "dev": true + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=" } } }, @@ -12762,15 +11008,10 @@ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, - "util.promisify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.0.tgz", - "integrity": "sha1-RA9xZaRZyaFtwUXrjnLzVocJcDA=", - "dev": true, - "requires": { - "define-properties": "1.1.2", - "object.getownpropertydescriptors": "2.0.3" - } + "util-extend": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/util-extend/-/util-extend-1.0.3.tgz", + "integrity": "sha1-p8IW0mdUUWljeztu3GypEZ4v+T8=" }, "utils-merge": { "version": "1.0.1", @@ -12783,20 +11024,14 @@ "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz", "integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==" }, - "vali-date": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/vali-date/-/vali-date-1.0.0.tgz", - "integrity": "sha1-G5BKWWCfsyjvB4E4Qgk09rhnCaY=", - "dev": true - }, "validate-npm-package-license": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.3.tgz", - "integrity": "sha1-gWQ7y+8b3+zUYjeT3EZIlIupgzg=", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha1-/JH2uce6FchX9MssXe/uw51PQQo=", "dev": true, "requires": { - "spdx-correct": "3.0.0", - "spdx-expression-parse": "3.0.0" + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" } }, "vary": { @@ -12816,9 +11051,9 @@ "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", "requires": { - "assert-plus": "1.0.0", + "assert-plus": "^1.0.0", "core-util-is": "1.0.2", - "extsprintf": "1.3.0" + "extsprintf": "^1.2.0" }, "dependencies": { "assert-plus": { @@ -12828,78 +11063,6 @@ } } }, - "vinyl": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", - "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", - "dev": true, - "requires": { - "clone": "1.0.4", - "clone-stats": "0.0.1", - "replace-ext": "0.0.1" - }, - "dependencies": { - "clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", - "dev": true - }, - "replace-ext": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", - "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", - "dev": true - } - } - }, - "vinyl-assign": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/vinyl-assign/-/vinyl-assign-1.2.1.tgz", - "integrity": "sha1-TRmIkbVRWRHXcajNnFSApGoHSkU=", - "dev": true, - "requires": { - "object-assign": "4.1.1", - "readable-stream": "2.3.4" - } - }, - "vinyl-fs": { - "version": "2.4.4", - "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-2.4.4.tgz", - "integrity": "sha1-vm/zJwy1Xf19MGNkDegfJddTIjk=", - "dev": true, - "requires": { - "duplexify": "3.5.4", - "glob-stream": "5.3.5", - "graceful-fs": "4.1.11", - "gulp-sourcemaps": "1.6.0", - "is-valid-glob": "0.3.0", - "lazystream": "1.0.0", - "lodash.isequal": "4.5.0", - "merge-stream": "1.0.1", - "mkdirp": "0.5.1", - "object-assign": "4.1.1", - "readable-stream": "2.3.4", - "strip-bom": "2.0.0", - "strip-bom-stream": "1.0.0", - "through2": "2.0.3", - "through2-filter": "2.0.0", - "vali-date": "1.0.0", - "vinyl": "1.2.0" - }, - "dependencies": { - "through2": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", - "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", - "dev": true, - "requires": { - "readable-stream": "2.3.4", - "xtend": "4.0.1" - } - } - } - }, "vm-browserify": { "version": "0.0.4", "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", @@ -12927,25 +11090,25 @@ "integrity": "sha512-v6PbKMGl/hWHGPxB2uGHsA66vusrXF66J/h1QiFXtU6z5zVSK8jq5xl95M1p3QNXmuEJKNP3nxoXfbgQNs7hJg==", "dev": true, "requires": { - "consolidate": "0.14.5", - "hash-sum": "1.0.2", - "loader-utils": "1.1.0", - "lru-cache": "4.1.1", - "postcss": "6.0.19", - "postcss-load-config": "1.2.0", - "postcss-selector-parser": "2.2.3", - "prettier": "1.11.1", - "resolve": "1.5.0", - "source-map": "0.6.1", - "vue-hot-reload-api": "2.3.0", - "vue-style-loader": "3.1.2", - "vue-template-es2015-compiler": "1.6.0" + "consolidate": "^0.14.0", + "hash-sum": "^1.0.2", + "loader-utils": "^1.1.0", + "lru-cache": "^4.1.1", + "postcss": "^6.0.8", + "postcss-load-config": "^1.1.0", + "postcss-selector-parser": "^2.0.0", + "prettier": "^1.7.0", + "resolve": "^1.4.0", + "source-map": "^0.6.1", + "vue-hot-reload-api": "^2.2.0", + "vue-style-loader": "^3.0.0", + "vue-template-es2015-compiler": "^1.6.0" }, "dependencies": { "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", "dev": true } } @@ -12955,7 +11118,7 @@ "resolved": "https://registry.npmjs.org/vue-resource/-/vue-resource-1.5.0.tgz", "integrity": "sha512-em+Ihe+duUWQv4uKO8aFTGK+e/lvNtk5EBEmWaBYcfQzBmHhKR4jJAeVIHcG6otugmsme/DmYrOEPfbss+2XfQ==", "requires": { - "got": "8.3.0" + "got": "^8.0.3" } }, "vue-style-loader": { @@ -12964,8 +11127,8 @@ "integrity": "sha1-a2atNJmPyVIMLx5NX6QJFkHBWXo=", "dev": true, "requires": { - "hash-sum": "1.0.2", - "loader-utils": "1.1.0" + "hash-sum": "^1.0.2", + "loader-utils": "^1.0.2" } }, "vue-template-compiler": { @@ -12974,8 +11137,8 @@ "integrity": "sha1-LN47cEEkmFwn1QtTh8lpG6UV+1c=", "dev": true, "requires": { - "de-indent": "1.0.2", - "he": "1.1.1" + "de-indent": "^1.0.2", + "he": "^1.1.0" } }, "vue-template-es2015-compiler": { @@ -12984,24 +11147,15 @@ "integrity": "sha1-3EJpcTMwLOMBdSQ1amxht7abShg=", "dev": true }, - "ware": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/ware/-/ware-1.3.0.tgz", - "integrity": "sha1-0bFPOdLiy0q4xAmPdW/ksWTkc9Q=", - "dev": true, - "requires": { - "wrap-fn": "0.1.5" - } - }, "watchpack": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.0.tgz", "integrity": "sha1-S8EsLr6KonenHx0/FNaFx7RGzQA=", "dev": true, "requires": { - "chokidar": "2.0.3", - "graceful-fs": "4.1.11", - "neo-async": "2.5.1" + "chokidar": "^2.0.2", + "graceful-fs": "^4.1.2", + "neo-async": "^2.5.0" } }, "wbuf": { @@ -13010,64 +11164,57 @@ "integrity": "sha1-wdjRSTFtPqhShIiVy2oL/oh7h98=", "dev": true, "requires": { - "minimalistic-assert": "1.0.1" + "minimalistic-assert": "^1.0.0" } }, "webpack": { - "version": "3.11.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-3.11.0.tgz", - "integrity": "sha512-3kOFejWqj5ISpJk4Qj/V7w98h9Vl52wak3CLiw/cDOfbVTq7FeoZ0SdoHHY9PYlHr50ZS42OfvzE2vB4nncKQg==", + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-3.12.0.tgz", + "integrity": "sha1-P540NgNwYC/PY56Xk520hvTsDXQ=", "dev": true, "requires": { - "acorn": "5.5.3", - "acorn-dynamic-import": "2.0.2", - "ajv": "6.4.0", - "ajv-keywords": "3.2.0", - "async": "2.6.0", - "enhanced-resolve": "3.4.1", - "escope": "3.6.0", - "interpret": "1.1.0", - "json-loader": "0.5.7", - "json5": "0.5.1", - "loader-runner": "2.3.0", - "loader-utils": "1.1.0", - "memory-fs": "0.4.1", - "mkdirp": "0.5.1", - "node-libs-browser": "2.1.0", - "source-map": "0.5.7", - "supports-color": "4.5.0", - "tapable": "0.2.8", - "uglifyjs-webpack-plugin": "0.4.6", - "watchpack": "1.6.0", - "webpack-sources": "1.1.0", - "yargs": "8.0.2" + "acorn": "^5.0.0", + "acorn-dynamic-import": "^2.0.0", + "ajv": "^6.1.0", + "ajv-keywords": "^3.1.0", + "async": "^2.1.2", + "enhanced-resolve": "^3.4.0", + "escope": "^3.6.0", + "interpret": "^1.0.0", + "json-loader": "^0.5.4", + "json5": "^0.5.1", + "loader-runner": "^2.3.0", + "loader-utils": "^1.1.0", + "memory-fs": "~0.4.1", + "mkdirp": "~0.5.0", + "node-libs-browser": "^2.0.0", + "source-map": "^0.5.3", + "supports-color": "^4.2.1", + "tapable": "^0.2.7", + "uglifyjs-webpack-plugin": "^0.4.6", + "watchpack": "^1.4.0", + "webpack-sources": "^1.0.1", + "yargs": "^8.0.2" }, "dependencies": { - "ajv": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.4.0.tgz", - "integrity": "sha1-06/3jpJ3VJdx2vAWTP9ISCt1T8Y=", - "dev": true, - "requires": { - "fast-deep-equal": "1.1.0", - "fast-json-stable-stringify": "2.0.0", - "json-schema-traverse": "0.3.1", - "uri-js": "3.0.2" - } - }, "has-flag": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", "dev": true }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, "supports-color": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", "dev": true, "requires": { - "has-flag": "2.0.0" + "has-flag": "^2.0.0" } }, "uglifyjs-webpack-plugin": { @@ -13076,9 +11223,9 @@ "integrity": "sha1-uVH0q7a9YX5m9j64kUmOORdj4wk=", "dev": true, "requires": { - "source-map": "0.5.7", - "uglify-js": "2.8.29", - "webpack-sources": "1.1.0" + "source-map": "^0.5.6", + "uglify-js": "^2.8.29", + "webpack-sources": "^1.0.1" } } } @@ -13095,52 +11242,44 @@ "integrity": "sha1-+PwRIM47T8VoDO7LQ9d3lmshEF4=", "dev": true, "requires": { - "memory-fs": "0.4.1", - "mime": "1.6.0", - "path-is-absolute": "1.0.1", - "range-parser": "1.2.0", - "time-stamp": "2.0.0" - }, - "dependencies": { - "time-stamp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-2.0.0.tgz", - "integrity": "sha1-lcakRTDhW6jW9KPsuMOj+sRto1c=", - "dev": true - } + "memory-fs": "~0.4.1", + "mime": "^1.5.0", + "path-is-absolute": "^1.0.0", + "range-parser": "^1.0.3", + "time-stamp": "^2.0.0" } }, "webpack-dev-server": { - "version": "2.11.2", - "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-2.11.2.tgz", - "integrity": "sha1-H09MeL8YlTePN2gVkQgS2veaIW8=", + "version": "2.11.3", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-2.11.3.tgz", + "integrity": "sha1-P9SKQCFkpladlNPRfxMUMmMbSHM=", "dev": true, "requires": { "ansi-html": "0.0.7", - "array-includes": "3.0.3", - "bonjour": "3.5.0", - "chokidar": "2.0.3", - "compression": "1.7.2", - "connect-history-api-fallback": "1.5.0", - "debug": "3.1.0", - "del": "3.0.0", - "express": "4.16.3", - "html-entities": "1.2.1", - "http-proxy-middleware": "0.17.4", - "import-local": "1.0.0", + "array-includes": "^3.0.3", + "bonjour": "^3.5.0", + "chokidar": "^2.0.0", + "compression": "^1.5.2", + "connect-history-api-fallback": "^1.3.0", + "debug": "^3.1.0", + "del": "^3.0.0", + "express": "^4.16.2", + "html-entities": "^1.2.0", + "http-proxy-middleware": "~0.17.4", + "import-local": "^1.0.0", "internal-ip": "1.2.0", - "ip": "1.1.5", - "killable": "1.0.0", - "loglevel": "1.6.1", - "opn": "5.3.0", - "portfinder": "1.0.13", - "selfsigned": "1.10.2", - "serve-index": "1.9.1", + "ip": "^1.1.5", + "killable": "^1.0.0", + "loglevel": "^1.4.1", + "opn": "^5.1.0", + "portfinder": "^1.0.9", + "selfsigned": "^1.9.1", + "serve-index": "^1.7.2", "sockjs": "0.3.19", - "sockjs-client": "1.1.4", - "spdy": "3.4.7", - "strip-ansi": "3.0.1", - "supports-color": "5.4.0", + "sockjs-client": "1.1.5", + "spdy": "^3.4.1", + "strip-ansi": "^3.0.0", + "supports-color": "^5.1.0", "webpack-dev-middleware": "1.12.2", "yargs": "6.6.0" }, @@ -13157,7 +11296,7 @@ "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", "dev": true, "requires": { - "number-is-nan": "1.0.1" + "number-is-nan": "^1.0.0" } }, "string-width": { @@ -13166,18 +11305,18 @@ "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "dev": true, "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "strip-ansi": "3.0.1" + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" } }, "supports-color": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", - "integrity": "sha1-HGszdALCE3YF7+GfEP7DkPb6q1Q=", + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha1-4uaaRKyHcveKHsCzW2id9lMO/I8=", "dev": true, "requires": { - "has-flag": "3.0.0" + "has-flag": "^3.0.0" } }, "yargs": { @@ -13186,19 +11325,19 @@ "integrity": "sha1-eC7CHvQDNF+DCoCMo9UTr1YGUgg=", "dev": true, "requires": { - "camelcase": "3.0.0", - "cliui": "3.2.0", - "decamelize": "1.2.0", - "get-caller-file": "1.0.2", - "os-locale": "1.4.0", - "read-pkg-up": "1.0.1", - "require-directory": "2.1.1", - "require-main-filename": "1.0.1", - "set-blocking": "2.0.0", - "string-width": "1.0.2", - "which-module": "1.0.0", - "y18n": "3.2.1", - "yargs-parser": "4.2.1" + "camelcase": "^3.0.0", + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "os-locale": "^1.4.0", + "read-pkg-up": "^1.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^1.0.2", + "which-module": "^1.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^4.2.0" } }, "yargs-parser": { @@ -13207,18 +11346,18 @@ "integrity": "sha1-KczqwNxPA8bIe0qfIX3RjJ90hxw=", "dev": true, "requires": { - "camelcase": "3.0.0" + "camelcase": "^3.0.0" } } } }, "webpack-merge": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-4.1.2.tgz", - "integrity": "sha512-/0QYwW/H1N/CdXYA2PNPVbsxO3u2Fpz34vs72xm03SRfg6bMNGfMJIQEpQjKRvkG2JvT6oRJFpDtSrwbX8Jzvw==", + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-4.1.4.tgz", + "integrity": "sha1-D9446r8tX9hSUcJKWoxI+KP063s=", "dev": true, "requires": { - "lodash": "4.17.5" + "lodash": "^4.17.5" } }, "webpack-notifier": { @@ -13227,19 +11366,19 @@ "integrity": "sha1-/6yOVf+MRpdSuMG7sBGhbxCYbgI=", "dev": true, "requires": { - "node-notifier": "5.2.1", - "object-assign": "4.1.1", - "strip-ansi": "3.0.1" + "node-notifier": "^5.1.2", + "object-assign": "^4.1.0", + "strip-ansi": "^3.0.1" } }, "webpack-sources": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.1.0.tgz", - "integrity": "sha1-oQHrrlnWUHNU1x2AE5UKOot6WlQ=", + "integrity": "sha512-aqYp18kPphgoO5c/+NaUvEeACtZjMESmDChuD3NBciVpah3XpMEU9VAAtIaB1BsfJWWTSdv8Vv1m3T0aRk2dUw==", "dev": true, "requires": { - "source-list-map": "2.0.0", - "source-map": "0.6.1" + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" }, "dependencies": { "source-map": { @@ -13256,8 +11395,8 @@ "integrity": "sha1-DK+dLXVdk67gSdS90NP+LMoqJOs=", "dev": true, "requires": { - "http-parser-js": "0.4.12", - "websocket-extensions": "0.1.3" + "http-parser-js": ">=0.4.0", + "websocket-extensions": ">=0.1.1" } }, "websocket-extensions": { @@ -13278,7 +11417,7 @@ "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==", "dev": true, "requires": { - "isexe": "2.0.0" + "isexe": "^2.0.0" } }, "which-module": { @@ -13288,34 +11427,12 @@ "dev": true }, "wide-align": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.2.tgz", - "integrity": "sha512-ijDLlyQ7s6x1JgCLur53osjm/UXUYD9+0PbYKrBsYisYXzCxN+HC3mYDNy/dWdmf3AwqwU3CXwDCvsNgGK1S0w==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha1-rgdOa9wMFKQx6ATmJFScYzsABFc=", "dev": true, "requires": { - "string-width": "1.0.2" - }, - "dependencies": { - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "1.0.1" - } - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "strip-ansi": "3.0.1" - } - } + "string-width": "^1.0.2 || 2" } }, "window-size": { @@ -13336,7 +11453,7 @@ "integrity": "sha1-rsxAWXb6talVJhgIRvDboojzpKA=", "dev": true, "requires": { - "errno": "0.1.7" + "errno": "~0.1.7" } }, "wrap-ansi": { @@ -13345,8 +11462,8 @@ "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", "dev": true, "requires": { - "string-width": "1.0.2", - "strip-ansi": "3.0.1" + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" }, "dependencies": { "is-fullwidth-code-point": { @@ -13355,7 +11472,7 @@ "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", "dev": true, "requires": { - "number-is-nan": "1.0.1" + "number-is-nan": "^1.0.0" } }, "string-width": { @@ -13364,41 +11481,43 @@ "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "dev": true, "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "strip-ansi": "3.0.1" + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" } } } }, - "wrap-fn": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/wrap-fn/-/wrap-fn-0.1.5.tgz", - "integrity": "sha1-8htuQQFv9KfjFyDbxjoJAWvfmEU=", - "dev": true, - "requires": { - "co": "3.1.0" - }, - "dependencies": { - "co": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/co/-/co-3.1.0.tgz", - "integrity": "sha1-TqVOpaCJOBUxheFSEMaNkJK8G3g=", - "dev": true - } - } - }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "xlsx": { + "version": "0.13.5", + "resolved": "https://registry.npmjs.org/xlsx/-/xlsx-0.13.5.tgz", + "integrity": "sha512-AQo8Anyuv8ZxegAH2EUJ9ZauLf3lIDPfmV7OpJi79LNW6jO4gsviJyQCjNCJY7Deu1SLCrr7LY6rM9N91ixaDQ==", + "requires": { + "adler-32": "~1.2.0", + "cfb": "~1.0.8", + "codepage": "~1.14.0", + "commander": "~2.15.1", + "crc-32": "~1.2.0", + "exit-on-epipe": "~1.0.1", + "ssf": "~0.10.2" + }, + "dependencies": { + "commander": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", + "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==" + } + } }, "xtend": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", - "dev": true + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" }, "y18n": { "version": "3.2.1", @@ -13418,19 +11537,19 @@ "integrity": "sha1-YpmpBVsc78lp/355wdkY3Osiw2A=", "dev": true, "requires": { - "camelcase": "4.1.0", - "cliui": "3.2.0", - "decamelize": "1.2.0", - "get-caller-file": "1.0.2", - "os-locale": "2.1.0", - "read-pkg-up": "2.0.0", - "require-directory": "2.1.1", - "require-main-filename": "1.0.1", - "set-blocking": "2.0.0", - "string-width": "2.1.1", - "which-module": "2.0.0", - "y18n": "3.2.1", - "yargs-parser": "7.0.0" + "camelcase": "^4.1.0", + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "os-locale": "^2.0.0", + "read-pkg-up": "^2.0.0", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^7.0.0" }, "dependencies": { "camelcase": { @@ -13445,10 +11564,10 @@ "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", "dev": true, "requires": { - "graceful-fs": "4.1.11", - "parse-json": "2.2.0", - "pify": "2.3.0", - "strip-bom": "3.0.0" + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "strip-bom": "^3.0.0" } }, "os-locale": { @@ -13457,9 +11576,9 @@ "integrity": "sha1-QrwpAKa1uL0XN2yOiCtlr8zyS/I=", "dev": true, "requires": { - "execa": "0.7.0", - "lcid": "1.0.0", - "mem": "1.1.0" + "execa": "^0.7.0", + "lcid": "^1.0.0", + "mem": "^1.1.0" } }, "path-type": { @@ -13468,7 +11587,7 @@ "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", "dev": true, "requires": { - "pify": "2.3.0" + "pify": "^2.0.0" } }, "pify": { @@ -13483,9 +11602,9 @@ "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", "dev": true, "requires": { - "load-json-file": "2.0.0", - "normalize-package-data": "2.4.0", - "path-type": "2.0.0" + "load-json-file": "^2.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^2.0.0" } }, "read-pkg-up": { @@ -13494,8 +11613,8 @@ "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", "dev": true, "requires": { - "find-up": "2.1.0", - "read-pkg": "2.0.0" + "find-up": "^2.0.0", + "read-pkg": "^2.0.0" } }, "strip-bom": { @@ -13516,7 +11635,7 @@ "integrity": "sha1-jQrELxbqVd69MyyvTEA4s+P139k=", "dev": true, "requires": { - "camelcase": "4.1.0" + "camelcase": "^4.1.0" } } } @@ -13527,7 +11646,7 @@ "integrity": "sha1-J17PDX/+Bcd+ZOfIbkzZS/DhIoo=", "dev": true, "requires": { - "camelcase": "3.0.0" + "camelcase": "^3.0.0" }, "dependencies": { "camelcase": { @@ -13537,16 +11656,6 @@ "dev": true } } - }, - "yauzl": { - "version": "2.9.1", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.9.1.tgz", - "integrity": "sha1-qBmB6nCleUYTOIPwKcWCGok1mn8=", - "dev": true, - "requires": { - "buffer-crc32": "0.2.13", - "fd-slicer": "1.0.1" - } } } } diff --git a/package.json b/package.json index 27a862d458..673190c230 100644 --- a/package.json +++ b/package.json @@ -14,29 +14,37 @@ "babel-preset-latest": "^6.24.1", "cross-env": "^5.0.5", "jquery": "^3.1.1", - "laravel-mix": "2.1", + "laravel-mix": "^2.1.14", "lodash": "^4.17.4", "vue": "2.4.4", "vue-loader": "^13.6.1", "vue-template-compiler": "2.4.4" }, "dependencies": { + "@fortawesome/fontawesome-free": "^5.2.0", + "admin-lte": "^2.4.8", + "ajv": "^6.5.3", "blueimp-file-upload": "^9.18.0", "bootstrap": "^3.3.7", "bootstrap-colorpicker": "^2.5.1", "bootstrap-datepicker": "^1.6.4", "bootstrap-less": "^3.3.8", + "bootstrap-table": "^1.12.1", + "chart.js": "^2.7.3", "ekko-lightbox": "^5.1.1", "font-awesome": "^4.7.0", "icheck": "^1.0.2", + "imagemin": "^5.3.1", + "jquery-form-validator": "^2.3.79", "jquery-slimscroll": "^1.3.8", "jquery-ui": "^1.12.1", - "jquery-ui-bundle": "^1.12.1", + "jquery-ui-dist": "^1.12.1", "jquery.iframe-transport": "^1.0.0", "less": "less/less.js#efa6eb5306f28a7ef7e235d79ce854b780345591", "less-loader": "^4.1.0", "papaparse": "^4.3.3", - "select2": "^4.0.3", + "select2": "^4.0.5", + "tableexport.jquery.plugin": "^1.9.15", "tether": "^1.4.0", "vue-resource": "^1.3.3" } diff --git a/phpmd.xml b/phpmd.xml new file mode 100644 index 0000000000..d991b90fbb --- /dev/null +++ b/phpmd.xml @@ -0,0 +1,54 @@ + + + + Inspired by https://github.com/phpmd/phpmd/issues/137 + using http://phpmd.org/documentation/creating-a-ruleset.html + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 3 + + + + + + + \ No newline at end of file diff --git a/public/_debugbar/assets/jquery.min.map b/public/_debugbar/assets/jquery.min.map deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/public/css/AdminLTE.css b/public/css/AdminLTE.css deleted file mode 100755 index 9089be3ccf..0000000000 Binary files a/public/css/AdminLTE.css and /dev/null differ diff --git a/public/css/AdminLTE.css.map b/public/css/AdminLTE.css.map deleted file mode 100644 index 311c875fa8..0000000000 Binary files a/public/css/AdminLTE.css.map and /dev/null differ diff --git a/public/css/AdminLTE.min.css b/public/css/AdminLTE.min.css deleted file mode 100755 index 396657a381..0000000000 Binary files a/public/css/AdminLTE.min.css and /dev/null differ diff --git a/public/css/all.47a3626f2a026645fe48f025aacc900f.css b/public/css/all.47a3626f2a026645fe48f025aacc900f.css deleted file mode 100644 index be3881e615..0000000000 Binary files a/public/css/all.47a3626f2a026645fe48f025aacc900f.css and /dev/null differ diff --git a/public/css/all.62471b1dabf4426689e067404cda00a2.css b/public/css/all.62471b1dabf4426689e067404cda00a2.css deleted file mode 100644 index 20547187db..0000000000 Binary files a/public/css/all.62471b1dabf4426689e067404cda00a2.css and /dev/null differ diff --git a/public/css/all.c320a5e511c1340ea16bc7facdbdb57b.css b/public/css/all.c320a5e511c1340ea16bc7facdbdb57b.css deleted file mode 100644 index 88519a3d43..0000000000 Binary files a/public/css/all.c320a5e511c1340ea16bc7facdbdb57b.css and /dev/null differ diff --git a/public/css/all.css b/public/css/all.css index 88519a3d43..64635f5adf 100644 Binary files a/public/css/all.css and b/public/css/all.css differ diff --git a/public/css/app.47a3626f2a026645fe48f025aacc900f.css b/public/css/app.47a3626f2a026645fe48f025aacc900f.css deleted file mode 100644 index be3881e615..0000000000 Binary files a/public/css/app.47a3626f2a026645fe48f025aacc900f.css and /dev/null differ diff --git a/public/css/app.62471b1dabf4426689e067404cda00a2.css b/public/css/app.62471b1dabf4426689e067404cda00a2.css deleted file mode 100644 index 20547187db..0000000000 Binary files a/public/css/app.62471b1dabf4426689e067404cda00a2.css and /dev/null differ diff --git a/public/css/app.css b/public/css/app.css deleted file mode 100644 index 89a60fedb2..0000000000 Binary files a/public/css/app.css and /dev/null differ diff --git a/public/css/app.css.map b/public/css/app.css.map deleted file mode 100644 index 051d67395d..0000000000 Binary files a/public/css/app.css.map and /dev/null differ diff --git a/public/js/plugins/iCheck/minimal/blue.png b/public/css/blue.png old mode 100755 new mode 100644 similarity index 100% rename from public/js/plugins/iCheck/minimal/blue.png rename to public/css/blue.png diff --git a/public/js/plugins/iCheck/minimal/blue@2x.png b/public/css/blue@2x.png old mode 100755 new mode 100644 similarity index 100% rename from public/js/plugins/iCheck/minimal/blue@2x.png rename to public/css/blue@2x.png diff --git a/public/css/bootstrap-table.css b/public/css/bootstrap-table.css deleted file mode 100755 index 733c03a69c..0000000000 Binary files a/public/css/bootstrap-table.css and /dev/null differ diff --git a/public/css/bootstrap-tables-sticky-header.css b/public/css/bootstrap-tables-sticky-header.css deleted file mode 100644 index 521a8b04d6..0000000000 Binary files a/public/css/bootstrap-tables-sticky-header.css and /dev/null differ diff --git a/public/css/bootstrap.css b/public/css/bootstrap.css deleted file mode 100755 index 680e768786..0000000000 Binary files a/public/css/bootstrap.css and /dev/null differ diff --git a/public/css/bootstrap.css.map b/public/css/bootstrap.css.map deleted file mode 100755 index 9f60ed2b1b..0000000000 Binary files a/public/css/bootstrap.css.map and /dev/null differ diff --git a/public/css/bootstrap.datepicker.css b/public/css/bootstrap.datepicker.css deleted file mode 100755 index 88859de21a..0000000000 Binary files a/public/css/bootstrap.datepicker.css and /dev/null differ diff --git a/public/css/bootstrap.min.css b/public/css/bootstrap.min.css deleted file mode 100755 index d65c66b1ba..0000000000 Binary files a/public/css/bootstrap.min.css and /dev/null differ diff --git a/public/css/build/AdminLTE.css b/public/css/build/AdminLTE.css new file mode 100644 index 0000000000..76f1e42edf Binary files /dev/null and b/public/css/build/AdminLTE.css differ diff --git a/public/css/build/all.css b/public/css/build/all.css deleted file mode 100644 index 418fe416f0..0000000000 Binary files a/public/css/build/all.css and /dev/null differ diff --git a/public/css/build/app.css b/public/css/build/app.css new file mode 100644 index 0000000000..5f2161d952 Binary files /dev/null and b/public/css/build/app.css differ diff --git a/public/js/bootstrap/css/bootstrap.css b/public/css/build/bootstrap.css old mode 100755 new mode 100644 similarity index 83% rename from public/js/bootstrap/css/bootstrap.css rename to public/css/build/bootstrap.css index 680e768786..d654e48159 Binary files a/public/js/bootstrap/css/bootstrap.css and b/public/css/build/bootstrap.css differ diff --git a/public/css/dist/all.css b/public/css/dist/all.css deleted file mode 100644 index 418fe416f0..0000000000 Binary files a/public/css/dist/all.css and /dev/null differ diff --git a/public/css/dist/bootstrap-table.css b/public/css/dist/bootstrap-table.css new file mode 100644 index 0000000000..31703a3264 Binary files /dev/null and b/public/css/dist/bootstrap-table.css differ diff --git a/public/css/ekko-lightbox.css b/public/css/ekko-lightbox.css deleted file mode 100755 index ec3432ff48..0000000000 Binary files a/public/css/ekko-lightbox.css and /dev/null differ diff --git a/public/css/ekko-lightbox.min.css b/public/css/ekko-lightbox.min.css deleted file mode 100755 index c81b9cc68a..0000000000 Binary files a/public/css/ekko-lightbox.min.css and /dev/null differ diff --git a/public/css/font-awesome/font-awesome.css b/public/css/font-awesome/font-awesome.css deleted file mode 100644 index ee906a8196..0000000000 Binary files a/public/css/font-awesome/font-awesome.css and /dev/null differ diff --git a/public/css/font-awesome/font-awesome.min.css b/public/css/font-awesome/font-awesome.min.css deleted file mode 100644 index 540440ce89..0000000000 Binary files a/public/css/font-awesome/font-awesome.min.css and /dev/null differ diff --git a/public/css/jquery.typeahead.min.css b/public/css/jquery.typeahead.min.css deleted file mode 100755 index 1c97a579e8..0000000000 Binary files a/public/css/jquery.typeahead.min.css and /dev/null differ diff --git a/public/css/lib/bootstrap-wysihtml5.css b/public/css/lib/bootstrap-wysihtml5.css deleted file mode 100755 index d44362bcc9..0000000000 Binary files a/public/css/lib/bootstrap-wysihtml5.css and /dev/null differ diff --git a/public/css/lib/bootstrap.datepicker.css b/public/css/lib/bootstrap.datepicker.css deleted file mode 100755 index 5d0925edc3..0000000000 Binary files a/public/css/lib/bootstrap.datepicker.css and /dev/null differ diff --git a/public/css/lib/dragtable.css b/public/css/lib/dragtable.css deleted file mode 100644 index 874b0ee24d..0000000000 Binary files a/public/css/lib/dragtable.css and /dev/null differ diff --git a/public/css/lib/font-awesome.css b/public/css/lib/font-awesome.css deleted file mode 100644 index 31d5cc4273..0000000000 Binary files a/public/css/lib/font-awesome.css and /dev/null differ diff --git a/public/css/lib/font-awesome.min.css b/public/css/lib/font-awesome.min.css deleted file mode 100644 index 8ecfb7c04c..0000000000 Binary files a/public/css/lib/font-awesome.min.css and /dev/null differ diff --git a/public/css/lib/fullcalendar.css b/public/css/lib/fullcalendar.css deleted file mode 100755 index 5c63e59fdc..0000000000 Binary files a/public/css/lib/fullcalendar.css and /dev/null differ diff --git a/public/css/lib/fullcalendar.print.css b/public/css/lib/fullcalendar.print.css deleted file mode 100755 index 8fea38dbc0..0000000000 Binary files a/public/css/lib/fullcalendar.print.css and /dev/null differ diff --git a/public/css/lib/jquery-ui-1.10.2.custom.css b/public/css/lib/jquery-ui-1.10.2.custom.css deleted file mode 100755 index ffd0ebd181..0000000000 Binary files a/public/css/lib/jquery-ui-1.10.2.custom.css and /dev/null differ diff --git a/public/css/lib/jquery.dataTables.css b/public/css/lib/jquery.dataTables.css deleted file mode 100755 index 420d93abe8..0000000000 Binary files a/public/css/lib/jquery.dataTables.css and /dev/null differ diff --git a/public/css/lib/jquery.fileupload-ui.css b/public/css/lib/jquery.fileupload-ui.css deleted file mode 100755 index 76fb376de0..0000000000 Binary files a/public/css/lib/jquery.fileupload-ui.css and /dev/null differ diff --git a/public/css/lib/jquery.fileupload.css b/public/css/lib/jquery.fileupload.css deleted file mode 100755 index 4303179e73..0000000000 Binary files a/public/css/lib/jquery.fileupload.css and /dev/null differ diff --git a/public/css/lib/morris.css b/public/css/lib/morris.css deleted file mode 100755 index bc687242ee..0000000000 Binary files a/public/css/lib/morris.css and /dev/null differ diff --git a/public/css/lib/select2.css b/public/css/lib/select2.css deleted file mode 100755 index ae46ec3b42..0000000000 Binary files a/public/css/lib/select2.css and /dev/null differ diff --git a/public/css/lib/select2x2.png b/public/css/lib/select2x2.png deleted file mode 100755 index 4bdd5c961d..0000000000 Binary files a/public/css/lib/select2x2.png and /dev/null differ diff --git a/public/css/lib/uniform.default.css b/public/css/lib/uniform.default.css deleted file mode 100755 index ad280bfff9..0000000000 Binary files a/public/css/lib/uniform.default.css and /dev/null differ diff --git a/public/css/metisMenu.css b/public/css/metisMenu.css deleted file mode 100755 index 76376c39ae..0000000000 Binary files a/public/css/metisMenu.css and /dev/null differ diff --git a/public/css/metisMenu.min.css b/public/css/metisMenu.min.css deleted file mode 100755 index a1d0ef3994..0000000000 Binary files a/public/css/metisMenu.min.css and /dev/null differ diff --git a/public/css/morris.css b/public/css/morris.css deleted file mode 100755 index 209f09156b..0000000000 Binary files a/public/css/morris.css and /dev/null differ diff --git a/public/css/overrides.css b/public/css/overrides.css deleted file mode 100644 index 0f11860559..0000000000 Binary files a/public/css/overrides.css and /dev/null differ diff --git a/public/css/overrides.css.map b/public/css/overrides.css.map deleted file mode 100644 index dfc414f418..0000000000 Binary files a/public/css/overrides.css.map and /dev/null differ diff --git a/public/css/select2.css b/public/css/select2.css deleted file mode 100755 index ae46ec3b42..0000000000 Binary files a/public/css/select2.css and /dev/null differ diff --git a/public/css/select2x2.png b/public/css/select2x2.png deleted file mode 100755 index 4bdd5c961d..0000000000 Binary files a/public/css/select2x2.png and /dev/null differ diff --git a/public/css/signature-pad.min.css b/public/css/signature-pad.min.css new file mode 100644 index 0000000000..7065929572 Binary files /dev/null and b/public/css/signature-pad.min.css differ diff --git a/public/css/skins/_all-skins.css b/public/css/skins/_all-skins.css deleted file mode 100755 index 9af6a45871..0000000000 Binary files a/public/css/skins/_all-skins.css and /dev/null differ diff --git a/public/css/skins/_all-skins.min.css b/public/css/skins/_all-skins.min.css deleted file mode 100755 index 1710db5cb2..0000000000 Binary files a/public/css/skins/_all-skins.min.css and /dev/null differ diff --git a/public/css/skins/skin-blue-light.css b/public/css/skins/skin-blue-light.css deleted file mode 100755 index 7614d60e92..0000000000 Binary files a/public/css/skins/skin-blue-light.css and /dev/null differ diff --git a/public/css/skins/skin-blue-light.min.css b/public/css/skins/skin-blue-light.min.css deleted file mode 100755 index 4fab22a553..0000000000 Binary files a/public/css/skins/skin-blue-light.min.css and /dev/null differ diff --git a/public/css/skins/skin-blue.css b/public/css/skins/skin-blue.css deleted file mode 100755 index 1bc543fd34..0000000000 Binary files a/public/css/skins/skin-blue.css and /dev/null differ diff --git a/public/css/skins/skin-green-dark.min.css b/public/css/skins/skin-green-dark.min.css new file mode 100644 index 0000000000..026c8a7356 Binary files /dev/null and b/public/css/skins/skin-green-dark.min.css differ diff --git a/public/css/skins/skin-orange-dark.min.css b/public/css/skins/skin-orange-dark.min.css new file mode 100644 index 0000000000..2b1279fed3 Binary files /dev/null and b/public/css/skins/skin-orange-dark.min.css differ diff --git a/public/css/skins/skin-red-dark.min.css b/public/css/skins/skin-red-dark.min.css new file mode 100644 index 0000000000..500fa51980 Binary files /dev/null and b/public/css/skins/skin-red-dark.min.css differ diff --git a/public/favicon.ico b/public/favicon.ico index e80625534b..e69de29bb2 100644 Binary files a/public/favicon.ico and b/public/favicon.ico differ diff --git a/public/css/fonts/FontAwesome.otf b/public/fonts/FontAwesome.otf similarity index 100% rename from public/css/fonts/FontAwesome.otf rename to public/fonts/FontAwesome.otf diff --git a/public/css/fonts/fontawesome-webfont.eot b/public/fonts/fontawesome-webfont.eot similarity index 100% rename from public/css/fonts/fontawesome-webfont.eot rename to public/fonts/fontawesome-webfont.eot diff --git a/public/css/fonts/fontawesome-webfont.svg b/public/fonts/fontawesome-webfont.svg similarity index 100% rename from public/css/fonts/fontawesome-webfont.svg rename to public/fonts/fontawesome-webfont.svg diff --git a/public/css/fonts/fontawesome-webfont.ttf b/public/fonts/fontawesome-webfont.ttf similarity index 100% rename from public/css/fonts/fontawesome-webfont.ttf rename to public/fonts/fontawesome-webfont.ttf diff --git a/public/css/fonts/fontawesome-webfont.woff b/public/fonts/fontawesome-webfont.woff similarity index 100% rename from public/css/fonts/fontawesome-webfont.woff rename to public/fonts/fontawesome-webfont.woff diff --git a/public/css/fonts/fontawesome-webfont.woff2 b/public/fonts/fontawesome-webfont.woff2 similarity index 100% rename from public/css/fonts/fontawesome-webfont.woff2 rename to public/fonts/fontawesome-webfont.woff2 diff --git a/public/img/demo/accessories/bluetooth.jpg b/public/img/demo/accessories/bluetooth.jpg new file mode 100644 index 0000000000..0d3558c4dc Binary files /dev/null and b/public/img/demo/accessories/bluetooth.jpg differ diff --git a/public/img/demo/accessories/comfort-mouse.jpg b/public/img/demo/accessories/comfort-mouse.jpg new file mode 100644 index 0000000000..6652da1189 Binary files /dev/null and b/public/img/demo/accessories/comfort-mouse.jpg differ diff --git a/public/img/demo/accessories/magic-mouse.jpg b/public/img/demo/accessories/magic-mouse.jpg new file mode 100644 index 0000000000..b23683fb4b Binary files /dev/null and b/public/img/demo/accessories/magic-mouse.jpg differ diff --git a/public/img/demo/accessories/usb-keyboard.jpg b/public/img/demo/accessories/usb-keyboard.jpg new file mode 100644 index 0000000000..e87fa202a5 Binary files /dev/null and b/public/img/demo/accessories/usb-keyboard.jpg differ diff --git a/public/img/demo/logo.png b/public/img/demo/logo.png new file mode 100644 index 0000000000..423a5b7490 Binary files /dev/null and b/public/img/demo/logo.png differ diff --git a/public/js/FileSaver.min.js b/public/js/FileSaver.min.js deleted file mode 100644 index 9a1e397f20..0000000000 Binary files a/public/js/FileSaver.min.js and /dev/null differ diff --git a/public/js/app.js b/public/js/app.js old mode 100755 new mode 100644 index 4c28e585af..6090500cef Binary files a/public/js/app.js and b/public/js/app.js differ diff --git a/public/js/app.min.js b/public/js/app.min.js deleted file mode 100755 index 679f18f1b3..0000000000 Binary files a/public/js/app.min.js and /dev/null differ diff --git a/public/js/bootstrap-table-locale-all.js b/public/js/bootstrap-table-locale-all.js deleted file mode 100755 index 2e02e8cc43..0000000000 Binary files a/public/js/bootstrap-table-locale-all.js and /dev/null differ diff --git a/public/js/bootstrap-table-locale-all.min.js b/public/js/bootstrap-table-locale-all.min.js deleted file mode 100755 index 38d47669de..0000000000 Binary files a/public/js/bootstrap-table-locale-all.min.js and /dev/null differ diff --git a/public/js/bootstrap-table.css b/public/js/bootstrap-table.css deleted file mode 100755 index b557667625..0000000000 Binary files a/public/js/bootstrap-table.css and /dev/null differ diff --git a/public/js/bootstrap-table.js b/public/js/bootstrap-table.js deleted file mode 100755 index 9813921f5b..0000000000 Binary files a/public/js/bootstrap-table.js and /dev/null differ diff --git a/public/js/bootstrap-table.min.css b/public/js/bootstrap-table.min.css deleted file mode 100755 index ad36a502bf..0000000000 Binary files a/public/js/bootstrap-table.min.css and /dev/null differ diff --git a/public/js/bootstrap-table.min.js b/public/js/bootstrap-table.min.js deleted file mode 100755 index 9723e1a67d..0000000000 Binary files a/public/js/bootstrap-table.min.js and /dev/null differ diff --git a/public/js/bootstrap.datepicker.js b/public/js/bootstrap.datepicker.js deleted file mode 100755 index 4005b732b3..0000000000 Binary files a/public/js/bootstrap.datepicker.js and /dev/null differ diff --git a/public/js/bootstrap/css/bootstrap.css.map b/public/js/bootstrap/css/bootstrap.css.map deleted file mode 100755 index 9f60ed2b1b..0000000000 Binary files a/public/js/bootstrap/css/bootstrap.css.map and /dev/null differ diff --git a/public/js/bootstrap/css/bootstrap.min.css b/public/js/bootstrap/css/bootstrap.min.css deleted file mode 100755 index d65c66b1ba..0000000000 Binary files a/public/js/bootstrap/css/bootstrap.min.css and /dev/null differ diff --git a/public/js/bootstrap/fonts/glyphicons-halflings-regular.eot b/public/js/bootstrap/fonts/glyphicons-halflings-regular.eot deleted file mode 100755 index b93a4953ff..0000000000 Binary files a/public/js/bootstrap/fonts/glyphicons-halflings-regular.eot and /dev/null differ diff --git a/public/js/bootstrap/fonts/glyphicons-halflings-regular.svg b/public/js/bootstrap/fonts/glyphicons-halflings-regular.svg deleted file mode 100755 index 94fb5490a2..0000000000 Binary files a/public/js/bootstrap/fonts/glyphicons-halflings-regular.svg and /dev/null differ diff --git a/public/js/bootstrap/fonts/glyphicons-halflings-regular.ttf b/public/js/bootstrap/fonts/glyphicons-halflings-regular.ttf deleted file mode 100755 index 1413fc609a..0000000000 Binary files a/public/js/bootstrap/fonts/glyphicons-halflings-regular.ttf and /dev/null differ diff --git a/public/js/bootstrap/fonts/glyphicons-halflings-regular.woff b/public/js/bootstrap/fonts/glyphicons-halflings-regular.woff deleted file mode 100755 index 9e612858f8..0000000000 Binary files a/public/js/bootstrap/fonts/glyphicons-halflings-regular.woff and /dev/null differ diff --git a/public/js/bootstrap/fonts/glyphicons-halflings-regular.woff2 b/public/js/bootstrap/fonts/glyphicons-halflings-regular.woff2 deleted file mode 100755 index 64539b54c3..0000000000 Binary files a/public/js/bootstrap/fonts/glyphicons-halflings-regular.woff2 and /dev/null differ diff --git a/public/js/bootstrap/js/bootstrap.js b/public/js/bootstrap/js/bootstrap.js deleted file mode 100755 index 1c88b71e8b..0000000000 Binary files a/public/js/bootstrap/js/bootstrap.js and /dev/null differ diff --git a/public/js/bootstrap/js/bootstrap.min.js b/public/js/bootstrap/js/bootstrap.min.js deleted file mode 100755 index c8f1c68929..0000000000 Binary files a/public/js/bootstrap/js/bootstrap.min.js and /dev/null differ diff --git a/public/js/bootstrap/js/npm.js b/public/js/bootstrap/js/npm.js deleted file mode 100755 index bf6aa80602..0000000000 Binary files a/public/js/bootstrap/js/npm.js and /dev/null differ diff --git a/public/js/build/all.js b/public/js/build/all.js index de69adc765..b1e269197d 100644 Binary files a/public/js/build/all.js and b/public/js/build/all.js differ diff --git a/public/js/build/app.js b/public/js/build/app.js new file mode 100644 index 0000000000..c465642a00 Binary files /dev/null and b/public/js/build/app.js differ diff --git a/public/js/build/vue.js b/public/js/build/vue.js index f70ca5ece8..fabec21b5b 100644 Binary files a/public/js/build/vue.js and b/public/js/build/vue.js differ diff --git a/public/js/build/vue.js.map b/public/js/build/vue.js.map index 388c23e39a..779f53b315 100644 Binary files a/public/js/build/vue.js.map and b/public/js/build/vue.js.map differ diff --git a/public/js/dashboard.js b/public/js/dashboard.js deleted file mode 100755 index 9c4ff7b286..0000000000 Binary files a/public/js/dashboard.js and /dev/null differ diff --git a/public/js/dashboard2.js b/public/js/dashboard2.js deleted file mode 100755 index a892b5b439..0000000000 Binary files a/public/js/dashboard2.js and /dev/null differ diff --git a/public/js/demo.js b/public/js/demo.js deleted file mode 100755 index 988ec453cb..0000000000 Binary files a/public/js/demo.js and /dev/null differ diff --git a/public/js/dist/all.js b/public/js/dist/all.js index de69adc765..f3e9beaf7a 100644 Binary files a/public/js/dist/all.js and b/public/js/dist/all.js differ diff --git a/public/js/dist/bootstrap-table-simple-view.js b/public/js/dist/bootstrap-table-simple-view.js new file mode 100644 index 0000000000..c224ff0c55 Binary files /dev/null and b/public/js/dist/bootstrap-table-simple-view.js differ diff --git a/public/js/dist/bootstrap-table.js b/public/js/dist/bootstrap-table.js new file mode 100644 index 0000000000..a9366bb886 Binary files /dev/null and b/public/js/dist/bootstrap-table.js differ diff --git a/public/js/ekko-lightbox.js b/public/js/ekko-lightbox.js deleted file mode 100755 index a662601084..0000000000 Binary files a/public/js/ekko-lightbox.js and /dev/null differ diff --git a/public/js/ekko-lightbox.min.js b/public/js/ekko-lightbox.min.js deleted file mode 100755 index 161e29c98b..0000000000 Binary files a/public/js/ekko-lightbox.min.js and /dev/null differ diff --git a/public/js/extensions/accent-neutralise/bootstrap-table-accent-neutralise.js b/public/js/extensions/accent-neutralise/bootstrap-table-accent-neutralise.js deleted file mode 100755 index dc7b4f08fc..0000000000 Binary files a/public/js/extensions/accent-neutralise/bootstrap-table-accent-neutralise.js and /dev/null differ diff --git a/public/js/extensions/accent-neutralise/bootstrap-table-accent-neutralise.min.js b/public/js/extensions/accent-neutralise/bootstrap-table-accent-neutralise.min.js deleted file mode 100755 index d7aa59839f..0000000000 Binary files a/public/js/extensions/accent-neutralise/bootstrap-table-accent-neutralise.min.js and /dev/null differ diff --git a/public/js/extensions/angular/bootstrap-table-angular.js b/public/js/extensions/angular/bootstrap-table-angular.js deleted file mode 100755 index 84c4ed330a..0000000000 Binary files a/public/js/extensions/angular/bootstrap-table-angular.js and /dev/null differ diff --git a/public/js/extensions/angular/bootstrap-table-angular.min.js b/public/js/extensions/angular/bootstrap-table-angular.min.js deleted file mode 100755 index 43c3d7df0f..0000000000 Binary files a/public/js/extensions/angular/bootstrap-table-angular.min.js and /dev/null differ diff --git a/public/js/extensions/cookie/bootstrap-table-cookie.js b/public/js/extensions/cookie/bootstrap-table-cookie.js deleted file mode 100755 index 1cc5c56070..0000000000 Binary files a/public/js/extensions/cookie/bootstrap-table-cookie.js and /dev/null differ diff --git a/public/js/extensions/cookie/bootstrap-table-cookie.min.js b/public/js/extensions/cookie/bootstrap-table-cookie.min.js deleted file mode 100755 index 425ef8b6f6..0000000000 Binary files a/public/js/extensions/cookie/bootstrap-table-cookie.min.js and /dev/null differ diff --git a/public/js/extensions/editable/bootstrap-table-editable.js b/public/js/extensions/editable/bootstrap-table-editable.js deleted file mode 100755 index 0bb43a6c21..0000000000 Binary files a/public/js/extensions/editable/bootstrap-table-editable.js and /dev/null differ diff --git a/public/js/extensions/editable/bootstrap-table-editable.min.js b/public/js/extensions/editable/bootstrap-table-editable.min.js deleted file mode 100755 index 5c95094998..0000000000 Binary files a/public/js/extensions/editable/bootstrap-table-editable.min.js and /dev/null differ diff --git a/public/js/extensions/export/bootstrap-table-export.js b/public/js/extensions/export/bootstrap-table-export.js deleted file mode 100755 index ef775c692c..0000000000 Binary files a/public/js/extensions/export/bootstrap-table-export.js and /dev/null differ diff --git a/public/js/extensions/export/bootstrap-table-export.min.js b/public/js/extensions/export/bootstrap-table-export.min.js deleted file mode 100755 index f2550f6265..0000000000 Binary files a/public/js/extensions/export/bootstrap-table-export.min.js and /dev/null differ diff --git a/public/js/extensions/export/tableExport.js b/public/js/extensions/export/tableExport.js deleted file mode 100644 index 124621767c..0000000000 Binary files a/public/js/extensions/export/tableExport.js and /dev/null differ diff --git a/public/js/extensions/export/tableExport.min.js b/public/js/extensions/export/tableExport.min.js deleted file mode 100644 index 7844ddfac0..0000000000 Binary files a/public/js/extensions/export/tableExport.min.js and /dev/null differ diff --git a/public/js/extensions/filter-control/bootstrap-table-filter-control.js b/public/js/extensions/filter-control/bootstrap-table-filter-control.js deleted file mode 100755 index fa696d3bb2..0000000000 Binary files a/public/js/extensions/filter-control/bootstrap-table-filter-control.js and /dev/null differ diff --git a/public/js/extensions/filter-control/bootstrap-table-filter-control.min.js b/public/js/extensions/filter-control/bootstrap-table-filter-control.min.js deleted file mode 100755 index 1de25e7d54..0000000000 Binary files a/public/js/extensions/filter-control/bootstrap-table-filter-control.min.js and /dev/null differ diff --git a/public/js/extensions/filter/bootstrap-table-filter.js b/public/js/extensions/filter/bootstrap-table-filter.js deleted file mode 100755 index 14af13da06..0000000000 Binary files a/public/js/extensions/filter/bootstrap-table-filter.js and /dev/null differ diff --git a/public/js/extensions/filter/bootstrap-table-filter.min.js b/public/js/extensions/filter/bootstrap-table-filter.min.js deleted file mode 100755 index 9d0e05704d..0000000000 Binary files a/public/js/extensions/filter/bootstrap-table-filter.min.js and /dev/null differ diff --git a/public/js/extensions/flat-json/bootstrap-table-flat-json.js b/public/js/extensions/flat-json/bootstrap-table-flat-json.js deleted file mode 100755 index 4bbf3a2a9e..0000000000 Binary files a/public/js/extensions/flat-json/bootstrap-table-flat-json.js and /dev/null differ diff --git a/public/js/extensions/flat-json/bootstrap-table-flat-json.min.js b/public/js/extensions/flat-json/bootstrap-table-flat-json.min.js deleted file mode 100755 index 844f5428dd..0000000000 Binary files a/public/js/extensions/flat-json/bootstrap-table-flat-json.min.js and /dev/null differ diff --git a/public/js/extensions/group-by-v2/bootstrap-table-group-by.css b/public/js/extensions/group-by-v2/bootstrap-table-group-by.css deleted file mode 100755 index 80b1161b76..0000000000 Binary files a/public/js/extensions/group-by-v2/bootstrap-table-group-by.css and /dev/null differ diff --git a/public/js/extensions/group-by-v2/bootstrap-table-group-by.js b/public/js/extensions/group-by-v2/bootstrap-table-group-by.js deleted file mode 100755 index f9a1092d48..0000000000 Binary files a/public/js/extensions/group-by-v2/bootstrap-table-group-by.js and /dev/null differ diff --git a/public/js/extensions/group-by-v2/bootstrap-table-group-by.min.js b/public/js/extensions/group-by-v2/bootstrap-table-group-by.min.js deleted file mode 100755 index 51532f2dc3..0000000000 Binary files a/public/js/extensions/group-by-v2/bootstrap-table-group-by.min.js and /dev/null differ diff --git a/public/js/extensions/group-by/bootstrap-table-group-by.css b/public/js/extensions/group-by/bootstrap-table-group-by.css deleted file mode 100755 index fce5a9a7b1..0000000000 Binary files a/public/js/extensions/group-by/bootstrap-table-group-by.css and /dev/null differ diff --git a/public/js/extensions/group-by/bootstrap-table-group-by.js b/public/js/extensions/group-by/bootstrap-table-group-by.js deleted file mode 100755 index 6f95e61bdd..0000000000 Binary files a/public/js/extensions/group-by/bootstrap-table-group-by.js and /dev/null differ diff --git a/public/js/extensions/group-by/bootstrap-table-group-by.min.js b/public/js/extensions/group-by/bootstrap-table-group-by.min.js deleted file mode 100755 index 9d55090040..0000000000 Binary files a/public/js/extensions/group-by/bootstrap-table-group-by.min.js and /dev/null differ diff --git a/public/js/extensions/key-events/bootstrap-table-key-events.js b/public/js/extensions/key-events/bootstrap-table-key-events.js deleted file mode 100755 index 887f803562..0000000000 Binary files a/public/js/extensions/key-events/bootstrap-table-key-events.js and /dev/null differ diff --git a/public/js/extensions/key-events/bootstrap-table-key-events.min.js b/public/js/extensions/key-events/bootstrap-table-key-events.min.js deleted file mode 100755 index db1561aa48..0000000000 Binary files a/public/js/extensions/key-events/bootstrap-table-key-events.min.js and /dev/null differ diff --git a/public/js/extensions/mobile/bootstrap-table-mobile.js b/public/js/extensions/mobile/bootstrap-table-mobile.js deleted file mode 100755 index 5fb6704338..0000000000 Binary files a/public/js/extensions/mobile/bootstrap-table-mobile.js and /dev/null differ diff --git a/public/js/extensions/mobile/bootstrap-table-mobile.min.js b/public/js/extensions/mobile/bootstrap-table-mobile.min.js deleted file mode 100755 index c693a824c3..0000000000 Binary files a/public/js/extensions/mobile/bootstrap-table-mobile.min.js and /dev/null differ diff --git a/public/js/extensions/multiple-search/bootstrap-table-multiple-search.js b/public/js/extensions/multiple-search/bootstrap-table-multiple-search.js deleted file mode 100755 index 22df2ae933..0000000000 Binary files a/public/js/extensions/multiple-search/bootstrap-table-multiple-search.js and /dev/null differ diff --git a/public/js/extensions/multiple-search/bootstrap-table-multiple-search.min.js b/public/js/extensions/multiple-search/bootstrap-table-multiple-search.min.js deleted file mode 100755 index 49cbf7c9d6..0000000000 Binary files a/public/js/extensions/multiple-search/bootstrap-table-multiple-search.min.js and /dev/null differ diff --git a/public/js/extensions/multiple-sort/bootstrap-table-multiple-sort.js b/public/js/extensions/multiple-sort/bootstrap-table-multiple-sort.js deleted file mode 100755 index 68f6a52f19..0000000000 Binary files a/public/js/extensions/multiple-sort/bootstrap-table-multiple-sort.js and /dev/null differ diff --git a/public/js/extensions/multiple-sort/bootstrap-table-multiple-sort.min.js b/public/js/extensions/multiple-sort/bootstrap-table-multiple-sort.min.js deleted file mode 100755 index a8cb610da8..0000000000 Binary files a/public/js/extensions/multiple-sort/bootstrap-table-multiple-sort.min.js and /dev/null differ diff --git a/public/js/extensions/natural-sorting/bootstrap-table-natural-sorting.js b/public/js/extensions/natural-sorting/bootstrap-table-natural-sorting.js deleted file mode 100755 index 8e84eb659b..0000000000 Binary files a/public/js/extensions/natural-sorting/bootstrap-table-natural-sorting.js and /dev/null differ diff --git a/public/js/extensions/natural-sorting/bootstrap-table-natural-sorting.min.js b/public/js/extensions/natural-sorting/bootstrap-table-natural-sorting.min.js deleted file mode 100755 index 2ccb66b63d..0000000000 Binary files a/public/js/extensions/natural-sorting/bootstrap-table-natural-sorting.min.js and /dev/null differ diff --git a/public/js/extensions/reorder-columns/bootstrap-table-reorder-columns.js b/public/js/extensions/reorder-columns/bootstrap-table-reorder-columns.js deleted file mode 100755 index 0c8b8b3f7e..0000000000 Binary files a/public/js/extensions/reorder-columns/bootstrap-table-reorder-columns.js and /dev/null differ diff --git a/public/js/extensions/reorder-columns/bootstrap-table-reorder-columns.min.js b/public/js/extensions/reorder-columns/bootstrap-table-reorder-columns.min.js deleted file mode 100755 index 50cad77bed..0000000000 Binary files a/public/js/extensions/reorder-columns/bootstrap-table-reorder-columns.min.js and /dev/null differ diff --git a/public/js/extensions/reorder-rows/bootstrap-table-reorder-rows.css b/public/js/extensions/reorder-rows/bootstrap-table-reorder-rows.css deleted file mode 100755 index 412ff145e3..0000000000 Binary files a/public/js/extensions/reorder-rows/bootstrap-table-reorder-rows.css and /dev/null differ diff --git a/public/js/extensions/reorder-rows/bootstrap-table-reorder-rows.js b/public/js/extensions/reorder-rows/bootstrap-table-reorder-rows.js deleted file mode 100755 index c733717695..0000000000 Binary files a/public/js/extensions/reorder-rows/bootstrap-table-reorder-rows.js and /dev/null differ diff --git a/public/js/extensions/reorder-rows/bootstrap-table-reorder-rows.min.js b/public/js/extensions/reorder-rows/bootstrap-table-reorder-rows.min.js deleted file mode 100755 index a47c9bbba8..0000000000 Binary files a/public/js/extensions/reorder-rows/bootstrap-table-reorder-rows.min.js and /dev/null differ diff --git a/public/js/extensions/resizable/bootstrap-table-resizable.js b/public/js/extensions/resizable/bootstrap-table-resizable.js deleted file mode 100755 index 8be7b09641..0000000000 Binary files a/public/js/extensions/resizable/bootstrap-table-resizable.js and /dev/null differ diff --git a/public/js/extensions/resizable/bootstrap-table-resizable.min.js b/public/js/extensions/resizable/bootstrap-table-resizable.min.js deleted file mode 100755 index 3b4a9ac9d1..0000000000 Binary files a/public/js/extensions/resizable/bootstrap-table-resizable.min.js and /dev/null differ diff --git a/public/js/extensions/sticky-header/bootstrap-table-sticky-header.css b/public/js/extensions/sticky-header/bootstrap-table-sticky-header.css deleted file mode 100755 index d0ea09cbf2..0000000000 Binary files a/public/js/extensions/sticky-header/bootstrap-table-sticky-header.css and /dev/null differ diff --git a/public/js/extensions/sticky-header/bootstrap-table-sticky-header.js b/public/js/extensions/sticky-header/bootstrap-table-sticky-header.js deleted file mode 100755 index d9fc6c5bd4..0000000000 Binary files a/public/js/extensions/sticky-header/bootstrap-table-sticky-header.js and /dev/null differ diff --git a/public/js/extensions/sticky-header/bootstrap-table-sticky-header.min.js b/public/js/extensions/sticky-header/bootstrap-table-sticky-header.min.js deleted file mode 100755 index 527f4d1d30..0000000000 Binary files a/public/js/extensions/sticky-header/bootstrap-table-sticky-header.min.js and /dev/null differ diff --git a/public/js/extensions/toolbar/bootstrap-table-toolbar.js b/public/js/extensions/toolbar/bootstrap-table-toolbar.js deleted file mode 100755 index e54bf936ce..0000000000 Binary files a/public/js/extensions/toolbar/bootstrap-table-toolbar.js and /dev/null differ diff --git a/public/js/extensions/toolbar/bootstrap-table-toolbar.min.js b/public/js/extensions/toolbar/bootstrap-table-toolbar.min.js deleted file mode 100755 index 5626a8419d..0000000000 Binary files a/public/js/extensions/toolbar/bootstrap-table-toolbar.min.js and /dev/null differ diff --git a/public/js/html5.js b/public/js/html5.js deleted file mode 100644 index 6168aacd5e..0000000000 Binary files a/public/js/html5.js and /dev/null differ diff --git a/public/js/html5shiv.js b/public/js/html5shiv.js deleted file mode 100644 index 1a01c94ba4..0000000000 Binary files a/public/js/html5shiv.js and /dev/null differ diff --git a/public/js/jquery.dragtable.js b/public/js/jquery.dragtable.js deleted file mode 100644 index f42265dfda..0000000000 Binary files a/public/js/jquery.dragtable.js and /dev/null differ diff --git a/public/js/jquery.fileupload.js b/public/js/jquery.fileupload.js deleted file mode 100755 index ab0748fc04..0000000000 Binary files a/public/js/jquery.fileupload.js and /dev/null differ diff --git a/public/js/jquery.iframe-transport.js b/public/js/jquery.iframe-transport.js deleted file mode 100755 index b7581f23f4..0000000000 Binary files a/public/js/jquery.iframe-transport.js and /dev/null differ diff --git a/public/js/jquery.js b/public/js/jquery.js deleted file mode 100644 index d1608e37ff..0000000000 Binary files a/public/js/jquery.js and /dev/null differ diff --git a/public/js/jquery.typeahead.min.js b/public/js/jquery.typeahead.min.js deleted file mode 100755 index b20392b1c6..0000000000 Binary files a/public/js/jquery.typeahead.min.js and /dev/null differ diff --git a/public/js/jquery.ui.widget.js b/public/js/jquery.ui.widget.js deleted file mode 100755 index 5ac2ed5a57..0000000000 Binary files a/public/js/jquery.ui.widget.js and /dev/null differ diff --git a/public/js/jspdf.min.js b/public/js/jspdf.min.js deleted file mode 100644 index e842d43616..0000000000 Binary files a/public/js/jspdf.min.js and /dev/null differ diff --git a/public/js/jspdf.plugin.autotable.js b/public/js/jspdf.plugin.autotable.js deleted file mode 100644 index efbd41c8b7..0000000000 Binary files a/public/js/jspdf.plugin.autotable.js and /dev/null differ diff --git a/public/js/locale/bootstrap-table-af-ZA.js b/public/js/locale/bootstrap-table-af-ZA.js deleted file mode 100755 index 1c7ff8891c..0000000000 Binary files a/public/js/locale/bootstrap-table-af-ZA.js and /dev/null differ diff --git a/public/js/locale/bootstrap-table-af-ZA.min.js b/public/js/locale/bootstrap-table-af-ZA.min.js deleted file mode 100755 index 2e502394d9..0000000000 Binary files a/public/js/locale/bootstrap-table-af-ZA.min.js and /dev/null differ diff --git a/public/js/locale/bootstrap-table-ar-SA.js b/public/js/locale/bootstrap-table-ar-SA.js deleted file mode 100755 index c36223633c..0000000000 Binary files a/public/js/locale/bootstrap-table-ar-SA.js and /dev/null differ diff --git a/public/js/locale/bootstrap-table-ar-SA.min.js b/public/js/locale/bootstrap-table-ar-SA.min.js deleted file mode 100755 index 178bc134ec..0000000000 Binary files a/public/js/locale/bootstrap-table-ar-SA.min.js and /dev/null differ diff --git a/public/js/locale/bootstrap-table-ca-ES.js b/public/js/locale/bootstrap-table-ca-ES.js deleted file mode 100755 index 2c992965e7..0000000000 Binary files a/public/js/locale/bootstrap-table-ca-ES.js and /dev/null differ diff --git a/public/js/locale/bootstrap-table-ca-ES.min.js b/public/js/locale/bootstrap-table-ca-ES.min.js deleted file mode 100755 index 064ae06961..0000000000 Binary files a/public/js/locale/bootstrap-table-ca-ES.min.js and /dev/null differ diff --git a/public/js/locale/bootstrap-table-cs-CZ.js b/public/js/locale/bootstrap-table-cs-CZ.js deleted file mode 100755 index d8c71307eb..0000000000 Binary files a/public/js/locale/bootstrap-table-cs-CZ.js and /dev/null differ diff --git a/public/js/locale/bootstrap-table-cs-CZ.min.js b/public/js/locale/bootstrap-table-cs-CZ.min.js deleted file mode 100755 index 1edc7f0939..0000000000 Binary files a/public/js/locale/bootstrap-table-cs-CZ.min.js and /dev/null differ diff --git a/public/js/locale/bootstrap-table-da-DK.js b/public/js/locale/bootstrap-table-da-DK.js deleted file mode 100755 index de38a17206..0000000000 Binary files a/public/js/locale/bootstrap-table-da-DK.js and /dev/null differ diff --git a/public/js/locale/bootstrap-table-da-DK.min.js b/public/js/locale/bootstrap-table-da-DK.min.js deleted file mode 100755 index ee30beefff..0000000000 Binary files a/public/js/locale/bootstrap-table-da-DK.min.js and /dev/null differ diff --git a/public/js/locale/bootstrap-table-de-DE.js b/public/js/locale/bootstrap-table-de-DE.js deleted file mode 100755 index efa48319f4..0000000000 Binary files a/public/js/locale/bootstrap-table-de-DE.js and /dev/null differ diff --git a/public/js/locale/bootstrap-table-de-DE.min.js b/public/js/locale/bootstrap-table-de-DE.min.js deleted file mode 100755 index 07ab4c7a9f..0000000000 Binary files a/public/js/locale/bootstrap-table-de-DE.min.js and /dev/null differ diff --git a/public/js/locale/bootstrap-table-el-GR.js b/public/js/locale/bootstrap-table-el-GR.js deleted file mode 100755 index dd74491090..0000000000 Binary files a/public/js/locale/bootstrap-table-el-GR.js and /dev/null differ diff --git a/public/js/locale/bootstrap-table-el-GR.min.js b/public/js/locale/bootstrap-table-el-GR.min.js deleted file mode 100755 index b63327540a..0000000000 Binary files a/public/js/locale/bootstrap-table-el-GR.min.js and /dev/null differ diff --git a/public/js/locale/bootstrap-table-en-US.js b/public/js/locale/bootstrap-table-en-US.js deleted file mode 100755 index c08db68bef..0000000000 Binary files a/public/js/locale/bootstrap-table-en-US.js and /dev/null differ diff --git a/public/js/locale/bootstrap-table-en-US.min.js b/public/js/locale/bootstrap-table-en-US.min.js deleted file mode 100755 index 21c1a009bd..0000000000 Binary files a/public/js/locale/bootstrap-table-en-US.min.js and /dev/null differ diff --git a/public/js/locale/bootstrap-table-es-AR.js b/public/js/locale/bootstrap-table-es-AR.js deleted file mode 100755 index 6f585f728f..0000000000 Binary files a/public/js/locale/bootstrap-table-es-AR.js and /dev/null differ diff --git a/public/js/locale/bootstrap-table-es-AR.min.js b/public/js/locale/bootstrap-table-es-AR.min.js deleted file mode 100755 index 5534f3dc40..0000000000 Binary files a/public/js/locale/bootstrap-table-es-AR.min.js and /dev/null differ diff --git a/public/js/locale/bootstrap-table-es-CR.js b/public/js/locale/bootstrap-table-es-CR.js deleted file mode 100755 index 7febab73cd..0000000000 Binary files a/public/js/locale/bootstrap-table-es-CR.js and /dev/null differ diff --git a/public/js/locale/bootstrap-table-es-CR.min.js b/public/js/locale/bootstrap-table-es-CR.min.js deleted file mode 100755 index 36cc924203..0000000000 Binary files a/public/js/locale/bootstrap-table-es-CR.min.js and /dev/null differ diff --git a/public/js/locale/bootstrap-table-es-ES.js b/public/js/locale/bootstrap-table-es-ES.js deleted file mode 100755 index 30448d7d80..0000000000 Binary files a/public/js/locale/bootstrap-table-es-ES.js and /dev/null differ diff --git a/public/js/locale/bootstrap-table-es-ES.min.js b/public/js/locale/bootstrap-table-es-ES.min.js deleted file mode 100755 index 185f922bdf..0000000000 Binary files a/public/js/locale/bootstrap-table-es-ES.min.js and /dev/null differ diff --git a/public/js/locale/bootstrap-table-es-MX.js b/public/js/locale/bootstrap-table-es-MX.js deleted file mode 100755 index f745fae2e6..0000000000 Binary files a/public/js/locale/bootstrap-table-es-MX.js and /dev/null differ diff --git a/public/js/locale/bootstrap-table-es-MX.min.js b/public/js/locale/bootstrap-table-es-MX.min.js deleted file mode 100755 index 0bb88df139..0000000000 Binary files a/public/js/locale/bootstrap-table-es-MX.min.js and /dev/null differ diff --git a/public/js/locale/bootstrap-table-es-NI.js b/public/js/locale/bootstrap-table-es-NI.js deleted file mode 100755 index 2e8aa2ab9f..0000000000 Binary files a/public/js/locale/bootstrap-table-es-NI.js and /dev/null differ diff --git a/public/js/locale/bootstrap-table-es-NI.min.js b/public/js/locale/bootstrap-table-es-NI.min.js deleted file mode 100755 index 265af8a048..0000000000 Binary files a/public/js/locale/bootstrap-table-es-NI.min.js and /dev/null differ diff --git a/public/js/locale/bootstrap-table-es-SP.js b/public/js/locale/bootstrap-table-es-SP.js deleted file mode 100755 index 7da9350da8..0000000000 Binary files a/public/js/locale/bootstrap-table-es-SP.js and /dev/null differ diff --git a/public/js/locale/bootstrap-table-es-SP.min.js b/public/js/locale/bootstrap-table-es-SP.min.js deleted file mode 100755 index 3e5d8f895a..0000000000 Binary files a/public/js/locale/bootstrap-table-es-SP.min.js and /dev/null differ diff --git a/public/js/locale/bootstrap-table-et-EE.js b/public/js/locale/bootstrap-table-et-EE.js deleted file mode 100755 index 3d71d10285..0000000000 Binary files a/public/js/locale/bootstrap-table-et-EE.js and /dev/null differ diff --git a/public/js/locale/bootstrap-table-et-EE.min.js b/public/js/locale/bootstrap-table-et-EE.min.js deleted file mode 100755 index e6391cfaa8..0000000000 Binary files a/public/js/locale/bootstrap-table-et-EE.min.js and /dev/null differ diff --git a/public/js/locale/bootstrap-table-fa-IR.js b/public/js/locale/bootstrap-table-fa-IR.js deleted file mode 100755 index 4cdee6e5aa..0000000000 Binary files a/public/js/locale/bootstrap-table-fa-IR.js and /dev/null differ diff --git a/public/js/locale/bootstrap-table-fa-IR.min.js b/public/js/locale/bootstrap-table-fa-IR.min.js deleted file mode 100755 index 0247231d0d..0000000000 Binary files a/public/js/locale/bootstrap-table-fa-IR.min.js and /dev/null differ diff --git a/public/js/locale/bootstrap-table-fr-BE.js b/public/js/locale/bootstrap-table-fr-BE.js deleted file mode 100755 index e4b7cf18e6..0000000000 Binary files a/public/js/locale/bootstrap-table-fr-BE.js and /dev/null differ diff --git a/public/js/locale/bootstrap-table-fr-BE.min.js b/public/js/locale/bootstrap-table-fr-BE.min.js deleted file mode 100755 index 89eb1d54aa..0000000000 Binary files a/public/js/locale/bootstrap-table-fr-BE.min.js and /dev/null differ diff --git a/public/js/locale/bootstrap-table-fr-FR.js b/public/js/locale/bootstrap-table-fr-FR.js deleted file mode 100755 index 802eaf643e..0000000000 Binary files a/public/js/locale/bootstrap-table-fr-FR.js and /dev/null differ diff --git a/public/js/locale/bootstrap-table-fr-FR.min.js b/public/js/locale/bootstrap-table-fr-FR.min.js deleted file mode 100755 index 4cdac8463a..0000000000 Binary files a/public/js/locale/bootstrap-table-fr-FR.min.js and /dev/null differ diff --git a/public/js/locale/bootstrap-table-he-IL.js b/public/js/locale/bootstrap-table-he-IL.js deleted file mode 100755 index 6a4a1790d5..0000000000 Binary files a/public/js/locale/bootstrap-table-he-IL.js and /dev/null differ diff --git a/public/js/locale/bootstrap-table-he-IL.min.js b/public/js/locale/bootstrap-table-he-IL.min.js deleted file mode 100755 index 26e8b51ff8..0000000000 Binary files a/public/js/locale/bootstrap-table-he-IL.min.js and /dev/null differ diff --git a/public/js/locale/bootstrap-table-hr-HR.js b/public/js/locale/bootstrap-table-hr-HR.js deleted file mode 100755 index f63a4fe5f4..0000000000 Binary files a/public/js/locale/bootstrap-table-hr-HR.js and /dev/null differ diff --git a/public/js/locale/bootstrap-table-hr-HR.min.js b/public/js/locale/bootstrap-table-hr-HR.min.js deleted file mode 100755 index 80c7344651..0000000000 Binary files a/public/js/locale/bootstrap-table-hr-HR.min.js and /dev/null differ diff --git a/public/js/locale/bootstrap-table-hu-HU.js b/public/js/locale/bootstrap-table-hu-HU.js deleted file mode 100755 index 353f098359..0000000000 Binary files a/public/js/locale/bootstrap-table-hu-HU.js and /dev/null differ diff --git a/public/js/locale/bootstrap-table-hu-HU.min.js b/public/js/locale/bootstrap-table-hu-HU.min.js deleted file mode 100755 index f48207f814..0000000000 Binary files a/public/js/locale/bootstrap-table-hu-HU.min.js and /dev/null differ diff --git a/public/js/locale/bootstrap-table-it-IT.js b/public/js/locale/bootstrap-table-it-IT.js deleted file mode 100755 index 0c2ea74751..0000000000 Binary files a/public/js/locale/bootstrap-table-it-IT.js and /dev/null differ diff --git a/public/js/locale/bootstrap-table-it-IT.min.js b/public/js/locale/bootstrap-table-it-IT.min.js deleted file mode 100755 index 32d1e98ac4..0000000000 Binary files a/public/js/locale/bootstrap-table-it-IT.min.js and /dev/null differ diff --git a/public/js/locale/bootstrap-table-ja-JP.js b/public/js/locale/bootstrap-table-ja-JP.js deleted file mode 100755 index 3a0f3eca8f..0000000000 Binary files a/public/js/locale/bootstrap-table-ja-JP.js and /dev/null differ diff --git a/public/js/locale/bootstrap-table-ja-JP.min.js b/public/js/locale/bootstrap-table-ja-JP.min.js deleted file mode 100755 index baf977d39f..0000000000 Binary files a/public/js/locale/bootstrap-table-ja-JP.min.js and /dev/null differ diff --git a/public/js/locale/bootstrap-table-ka-GE.js b/public/js/locale/bootstrap-table-ka-GE.js deleted file mode 100755 index 05da1421dd..0000000000 Binary files a/public/js/locale/bootstrap-table-ka-GE.js and /dev/null differ diff --git a/public/js/locale/bootstrap-table-ka-GE.min.js b/public/js/locale/bootstrap-table-ka-GE.min.js deleted file mode 100755 index 61cedd1a2f..0000000000 Binary files a/public/js/locale/bootstrap-table-ka-GE.min.js and /dev/null differ diff --git a/public/js/locale/bootstrap-table-ko-KR.js b/public/js/locale/bootstrap-table-ko-KR.js deleted file mode 100755 index c8cf703f4e..0000000000 Binary files a/public/js/locale/bootstrap-table-ko-KR.js and /dev/null differ diff --git a/public/js/locale/bootstrap-table-ko-KR.min.js b/public/js/locale/bootstrap-table-ko-KR.min.js deleted file mode 100755 index 6228ff6c6b..0000000000 Binary files a/public/js/locale/bootstrap-table-ko-KR.min.js and /dev/null differ diff --git a/public/js/locale/bootstrap-table-ms-MY.js b/public/js/locale/bootstrap-table-ms-MY.js deleted file mode 100755 index edb5eb61c9..0000000000 Binary files a/public/js/locale/bootstrap-table-ms-MY.js and /dev/null differ diff --git a/public/js/locale/bootstrap-table-ms-MY.min.js b/public/js/locale/bootstrap-table-ms-MY.min.js deleted file mode 100755 index 5bc0938562..0000000000 Binary files a/public/js/locale/bootstrap-table-ms-MY.min.js and /dev/null differ diff --git a/public/js/locale/bootstrap-table-nb-NO.js b/public/js/locale/bootstrap-table-nb-NO.js deleted file mode 100755 index 473051d257..0000000000 Binary files a/public/js/locale/bootstrap-table-nb-NO.js and /dev/null differ diff --git a/public/js/locale/bootstrap-table-nb-NO.min.js b/public/js/locale/bootstrap-table-nb-NO.min.js deleted file mode 100755 index 93fe50d01e..0000000000 Binary files a/public/js/locale/bootstrap-table-nb-NO.min.js and /dev/null differ diff --git a/public/js/locale/bootstrap-table-nl-NL.js b/public/js/locale/bootstrap-table-nl-NL.js deleted file mode 100755 index 72fa064f3f..0000000000 Binary files a/public/js/locale/bootstrap-table-nl-NL.js and /dev/null differ diff --git a/public/js/locale/bootstrap-table-nl-NL.min.js b/public/js/locale/bootstrap-table-nl-NL.min.js deleted file mode 100755 index cb134bcc13..0000000000 Binary files a/public/js/locale/bootstrap-table-nl-NL.min.js and /dev/null differ diff --git a/public/js/locale/bootstrap-table-pl-PL.js b/public/js/locale/bootstrap-table-pl-PL.js deleted file mode 100755 index af79be26dd..0000000000 Binary files a/public/js/locale/bootstrap-table-pl-PL.js and /dev/null differ diff --git a/public/js/locale/bootstrap-table-pl-PL.min.js b/public/js/locale/bootstrap-table-pl-PL.min.js deleted file mode 100755 index fe92d796b3..0000000000 Binary files a/public/js/locale/bootstrap-table-pl-PL.min.js and /dev/null differ diff --git a/public/js/locale/bootstrap-table-pt-BR.js b/public/js/locale/bootstrap-table-pt-BR.js deleted file mode 100755 index 63319a1111..0000000000 Binary files a/public/js/locale/bootstrap-table-pt-BR.js and /dev/null differ diff --git a/public/js/locale/bootstrap-table-pt-BR.min.js b/public/js/locale/bootstrap-table-pt-BR.min.js deleted file mode 100755 index e96cadc4b1..0000000000 Binary files a/public/js/locale/bootstrap-table-pt-BR.min.js and /dev/null differ diff --git a/public/js/locale/bootstrap-table-pt-PT.js b/public/js/locale/bootstrap-table-pt-PT.js deleted file mode 100755 index cb0b68277a..0000000000 Binary files a/public/js/locale/bootstrap-table-pt-PT.js and /dev/null differ diff --git a/public/js/locale/bootstrap-table-pt-PT.min.js b/public/js/locale/bootstrap-table-pt-PT.min.js deleted file mode 100755 index 7f5c35f079..0000000000 Binary files a/public/js/locale/bootstrap-table-pt-PT.min.js and /dev/null differ diff --git a/public/js/locale/bootstrap-table-ro-RO.js b/public/js/locale/bootstrap-table-ro-RO.js deleted file mode 100755 index 64cd1a7cb9..0000000000 Binary files a/public/js/locale/bootstrap-table-ro-RO.js and /dev/null differ diff --git a/public/js/locale/bootstrap-table-ro-RO.min.js b/public/js/locale/bootstrap-table-ro-RO.min.js deleted file mode 100755 index dbe23b9d66..0000000000 Binary files a/public/js/locale/bootstrap-table-ro-RO.min.js and /dev/null differ diff --git a/public/js/locale/bootstrap-table-ru-RU.js b/public/js/locale/bootstrap-table-ru-RU.js deleted file mode 100755 index 49d6ee271d..0000000000 Binary files a/public/js/locale/bootstrap-table-ru-RU.js and /dev/null differ diff --git a/public/js/locale/bootstrap-table-ru-RU.min.js b/public/js/locale/bootstrap-table-ru-RU.min.js deleted file mode 100755 index 7bb74db228..0000000000 Binary files a/public/js/locale/bootstrap-table-ru-RU.min.js and /dev/null differ diff --git a/public/js/locale/bootstrap-table-sk-SK.js b/public/js/locale/bootstrap-table-sk-SK.js deleted file mode 100755 index 1762762f1f..0000000000 Binary files a/public/js/locale/bootstrap-table-sk-SK.js and /dev/null differ diff --git a/public/js/locale/bootstrap-table-sk-SK.min.js b/public/js/locale/bootstrap-table-sk-SK.min.js deleted file mode 100755 index 1ffa3f6d10..0000000000 Binary files a/public/js/locale/bootstrap-table-sk-SK.min.js and /dev/null differ diff --git a/public/js/locale/bootstrap-table-sv-SE.js b/public/js/locale/bootstrap-table-sv-SE.js deleted file mode 100755 index 67b8eb4f6a..0000000000 Binary files a/public/js/locale/bootstrap-table-sv-SE.js and /dev/null differ diff --git a/public/js/locale/bootstrap-table-sv-SE.min.js b/public/js/locale/bootstrap-table-sv-SE.min.js deleted file mode 100755 index fcb1bc1df0..0000000000 Binary files a/public/js/locale/bootstrap-table-sv-SE.min.js and /dev/null differ diff --git a/public/js/locale/bootstrap-table-th-TH.js b/public/js/locale/bootstrap-table-th-TH.js deleted file mode 100755 index 938216888a..0000000000 Binary files a/public/js/locale/bootstrap-table-th-TH.js and /dev/null differ diff --git a/public/js/locale/bootstrap-table-th-TH.min.js b/public/js/locale/bootstrap-table-th-TH.min.js deleted file mode 100755 index f082014274..0000000000 Binary files a/public/js/locale/bootstrap-table-th-TH.min.js and /dev/null differ diff --git a/public/js/locale/bootstrap-table-tr-TR.js b/public/js/locale/bootstrap-table-tr-TR.js deleted file mode 100755 index df38a7900a..0000000000 Binary files a/public/js/locale/bootstrap-table-tr-TR.js and /dev/null differ diff --git a/public/js/locale/bootstrap-table-tr-TR.min.js b/public/js/locale/bootstrap-table-tr-TR.min.js deleted file mode 100755 index 595df9bd18..0000000000 Binary files a/public/js/locale/bootstrap-table-tr-TR.min.js and /dev/null differ diff --git a/public/js/locale/bootstrap-table-uk-UA.js b/public/js/locale/bootstrap-table-uk-UA.js deleted file mode 100755 index 6460fe3cdf..0000000000 Binary files a/public/js/locale/bootstrap-table-uk-UA.js and /dev/null differ diff --git a/public/js/locale/bootstrap-table-uk-UA.min.js b/public/js/locale/bootstrap-table-uk-UA.min.js deleted file mode 100755 index bc4a8d015e..0000000000 Binary files a/public/js/locale/bootstrap-table-uk-UA.min.js and /dev/null differ diff --git a/public/js/locale/bootstrap-table-ur-PK.js b/public/js/locale/bootstrap-table-ur-PK.js deleted file mode 100755 index 466498cf7c..0000000000 Binary files a/public/js/locale/bootstrap-table-ur-PK.js and /dev/null differ diff --git a/public/js/locale/bootstrap-table-ur-PK.min.js b/public/js/locale/bootstrap-table-ur-PK.min.js deleted file mode 100755 index cf77a8a95b..0000000000 Binary files a/public/js/locale/bootstrap-table-ur-PK.min.js and /dev/null differ diff --git a/public/js/locale/bootstrap-table-vi-VN.js b/public/js/locale/bootstrap-table-vi-VN.js deleted file mode 100755 index 42c81038b3..0000000000 Binary files a/public/js/locale/bootstrap-table-vi-VN.js and /dev/null differ diff --git a/public/js/locale/bootstrap-table-vi-VN.min.js b/public/js/locale/bootstrap-table-vi-VN.min.js deleted file mode 100755 index 42ab0e1558..0000000000 Binary files a/public/js/locale/bootstrap-table-vi-VN.min.js and /dev/null differ diff --git a/public/js/locale/bootstrap-table-zh-CN.js b/public/js/locale/bootstrap-table-zh-CN.js deleted file mode 100755 index e352922de3..0000000000 Binary files a/public/js/locale/bootstrap-table-zh-CN.js and /dev/null differ diff --git a/public/js/locale/bootstrap-table-zh-CN.min.js b/public/js/locale/bootstrap-table-zh-CN.min.js deleted file mode 100755 index e903fdf88e..0000000000 Binary files a/public/js/locale/bootstrap-table-zh-CN.min.js and /dev/null differ diff --git a/public/js/locale/bootstrap-table-zh-TW.js b/public/js/locale/bootstrap-table-zh-TW.js deleted file mode 100755 index ff3484f643..0000000000 Binary files a/public/js/locale/bootstrap-table-zh-TW.js and /dev/null differ diff --git a/public/js/locale/bootstrap-table-zh-TW.min.js b/public/js/locale/bootstrap-table-zh-TW.min.js deleted file mode 100755 index 87c11db147..0000000000 Binary files a/public/js/locale/bootstrap-table-zh-TW.min.js and /dev/null differ diff --git a/public/js/metisMenu.js b/public/js/metisMenu.js deleted file mode 100755 index 3785904513..0000000000 Binary files a/public/js/metisMenu.js and /dev/null differ diff --git a/public/js/metisMenu.min.js b/public/js/metisMenu.min.js deleted file mode 100755 index 8a590e75ff..0000000000 Binary files a/public/js/metisMenu.min.js and /dev/null differ diff --git a/public/js/pGenerator.jquery.js b/public/js/pGenerator.jquery.js deleted file mode 100755 index 466cf22d1d..0000000000 Binary files a/public/js/pGenerator.jquery.js and /dev/null differ diff --git a/public/js/plugins/bootstrap-slider/bootstrap-slider.js b/public/js/plugins/bootstrap-slider/bootstrap-slider.js deleted file mode 100755 index 2e072fe6af..0000000000 Binary files a/public/js/plugins/bootstrap-slider/bootstrap-slider.js and /dev/null differ diff --git a/public/js/plugins/bootstrap-slider/slider.css b/public/js/plugins/bootstrap-slider/slider.css deleted file mode 100755 index a96db7fb71..0000000000 Binary files a/public/js/plugins/bootstrap-slider/slider.css and /dev/null differ diff --git a/public/js/plugins/bootstrap-wysihtml5/bootstrap3-wysihtml5.all.js b/public/js/plugins/bootstrap-wysihtml5/bootstrap3-wysihtml5.all.js deleted file mode 100755 index acccf91e01..0000000000 Binary files a/public/js/plugins/bootstrap-wysihtml5/bootstrap3-wysihtml5.all.js and /dev/null differ diff --git a/public/js/plugins/bootstrap-wysihtml5/bootstrap3-wysihtml5.all.min.js b/public/js/plugins/bootstrap-wysihtml5/bootstrap3-wysihtml5.all.min.js deleted file mode 100755 index 58765c0727..0000000000 Binary files a/public/js/plugins/bootstrap-wysihtml5/bootstrap3-wysihtml5.all.min.js and /dev/null differ diff --git a/public/js/plugins/bootstrap-wysihtml5/bootstrap3-wysihtml5.css b/public/js/plugins/bootstrap-wysihtml5/bootstrap3-wysihtml5.css deleted file mode 100755 index 51c58df889..0000000000 Binary files a/public/js/plugins/bootstrap-wysihtml5/bootstrap3-wysihtml5.css and /dev/null differ diff --git a/public/js/plugins/bootstrap-wysihtml5/bootstrap3-wysihtml5.min.css b/public/js/plugins/bootstrap-wysihtml5/bootstrap3-wysihtml5.min.css deleted file mode 100755 index 28f1831675..0000000000 Binary files a/public/js/plugins/bootstrap-wysihtml5/bootstrap3-wysihtml5.min.css and /dev/null differ diff --git a/public/js/plugins/chartjs/Chart.bundle.js b/public/js/plugins/chartjs/Chart.bundle.js deleted file mode 100755 index 3d954455d7..0000000000 Binary files a/public/js/plugins/chartjs/Chart.bundle.js and /dev/null differ diff --git a/public/js/plugins/chartjs/Chart.bundle.min.js b/public/js/plugins/chartjs/Chart.bundle.min.js deleted file mode 100755 index 3b96e43d2c..0000000000 Binary files a/public/js/plugins/chartjs/Chart.bundle.min.js and /dev/null differ diff --git a/public/js/plugins/chartjs/Chart.js b/public/js/plugins/chartjs/Chart.js deleted file mode 100755 index e88c315999..0000000000 Binary files a/public/js/plugins/chartjs/Chart.js and /dev/null differ diff --git a/public/js/plugins/chartjs/Chart.min.js b/public/js/plugins/chartjs/Chart.min.js deleted file mode 100755 index e4623645af..0000000000 Binary files a/public/js/plugins/chartjs/Chart.min.js and /dev/null differ diff --git a/public/js/plugins/colorpicker/bootstrap-colorpicker.css b/public/js/plugins/colorpicker/bootstrap-colorpicker.css deleted file mode 100755 index ba4365e281..0000000000 Binary files a/public/js/plugins/colorpicker/bootstrap-colorpicker.css and /dev/null differ diff --git a/public/js/plugins/colorpicker/bootstrap-colorpicker.js b/public/js/plugins/colorpicker/bootstrap-colorpicker.js deleted file mode 100755 index 2200b0cc97..0000000000 Binary files a/public/js/plugins/colorpicker/bootstrap-colorpicker.js and /dev/null differ diff --git a/public/js/plugins/colorpicker/bootstrap-colorpicker.min.css b/public/js/plugins/colorpicker/bootstrap-colorpicker.min.css deleted file mode 100755 index 16a2d1a0ff..0000000000 Binary files a/public/js/plugins/colorpicker/bootstrap-colorpicker.min.css and /dev/null differ diff --git a/public/js/plugins/colorpicker/bootstrap-colorpicker.min.js b/public/js/plugins/colorpicker/bootstrap-colorpicker.min.js deleted file mode 100755 index bc4fba9efe..0000000000 Binary files a/public/js/plugins/colorpicker/bootstrap-colorpicker.min.js and /dev/null differ diff --git a/public/js/plugins/colorpicker/img/alpha-horizontal.png b/public/js/plugins/colorpicker/img/alpha-horizontal.png deleted file mode 100755 index d0a65c08b0..0000000000 Binary files a/public/js/plugins/colorpicker/img/alpha-horizontal.png and /dev/null differ diff --git a/public/js/plugins/colorpicker/img/alpha.png b/public/js/plugins/colorpicker/img/alpha.png deleted file mode 100755 index 38043f1c85..0000000000 Binary files a/public/js/plugins/colorpicker/img/alpha.png and /dev/null differ diff --git a/public/js/plugins/colorpicker/img/hue-horizontal.png b/public/js/plugins/colorpicker/img/hue-horizontal.png deleted file mode 100755 index a0d9add8e7..0000000000 Binary files a/public/js/plugins/colorpicker/img/hue-horizontal.png and /dev/null differ diff --git a/public/js/plugins/colorpicker/img/hue.png b/public/js/plugins/colorpicker/img/hue.png deleted file mode 100755 index d89560e999..0000000000 Binary files a/public/js/plugins/colorpicker/img/hue.png and /dev/null differ diff --git a/public/js/plugins/colorpicker/img/saturation.png b/public/js/plugins/colorpicker/img/saturation.png deleted file mode 100755 index 594ae50ed7..0000000000 Binary files a/public/js/plugins/colorpicker/img/saturation.png and /dev/null differ diff --git a/public/js/plugins/datepicker/bootstrap-datepicker.css b/public/js/plugins/datepicker/bootstrap-datepicker.css deleted file mode 100755 index 5d0925edc3..0000000000 Binary files a/public/js/plugins/datepicker/bootstrap-datepicker.css and /dev/null differ diff --git a/public/js/plugins/datepicker/bootstrap-datepicker.js b/public/js/plugins/datepicker/bootstrap-datepicker.js deleted file mode 100755 index e53af251c5..0000000000 Binary files a/public/js/plugins/datepicker/bootstrap-datepicker.js and /dev/null differ diff --git a/public/js/plugins/datepicker/datepicker3.css b/public/js/plugins/datepicker/datepicker3.css deleted file mode 100755 index d9c3fb6b52..0000000000 Binary files a/public/js/plugins/datepicker/datepicker3.css and /dev/null differ diff --git a/public/js/plugins/datepicker/locales/bootstrap-datepicker.ar.js b/public/js/plugins/datepicker/locales/bootstrap-datepicker.ar.js deleted file mode 100755 index 12ae1821d5..0000000000 Binary files a/public/js/plugins/datepicker/locales/bootstrap-datepicker.ar.js and /dev/null differ diff --git a/public/js/plugins/datepicker/locales/bootstrap-datepicker.az.js b/public/js/plugins/datepicker/locales/bootstrap-datepicker.az.js deleted file mode 100755 index 0285341cac..0000000000 Binary files a/public/js/plugins/datepicker/locales/bootstrap-datepicker.az.js and /dev/null differ diff --git a/public/js/plugins/datepicker/locales/bootstrap-datepicker.bg.js b/public/js/plugins/datepicker/locales/bootstrap-datepicker.bg.js deleted file mode 100755 index 6837afd9cb..0000000000 Binary files a/public/js/plugins/datepicker/locales/bootstrap-datepicker.bg.js and /dev/null differ diff --git a/public/js/plugins/datepicker/locales/bootstrap-datepicker.ca.js b/public/js/plugins/datepicker/locales/bootstrap-datepicker.ca.js deleted file mode 100755 index 3fc4d844a5..0000000000 Binary files a/public/js/plugins/datepicker/locales/bootstrap-datepicker.ca.js and /dev/null differ diff --git a/public/js/plugins/datepicker/locales/bootstrap-datepicker.cs.js b/public/js/plugins/datepicker/locales/bootstrap-datepicker.cs.js deleted file mode 100755 index f76a2c0824..0000000000 Binary files a/public/js/plugins/datepicker/locales/bootstrap-datepicker.cs.js and /dev/null differ diff --git a/public/js/plugins/datepicker/locales/bootstrap-datepicker.cy.js b/public/js/plugins/datepicker/locales/bootstrap-datepicker.cy.js deleted file mode 100755 index 7e1136ab62..0000000000 Binary files a/public/js/plugins/datepicker/locales/bootstrap-datepicker.cy.js and /dev/null differ diff --git a/public/js/plugins/datepicker/locales/bootstrap-datepicker.da.js b/public/js/plugins/datepicker/locales/bootstrap-datepicker.da.js deleted file mode 100755 index c3d702d451..0000000000 Binary files a/public/js/plugins/datepicker/locales/bootstrap-datepicker.da.js and /dev/null differ diff --git a/public/js/plugins/datepicker/locales/bootstrap-datepicker.de.js b/public/js/plugins/datepicker/locales/bootstrap-datepicker.de.js deleted file mode 100755 index a27ba578ef..0000000000 Binary files a/public/js/plugins/datepicker/locales/bootstrap-datepicker.de.js and /dev/null differ diff --git a/public/js/plugins/datepicker/locales/bootstrap-datepicker.el.js b/public/js/plugins/datepicker/locales/bootstrap-datepicker.el.js deleted file mode 100755 index 3b630f387d..0000000000 Binary files a/public/js/plugins/datepicker/locales/bootstrap-datepicker.el.js and /dev/null differ diff --git a/public/js/plugins/datepicker/locales/bootstrap-datepicker.es.js b/public/js/plugins/datepicker/locales/bootstrap-datepicker.es.js deleted file mode 100755 index 72176902d1..0000000000 Binary files a/public/js/plugins/datepicker/locales/bootstrap-datepicker.es.js and /dev/null differ diff --git a/public/js/plugins/datepicker/locales/bootstrap-datepicker.et.js b/public/js/plugins/datepicker/locales/bootstrap-datepicker.et.js deleted file mode 100755 index 87c812ed58..0000000000 Binary files a/public/js/plugins/datepicker/locales/bootstrap-datepicker.et.js and /dev/null differ diff --git a/public/js/plugins/datepicker/locales/bootstrap-datepicker.fa.js b/public/js/plugins/datepicker/locales/bootstrap-datepicker.fa.js deleted file mode 100755 index 6503c85dd4..0000000000 Binary files a/public/js/plugins/datepicker/locales/bootstrap-datepicker.fa.js and /dev/null differ diff --git a/public/js/plugins/datepicker/locales/bootstrap-datepicker.fi.js b/public/js/plugins/datepicker/locales/bootstrap-datepicker.fi.js deleted file mode 100755 index 01f40dc2fe..0000000000 Binary files a/public/js/plugins/datepicker/locales/bootstrap-datepicker.fi.js and /dev/null differ diff --git a/public/js/plugins/datepicker/locales/bootstrap-datepicker.fr.js b/public/js/plugins/datepicker/locales/bootstrap-datepicker.fr.js deleted file mode 100755 index eff07aa6f7..0000000000 Binary files a/public/js/plugins/datepicker/locales/bootstrap-datepicker.fr.js and /dev/null differ diff --git a/public/js/plugins/datepicker/locales/bootstrap-datepicker.gl.js b/public/js/plugins/datepicker/locales/bootstrap-datepicker.gl.js deleted file mode 100755 index 538fd5e3b8..0000000000 Binary files a/public/js/plugins/datepicker/locales/bootstrap-datepicker.gl.js and /dev/null differ diff --git a/public/js/plugins/datepicker/locales/bootstrap-datepicker.he.js b/public/js/plugins/datepicker/locales/bootstrap-datepicker.he.js deleted file mode 100755 index 2e17393b12..0000000000 Binary files a/public/js/plugins/datepicker/locales/bootstrap-datepicker.he.js and /dev/null differ diff --git a/public/js/plugins/datepicker/locales/bootstrap-datepicker.hr.js b/public/js/plugins/datepicker/locales/bootstrap-datepicker.hr.js deleted file mode 100755 index 655ea54b40..0000000000 Binary files a/public/js/plugins/datepicker/locales/bootstrap-datepicker.hr.js and /dev/null differ diff --git a/public/js/plugins/datepicker/locales/bootstrap-datepicker.hu.js b/public/js/plugins/datepicker/locales/bootstrap-datepicker.hu.js deleted file mode 100755 index bf5308a136..0000000000 Binary files a/public/js/plugins/datepicker/locales/bootstrap-datepicker.hu.js and /dev/null differ diff --git a/public/js/plugins/datepicker/locales/bootstrap-datepicker.id.js b/public/js/plugins/datepicker/locales/bootstrap-datepicker.id.js deleted file mode 100755 index aae6e8960c..0000000000 Binary files a/public/js/plugins/datepicker/locales/bootstrap-datepicker.id.js and /dev/null differ diff --git a/public/js/plugins/datepicker/locales/bootstrap-datepicker.is.js b/public/js/plugins/datepicker/locales/bootstrap-datepicker.is.js deleted file mode 100755 index 0e57a91681..0000000000 Binary files a/public/js/plugins/datepicker/locales/bootstrap-datepicker.is.js and /dev/null differ diff --git a/public/js/plugins/datepicker/locales/bootstrap-datepicker.it.js b/public/js/plugins/datepicker/locales/bootstrap-datepicker.it.js deleted file mode 100755 index 9f476fa232..0000000000 Binary files a/public/js/plugins/datepicker/locales/bootstrap-datepicker.it.js and /dev/null differ diff --git a/public/js/plugins/datepicker/locales/bootstrap-datepicker.ja.js b/public/js/plugins/datepicker/locales/bootstrap-datepicker.ja.js deleted file mode 100755 index ed0bc0f9db..0000000000 Binary files a/public/js/plugins/datepicker/locales/bootstrap-datepicker.ja.js and /dev/null differ diff --git a/public/js/plugins/datepicker/locales/bootstrap-datepicker.ka.js b/public/js/plugins/datepicker/locales/bootstrap-datepicker.ka.js deleted file mode 100755 index 5434454943..0000000000 Binary files a/public/js/plugins/datepicker/locales/bootstrap-datepicker.ka.js and /dev/null differ diff --git a/public/js/plugins/datepicker/locales/bootstrap-datepicker.kk.js b/public/js/plugins/datepicker/locales/bootstrap-datepicker.kk.js deleted file mode 100755 index 94dd6b8f12..0000000000 Binary files a/public/js/plugins/datepicker/locales/bootstrap-datepicker.kk.js and /dev/null differ diff --git a/public/js/plugins/datepicker/locales/bootstrap-datepicker.kr.js b/public/js/plugins/datepicker/locales/bootstrap-datepicker.kr.js deleted file mode 100755 index 183a88d159..0000000000 Binary files a/public/js/plugins/datepicker/locales/bootstrap-datepicker.kr.js and /dev/null differ diff --git a/public/js/plugins/datepicker/locales/bootstrap-datepicker.lt.js b/public/js/plugins/datepicker/locales/bootstrap-datepicker.lt.js deleted file mode 100755 index 11c1b3ad41..0000000000 Binary files a/public/js/plugins/datepicker/locales/bootstrap-datepicker.lt.js and /dev/null differ diff --git a/public/js/plugins/datepicker/locales/bootstrap-datepicker.lv.js b/public/js/plugins/datepicker/locales/bootstrap-datepicker.lv.js deleted file mode 100755 index 76d0f3a6cb..0000000000 Binary files a/public/js/plugins/datepicker/locales/bootstrap-datepicker.lv.js and /dev/null differ diff --git a/public/js/plugins/datepicker/locales/bootstrap-datepicker.mk.js b/public/js/plugins/datepicker/locales/bootstrap-datepicker.mk.js deleted file mode 100755 index 0ab8cf6814..0000000000 Binary files a/public/js/plugins/datepicker/locales/bootstrap-datepicker.mk.js and /dev/null differ diff --git a/public/js/plugins/datepicker/locales/bootstrap-datepicker.ms.js b/public/js/plugins/datepicker/locales/bootstrap-datepicker.ms.js deleted file mode 100755 index fa3a21a54d..0000000000 Binary files a/public/js/plugins/datepicker/locales/bootstrap-datepicker.ms.js and /dev/null differ diff --git a/public/js/plugins/datepicker/locales/bootstrap-datepicker.nb.js b/public/js/plugins/datepicker/locales/bootstrap-datepicker.nb.js deleted file mode 100755 index 7b28e84f5c..0000000000 Binary files a/public/js/plugins/datepicker/locales/bootstrap-datepicker.nb.js and /dev/null differ diff --git a/public/js/plugins/datepicker/locales/bootstrap-datepicker.nl-BE.js b/public/js/plugins/datepicker/locales/bootstrap-datepicker.nl-BE.js deleted file mode 100755 index ee4201a669..0000000000 Binary files a/public/js/plugins/datepicker/locales/bootstrap-datepicker.nl-BE.js and /dev/null differ diff --git a/public/js/plugins/datepicker/locales/bootstrap-datepicker.nl.js b/public/js/plugins/datepicker/locales/bootstrap-datepicker.nl.js deleted file mode 100755 index 13a2f1a358..0000000000 Binary files a/public/js/plugins/datepicker/locales/bootstrap-datepicker.nl.js and /dev/null differ diff --git a/public/js/plugins/datepicker/locales/bootstrap-datepicker.no.js b/public/js/plugins/datepicker/locales/bootstrap-datepicker.no.js deleted file mode 100755 index c29ec83bc1..0000000000 Binary files a/public/js/plugins/datepicker/locales/bootstrap-datepicker.no.js and /dev/null differ diff --git a/public/js/plugins/datepicker/locales/bootstrap-datepicker.pl.js b/public/js/plugins/datepicker/locales/bootstrap-datepicker.pl.js deleted file mode 100755 index f3fff8c8ff..0000000000 Binary files a/public/js/plugins/datepicker/locales/bootstrap-datepicker.pl.js and /dev/null differ diff --git a/public/js/plugins/datepicker/locales/bootstrap-datepicker.pt-BR.js b/public/js/plugins/datepicker/locales/bootstrap-datepicker.pt-BR.js deleted file mode 100755 index eb642b7c77..0000000000 Binary files a/public/js/plugins/datepicker/locales/bootstrap-datepicker.pt-BR.js and /dev/null differ diff --git a/public/js/plugins/datepicker/locales/bootstrap-datepicker.pt.js b/public/js/plugins/datepicker/locales/bootstrap-datepicker.pt.js deleted file mode 100755 index e54981d330..0000000000 Binary files a/public/js/plugins/datepicker/locales/bootstrap-datepicker.pt.js and /dev/null differ diff --git a/public/js/plugins/datepicker/locales/bootstrap-datepicker.ro.js b/public/js/plugins/datepicker/locales/bootstrap-datepicker.ro.js deleted file mode 100755 index e1e65df2ed..0000000000 Binary files a/public/js/plugins/datepicker/locales/bootstrap-datepicker.ro.js and /dev/null differ diff --git a/public/js/plugins/datepicker/locales/bootstrap-datepicker.rs-latin.js b/public/js/plugins/datepicker/locales/bootstrap-datepicker.rs-latin.js deleted file mode 100755 index d94248526d..0000000000 Binary files a/public/js/plugins/datepicker/locales/bootstrap-datepicker.rs-latin.js and /dev/null differ diff --git a/public/js/plugins/datepicker/locales/bootstrap-datepicker.rs.js b/public/js/plugins/datepicker/locales/bootstrap-datepicker.rs.js deleted file mode 100755 index 6b65747332..0000000000 Binary files a/public/js/plugins/datepicker/locales/bootstrap-datepicker.rs.js and /dev/null differ diff --git a/public/js/plugins/datepicker/locales/bootstrap-datepicker.ru.js b/public/js/plugins/datepicker/locales/bootstrap-datepicker.ru.js deleted file mode 100755 index e230aa92a4..0000000000 Binary files a/public/js/plugins/datepicker/locales/bootstrap-datepicker.ru.js and /dev/null differ diff --git a/public/js/plugins/datepicker/locales/bootstrap-datepicker.sk.js b/public/js/plugins/datepicker/locales/bootstrap-datepicker.sk.js deleted file mode 100755 index c48032a562..0000000000 Binary files a/public/js/plugins/datepicker/locales/bootstrap-datepicker.sk.js and /dev/null differ diff --git a/public/js/plugins/datepicker/locales/bootstrap-datepicker.sl.js b/public/js/plugins/datepicker/locales/bootstrap-datepicker.sl.js deleted file mode 100755 index 41b0e06033..0000000000 Binary files a/public/js/plugins/datepicker/locales/bootstrap-datepicker.sl.js and /dev/null differ diff --git a/public/js/plugins/datepicker/locales/bootstrap-datepicker.sq.js b/public/js/plugins/datepicker/locales/bootstrap-datepicker.sq.js deleted file mode 100755 index a045a9d9a1..0000000000 Binary files a/public/js/plugins/datepicker/locales/bootstrap-datepicker.sq.js and /dev/null differ diff --git a/public/js/plugins/datepicker/locales/bootstrap-datepicker.sv.js b/public/js/plugins/datepicker/locales/bootstrap-datepicker.sv.js deleted file mode 100755 index 029cea0032..0000000000 Binary files a/public/js/plugins/datepicker/locales/bootstrap-datepicker.sv.js and /dev/null differ diff --git a/public/js/plugins/datepicker/locales/bootstrap-datepicker.sw.js b/public/js/plugins/datepicker/locales/bootstrap-datepicker.sw.js deleted file mode 100755 index 622e0ef0d7..0000000000 Binary files a/public/js/plugins/datepicker/locales/bootstrap-datepicker.sw.js and /dev/null differ diff --git a/public/js/plugins/datepicker/locales/bootstrap-datepicker.th.js b/public/js/plugins/datepicker/locales/bootstrap-datepicker.th.js deleted file mode 100755 index 562b063c50..0000000000 Binary files a/public/js/plugins/datepicker/locales/bootstrap-datepicker.th.js and /dev/null differ diff --git a/public/js/plugins/datepicker/locales/bootstrap-datepicker.tr.js b/public/js/plugins/datepicker/locales/bootstrap-datepicker.tr.js deleted file mode 100755 index 2be8b6d830..0000000000 Binary files a/public/js/plugins/datepicker/locales/bootstrap-datepicker.tr.js and /dev/null differ diff --git a/public/js/plugins/datepicker/locales/bootstrap-datepicker.ua.js b/public/js/plugins/datepicker/locales/bootstrap-datepicker.ua.js deleted file mode 100755 index d4bb0f028a..0000000000 Binary files a/public/js/plugins/datepicker/locales/bootstrap-datepicker.ua.js and /dev/null differ diff --git a/public/js/plugins/datepicker/locales/bootstrap-datepicker.vi.js b/public/js/plugins/datepicker/locales/bootstrap-datepicker.vi.js deleted file mode 100755 index a8cc52eec3..0000000000 Binary files a/public/js/plugins/datepicker/locales/bootstrap-datepicker.vi.js and /dev/null differ diff --git a/public/js/plugins/datepicker/locales/bootstrap-datepicker.zh-CN.js b/public/js/plugins/datepicker/locales/bootstrap-datepicker.zh-CN.js deleted file mode 100755 index d6625ec61d..0000000000 Binary files a/public/js/plugins/datepicker/locales/bootstrap-datepicker.zh-CN.js and /dev/null differ diff --git a/public/js/plugins/datepicker/locales/bootstrap-datepicker.zh-TW.js b/public/js/plugins/datepicker/locales/bootstrap-datepicker.zh-TW.js deleted file mode 100755 index 53337ae06b..0000000000 Binary files a/public/js/plugins/datepicker/locales/bootstrap-datepicker.zh-TW.js and /dev/null differ diff --git a/public/js/plugins/daterangepicker/daterangepicker-bs3.css b/public/js/plugins/daterangepicker/daterangepicker-bs3.css deleted file mode 100755 index 7a501fb0ef..0000000000 Binary files a/public/js/plugins/daterangepicker/daterangepicker-bs3.css and /dev/null differ diff --git a/public/js/plugins/daterangepicker/daterangepicker.js b/public/js/plugins/daterangepicker/daterangepicker.js deleted file mode 100755 index 228612b9bb..0000000000 Binary files a/public/js/plugins/daterangepicker/daterangepicker.js and /dev/null differ diff --git a/public/js/plugins/daterangepicker/moment.js b/public/js/plugins/daterangepicker/moment.js deleted file mode 100755 index c635ec0b35..0000000000 Binary files a/public/js/plugins/daterangepicker/moment.js and /dev/null differ diff --git a/public/js/plugins/daterangepicker/moment.min.js b/public/js/plugins/daterangepicker/moment.min.js deleted file mode 100755 index 024d488fbc..0000000000 Binary files a/public/js/plugins/daterangepicker/moment.min.js and /dev/null differ diff --git a/public/js/plugins/fastclick/fastclick.js b/public/js/plugins/fastclick/fastclick.js deleted file mode 100755 index 3af4f9d6f1..0000000000 Binary files a/public/js/plugins/fastclick/fastclick.js and /dev/null differ diff --git a/public/js/plugins/fastclick/fastclick.min.js b/public/js/plugins/fastclick/fastclick.min.js deleted file mode 100755 index 131e29e46b..0000000000 Binary files a/public/js/plugins/fastclick/fastclick.min.js and /dev/null differ diff --git a/public/js/plugins/flot/excanvas.js b/public/js/plugins/flot/excanvas.js deleted file mode 100755 index f45bf03d3b..0000000000 Binary files a/public/js/plugins/flot/excanvas.js and /dev/null differ diff --git a/public/js/plugins/flot/excanvas.min.js b/public/js/plugins/flot/excanvas.min.js deleted file mode 100755 index fcf876c749..0000000000 Binary files a/public/js/plugins/flot/excanvas.min.js and /dev/null differ diff --git a/public/js/plugins/flot/jquery.colorhelpers.js b/public/js/plugins/flot/jquery.colorhelpers.js deleted file mode 100755 index cc1643b5fb..0000000000 Binary files a/public/js/plugins/flot/jquery.colorhelpers.js and /dev/null differ diff --git a/public/js/plugins/flot/jquery.colorhelpers.min.js b/public/js/plugins/flot/jquery.colorhelpers.min.js deleted file mode 100755 index 7f42659643..0000000000 Binary files a/public/js/plugins/flot/jquery.colorhelpers.min.js and /dev/null differ diff --git a/public/js/plugins/flot/jquery.flot.canvas.js b/public/js/plugins/flot/jquery.flot.canvas.js deleted file mode 100755 index d94b9611a0..0000000000 Binary files a/public/js/plugins/flot/jquery.flot.canvas.js and /dev/null differ diff --git a/public/js/plugins/flot/jquery.flot.canvas.min.js b/public/js/plugins/flot/jquery.flot.canvas.min.js deleted file mode 100755 index 826d21776b..0000000000 Binary files a/public/js/plugins/flot/jquery.flot.canvas.min.js and /dev/null differ diff --git a/public/js/plugins/flot/jquery.flot.categories.js b/public/js/plugins/flot/jquery.flot.categories.js deleted file mode 100755 index 6e6e8baa73..0000000000 Binary files a/public/js/plugins/flot/jquery.flot.categories.js and /dev/null differ diff --git a/public/js/plugins/flot/jquery.flot.categories.min.js b/public/js/plugins/flot/jquery.flot.categories.min.js deleted file mode 100755 index 552dd90a65..0000000000 Binary files a/public/js/plugins/flot/jquery.flot.categories.min.js and /dev/null differ diff --git a/public/js/plugins/flot/jquery.flot.crosshair.js b/public/js/plugins/flot/jquery.flot.crosshair.js deleted file mode 100755 index c5df9d910b..0000000000 Binary files a/public/js/plugins/flot/jquery.flot.crosshair.js and /dev/null differ diff --git a/public/js/plugins/flot/jquery.flot.crosshair.min.js b/public/js/plugins/flot/jquery.flot.crosshair.min.js deleted file mode 100755 index f97ce65a2a..0000000000 Binary files a/public/js/plugins/flot/jquery.flot.crosshair.min.js and /dev/null differ diff --git a/public/js/plugins/flot/jquery.flot.errorbars.js b/public/js/plugins/flot/jquery.flot.errorbars.js deleted file mode 100755 index 7298436787..0000000000 Binary files a/public/js/plugins/flot/jquery.flot.errorbars.js and /dev/null differ diff --git a/public/js/plugins/flot/jquery.flot.errorbars.min.js b/public/js/plugins/flot/jquery.flot.errorbars.min.js deleted file mode 100755 index a7bd0422c9..0000000000 Binary files a/public/js/plugins/flot/jquery.flot.errorbars.min.js and /dev/null differ diff --git a/public/js/plugins/flot/jquery.flot.fillbetween.js b/public/js/plugins/flot/jquery.flot.fillbetween.js deleted file mode 100755 index 2854d2d588..0000000000 Binary files a/public/js/plugins/flot/jquery.flot.fillbetween.js and /dev/null differ diff --git a/public/js/plugins/flot/jquery.flot.fillbetween.min.js b/public/js/plugins/flot/jquery.flot.fillbetween.min.js deleted file mode 100755 index 5bdad05fb4..0000000000 Binary files a/public/js/plugins/flot/jquery.flot.fillbetween.min.js and /dev/null differ diff --git a/public/js/plugins/flot/jquery.flot.image.js b/public/js/plugins/flot/jquery.flot.image.js deleted file mode 100755 index 2e00ab180e..0000000000 Binary files a/public/js/plugins/flot/jquery.flot.image.js and /dev/null differ diff --git a/public/js/plugins/flot/jquery.flot.image.min.js b/public/js/plugins/flot/jquery.flot.image.min.js deleted file mode 100755 index 606002417b..0000000000 Binary files a/public/js/plugins/flot/jquery.flot.image.min.js and /dev/null differ diff --git a/public/js/plugins/flot/jquery.flot.js b/public/js/plugins/flot/jquery.flot.js deleted file mode 100755 index 965e78efe7..0000000000 Binary files a/public/js/plugins/flot/jquery.flot.js and /dev/null differ diff --git a/public/js/plugins/flot/jquery.flot.min.js b/public/js/plugins/flot/jquery.flot.min.js deleted file mode 100755 index 9620fc00d7..0000000000 Binary files a/public/js/plugins/flot/jquery.flot.min.js and /dev/null differ diff --git a/public/js/plugins/flot/jquery.flot.navigate.js b/public/js/plugins/flot/jquery.flot.navigate.js deleted file mode 100755 index 10256b83ac..0000000000 Binary files a/public/js/plugins/flot/jquery.flot.navigate.js and /dev/null differ diff --git a/public/js/plugins/flot/jquery.flot.navigate.min.js b/public/js/plugins/flot/jquery.flot.navigate.min.js deleted file mode 100755 index a69a939994..0000000000 Binary files a/public/js/plugins/flot/jquery.flot.navigate.min.js and /dev/null differ diff --git a/public/js/plugins/flot/jquery.flot.pie.js b/public/js/plugins/flot/jquery.flot.pie.js deleted file mode 100755 index bf190e183d..0000000000 Binary files a/public/js/plugins/flot/jquery.flot.pie.js and /dev/null differ diff --git a/public/js/plugins/flot/jquery.flot.pie.min.js b/public/js/plugins/flot/jquery.flot.pie.min.js deleted file mode 100755 index 88ffc9c9bd..0000000000 Binary files a/public/js/plugins/flot/jquery.flot.pie.min.js and /dev/null differ diff --git a/public/js/plugins/flot/jquery.flot.resize.js b/public/js/plugins/flot/jquery.flot.resize.js deleted file mode 100755 index 44e04f8fca..0000000000 Binary files a/public/js/plugins/flot/jquery.flot.resize.js and /dev/null differ diff --git a/public/js/plugins/flot/jquery.flot.resize.min.js b/public/js/plugins/flot/jquery.flot.resize.min.js deleted file mode 100755 index 29838425f0..0000000000 Binary files a/public/js/plugins/flot/jquery.flot.resize.min.js and /dev/null differ diff --git a/public/js/plugins/flot/jquery.flot.selection.js b/public/js/plugins/flot/jquery.flot.selection.js deleted file mode 100755 index f8fa668ff4..0000000000 Binary files a/public/js/plugins/flot/jquery.flot.selection.js and /dev/null differ diff --git a/public/js/plugins/flot/jquery.flot.selection.min.js b/public/js/plugins/flot/jquery.flot.selection.min.js deleted file mode 100755 index 6e319781cc..0000000000 Binary files a/public/js/plugins/flot/jquery.flot.selection.min.js and /dev/null differ diff --git a/public/js/plugins/flot/jquery.flot.stack.js b/public/js/plugins/flot/jquery.flot.stack.js deleted file mode 100755 index c01de67da1..0000000000 Binary files a/public/js/plugins/flot/jquery.flot.stack.js and /dev/null differ diff --git a/public/js/plugins/flot/jquery.flot.stack.min.js b/public/js/plugins/flot/jquery.flot.stack.min.js deleted file mode 100755 index 57785ebda8..0000000000 Binary files a/public/js/plugins/flot/jquery.flot.stack.min.js and /dev/null differ diff --git a/public/js/plugins/flot/jquery.flot.symbol.js b/public/js/plugins/flot/jquery.flot.symbol.js deleted file mode 100755 index cc181fffc3..0000000000 Binary files a/public/js/plugins/flot/jquery.flot.symbol.js and /dev/null differ diff --git a/public/js/plugins/flot/jquery.flot.symbol.min.js b/public/js/plugins/flot/jquery.flot.symbol.min.js deleted file mode 100755 index 3eab213e52..0000000000 Binary files a/public/js/plugins/flot/jquery.flot.symbol.min.js and /dev/null differ diff --git a/public/js/plugins/flot/jquery.flot.threshold.js b/public/js/plugins/flot/jquery.flot.threshold.js deleted file mode 100755 index 2f6e63594b..0000000000 Binary files a/public/js/plugins/flot/jquery.flot.threshold.js and /dev/null differ diff --git a/public/js/plugins/flot/jquery.flot.threshold.min.js b/public/js/plugins/flot/jquery.flot.threshold.min.js deleted file mode 100755 index a53849a56d..0000000000 Binary files a/public/js/plugins/flot/jquery.flot.threshold.min.js and /dev/null differ diff --git a/public/js/plugins/flot/jquery.flot.time.js b/public/js/plugins/flot/jquery.flot.time.js deleted file mode 100755 index ac9e666a70..0000000000 Binary files a/public/js/plugins/flot/jquery.flot.time.js and /dev/null differ diff --git a/public/js/plugins/flot/jquery.flot.time.min.js b/public/js/plugins/flot/jquery.flot.time.min.js deleted file mode 100755 index aaf319c919..0000000000 Binary files a/public/js/plugins/flot/jquery.flot.time.min.js and /dev/null differ diff --git a/public/js/plugins/fullcalendar/fullcalendar.css b/public/js/plugins/fullcalendar/fullcalendar.css deleted file mode 100755 index 624f2c4f6a..0000000000 Binary files a/public/js/plugins/fullcalendar/fullcalendar.css and /dev/null differ diff --git a/public/js/plugins/fullcalendar/fullcalendar.js b/public/js/plugins/fullcalendar/fullcalendar.js deleted file mode 100755 index d52e8241d5..0000000000 Binary files a/public/js/plugins/fullcalendar/fullcalendar.js and /dev/null differ diff --git a/public/js/plugins/fullcalendar/fullcalendar.min.css b/public/js/plugins/fullcalendar/fullcalendar.min.css deleted file mode 100755 index 083ec9d633..0000000000 Binary files a/public/js/plugins/fullcalendar/fullcalendar.min.css and /dev/null differ diff --git a/public/js/plugins/fullcalendar/fullcalendar.min.js b/public/js/plugins/fullcalendar/fullcalendar.min.js deleted file mode 100755 index 343d907612..0000000000 Binary files a/public/js/plugins/fullcalendar/fullcalendar.min.js and /dev/null differ diff --git a/public/js/plugins/fullcalendar/fullcalendar.print.css b/public/js/plugins/fullcalendar/fullcalendar.print.css deleted file mode 100755 index e29366a7f7..0000000000 Binary files a/public/js/plugins/fullcalendar/fullcalendar.print.css and /dev/null differ diff --git a/public/js/plugins/iCheck/all.css b/public/js/plugins/iCheck/all.css deleted file mode 100755 index 6439b7429b..0000000000 Binary files a/public/js/plugins/iCheck/all.css and /dev/null differ diff --git a/public/js/plugins/iCheck/flat/_all.css b/public/js/plugins/iCheck/flat/_all.css deleted file mode 100755 index 21647b50d8..0000000000 Binary files a/public/js/plugins/iCheck/flat/_all.css and /dev/null differ diff --git a/public/js/plugins/iCheck/flat/aero.css b/public/js/plugins/iCheck/flat/aero.css deleted file mode 100755 index 98fd65c8cc..0000000000 Binary files a/public/js/plugins/iCheck/flat/aero.css and /dev/null differ diff --git a/public/js/plugins/iCheck/flat/aero.png b/public/js/plugins/iCheck/flat/aero.png deleted file mode 100755 index f4277aa4cf..0000000000 Binary files a/public/js/plugins/iCheck/flat/aero.png and /dev/null differ diff --git a/public/js/plugins/iCheck/flat/aero@2x.png b/public/js/plugins/iCheck/flat/aero@2x.png deleted file mode 100755 index a9a749459d..0000000000 Binary files a/public/js/plugins/iCheck/flat/aero@2x.png and /dev/null differ diff --git a/public/js/plugins/iCheck/flat/blue.css b/public/js/plugins/iCheck/flat/blue.css deleted file mode 100755 index 07836749af..0000000000 Binary files a/public/js/plugins/iCheck/flat/blue.css and /dev/null differ diff --git a/public/js/plugins/iCheck/flat/blue.png b/public/js/plugins/iCheck/flat/blue.png deleted file mode 100755 index 4b6ef9825e..0000000000 Binary files a/public/js/plugins/iCheck/flat/blue.png and /dev/null differ diff --git a/public/js/plugins/iCheck/flat/blue@2x.png b/public/js/plugins/iCheck/flat/blue@2x.png deleted file mode 100755 index d52da05771..0000000000 Binary files a/public/js/plugins/iCheck/flat/blue@2x.png and /dev/null differ diff --git a/public/js/plugins/iCheck/flat/flat.css b/public/js/plugins/iCheck/flat/flat.css deleted file mode 100755 index 418620eebc..0000000000 Binary files a/public/js/plugins/iCheck/flat/flat.css and /dev/null differ diff --git a/public/js/plugins/iCheck/flat/flat.png b/public/js/plugins/iCheck/flat/flat.png deleted file mode 100755 index 15af826e0a..0000000000 Binary files a/public/js/plugins/iCheck/flat/flat.png and /dev/null differ diff --git a/public/js/plugins/iCheck/flat/flat@2x.png b/public/js/plugins/iCheck/flat/flat@2x.png deleted file mode 100755 index e70e438c5d..0000000000 Binary files a/public/js/plugins/iCheck/flat/flat@2x.png and /dev/null differ diff --git a/public/js/plugins/iCheck/flat/green.css b/public/js/plugins/iCheck/flat/green.css deleted file mode 100755 index c9d17c1609..0000000000 Binary files a/public/js/plugins/iCheck/flat/green.css and /dev/null differ diff --git a/public/js/plugins/iCheck/flat/green.png b/public/js/plugins/iCheck/flat/green.png deleted file mode 100755 index 6b303fbead..0000000000 Binary files a/public/js/plugins/iCheck/flat/green.png and /dev/null differ diff --git a/public/js/plugins/iCheck/flat/green@2x.png b/public/js/plugins/iCheck/flat/green@2x.png deleted file mode 100755 index 92b4411d90..0000000000 Binary files a/public/js/plugins/iCheck/flat/green@2x.png and /dev/null differ diff --git a/public/js/plugins/iCheck/flat/grey.css b/public/js/plugins/iCheck/flat/grey.css deleted file mode 100755 index a451650ef8..0000000000 Binary files a/public/js/plugins/iCheck/flat/grey.css and /dev/null differ diff --git a/public/js/plugins/iCheck/flat/grey.png b/public/js/plugins/iCheck/flat/grey.png deleted file mode 100755 index c6e2873ed5..0000000000 Binary files a/public/js/plugins/iCheck/flat/grey.png and /dev/null differ diff --git a/public/js/plugins/iCheck/flat/grey@2x.png b/public/js/plugins/iCheck/flat/grey@2x.png deleted file mode 100755 index 0b47b1c6d9..0000000000 Binary files a/public/js/plugins/iCheck/flat/grey@2x.png and /dev/null differ diff --git a/public/js/plugins/iCheck/flat/orange.css b/public/js/plugins/iCheck/flat/orange.css deleted file mode 100755 index 8c9c929773..0000000000 Binary files a/public/js/plugins/iCheck/flat/orange.css and /dev/null differ diff --git a/public/js/plugins/iCheck/flat/orange.png b/public/js/plugins/iCheck/flat/orange.png deleted file mode 100755 index ec2532ebe4..0000000000 Binary files a/public/js/plugins/iCheck/flat/orange.png and /dev/null differ diff --git a/public/js/plugins/iCheck/flat/orange@2x.png b/public/js/plugins/iCheck/flat/orange@2x.png deleted file mode 100755 index 9350b50624..0000000000 Binary files a/public/js/plugins/iCheck/flat/orange@2x.png and /dev/null differ diff --git a/public/js/plugins/iCheck/flat/pink.css b/public/js/plugins/iCheck/flat/pink.css deleted file mode 100755 index afa4956623..0000000000 Binary files a/public/js/plugins/iCheck/flat/pink.css and /dev/null differ diff --git a/public/js/plugins/iCheck/flat/pink.png b/public/js/plugins/iCheck/flat/pink.png deleted file mode 100755 index 3e65d9dd62..0000000000 Binary files a/public/js/plugins/iCheck/flat/pink.png and /dev/null differ diff --git a/public/js/plugins/iCheck/flat/pink@2x.png b/public/js/plugins/iCheck/flat/pink@2x.png deleted file mode 100755 index 281ba06bec..0000000000 Binary files a/public/js/plugins/iCheck/flat/pink@2x.png and /dev/null differ diff --git a/public/js/plugins/iCheck/flat/purple.css b/public/js/plugins/iCheck/flat/purple.css deleted file mode 100755 index a9760b36d2..0000000000 Binary files a/public/js/plugins/iCheck/flat/purple.css and /dev/null differ diff --git a/public/js/plugins/iCheck/flat/purple.png b/public/js/plugins/iCheck/flat/purple.png deleted file mode 100755 index 3699fd5832..0000000000 Binary files a/public/js/plugins/iCheck/flat/purple.png and /dev/null differ diff --git a/public/js/plugins/iCheck/flat/purple@2x.png b/public/js/plugins/iCheck/flat/purple@2x.png deleted file mode 100755 index 7f4be74a7c..0000000000 Binary files a/public/js/plugins/iCheck/flat/purple@2x.png and /dev/null differ diff --git a/public/js/plugins/iCheck/flat/red.css b/public/js/plugins/iCheck/flat/red.css deleted file mode 100755 index 34b71e4702..0000000000 Binary files a/public/js/plugins/iCheck/flat/red.css and /dev/null differ diff --git a/public/js/plugins/iCheck/flat/red.png b/public/js/plugins/iCheck/flat/red.png deleted file mode 100755 index 0d5ac3819b..0000000000 Binary files a/public/js/plugins/iCheck/flat/red.png and /dev/null differ diff --git a/public/js/plugins/iCheck/flat/red@2x.png b/public/js/plugins/iCheck/flat/red@2x.png deleted file mode 100755 index 38590d9852..0000000000 Binary files a/public/js/plugins/iCheck/flat/red@2x.png and /dev/null differ diff --git a/public/js/plugins/iCheck/flat/yellow.css b/public/js/plugins/iCheck/flat/yellow.css deleted file mode 100755 index 96ae5b1f9e..0000000000 Binary files a/public/js/plugins/iCheck/flat/yellow.css and /dev/null differ diff --git a/public/js/plugins/iCheck/flat/yellow.png b/public/js/plugins/iCheck/flat/yellow.png deleted file mode 100755 index 909dadc529..0000000000 Binary files a/public/js/plugins/iCheck/flat/yellow.png and /dev/null differ diff --git a/public/js/plugins/iCheck/flat/yellow@2x.png b/public/js/plugins/iCheck/flat/yellow@2x.png deleted file mode 100755 index 9fd5d73393..0000000000 Binary files a/public/js/plugins/iCheck/flat/yellow@2x.png and /dev/null differ diff --git a/public/js/plugins/iCheck/futurico/futurico.css b/public/js/plugins/iCheck/futurico/futurico.css deleted file mode 100755 index 2654cf4fe3..0000000000 Binary files a/public/js/plugins/iCheck/futurico/futurico.css and /dev/null differ diff --git a/public/js/plugins/iCheck/futurico/futurico.png b/public/js/plugins/iCheck/futurico/futurico.png deleted file mode 100755 index 50d62b5d40..0000000000 Binary files a/public/js/plugins/iCheck/futurico/futurico.png and /dev/null differ diff --git a/public/js/plugins/iCheck/futurico/futurico@2x.png b/public/js/plugins/iCheck/futurico/futurico@2x.png deleted file mode 100755 index f7eb45aad0..0000000000 Binary files a/public/js/plugins/iCheck/futurico/futurico@2x.png and /dev/null differ diff --git a/public/js/plugins/iCheck/icheck.js b/public/js/plugins/iCheck/icheck.js deleted file mode 100755 index 4da1937ad4..0000000000 Binary files a/public/js/plugins/iCheck/icheck.js and /dev/null differ diff --git a/public/js/plugins/iCheck/icheck.min.js b/public/js/plugins/iCheck/icheck.min.js deleted file mode 100755 index d2720ed043..0000000000 Binary files a/public/js/plugins/iCheck/icheck.min.js and /dev/null differ diff --git a/public/js/plugins/iCheck/line/_all.css b/public/js/plugins/iCheck/line/_all.css deleted file mode 100755 index a18d0d90e8..0000000000 Binary files a/public/js/plugins/iCheck/line/_all.css and /dev/null differ diff --git a/public/js/plugins/iCheck/line/aero.css b/public/js/plugins/iCheck/line/aero.css deleted file mode 100755 index 44989a462e..0000000000 Binary files a/public/js/plugins/iCheck/line/aero.css and /dev/null differ diff --git a/public/js/plugins/iCheck/line/blue.css b/public/js/plugins/iCheck/line/blue.css deleted file mode 100755 index 5c9c0a7826..0000000000 Binary files a/public/js/plugins/iCheck/line/blue.css and /dev/null differ diff --git a/public/js/plugins/iCheck/line/green.css b/public/js/plugins/iCheck/line/green.css deleted file mode 100755 index 8bbe5140fc..0000000000 Binary files a/public/js/plugins/iCheck/line/green.css and /dev/null differ diff --git a/public/js/plugins/iCheck/line/grey.css b/public/js/plugins/iCheck/line/grey.css deleted file mode 100755 index fc16a80e29..0000000000 Binary files a/public/js/plugins/iCheck/line/grey.css and /dev/null differ diff --git a/public/js/plugins/iCheck/line/line.css b/public/js/plugins/iCheck/line/line.css deleted file mode 100755 index dbde8d4d8b..0000000000 Binary files a/public/js/plugins/iCheck/line/line.css and /dev/null differ diff --git a/public/js/plugins/iCheck/line/line.png b/public/js/plugins/iCheck/line/line.png deleted file mode 100755 index d21d7a7b43..0000000000 Binary files a/public/js/plugins/iCheck/line/line.png and /dev/null differ diff --git a/public/js/plugins/iCheck/line/line@2x.png b/public/js/plugins/iCheck/line/line@2x.png deleted file mode 100755 index 62900a2d93..0000000000 Binary files a/public/js/plugins/iCheck/line/line@2x.png and /dev/null differ diff --git a/public/js/plugins/iCheck/line/orange.css b/public/js/plugins/iCheck/line/orange.css deleted file mode 100755 index 210f334014..0000000000 Binary files a/public/js/plugins/iCheck/line/orange.css and /dev/null differ diff --git a/public/js/plugins/iCheck/line/pink.css b/public/js/plugins/iCheck/line/pink.css deleted file mode 100755 index 44c9cea197..0000000000 Binary files a/public/js/plugins/iCheck/line/pink.css and /dev/null differ diff --git a/public/js/plugins/iCheck/line/purple.css b/public/js/plugins/iCheck/line/purple.css deleted file mode 100755 index be4c4e2bb5..0000000000 Binary files a/public/js/plugins/iCheck/line/purple.css and /dev/null differ diff --git a/public/js/plugins/iCheck/line/red.css b/public/js/plugins/iCheck/line/red.css deleted file mode 100755 index ebcd8befdb..0000000000 Binary files a/public/js/plugins/iCheck/line/red.css and /dev/null differ diff --git a/public/js/plugins/iCheck/line/yellow.css b/public/js/plugins/iCheck/line/yellow.css deleted file mode 100755 index 8e088714e2..0000000000 Binary files a/public/js/plugins/iCheck/line/yellow.css and /dev/null differ diff --git a/public/js/plugins/iCheck/minimal/_all.css b/public/js/plugins/iCheck/minimal/_all.css deleted file mode 100755 index b2165ecc35..0000000000 Binary files a/public/js/plugins/iCheck/minimal/_all.css and /dev/null differ diff --git a/public/js/plugins/iCheck/minimal/aero.css b/public/js/plugins/iCheck/minimal/aero.css deleted file mode 100755 index c97acc8c11..0000000000 Binary files a/public/js/plugins/iCheck/minimal/aero.css and /dev/null differ diff --git a/public/js/plugins/iCheck/minimal/aero.png b/public/js/plugins/iCheck/minimal/aero.png deleted file mode 100755 index dccf7740c9..0000000000 Binary files a/public/js/plugins/iCheck/minimal/aero.png and /dev/null differ diff --git a/public/js/plugins/iCheck/minimal/aero@2x.png b/public/js/plugins/iCheck/minimal/aero@2x.png deleted file mode 100755 index 5537ee36fe..0000000000 Binary files a/public/js/plugins/iCheck/minimal/aero@2x.png and /dev/null differ diff --git a/public/js/plugins/iCheck/minimal/blue.css b/public/js/plugins/iCheck/minimal/blue.css deleted file mode 100755 index 42477cd660..0000000000 Binary files a/public/js/plugins/iCheck/minimal/blue.css and /dev/null differ diff --git a/public/js/plugins/iCheck/minimal/green.css b/public/js/plugins/iCheck/minimal/green.css deleted file mode 100755 index bd1e3d0feb..0000000000 Binary files a/public/js/plugins/iCheck/minimal/green.css and /dev/null differ diff --git a/public/js/plugins/iCheck/minimal/green.png b/public/js/plugins/iCheck/minimal/green.png deleted file mode 100755 index 9171ebc7e4..0000000000 Binary files a/public/js/plugins/iCheck/minimal/green.png and /dev/null differ diff --git a/public/js/plugins/iCheck/minimal/green@2x.png b/public/js/plugins/iCheck/minimal/green@2x.png deleted file mode 100755 index 7f18f96a9c..0000000000 Binary files a/public/js/plugins/iCheck/minimal/green@2x.png and /dev/null differ diff --git a/public/js/plugins/iCheck/minimal/grey.css b/public/js/plugins/iCheck/minimal/grey.css deleted file mode 100755 index 6e2730c662..0000000000 Binary files a/public/js/plugins/iCheck/minimal/grey.css and /dev/null differ diff --git a/public/js/plugins/iCheck/minimal/grey.png b/public/js/plugins/iCheck/minimal/grey.png deleted file mode 100755 index 22dcdbcfa2..0000000000 Binary files a/public/js/plugins/iCheck/minimal/grey.png and /dev/null differ diff --git a/public/js/plugins/iCheck/minimal/grey@2x.png b/public/js/plugins/iCheck/minimal/grey@2x.png deleted file mode 100755 index 85e82ddda4..0000000000 Binary files a/public/js/plugins/iCheck/minimal/grey@2x.png and /dev/null differ diff --git a/public/js/plugins/iCheck/minimal/minimal.css b/public/js/plugins/iCheck/minimal/minimal.css deleted file mode 100755 index 7c0e52e1da..0000000000 Binary files a/public/js/plugins/iCheck/minimal/minimal.css and /dev/null differ diff --git a/public/js/plugins/iCheck/minimal/minimal.png b/public/js/plugins/iCheck/minimal/minimal.png deleted file mode 100755 index 943be16fb1..0000000000 Binary files a/public/js/plugins/iCheck/minimal/minimal.png and /dev/null differ diff --git a/public/js/plugins/iCheck/minimal/minimal@2x.png b/public/js/plugins/iCheck/minimal/minimal@2x.png deleted file mode 100755 index d62291daaa..0000000000 Binary files a/public/js/plugins/iCheck/minimal/minimal@2x.png and /dev/null differ diff --git a/public/js/plugins/iCheck/minimal/orange.css b/public/js/plugins/iCheck/minimal/orange.css deleted file mode 100755 index 842e400a9d..0000000000 Binary files a/public/js/plugins/iCheck/minimal/orange.css and /dev/null differ diff --git a/public/js/plugins/iCheck/minimal/orange.png b/public/js/plugins/iCheck/minimal/orange.png deleted file mode 100755 index f2a314978d..0000000000 Binary files a/public/js/plugins/iCheck/minimal/orange.png and /dev/null differ diff --git a/public/js/plugins/iCheck/minimal/orange@2x.png b/public/js/plugins/iCheck/minimal/orange@2x.png deleted file mode 100755 index 68c835915a..0000000000 Binary files a/public/js/plugins/iCheck/minimal/orange@2x.png and /dev/null differ diff --git a/public/js/plugins/iCheck/minimal/pink.css b/public/js/plugins/iCheck/minimal/pink.css deleted file mode 100755 index 10ace2188f..0000000000 Binary files a/public/js/plugins/iCheck/minimal/pink.css and /dev/null differ diff --git a/public/js/plugins/iCheck/minimal/pink.png b/public/js/plugins/iCheck/minimal/pink.png deleted file mode 100755 index 660553c074..0000000000 Binary files a/public/js/plugins/iCheck/minimal/pink.png and /dev/null differ diff --git a/public/js/plugins/iCheck/minimal/pink@2x.png b/public/js/plugins/iCheck/minimal/pink@2x.png deleted file mode 100755 index 7d7b385146..0000000000 Binary files a/public/js/plugins/iCheck/minimal/pink@2x.png and /dev/null differ diff --git a/public/js/plugins/iCheck/minimal/purple.css b/public/js/plugins/iCheck/minimal/purple.css deleted file mode 100755 index 1c5dcbc716..0000000000 Binary files a/public/js/plugins/iCheck/minimal/purple.css and /dev/null differ diff --git a/public/js/plugins/iCheck/minimal/purple.png b/public/js/plugins/iCheck/minimal/purple.png deleted file mode 100755 index 48dec794dd..0000000000 Binary files a/public/js/plugins/iCheck/minimal/purple.png and /dev/null differ diff --git a/public/js/plugins/iCheck/minimal/purple@2x.png b/public/js/plugins/iCheck/minimal/purple@2x.png deleted file mode 100755 index 3bb7041718..0000000000 Binary files a/public/js/plugins/iCheck/minimal/purple@2x.png and /dev/null differ diff --git a/public/js/plugins/iCheck/minimal/red.css b/public/js/plugins/iCheck/minimal/red.css deleted file mode 100755 index 9340c4f6f6..0000000000 Binary files a/public/js/plugins/iCheck/minimal/red.css and /dev/null differ diff --git a/public/js/plugins/iCheck/minimal/red.png b/public/js/plugins/iCheck/minimal/red.png deleted file mode 100755 index 4443f80976..0000000000 Binary files a/public/js/plugins/iCheck/minimal/red.png and /dev/null differ diff --git a/public/js/plugins/iCheck/minimal/red@2x.png b/public/js/plugins/iCheck/minimal/red@2x.png deleted file mode 100755 index 2eb55a65c7..0000000000 Binary files a/public/js/plugins/iCheck/minimal/red@2x.png and /dev/null differ diff --git a/public/js/plugins/iCheck/minimal/yellow.css b/public/js/plugins/iCheck/minimal/yellow.css deleted file mode 100755 index 2c38423130..0000000000 Binary files a/public/js/plugins/iCheck/minimal/yellow.css and /dev/null differ diff --git a/public/js/plugins/iCheck/minimal/yellow.png b/public/js/plugins/iCheck/minimal/yellow.png deleted file mode 100755 index 0999b7ecdc..0000000000 Binary files a/public/js/plugins/iCheck/minimal/yellow.png and /dev/null differ diff --git a/public/js/plugins/iCheck/minimal/yellow@2x.png b/public/js/plugins/iCheck/minimal/yellow@2x.png deleted file mode 100755 index c16f2b7dc5..0000000000 Binary files a/public/js/plugins/iCheck/minimal/yellow@2x.png and /dev/null differ diff --git a/public/js/plugins/iCheck/polaris/polaris.css b/public/js/plugins/iCheck/polaris/polaris.css deleted file mode 100755 index 1cb4bcc0ec..0000000000 Binary files a/public/js/plugins/iCheck/polaris/polaris.css and /dev/null differ diff --git a/public/js/plugins/iCheck/polaris/polaris.png b/public/js/plugins/iCheck/polaris/polaris.png deleted file mode 100755 index 60c14e6a88..0000000000 Binary files a/public/js/plugins/iCheck/polaris/polaris.png and /dev/null differ diff --git a/public/js/plugins/iCheck/polaris/polaris@2x.png b/public/js/plugins/iCheck/polaris/polaris@2x.png deleted file mode 100755 index c75b82695d..0000000000 Binary files a/public/js/plugins/iCheck/polaris/polaris@2x.png and /dev/null differ diff --git a/public/js/plugins/iCheck/square/_all.css b/public/js/plugins/iCheck/square/_all.css deleted file mode 100755 index a2ff036869..0000000000 Binary files a/public/js/plugins/iCheck/square/_all.css and /dev/null differ diff --git a/public/js/plugins/iCheck/square/aero.css b/public/js/plugins/iCheck/square/aero.css deleted file mode 100755 index 51fca0a81a..0000000000 Binary files a/public/js/plugins/iCheck/square/aero.css and /dev/null differ diff --git a/public/js/plugins/iCheck/square/aero.png b/public/js/plugins/iCheck/square/aero.png deleted file mode 100755 index 1a332e6c57..0000000000 Binary files a/public/js/plugins/iCheck/square/aero.png and /dev/null differ diff --git a/public/js/plugins/iCheck/square/aero@2x.png b/public/js/plugins/iCheck/square/aero@2x.png deleted file mode 100755 index 07c5a02248..0000000000 Binary files a/public/js/plugins/iCheck/square/aero@2x.png and /dev/null differ diff --git a/public/js/plugins/iCheck/square/blue.css b/public/js/plugins/iCheck/square/blue.css deleted file mode 100755 index 95340fea27..0000000000 Binary files a/public/js/plugins/iCheck/square/blue.css and /dev/null differ diff --git a/public/js/plugins/iCheck/square/blue.png b/public/js/plugins/iCheck/square/blue.png deleted file mode 100755 index a3e040fcce..0000000000 Binary files a/public/js/plugins/iCheck/square/blue.png and /dev/null differ diff --git a/public/js/plugins/iCheck/square/blue@2x.png b/public/js/plugins/iCheck/square/blue@2x.png deleted file mode 100755 index 8fdea12f96..0000000000 Binary files a/public/js/plugins/iCheck/square/blue@2x.png and /dev/null differ diff --git a/public/js/plugins/iCheck/square/green.css b/public/js/plugins/iCheck/square/green.css deleted file mode 100755 index eb43f2a426..0000000000 Binary files a/public/js/plugins/iCheck/square/green.css and /dev/null differ diff --git a/public/js/plugins/iCheck/square/green.png b/public/js/plugins/iCheck/square/green.png deleted file mode 100755 index 465824e70c..0000000000 Binary files a/public/js/plugins/iCheck/square/green.png and /dev/null differ diff --git a/public/js/plugins/iCheck/square/green@2x.png b/public/js/plugins/iCheck/square/green@2x.png deleted file mode 100755 index 784e874758..0000000000 Binary files a/public/js/plugins/iCheck/square/green@2x.png and /dev/null differ diff --git a/public/js/plugins/iCheck/square/grey.css b/public/js/plugins/iCheck/square/grey.css deleted file mode 100755 index ecc57ff43d..0000000000 Binary files a/public/js/plugins/iCheck/square/grey.css and /dev/null differ diff --git a/public/js/plugins/iCheck/square/grey.png b/public/js/plugins/iCheck/square/grey.png deleted file mode 100755 index f69375854d..0000000000 Binary files a/public/js/plugins/iCheck/square/grey.png and /dev/null differ diff --git a/public/js/plugins/iCheck/square/grey@2x.png b/public/js/plugins/iCheck/square/grey@2x.png deleted file mode 100755 index 5d6341c053..0000000000 Binary files a/public/js/plugins/iCheck/square/grey@2x.png and /dev/null differ diff --git a/public/js/plugins/iCheck/square/orange.css b/public/js/plugins/iCheck/square/orange.css deleted file mode 100755 index d0c7a2cf24..0000000000 Binary files a/public/js/plugins/iCheck/square/orange.css and /dev/null differ diff --git a/public/js/plugins/iCheck/square/orange.png b/public/js/plugins/iCheck/square/orange.png deleted file mode 100755 index 84608500a6..0000000000 Binary files a/public/js/plugins/iCheck/square/orange.png and /dev/null differ diff --git a/public/js/plugins/iCheck/square/orange@2x.png b/public/js/plugins/iCheck/square/orange@2x.png deleted file mode 100755 index b1f2319735..0000000000 Binary files a/public/js/plugins/iCheck/square/orange@2x.png and /dev/null differ diff --git a/public/js/plugins/iCheck/square/pink.css b/public/js/plugins/iCheck/square/pink.css deleted file mode 100755 index 6b706f6db4..0000000000 Binary files a/public/js/plugins/iCheck/square/pink.css and /dev/null differ diff --git a/public/js/plugins/iCheck/square/pink.png b/public/js/plugins/iCheck/square/pink.png deleted file mode 100755 index 9c8b4e2b6c..0000000000 Binary files a/public/js/plugins/iCheck/square/pink.png and /dev/null differ diff --git a/public/js/plugins/iCheck/square/pink@2x.png b/public/js/plugins/iCheck/square/pink@2x.png deleted file mode 100755 index b1f3a6eda6..0000000000 Binary files a/public/js/plugins/iCheck/square/pink@2x.png and /dev/null differ diff --git a/public/js/plugins/iCheck/square/purple.css b/public/js/plugins/iCheck/square/purple.css deleted file mode 100755 index 43051d3db9..0000000000 Binary files a/public/js/plugins/iCheck/square/purple.css and /dev/null differ diff --git a/public/js/plugins/iCheck/square/purple.png b/public/js/plugins/iCheck/square/purple.png deleted file mode 100755 index 6bfc16a38c..0000000000 Binary files a/public/js/plugins/iCheck/square/purple.png and /dev/null differ diff --git a/public/js/plugins/iCheck/square/purple@2x.png b/public/js/plugins/iCheck/square/purple@2x.png deleted file mode 100755 index 6d3c8b1af3..0000000000 Binary files a/public/js/plugins/iCheck/square/purple@2x.png and /dev/null differ diff --git a/public/js/plugins/iCheck/square/red.css b/public/js/plugins/iCheck/square/red.css deleted file mode 100755 index 40013c427b..0000000000 Binary files a/public/js/plugins/iCheck/square/red.css and /dev/null differ diff --git a/public/js/plugins/iCheck/square/red.png b/public/js/plugins/iCheck/square/red.png deleted file mode 100755 index 749675a979..0000000000 Binary files a/public/js/plugins/iCheck/square/red.png and /dev/null differ diff --git a/public/js/plugins/iCheck/square/red@2x.png b/public/js/plugins/iCheck/square/red@2x.png deleted file mode 100755 index c05700a574..0000000000 Binary files a/public/js/plugins/iCheck/square/red@2x.png and /dev/null differ diff --git a/public/js/plugins/iCheck/square/square.css b/public/js/plugins/iCheck/square/square.css deleted file mode 100755 index b604fa84fe..0000000000 Binary files a/public/js/plugins/iCheck/square/square.css and /dev/null differ diff --git a/public/js/plugins/iCheck/square/square.png b/public/js/plugins/iCheck/square/square.png deleted file mode 100755 index 2a3c88116c..0000000000 Binary files a/public/js/plugins/iCheck/square/square.png and /dev/null differ diff --git a/public/js/plugins/iCheck/square/square@2x.png b/public/js/plugins/iCheck/square/square@2x.png deleted file mode 100755 index 9b56c448d0..0000000000 Binary files a/public/js/plugins/iCheck/square/square@2x.png and /dev/null differ diff --git a/public/js/plugins/iCheck/square/yellow.css b/public/js/plugins/iCheck/square/yellow.css deleted file mode 100755 index 551134992d..0000000000 Binary files a/public/js/plugins/iCheck/square/yellow.css and /dev/null differ diff --git a/public/js/plugins/iCheck/square/yellow.png b/public/js/plugins/iCheck/square/yellow.png deleted file mode 100755 index b6c0330909..0000000000 Binary files a/public/js/plugins/iCheck/square/yellow.png and /dev/null differ diff --git a/public/js/plugins/iCheck/square/yellow@2x.png b/public/js/plugins/iCheck/square/yellow@2x.png deleted file mode 100755 index 6b8e328e1a..0000000000 Binary files a/public/js/plugins/iCheck/square/yellow@2x.png and /dev/null differ diff --git a/public/js/plugins/input-mask/jquery.inputmask.date.extensions.js b/public/js/plugins/input-mask/jquery.inputmask.date.extensions.js deleted file mode 100755 index 18f76c81ad..0000000000 Binary files a/public/js/plugins/input-mask/jquery.inputmask.date.extensions.js and /dev/null differ diff --git a/public/js/plugins/input-mask/jquery.inputmask.extensions.js b/public/js/plugins/input-mask/jquery.inputmask.extensions.js deleted file mode 100755 index c89f91ee50..0000000000 Binary files a/public/js/plugins/input-mask/jquery.inputmask.extensions.js and /dev/null differ diff --git a/public/js/plugins/input-mask/jquery.inputmask.js b/public/js/plugins/input-mask/jquery.inputmask.js deleted file mode 100755 index 86cb3205b5..0000000000 Binary files a/public/js/plugins/input-mask/jquery.inputmask.js and /dev/null differ diff --git a/public/js/plugins/input-mask/jquery.inputmask.numeric.extensions.js b/public/js/plugins/input-mask/jquery.inputmask.numeric.extensions.js deleted file mode 100755 index 2efb33f40e..0000000000 Binary files a/public/js/plugins/input-mask/jquery.inputmask.numeric.extensions.js and /dev/null differ diff --git a/public/js/plugins/input-mask/jquery.inputmask.phone.extensions.js b/public/js/plugins/input-mask/jquery.inputmask.phone.extensions.js deleted file mode 100755 index 554d4ef14f..0000000000 Binary files a/public/js/plugins/input-mask/jquery.inputmask.phone.extensions.js and /dev/null differ diff --git a/public/js/plugins/input-mask/jquery.inputmask.regex.extensions.js b/public/js/plugins/input-mask/jquery.inputmask.regex.extensions.js deleted file mode 100755 index e956569bfd..0000000000 Binary files a/public/js/plugins/input-mask/jquery.inputmask.regex.extensions.js and /dev/null differ diff --git a/public/js/plugins/input-mask/phone-codes/phone-be.json b/public/js/plugins/input-mask/phone-codes/phone-be.json deleted file mode 100755 index b510b78471..0000000000 Binary files a/public/js/plugins/input-mask/phone-codes/phone-be.json and /dev/null differ diff --git a/public/js/plugins/input-mask/phone-codes/phone-codes.json b/public/js/plugins/input-mask/phone-codes/phone-codes.json deleted file mode 100755 index 15bbd3a977..0000000000 Binary files a/public/js/plugins/input-mask/phone-codes/phone-codes.json and /dev/null differ diff --git a/public/js/plugins/input-mask/phone-codes/readme.txt b/public/js/plugins/input-mask/phone-codes/readme.txt deleted file mode 100755 index 0a170a7673..0000000000 Binary files a/public/js/plugins/input-mask/phone-codes/readme.txt and /dev/null differ diff --git a/public/js/plugins/jQuery/jQuery-2.1.4.min.js b/public/js/plugins/jQuery/jQuery-2.1.4.min.js deleted file mode 100755 index 49990d6e14..0000000000 Binary files a/public/js/plugins/jQuery/jQuery-2.1.4.min.js and /dev/null differ diff --git a/public/js/plugins/jQueryUI/jquery-ui.js b/public/js/plugins/jQueryUI/jquery-ui.js deleted file mode 100755 index 31ee9cd811..0000000000 Binary files a/public/js/plugins/jQueryUI/jquery-ui.js and /dev/null differ diff --git a/public/js/plugins/jQueryUI/jquery-ui.min.js b/public/js/plugins/jQueryUI/jquery-ui.min.js deleted file mode 100755 index 5824d1292d..0000000000 Binary files a/public/js/plugins/jQueryUI/jquery-ui.min.js and /dev/null differ diff --git a/public/js/plugins/jvectormap/jquery-jvectormap-1.2.2.css b/public/js/plugins/jvectormap/jquery-jvectormap-1.2.2.css deleted file mode 100755 index 63e717df23..0000000000 Binary files a/public/js/plugins/jvectormap/jquery-jvectormap-1.2.2.css and /dev/null differ diff --git a/public/js/plugins/jvectormap/jquery-jvectormap-1.2.2.min.js b/public/js/plugins/jvectormap/jquery-jvectormap-1.2.2.min.js deleted file mode 100755 index ea54476f29..0000000000 Binary files a/public/js/plugins/jvectormap/jquery-jvectormap-1.2.2.min.js and /dev/null differ diff --git a/public/js/plugins/jvectormap/jquery-jvectormap-world-mill-en.js b/public/js/plugins/jvectormap/jquery-jvectormap-world-mill-en.js deleted file mode 100755 index 89f778398c..0000000000 Binary files a/public/js/plugins/jvectormap/jquery-jvectormap-world-mill-en.js and /dev/null differ diff --git a/public/js/plugins/knob/jquery.knob.js b/public/js/plugins/knob/jquery.knob.js deleted file mode 100755 index 5294ffad52..0000000000 Binary files a/public/js/plugins/knob/jquery.knob.js and /dev/null differ diff --git a/public/js/plugins/morris/morris.css b/public/js/plugins/morris/morris.css deleted file mode 100755 index ed0b490cbe..0000000000 Binary files a/public/js/plugins/morris/morris.css and /dev/null differ diff --git a/public/js/plugins/morris/morris.js b/public/js/plugins/morris/morris.js deleted file mode 100755 index 16648323b2..0000000000 Binary files a/public/js/plugins/morris/morris.js and /dev/null differ diff --git a/public/js/plugins/morris/morris.min.js b/public/js/plugins/morris/morris.min.js deleted file mode 100755 index c3bda2f937..0000000000 Binary files a/public/js/plugins/morris/morris.min.js and /dev/null differ diff --git a/public/js/plugins/pace/pace.js b/public/js/plugins/pace/pace.js deleted file mode 100755 index c47d6e5a51..0000000000 Binary files a/public/js/plugins/pace/pace.js and /dev/null differ diff --git a/public/js/plugins/select2/i18n/az.js b/public/js/plugins/select2/i18n/az.js deleted file mode 100755 index 3ad855a78c..0000000000 Binary files a/public/js/plugins/select2/i18n/az.js and /dev/null differ diff --git a/public/js/plugins/select2/i18n/bg.js b/public/js/plugins/select2/i18n/bg.js deleted file mode 100755 index edad761bbe..0000000000 Binary files a/public/js/plugins/select2/i18n/bg.js and /dev/null differ diff --git a/public/js/plugins/select2/i18n/ca.js b/public/js/plugins/select2/i18n/ca.js deleted file mode 100755 index 3f5db5ea8f..0000000000 Binary files a/public/js/plugins/select2/i18n/ca.js and /dev/null differ diff --git a/public/js/plugins/select2/i18n/cs.js b/public/js/plugins/select2/i18n/cs.js deleted file mode 100755 index d5823e9696..0000000000 Binary files a/public/js/plugins/select2/i18n/cs.js and /dev/null differ diff --git a/public/js/plugins/select2/i18n/da.js b/public/js/plugins/select2/i18n/da.js deleted file mode 100755 index e9d25315a4..0000000000 Binary files a/public/js/plugins/select2/i18n/da.js and /dev/null differ diff --git a/public/js/plugins/select2/i18n/de.js b/public/js/plugins/select2/i18n/de.js deleted file mode 100755 index 2224138e3b..0000000000 Binary files a/public/js/plugins/select2/i18n/de.js and /dev/null differ diff --git a/public/js/plugins/select2/i18n/en.js b/public/js/plugins/select2/i18n/en.js deleted file mode 100755 index 869dfd7b21..0000000000 Binary files a/public/js/plugins/select2/i18n/en.js and /dev/null differ diff --git a/public/js/plugins/select2/i18n/es.js b/public/js/plugins/select2/i18n/es.js deleted file mode 100755 index f12d3f5216..0000000000 Binary files a/public/js/plugins/select2/i18n/es.js and /dev/null differ diff --git a/public/js/plugins/select2/i18n/et.js b/public/js/plugins/select2/i18n/et.js deleted file mode 100755 index b0603bdc8e..0000000000 Binary files a/public/js/plugins/select2/i18n/et.js and /dev/null differ diff --git a/public/js/plugins/select2/i18n/eu.js b/public/js/plugins/select2/i18n/eu.js deleted file mode 100755 index 3abb677a43..0000000000 Binary files a/public/js/plugins/select2/i18n/eu.js and /dev/null differ diff --git a/public/js/plugins/select2/i18n/fa.js b/public/js/plugins/select2/i18n/fa.js deleted file mode 100755 index 49abc419cd..0000000000 Binary files a/public/js/plugins/select2/i18n/fa.js and /dev/null differ diff --git a/public/js/plugins/select2/i18n/fi.js b/public/js/plugins/select2/i18n/fi.js deleted file mode 100755 index fef0d8b572..0000000000 Binary files a/public/js/plugins/select2/i18n/fi.js and /dev/null differ diff --git a/public/js/plugins/select2/i18n/fr.js b/public/js/plugins/select2/i18n/fr.js deleted file mode 100755 index 44395226dd..0000000000 Binary files a/public/js/plugins/select2/i18n/fr.js and /dev/null differ diff --git a/public/js/plugins/select2/i18n/gl.js b/public/js/plugins/select2/i18n/gl.js deleted file mode 100755 index 9e593af47d..0000000000 Binary files a/public/js/plugins/select2/i18n/gl.js and /dev/null differ diff --git a/public/js/plugins/select2/i18n/he.js b/public/js/plugins/select2/i18n/he.js deleted file mode 100755 index c5102c3106..0000000000 Binary files a/public/js/plugins/select2/i18n/he.js and /dev/null differ diff --git a/public/js/plugins/select2/i18n/hi.js b/public/js/plugins/select2/i18n/hi.js deleted file mode 100755 index f8dd58a46d..0000000000 Binary files a/public/js/plugins/select2/i18n/hi.js and /dev/null differ diff --git a/public/js/plugins/select2/i18n/hr.js b/public/js/plugins/select2/i18n/hr.js deleted file mode 100755 index a783b3fbb4..0000000000 Binary files a/public/js/plugins/select2/i18n/hr.js and /dev/null differ diff --git a/public/js/plugins/select2/i18n/hu.js b/public/js/plugins/select2/i18n/hu.js deleted file mode 100755 index d13fea25f5..0000000000 Binary files a/public/js/plugins/select2/i18n/hu.js and /dev/null differ diff --git a/public/js/plugins/select2/i18n/id.js b/public/js/plugins/select2/i18n/id.js deleted file mode 100755 index 7ffb8dbdb6..0000000000 Binary files a/public/js/plugins/select2/i18n/id.js and /dev/null differ diff --git a/public/js/plugins/select2/i18n/is.js b/public/js/plugins/select2/i18n/is.js deleted file mode 100755 index 588ec1de9f..0000000000 Binary files a/public/js/plugins/select2/i18n/is.js and /dev/null differ diff --git a/public/js/plugins/select2/i18n/it.js b/public/js/plugins/select2/i18n/it.js deleted file mode 100755 index 0488d3b152..0000000000 Binary files a/public/js/plugins/select2/i18n/it.js and /dev/null differ diff --git a/public/js/plugins/select2/i18n/ko.js b/public/js/plugins/select2/i18n/ko.js deleted file mode 100755 index 80b5a8b20b..0000000000 Binary files a/public/js/plugins/select2/i18n/ko.js and /dev/null differ diff --git a/public/js/plugins/select2/i18n/lt.js b/public/js/plugins/select2/i18n/lt.js deleted file mode 100755 index 27cfe36497..0000000000 Binary files a/public/js/plugins/select2/i18n/lt.js and /dev/null differ diff --git a/public/js/plugins/select2/i18n/lv.js b/public/js/plugins/select2/i18n/lv.js deleted file mode 100755 index b47bc8e2a9..0000000000 Binary files a/public/js/plugins/select2/i18n/lv.js and /dev/null differ diff --git a/public/js/plugins/select2/i18n/mk.js b/public/js/plugins/select2/i18n/mk.js deleted file mode 100755 index 065a47a032..0000000000 Binary files a/public/js/plugins/select2/i18n/mk.js and /dev/null differ diff --git a/public/js/plugins/select2/i18n/nb.js b/public/js/plugins/select2/i18n/nb.js deleted file mode 100755 index d7328a250f..0000000000 Binary files a/public/js/plugins/select2/i18n/nb.js and /dev/null differ diff --git a/public/js/plugins/select2/i18n/nl.js b/public/js/plugins/select2/i18n/nl.js deleted file mode 100755 index b30c81c739..0000000000 Binary files a/public/js/plugins/select2/i18n/nl.js and /dev/null differ diff --git a/public/js/plugins/select2/i18n/pl.js b/public/js/plugins/select2/i18n/pl.js deleted file mode 100755 index 0c0923c28c..0000000000 Binary files a/public/js/plugins/select2/i18n/pl.js and /dev/null differ diff --git a/public/js/plugins/select2/i18n/pt-BR.js b/public/js/plugins/select2/i18n/pt-BR.js deleted file mode 100755 index 2535114626..0000000000 Binary files a/public/js/plugins/select2/i18n/pt-BR.js and /dev/null differ diff --git a/public/js/plugins/select2/i18n/pt.js b/public/js/plugins/select2/i18n/pt.js deleted file mode 100755 index 6dcc51f0d2..0000000000 Binary files a/public/js/plugins/select2/i18n/pt.js and /dev/null differ diff --git a/public/js/plugins/select2/i18n/ro.js b/public/js/plugins/select2/i18n/ro.js deleted file mode 100755 index 61e7f1239e..0000000000 Binary files a/public/js/plugins/select2/i18n/ro.js and /dev/null differ diff --git a/public/js/plugins/select2/i18n/ru.js b/public/js/plugins/select2/i18n/ru.js deleted file mode 100755 index e082600f4e..0000000000 Binary files a/public/js/plugins/select2/i18n/ru.js and /dev/null differ diff --git a/public/js/plugins/select2/i18n/sk.js b/public/js/plugins/select2/i18n/sk.js deleted file mode 100755 index 8f92855695..0000000000 Binary files a/public/js/plugins/select2/i18n/sk.js and /dev/null differ diff --git a/public/js/plugins/select2/i18n/sr.js b/public/js/plugins/select2/i18n/sr.js deleted file mode 100755 index 5ed6a81788..0000000000 Binary files a/public/js/plugins/select2/i18n/sr.js and /dev/null differ diff --git a/public/js/plugins/select2/i18n/sv.js b/public/js/plugins/select2/i18n/sv.js deleted file mode 100755 index 1934e365ef..0000000000 Binary files a/public/js/plugins/select2/i18n/sv.js and /dev/null differ diff --git a/public/js/plugins/select2/i18n/th.js b/public/js/plugins/select2/i18n/th.js deleted file mode 100755 index 91c911c46f..0000000000 Binary files a/public/js/plugins/select2/i18n/th.js and /dev/null differ diff --git a/public/js/plugins/select2/i18n/tr.js b/public/js/plugins/select2/i18n/tr.js deleted file mode 100755 index 2d616c80c5..0000000000 Binary files a/public/js/plugins/select2/i18n/tr.js and /dev/null differ diff --git a/public/js/plugins/select2/i18n/uk.js b/public/js/plugins/select2/i18n/uk.js deleted file mode 100755 index ea34a4a150..0000000000 Binary files a/public/js/plugins/select2/i18n/uk.js and /dev/null differ diff --git a/public/js/plugins/select2/i18n/vi.js b/public/js/plugins/select2/i18n/vi.js deleted file mode 100755 index 5c22a14b35..0000000000 Binary files a/public/js/plugins/select2/i18n/vi.js and /dev/null differ diff --git a/public/js/plugins/select2/i18n/zh-CN.js b/public/js/plugins/select2/i18n/zh-CN.js deleted file mode 100755 index df0ea4103d..0000000000 Binary files a/public/js/plugins/select2/i18n/zh-CN.js and /dev/null differ diff --git a/public/js/plugins/select2/i18n/zh-TW.js b/public/js/plugins/select2/i18n/zh-TW.js deleted file mode 100755 index 017483be14..0000000000 Binary files a/public/js/plugins/select2/i18n/zh-TW.js and /dev/null differ diff --git a/public/js/plugins/select2/select2.css b/public/js/plugins/select2/select2.css deleted file mode 100755 index d365213c7b..0000000000 Binary files a/public/js/plugins/select2/select2.css and /dev/null differ diff --git a/public/js/plugins/select2/select2.full.js b/public/js/plugins/select2/select2.full.js deleted file mode 100755 index dd0e8bc74d..0000000000 Binary files a/public/js/plugins/select2/select2.full.js and /dev/null differ diff --git a/public/js/plugins/select2/select2.full.min.js b/public/js/plugins/select2/select2.full.min.js deleted file mode 100755 index 59d8c1aaa6..0000000000 Binary files a/public/js/plugins/select2/select2.full.min.js and /dev/null differ diff --git a/public/js/plugins/select2/select2.js b/public/js/plugins/select2/select2.js deleted file mode 100755 index fbaca5edbc..0000000000 Binary files a/public/js/plugins/select2/select2.js and /dev/null differ diff --git a/public/js/plugins/select2/select2.min.css b/public/js/plugins/select2/select2.min.css deleted file mode 100755 index 1c7234426a..0000000000 Binary files a/public/js/plugins/select2/select2.min.css and /dev/null differ diff --git a/public/js/plugins/select2/select2.min.js b/public/js/plugins/select2/select2.min.js deleted file mode 100755 index 49a988c7ab..0000000000 Binary files a/public/js/plugins/select2/select2.min.js and /dev/null differ diff --git a/public/js/plugins/slimScroll/jquery.slimscroll.js b/public/js/plugins/slimScroll/jquery.slimscroll.js deleted file mode 100755 index e9127d313a..0000000000 Binary files a/public/js/plugins/slimScroll/jquery.slimscroll.js and /dev/null differ diff --git a/public/js/plugins/slimScroll/jquery.slimscroll.min.js b/public/js/plugins/slimScroll/jquery.slimscroll.min.js deleted file mode 100755 index 298aa1cd2b..0000000000 Binary files a/public/js/plugins/slimScroll/jquery.slimscroll.min.js and /dev/null differ diff --git a/public/js/plugins/sparkline/jquery.sparkline.js b/public/js/plugins/sparkline/jquery.sparkline.js deleted file mode 100755 index 721e03b76b..0000000000 Binary files a/public/js/plugins/sparkline/jquery.sparkline.js and /dev/null differ diff --git a/public/js/plugins/sparkline/jquery.sparkline.min.js b/public/js/plugins/sparkline/jquery.sparkline.min.js deleted file mode 100755 index fa616bf96d..0000000000 Binary files a/public/js/plugins/sparkline/jquery.sparkline.min.js and /dev/null differ diff --git a/public/js/plugins/timepicker/bootstrap-timepicker.css b/public/js/plugins/timepicker/bootstrap-timepicker.css deleted file mode 100755 index 873e0c7236..0000000000 Binary files a/public/js/plugins/timepicker/bootstrap-timepicker.css and /dev/null differ diff --git a/public/js/plugins/timepicker/bootstrap-timepicker.js b/public/js/plugins/timepicker/bootstrap-timepicker.js deleted file mode 100755 index 3068c940c8..0000000000 Binary files a/public/js/plugins/timepicker/bootstrap-timepicker.js and /dev/null differ diff --git a/public/js/plugins/timepicker/bootstrap-timepicker.min.css b/public/js/plugins/timepicker/bootstrap-timepicker.min.css deleted file mode 100755 index b59d6f76c5..0000000000 Binary files a/public/js/plugins/timepicker/bootstrap-timepicker.min.css and /dev/null differ diff --git a/public/js/plugins/timepicker/bootstrap-timepicker.min.js b/public/js/plugins/timepicker/bootstrap-timepicker.min.js deleted file mode 100755 index 3c78d5c919..0000000000 Binary files a/public/js/plugins/timepicker/bootstrap-timepicker.min.js and /dev/null differ diff --git a/public/js/respond.js b/public/js/respond.js deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/public/js/select2.min.js b/public/js/select2.min.js deleted file mode 100755 index 4e296767dc..0000000000 Binary files a/public/js/select2.min.js and /dev/null differ diff --git a/public/js/signature_pad.min.js b/public/js/signature_pad.min.js deleted file mode 100755 index 42fa23d0fc..0000000000 Binary files a/public/js/signature_pad.min.js and /dev/null differ diff --git a/public/js/snipeit.js b/public/js/snipeit.js new file mode 100644 index 0000000000..2be8145758 Binary files /dev/null and b/public/js/snipeit.js differ diff --git a/public/js/vendor.js b/public/js/vendor.js new file mode 100644 index 0000000000..deaef993b5 Binary files /dev/null and b/public/js/vendor.js differ diff --git a/public/js/vue.js b/public/js/vue.js deleted file mode 100644 index ccc8a96d88..0000000000 Binary files a/public/js/vue.js and /dev/null differ diff --git a/public/js/xlsx.core.min.js b/public/js/xlsx.core.min.js deleted file mode 100644 index dbec1de42d..0000000000 Binary files a/public/js/xlsx.core.min.js and /dev/null differ diff --git a/public/mix-manifest.json b/public/mix-manifest.json index 48e7eb5f92..bf12640cc7 100644 --- a/public/mix-manifest.json +++ b/public/mix-manifest.json @@ -1,14 +1,17 @@ { - "/js/build/vue.js": "/js/build/vue.js?id=af0a53aa1b89d0e19039", - "/css/AdminLTE.css": "/css/AdminLTE.css?id=5e72463a66acbcc740d5", - "/css/app.css": "/css/app.css?id=407edb63cc6b6dc62405", - "/css/overrides.css": "/css/overrides.css?id=2d81c3704393bac77011", - "/js/build/vue.js.map": "/js/build/vue.js.map?id=79fce5e6515d8a4cc760", - "/css/AdminLTE.css.map": "/css/AdminLTE.css.map?id=0be7790b84909dca6a0a", - "/css/app.css.map": "/css/app.css.map?id=96b5c985e860716e6a16", - "/css/overrides.css.map": "/css/overrides.css.map?id=f7ce9ca49027594ac402", - "/css/dist/all.css": "/css/dist/all.css?id=98db4e9b7650453c8b00", - "/js/dist/all.js": "/js/dist/all.js?id=a3a656ed6316d4c4efe7", - "/css/build/all.css": "/css/build/all.css?id=98db4e9b7650453c8b00", - "/js/build/all.js": "/js/build/all.js?id=a3a656ed6316d4c4efe7" -} \ No newline at end of file + "/js/app.js": "/js/app.js?id=be43e3109667a86c9a02", + "/css/build/AdminLTE.css": "/css/build/AdminLTE.css?id=f7a5d783fef321018f4c", + "/css/build/app.css": "/css/build/app.css?id=0dfc05b0fe1dcc9b6e3d", + "/css/all.css": "/css/all.css?id=9399418f7ce5805e3571", + "/css/blue.png": "/css/blue.png?id=4c85d6a97173123bd14a", + "/css/blue@2x.png": "/css/blue@2x.png?id=62c67c6a822439e8a4ac", + "/css/skins/skin-green-dark.min.css": "/css/skins/skin-green-dark.min.css?id=1039ae0e198a7f3d8da7", + "/css/skins/skin-orange-dark.min.css": "/css/skins/skin-orange-dark.min.css?id=9a461970f7ab07f40847", + "/css/skins/skin-red-dark.min.css": "/css/skins/skin-red-dark.min.css?id=99f90bbd653d7db10795", + "/css/signature-pad.css": "/css/signature-pad.css?id=6a89d3cd901305e66ced", + "/css/signature-pad.min.css": "/css/signature-pad.min.css?id=6a89d3cd901305e66ced", + "/js/vendor.js": "/js/vendor.js?id=8bf903b80600aa42a9cb", + "/js/dist/bootstrap-table.js": "/js/dist/bootstrap-table.js?id=bc5e33610f678021cc48", + "/js/dist/bootstrap-table-simple-view.js": "/js/dist/bootstrap-table-simple-view.js?id=3926b8f4aaad6ca20d31", + "/css/dist/bootstrap-table.css": "/css/dist/bootstrap-table.css?id=6b4ccfd094c065f065ae" +} diff --git a/resources/assets/css/app.css b/resources/assets/css/app.css deleted file mode 100644 index 89a60fedb2..0000000000 --- a/resources/assets/css/app.css +++ /dev/null @@ -1,10 +0,0 @@ -/*! normalize.css v3.0.2 | MIT License | git.io/normalize */html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{font-size:2em;margin:.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{-webkit-box-sizing:content-box;box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type=checkbox],input[type=radio]{-webkit-box-sizing:border-box;box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-appearance:textfield;-webkit-box-sizing:content-box;box-sizing:content-box}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}textarea{overflow:auto}optgroup{font-weight:700}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */@media print{*,:after,:before{background:transparent!important;color:#000!important;-webkit-box-shadow:none!important;box-shadow:none!important;text-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}a[href^="#"]:after,a[href^="javascript:"]:after{content:""}blockquote,pre{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}img{max-width:100%!important}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}select{background:#fff!important}.navbar{display:none}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000!important}.label{border:1px solid #000}.table{border-collapse:collapse!important}.table td,.table th{background-color:#fff!important}.table-bordered td,.table-bordered th{border:1px solid #ddd!important}}@font-face{font-family:Glyphicons Halflings;src:url("../../../node_modules/bootstrap-less/fonts/glyphicons-halflings-regular.eot");src:url("../../../node_modules/bootstrap-less/fonts/glyphicons-halflings-regular.eot?#iefix") format("embedded-opentype"),url("../../../node_modules/bootstrap-less/fonts/glyphicons-halflings-regular.woff2") format("woff2"),url("../../../node_modules/bootstrap-less/fonts/glyphicons-halflings-regular.woff") format("woff"),url("../../../node_modules/bootstrap-less/fonts/glyphicons-halflings-regular.ttf") format("truetype"),url("../../../node_modules/bootstrap-less/fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular") format("svg")}.glyphicon{position:relative;top:1px;display:inline-block;font-family:Glyphicons Halflings;font-style:normal;font-weight:400;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.glyphicon-asterisk:before{content:"*"}.glyphicon-plus:before{content:"+"}.glyphicon-eur:before,.glyphicon-euro:before{content:"\20AC"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270F"}.glyphicon-glass:before{content:"\E001"}.glyphicon-music:before{content:"\E002"}.glyphicon-search:before{content:"\E003"}.glyphicon-heart:before{content:"\E005"}.glyphicon-star:before{content:"\E006"}.glyphicon-star-empty:before{content:"\E007"}.glyphicon-user:before{content:"\E008"}.glyphicon-film:before{content:"\E009"}.glyphicon-th-large:before{content:"\E010"}.glyphicon-th:before{content:"\E011"}.glyphicon-th-list:before{content:"\E012"}.glyphicon-ok:before{content:"\E013"}.glyphicon-remove:before{content:"\E014"}.glyphicon-zoom-in:before{content:"\E015"}.glyphicon-zoom-out:before{content:"\E016"}.glyphicon-off:before{content:"\E017"}.glyphicon-signal:before{content:"\E018"}.glyphicon-cog:before{content:"\E019"}.glyphicon-trash:before{content:"\E020"}.glyphicon-home:before{content:"\E021"}.glyphicon-file:before{content:"\E022"}.glyphicon-time:before{content:"\E023"}.glyphicon-road:before{content:"\E024"}.glyphicon-download-alt:before{content:"\E025"}.glyphicon-download:before{content:"\E026"}.glyphicon-upload:before{content:"\E027"}.glyphicon-inbox:before{content:"\E028"}.glyphicon-play-circle:before{content:"\E029"}.glyphicon-repeat:before{content:"\E030"}.glyphicon-refresh:before{content:"\E031"}.glyphicon-list-alt:before{content:"\E032"}.glyphicon-lock:before{content:"\E033"}.glyphicon-flag:before{content:"\E034"}.glyphicon-headphones:before{content:"\E035"}.glyphicon-volume-off:before{content:"\E036"}.glyphicon-volume-down:before{content:"\E037"}.glyphicon-volume-up:before{content:"\E038"}.glyphicon-qrcode:before{content:"\E039"}.glyphicon-barcode:before{content:"\E040"}.glyphicon-tag:before{content:"\E041"}.glyphicon-tags:before{content:"\E042"}.glyphicon-book:before{content:"\E043"}.glyphicon-bookmark:before{content:"\E044"}.glyphicon-print:before{content:"\E045"}.glyphicon-camera:before{content:"\E046"}.glyphicon-font:before{content:"\E047"}.glyphicon-bold:before{content:"\E048"}.glyphicon-italic:before{content:"\E049"}.glyphicon-text-height:before{content:"\E050"}.glyphicon-text-width:before{content:"\E051"}.glyphicon-align-left:before{content:"\E052"}.glyphicon-align-center:before{content:"\E053"}.glyphicon-align-right:before{content:"\E054"}.glyphicon-align-justify:before{content:"\E055"}.glyphicon-list:before{content:"\E056"}.glyphicon-indent-left:before{content:"\E057"}.glyphicon-indent-right:before{content:"\E058"}.glyphicon-facetime-video:before{content:"\E059"}.glyphicon-picture:before{content:"\E060"}.glyphicon-map-marker:before{content:"\E062"}.glyphicon-adjust:before{content:"\E063"}.glyphicon-tint:before{content:"\E064"}.glyphicon-edit:before{content:"\E065"}.glyphicon-share:before{content:"\E066"}.glyphicon-check:before{content:"\E067"}.glyphicon-move:before{content:"\E068"}.glyphicon-step-backward:before{content:"\E069"}.glyphicon-fast-backward:before{content:"\E070"}.glyphicon-backward:before{content:"\E071"}.glyphicon-play:before{content:"\E072"}.glyphicon-pause:before{content:"\E073"}.glyphicon-stop:before{content:"\E074"}.glyphicon-forward:before{content:"\E075"}.glyphicon-fast-forward:before{content:"\E076"}.glyphicon-step-forward:before{content:"\E077"}.glyphicon-eject:before{content:"\E078"}.glyphicon-chevron-left:before{content:"\E079"}.glyphicon-chevron-right:before{content:"\E080"}.glyphicon-plus-sign:before{content:"\E081"}.glyphicon-minus-sign:before{content:"\E082"}.glyphicon-remove-sign:before{content:"\E083"}.glyphicon-ok-sign:before{content:"\E084"}.glyphicon-question-sign:before{content:"\E085"}.glyphicon-info-sign:before{content:"\E086"}.glyphicon-screenshot:before{content:"\E087"}.glyphicon-remove-circle:before{content:"\E088"}.glyphicon-ok-circle:before{content:"\E089"}.glyphicon-ban-circle:before{content:"\E090"}.glyphicon-arrow-left:before{content:"\E091"}.glyphicon-arrow-right:before{content:"\E092"}.glyphicon-arrow-up:before{content:"\E093"}.glyphicon-arrow-down:before{content:"\E094"}.glyphicon-share-alt:before{content:"\E095"}.glyphicon-resize-full:before{content:"\E096"}.glyphicon-resize-small:before{content:"\E097"}.glyphicon-exclamation-sign:before{content:"\E101"}.glyphicon-gift:before{content:"\E102"}.glyphicon-leaf:before{content:"\E103"}.glyphicon-fire:before{content:"\E104"}.glyphicon-eye-open:before{content:"\E105"}.glyphicon-eye-close:before{content:"\E106"}.glyphicon-warning-sign:before{content:"\E107"}.glyphicon-plane:before{content:"\E108"}.glyphicon-calendar:before{content:"\E109"}.glyphicon-random:before{content:"\E110"}.glyphicon-comment:before{content:"\E111"}.glyphicon-magnet:before{content:"\E112"}.glyphicon-chevron-up:before{content:"\E113"}.glyphicon-chevron-down:before{content:"\E114"}.glyphicon-retweet:before{content:"\E115"}.glyphicon-shopping-cart:before{content:"\E116"}.glyphicon-folder-close:before{content:"\E117"}.glyphicon-folder-open:before{content:"\E118"}.glyphicon-resize-vertical:before{content:"\E119"}.glyphicon-resize-horizontal:before{content:"\E120"}.glyphicon-hdd:before{content:"\E121"}.glyphicon-bullhorn:before{content:"\E122"}.glyphicon-bell:before{content:"\E123"}.glyphicon-certificate:before{content:"\E124"}.glyphicon-thumbs-up:before{content:"\E125"}.glyphicon-thumbs-down:before{content:"\E126"}.glyphicon-hand-right:before{content:"\E127"}.glyphicon-hand-left:before{content:"\E128"}.glyphicon-hand-up:before{content:"\E129"}.glyphicon-hand-down:before{content:"\E130"}.glyphicon-circle-arrow-right:before{content:"\E131"}.glyphicon-circle-arrow-left:before{content:"\E132"}.glyphicon-circle-arrow-up:before{content:"\E133"}.glyphicon-circle-arrow-down:before{content:"\E134"}.glyphicon-globe:before{content:"\E135"}.glyphicon-wrench:before{content:"\E136"}.glyphicon-tasks:before{content:"\E137"}.glyphicon-filter:before{content:"\E138"}.glyphicon-briefcase:before{content:"\E139"}.glyphicon-fullscreen:before{content:"\E140"}.glyphicon-dashboard:before{content:"\E141"}.glyphicon-paperclip:before{content:"\E142"}.glyphicon-heart-empty:before{content:"\E143"}.glyphicon-link:before{content:"\E144"}.glyphicon-phone:before{content:"\E145"}.glyphicon-pushpin:before{content:"\E146"}.glyphicon-usd:before{content:"\E148"}.glyphicon-gbp:before{content:"\E149"}.glyphicon-sort:before{content:"\E150"}.glyphicon-sort-by-alphabet:before{content:"\E151"}.glyphicon-sort-by-alphabet-alt:before{content:"\E152"}.glyphicon-sort-by-order:before{content:"\E153"}.glyphicon-sort-by-order-alt:before{content:"\E154"}.glyphicon-sort-by-attributes:before{content:"\E155"}.glyphicon-sort-by-attributes-alt:before{content:"\E156"}.glyphicon-unchecked:before{content:"\E157"}.glyphicon-expand:before{content:"\E158"}.glyphicon-collapse-down:before{content:"\E159"}.glyphicon-collapse-up:before{content:"\E160"}.glyphicon-log-in:before{content:"\E161"}.glyphicon-flash:before{content:"\E162"}.glyphicon-log-out:before{content:"\E163"}.glyphicon-new-window:before{content:"\E164"}.glyphicon-record:before{content:"\E165"}.glyphicon-save:before{content:"\E166"}.glyphicon-open:before{content:"\E167"}.glyphicon-saved:before{content:"\E168"}.glyphicon-import:before{content:"\E169"}.glyphicon-export:before{content:"\E170"}.glyphicon-send:before{content:"\E171"}.glyphicon-floppy-disk:before{content:"\E172"}.glyphicon-floppy-saved:before{content:"\E173"}.glyphicon-floppy-remove:before{content:"\E174"}.glyphicon-floppy-save:before{content:"\E175"}.glyphicon-floppy-open:before{content:"\E176"}.glyphicon-credit-card:before{content:"\E177"}.glyphicon-transfer:before{content:"\E178"}.glyphicon-cutlery:before{content:"\E179"}.glyphicon-header:before{content:"\E180"}.glyphicon-compressed:before{content:"\E181"}.glyphicon-earphone:before{content:"\E182"}.glyphicon-phone-alt:before{content:"\E183"}.glyphicon-tower:before{content:"\E184"}.glyphicon-stats:before{content:"\E185"}.glyphicon-sd-video:before{content:"\E186"}.glyphicon-hd-video:before{content:"\E187"}.glyphicon-subtitles:before{content:"\E188"}.glyphicon-sound-stereo:before{content:"\E189"}.glyphicon-sound-dolby:before{content:"\E190"}.glyphicon-sound-5-1:before{content:"\E191"}.glyphicon-sound-6-1:before{content:"\E192"}.glyphicon-sound-7-1:before{content:"\E193"}.glyphicon-copyright-mark:before{content:"\E194"}.glyphicon-registration-mark:before{content:"\E195"}.glyphicon-cloud-download:before{content:"\E197"}.glyphicon-cloud-upload:before{content:"\E198"}.glyphicon-tree-conifer:before{content:"\E199"}.glyphicon-tree-deciduous:before{content:"\E200"}.glyphicon-cd:before{content:"\E201"}.glyphicon-save-file:before{content:"\E202"}.glyphicon-open-file:before{content:"\E203"}.glyphicon-level-up:before{content:"\E204"}.glyphicon-copy:before{content:"\E205"}.glyphicon-paste:before{content:"\E206"}.glyphicon-alert:before{content:"\E209"}.glyphicon-equalizer:before{content:"\E210"}.glyphicon-king:before{content:"\E211"}.glyphicon-queen:before{content:"\E212"}.glyphicon-pawn:before{content:"\E213"}.glyphicon-bishop:before{content:"\E214"}.glyphicon-knight:before{content:"\E215"}.glyphicon-baby-formula:before{content:"\E216"}.glyphicon-tent:before{content:"\26FA"}.glyphicon-blackboard:before{content:"\E218"}.glyphicon-bed:before{content:"\E219"}.glyphicon-apple:before{content:"\F8FF"}.glyphicon-erase:before{content:"\E221"}.glyphicon-hourglass:before{content:"\231B"}.glyphicon-lamp:before{content:"\E223"}.glyphicon-duplicate:before{content:"\E224"}.glyphicon-piggy-bank:before{content:"\E225"}.glyphicon-scissors:before{content:"\E226"}.glyphicon-bitcoin:before{content:"\E227"}.glyphicon-yen:before{content:"\A5"}.glyphicon-ruble:before{content:"\20BD"}.glyphicon-scale:before{content:"\E230"}.glyphicon-ice-lolly:before{content:"\E231"}.glyphicon-ice-lolly-tasted:before{content:"\E232"}.glyphicon-education:before{content:"\E233"}.glyphicon-option-horizontal:before{content:"\E234"}.glyphicon-option-vertical:before{content:"\E235"}.glyphicon-menu-hamburger:before{content:"\E236"}.glyphicon-modal-window:before{content:"\E237"}.glyphicon-oil:before{content:"\E238"}.glyphicon-grain:before{content:"\E239"}.glyphicon-sunglasses:before{content:"\E240"}.glyphicon-text-size:before{content:"\E241"}.glyphicon-text-color:before{content:"\E242"}.glyphicon-text-background:before{content:"\E243"}.glyphicon-object-align-top:before{content:"\E244"}.glyphicon-object-align-bottom:before{content:"\E245"}.glyphicon-object-align-horizontal:before{content:"\E246"}.glyphicon-object-align-left:before{content:"\E247"}.glyphicon-object-align-vertical:before{content:"\E248"}.glyphicon-object-align-right:before{content:"\E249"}.glyphicon-triangle-right:before{content:"\E250"}.glyphicon-triangle-left:before{content:"\E251"}.glyphicon-triangle-bottom:before{content:"\E252"}.glyphicon-triangle-top:before{content:"\E253"}.glyphicon-console:before{content:"\E254"}.glyphicon-superscript:before{content:"\E255"}.glyphicon-subscript:before{content:"\E256"}.glyphicon-menu-left:before{content:"\E257"}.glyphicon-menu-right:before{content:"\E258"}.glyphicon-menu-down:before{content:"\E259"}.glyphicon-menu-up:before{content:"\E260"}*,:after,:before{-webkit-box-sizing:border-box;box-sizing:border-box}html{font-size:10px;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:Helvetica Neue,Helvetica,Arial,sans-serif;font-size:14px;line-height:1.42857143;color:#333;background-color:#fff}button,input,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#337ab7;text-decoration:none}a:focus,a:hover{color:#23527c;text-decoration:underline}a:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.carousel-inner>.item>a>img,.carousel-inner>.item>img,.img-responsive,.thumbnail>img,.thumbnail a>img{display:block;max-width:100%;height:auto}.img-rounded{border-radius:6px}.img-thumbnail{padding:4px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out;display:inline-block;max-width:100%;height:auto}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}.sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{font-family:inherit;font-weight:500;line-height:1.1;color:inherit}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-weight:400;line-height:1;color:#777}.h1,.h2,.h3,h1,h2,h3{margin-top:20px;margin-bottom:10px}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small{font-size:65%}.h4,.h5,.h6,h4,h5,h6{margin-top:10px;margin-bottom:10px}.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-size:75%}.h1,h1{font-size:36px}.h2,h2{font-size:30px}.h3,h3{font-size:24px}.h4,h4{font-size:18px}.h5,h5{font-size:14px}.h6,h6{font-size:12px}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16px;font-weight:300;line-height:1.4}@media (min-width:768px){.lead{font-size:21px}}.small,small{font-size:85%}.mark,mark{background-color:#fcf8e3;padding:.2em}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}.text-nowrap{white-space:nowrap}.text-lowercase{text-transform:lowercase}.text-uppercase{text-transform:uppercase}.text-capitalize{text-transform:capitalize}.text-muted{color:#777}.text-primary{color:#337ab7}a.text-primary:hover{color:#286090}.text-success{color:#3c763d}a.text-success:hover{color:#2b542c}.text-info{color:#31708f}a.text-info:hover{color:#245269}.text-warning{color:#8a6d3b}a.text-warning:hover{color:#66512c}.text-danger{color:#a94442}a.text-danger:hover{color:#843534}.bg-primary{color:#fff;background-color:#337ab7}a.bg-primary:hover{background-color:#286090}.bg-success{background-color:#dff0d8}a.bg-success:hover{background-color:#c1e2b3}.bg-info{background-color:#d9edf7}a.bg-info:hover{background-color:#afd9ee}.bg-warning{background-color:#fcf8e3}a.bg-warning:hover{background-color:#f7ecb5}.bg-danger{background-color:#f2dede}a.bg-danger:hover{background-color:#e4b9b9}.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}ol,ul{margin-top:0;margin-bottom:10px}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}.list-inline,.list-unstyled{padding-left:0;list-style:none}.list-inline{margin-left:-5px}.list-inline>li{display:inline-block;padding-left:5px;padding-right:5px}dl{margin-top:0;margin-bottom:20px}dd,dt{line-height:1.42857143}dt{font-weight:700}dd{margin-left:0}@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;clear:left;text-align:right;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}}abbr[data-original-title],abbr[title]{cursor:help;border-bottom:1px dotted #777}.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10px 20px;margin:0 0 20px;font-size:17.5px;border-left:5px solid #eee}blockquote ol:last-child,blockquote p:last-child,blockquote ul:last-child{margin-bottom:0}blockquote .small,blockquote footer,blockquote small{display:block;font-size:80%;line-height:1.42857143;color:#777}blockquote .small:before,blockquote footer:before,blockquote small:before{content:"\2014 \A0"}.blockquote-reverse,blockquote.pull-right{padding-right:15px;padding-left:0;border-right:5px solid #eee;border-left:0;text-align:right}.blockquote-reverse .small:before,.blockquote-reverse footer:before,.blockquote-reverse small:before,blockquote.pull-right .small:before,blockquote.pull-right footer:before,blockquote.pull-right small:before{content:""}.blockquote-reverse .small:after,.blockquote-reverse footer:after,.blockquote-reverse small:after,blockquote.pull-right .small:after,blockquote.pull-right footer:after,blockquote.pull-right small:after{content:"\A0 \2014"}address{margin-bottom:20px;font-style:normal;line-height:1.42857143}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,Courier New,monospace}code{color:#c7254e;background-color:#f9f2f4;border-radius:4px}code,kbd{padding:2px 4px;font-size:90%}kbd{color:#fff;background-color:#333;border-radius:3px;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.25);box-shadow:inset 0 -1px 0 rgba(0,0,0,.25)}kbd kbd{padding:0;font-size:100%;font-weight:700;-webkit-box-shadow:none;box-shadow:none}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.42857143;word-break:break-all;word-wrap:break-word;color:#333;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{margin-right:auto;margin-left:auto;padding-left:15px;padding-right:15px}@media (min-width:768px){.container{width:750px}}@media (min-width:992px){.container{width:970px}}@media (min-width:1200px){.container{width:1170px}}.container-fluid{margin-right:auto;margin-left:auto;padding-left:15px;padding-right:15px}.row{margin-left:-15px;margin-right:-15px}.col-lg-1,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-10,.col-lg-11,.col-lg-12,.col-md-1,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-10,.col-md-11,.col-md-12,.col-sm-1,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-10,.col-sm-11,.col-sm-12,.col-xs-1,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9,.col-xs-10,.col-xs-11,.col-xs-12{position:relative;min-height:1px;padding-left:15px;padding-right:15px}.col-xs-1,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9,.col-xs-10,.col-xs-11,.col-xs-12{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666667%}.col-xs-10{width:83.33333333%}.col-xs-9{width:75%}.col-xs-8{width:66.66666667%}.col-xs-7{width:58.33333333%}.col-xs-6{width:50%}.col-xs-5{width:41.66666667%}.col-xs-4{width:33.33333333%}.col-xs-3{width:25%}.col-xs-2{width:16.66666667%}.col-xs-1{width:8.33333333%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666667%}.col-xs-pull-10{right:83.33333333%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666667%}.col-xs-pull-7{right:58.33333333%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666667%}.col-xs-pull-4{right:33.33333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.66666667%}.col-xs-pull-1{right:8.33333333%}.col-xs-pull-0{right:auto}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666667%}.col-xs-push-10{left:83.33333333%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666667%}.col-xs-push-7{left:58.33333333%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666667%}.col-xs-push-4{left:33.33333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.66666667%}.col-xs-push-1{left:8.33333333%}.col-xs-push-0{left:auto}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666667%}.col-xs-offset-10{margin-left:83.33333333%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666667%}.col-xs-offset-7{margin-left:58.33333333%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666667%}.col-xs-offset-4{margin-left:33.33333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.66666667%}.col-xs-offset-1{margin-left:8.33333333%}.col-xs-offset-0{margin-left:0}@media (min-width:768px){.col-sm-1,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-10,.col-sm-11,.col-sm-12{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666667%}.col-sm-10{width:83.33333333%}.col-sm-9{width:75%}.col-sm-8{width:66.66666667%}.col-sm-7{width:58.33333333%}.col-sm-6{width:50%}.col-sm-5{width:41.66666667%}.col-sm-4{width:33.33333333%}.col-sm-3{width:25%}.col-sm-2{width:16.66666667%}.col-sm-1{width:8.33333333%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666667%}.col-sm-pull-10{right:83.33333333%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666667%}.col-sm-pull-7{right:58.33333333%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666667%}.col-sm-pull-4{right:33.33333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.66666667%}.col-sm-pull-1{right:8.33333333%}.col-sm-pull-0{right:auto}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666667%}.col-sm-push-10{left:83.33333333%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666667%}.col-sm-push-7{left:58.33333333%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666667%}.col-sm-push-4{left:33.33333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.66666667%}.col-sm-push-1{left:8.33333333%}.col-sm-push-0{left:auto}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666667%}.col-sm-offset-10{margin-left:83.33333333%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666667%}.col-sm-offset-7{margin-left:58.33333333%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666667%}.col-sm-offset-4{margin-left:33.33333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.66666667%}.col-sm-offset-1{margin-left:8.33333333%}.col-sm-offset-0{margin-left:0}}@media (min-width:992px){.col-md-1,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-10,.col-md-11,.col-md-12{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666667%}.col-md-10{width:83.33333333%}.col-md-9{width:75%}.col-md-8{width:66.66666667%}.col-md-7{width:58.33333333%}.col-md-6{width:50%}.col-md-5{width:41.66666667%}.col-md-4{width:33.33333333%}.col-md-3{width:25%}.col-md-2{width:16.66666667%}.col-md-1{width:8.33333333%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666667%}.col-md-pull-10{right:83.33333333%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666667%}.col-md-pull-7{right:58.33333333%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666667%}.col-md-pull-4{right:33.33333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.66666667%}.col-md-pull-1{right:8.33333333%}.col-md-pull-0{right:auto}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666667%}.col-md-push-10{left:83.33333333%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666667%}.col-md-push-7{left:58.33333333%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666667%}.col-md-push-4{left:33.33333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.66666667%}.col-md-push-1{left:8.33333333%}.col-md-push-0{left:auto}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666667%}.col-md-offset-10{margin-left:83.33333333%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666667%}.col-md-offset-7{margin-left:58.33333333%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666667%}.col-md-offset-4{margin-left:33.33333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.66666667%}.col-md-offset-1{margin-left:8.33333333%}.col-md-offset-0{margin-left:0}}@media (min-width:1200px){.col-lg-1,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-10,.col-lg-11,.col-lg-12{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666667%}.col-lg-10{width:83.33333333%}.col-lg-9{width:75%}.col-lg-8{width:66.66666667%}.col-lg-7{width:58.33333333%}.col-lg-6{width:50%}.col-lg-5{width:41.66666667%}.col-lg-4{width:33.33333333%}.col-lg-3{width:25%}.col-lg-2{width:16.66666667%}.col-lg-1{width:8.33333333%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666667%}.col-lg-pull-10{right:83.33333333%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666667%}.col-lg-pull-7{right:58.33333333%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666667%}.col-lg-pull-4{right:33.33333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.66666667%}.col-lg-pull-1{right:8.33333333%}.col-lg-pull-0{right:auto}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666667%}.col-lg-push-10{left:83.33333333%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666667%}.col-lg-push-7{left:58.33333333%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666667%}.col-lg-push-4{left:33.33333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.66666667%}.col-lg-push-1{left:8.33333333%}.col-lg-push-0{left:auto}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666667%}.col-lg-offset-10{margin-left:83.33333333%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666667%}.col-lg-offset-7{margin-left:58.33333333%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666667%}.col-lg-offset-4{margin-left:33.33333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.66666667%}.col-lg-offset-1{margin-left:8.33333333%}.col-lg-offset-0{margin-left:0}}table{background-color:transparent}caption{padding-top:8px;padding-bottom:8px;color:#777}caption,th{text-align:left}.table{width:100%;max-width:100%;margin-bottom:20px}.table>tbody>tr>td,.table>tbody>tr>th,.table>tfoot>tr>td,.table>tfoot>tr>th,.table>thead>tr>td,.table>thead>tr>th{padding:8px;line-height:1.42857143;vertical-align:top;border-top:1px solid #ddd}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.table>caption+thead>tr:first-child>td,.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>td,.table>thead:first-child>tr:first-child>th{border-top:0}.table>tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed>tbody>tr>td,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>td,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>thead>tr>th{padding:5px}.table-bordered,.table-bordered>tbody>tr>td,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>td,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border:1px solid #ddd}.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border-bottom-width:2px}.table-striped>tbody>tr:nth-of-type(odd){background-color:#f9f9f9}.table-hover>tbody>tr:hover{background-color:#f5f5f5}table col[class*=col-]{position:static;float:none;display:table-column}table td[class*=col-],table th[class*=col-]{position:static;float:none;display:table-cell}.table>tbody>tr.active>td,.table>tbody>tr.active>th,.table>tbody>tr>td.active,.table>tbody>tr>th.active,.table>tfoot>tr.active>td,.table>tfoot>tr.active>th,.table>tfoot>tr>td.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>thead>tr.active>th,.table>thead>tr>td.active,.table>thead>tr>th.active{background-color:#f5f5f5}.table-hover>tbody>tr.active:hover>td,.table-hover>tbody>tr.active:hover>th,.table-hover>tbody>tr:hover>.active,.table-hover>tbody>tr>td.active:hover,.table-hover>tbody>tr>th.active:hover{background-color:#e8e8e8}.table>tbody>tr.success>td,.table>tbody>tr.success>th,.table>tbody>tr>td.success,.table>tbody>tr>th.success,.table>tfoot>tr.success>td,.table>tfoot>tr.success>th,.table>tfoot>tr>td.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>thead>tr.success>th,.table>thead>tr>td.success,.table>thead>tr>th.success{background-color:#dff0d8}.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr.success:hover>th,.table-hover>tbody>tr:hover>.success,.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover{background-color:#d0e9c6}.table>tbody>tr.info>td,.table>tbody>tr.info>th,.table>tbody>tr>td.info,.table>tbody>tr>th.info,.table>tfoot>tr.info>td,.table>tfoot>tr.info>th,.table>tfoot>tr>td.info,.table>tfoot>tr>th.info,.table>thead>tr.info>td,.table>thead>tr.info>th,.table>thead>tr>td.info,.table>thead>tr>th.info{background-color:#d9edf7}.table-hover>tbody>tr.info:hover>td,.table-hover>tbody>tr.info:hover>th,.table-hover>tbody>tr:hover>.info,.table-hover>tbody>tr>td.info:hover,.table-hover>tbody>tr>th.info:hover{background-color:#c4e3f3}.table>tbody>tr.warning>td,.table>tbody>tr.warning>th,.table>tbody>tr>td.warning,.table>tbody>tr>th.warning,.table>tfoot>tr.warning>td,.table>tfoot>tr.warning>th,.table>tfoot>tr>td.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>thead>tr.warning>th,.table>thead>tr>td.warning,.table>thead>tr>th.warning{background-color:#fcf8e3}.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr.warning:hover>th,.table-hover>tbody>tr:hover>.warning,.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover{background-color:#faf2cc}.table>tbody>tr.danger>td,.table>tbody>tr.danger>th,.table>tbody>tr>td.danger,.table>tbody>tr>th.danger,.table>tfoot>tr.danger>td,.table>tfoot>tr.danger>th,.table>tfoot>tr>td.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>thead>tr.danger>th,.table>thead>tr>td.danger,.table>thead>tr>th.danger{background-color:#f2dede}.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr.danger:hover>th,.table-hover>tbody>tr:hover>.danger,.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover{background-color:#ebcccc}.table-responsive{overflow-x:auto;min-height:.01%}@media screen and (max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-y:hidden;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #ddd}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>td,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>thead>tr>th{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}}fieldset{margin:0;min-width:0}fieldset,legend{padding:0;border:0}legend{display:block;width:100%;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333;border-bottom:1px solid #e5e5e5}label{display:inline-block;max-width:100%;margin-bottom:5px;font-weight:700}input[type=search]{-webkit-box-sizing:border-box;box-sizing:border-box}input[type=checkbox],input[type=radio]{margin:4px 0 0;margin-top:1px\9;line-height:normal}input[type=file]{display:block}input[type=range]{display:block;width:100%}select[multiple],select[size]{height:auto}input[type=checkbox]:focus,input[type=file]:focus,input[type=radio]:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}output{padding-top:7px}.form-control,output{display:block;font-size:14px;line-height:1.42857143;color:#555}.form-control{width:100%;height:34px;padding:6px 12px;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-webkit-transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out;-webkit-transition:border-color .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;transition:border-color .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out,-webkit-box-shadow .15s ease-in-out}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)}.form-control::-moz-placeholder{color:#999;opacity:1}.form-control:-ms-input-placeholder{color:#999}.form-control::-webkit-input-placeholder{color:#999}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{cursor:not-allowed;background-color:#eee;opacity:1}textarea.form-control{height:auto}input[type=search]{-webkit-appearance:none}@media screen and (-webkit-min-device-pixel-ratio:0){input[type=date],input[type=datetime-local],input[type=month],input[type=time]{line-height:34px}.input-group-sm input[type=date],.input-group-sm input[type=datetime-local],.input-group-sm input[type=month],.input-group-sm input[type=time],input[type=date].input-sm,input[type=datetime-local].input-sm,input[type=month].input-sm,input[type=time].input-sm{line-height:30px}.input-group-lg input[type=date],.input-group-lg input[type=datetime-local],.input-group-lg input[type=month],.input-group-lg input[type=time],input[type=date].input-lg,input[type=datetime-local].input-lg,input[type=month].input-lg,input[type=time].input-lg{line-height:46px}}.form-group{margin-bottom:15px}.checkbox,.radio{position:relative;display:block;margin-top:10px;margin-bottom:10px}.checkbox label,.radio label{min-height:20px;padding-left:20px;margin-bottom:0;font-weight:400;cursor:pointer}.checkbox-inline input[type=checkbox],.checkbox input[type=checkbox],.radio-inline input[type=radio],.radio input[type=radio]{position:absolute;margin-left:-20px;margin-top:4px\9}.checkbox+.checkbox,.radio+.radio{margin-top:-5px}.checkbox-inline,.radio-inline{display:inline-block;padding-left:20px;margin-bottom:0;vertical-align:middle;font-weight:400;cursor:pointer}.checkbox-inline+.checkbox-inline,.radio-inline+.radio-inline{margin-top:0;margin-left:10px}.checkbox-inline.disabled,.checkbox.disabled label,.radio-inline.disabled,.radio.disabled label,fieldset[disabled] .checkbox-inline,fieldset[disabled] .checkbox label,fieldset[disabled] .radio-inline,fieldset[disabled] .radio label,fieldset[disabled] input[type=checkbox],fieldset[disabled] input[type=radio],input[type=checkbox].disabled,input[type=checkbox][disabled],input[type=radio].disabled,input[type=radio][disabled]{cursor:not-allowed}.form-control-static{padding-top:7px;padding-bottom:7px;margin-bottom:0}.form-control-static.input-lg,.form-control-static.input-sm{padding-left:0;padding-right:0}.input-sm{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-sm{height:30px;line-height:30px}select[multiple].input-sm,textarea.input-sm{height:auto}.form-group-sm .form-control{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.form-group-sm .form-control{height:30px;line-height:30px}select[multiple].form-group-sm .form-control,textarea.form-group-sm .form-control{height:auto}.form-group-sm .form-control-static{height:30px;padding:5px 10px;font-size:12px;line-height:1.5}.input-lg{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-lg{height:46px;line-height:46px}select[multiple].input-lg,textarea.input-lg{height:auto}.form-group-lg .form-control{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.form-group-lg .form-control{height:46px;line-height:46px}select[multiple].form-group-lg .form-control,textarea.form-group-lg .form-control{height:auto}.form-group-lg .form-control-static{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333}.has-feedback{position:relative}.has-feedback .form-control{padding-right:42.5px}.form-control-feedback{position:absolute;top:0;right:0;z-index:2;display:block;width:34px;height:34px;line-height:34px;text-align:center;pointer-events:none}.input-lg+.form-control-feedback{width:46px;height:46px;line-height:46px}.input-sm+.form-control-feedback{width:30px;height:30px;line-height:30px}.has-success .checkbox,.has-success .checkbox-inline,.has-success.checkbox-inline label,.has-success.checkbox label,.has-success .control-label,.has-success .help-block,.has-success .radio,.has-success .radio-inline,.has-success.radio-inline label,.has-success.radio label{color:#3c763d}.has-success .form-control{border-color:#3c763d;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-success .form-control:focus{border-color:#2b542c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168}.has-success .input-group-addon{color:#3c763d;border-color:#3c763d;background-color:#dff0d8}.has-success .form-control-feedback{color:#3c763d}.has-warning .checkbox,.has-warning .checkbox-inline,.has-warning.checkbox-inline label,.has-warning.checkbox label,.has-warning .control-label,.has-warning .help-block,.has-warning .radio,.has-warning .radio-inline,.has-warning.radio-inline label,.has-warning.radio label{color:#8a6d3b}.has-warning .form-control{border-color:#8a6d3b;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-warning .form-control:focus{border-color:#66512c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b}.has-warning .input-group-addon{color:#8a6d3b;border-color:#8a6d3b;background-color:#fcf8e3}.has-warning .form-control-feedback{color:#8a6d3b}.has-error .checkbox,.has-error .checkbox-inline,.has-error.checkbox-inline label,.has-error.checkbox label,.has-error .control-label,.has-error .help-block,.has-error .radio,.has-error .radio-inline,.has-error.radio-inline label,.has-error.radio label{color:#a94442}.has-error .form-control{border-color:#a94442;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-error .form-control:focus{border-color:#843534;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483}.has-error .input-group-addon{color:#a94442;border-color:#a94442;background-color:#f2dede}.has-error .form-control-feedback{color:#a94442}.has-feedback label~.form-control-feedback{top:25px}.has-feedback label.sr-only~.form-control-feedback{top:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373}@media (min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-static{display:inline-block}.form-inline .input-group{display:inline-table;vertical-align:middle}.form-inline .input-group .form-control,.form-inline .input-group .input-group-addon,.form-inline .input-group .input-group-btn{width:auto}.form-inline .input-group>.form-control{width:100%}.form-inline .control-label{margin-bottom:0;vertical-align:middle}.form-inline .checkbox,.form-inline .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.form-inline .checkbox label,.form-inline .radio label{padding-left:0}.form-inline .checkbox input[type=checkbox],.form-inline .radio input[type=radio]{position:relative;margin-left:0}.form-inline .has-feedback .form-control-feedback{top:0}}.form-horizontal .checkbox,.form-horizontal .checkbox-inline,.form-horizontal .radio,.form-horizontal .radio-inline{margin-top:0;margin-bottom:0;padding-top:7px}.form-horizontal .checkbox,.form-horizontal .radio{min-height:27px}.form-horizontal .form-group{margin-left:-15px;margin-right:-15px}@media (min-width:768px){.form-horizontal .control-label{text-align:right;margin-bottom:0;padding-top:7px}}.form-horizontal .has-feedback .form-control-feedback{right:15px}@media (min-width:768px){.form-horizontal .form-group-lg .control-label{padding-top:14.333333px}}@media (min-width:768px){.form-horizontal .form-group-sm .control-label{padding-top:6px}}.btn{display:inline-block;margin-bottom:0;font-weight:400;text-align:center;vertical-align:middle;-ms-touch-action:manipulation;touch-action:manipulation;cursor:pointer;background-image:none;border:1px solid transparent;white-space:nowrap;padding:6px 12px;font-size:14px;line-height:1.42857143;border-radius:4px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.btn.active.focus,.btn.active:focus,.btn.focus,.btn:active.focus,.btn:active:focus,.btn:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn.focus,.btn:focus,.btn:hover{color:#333;text-decoration:none}.btn.active,.btn:active{outline:0;background-image:none;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{cursor:not-allowed;pointer-events:none;opacity:.65;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none}.btn-default{color:#333;background-color:#fff;border-color:#ccc}.btn-default.active,.btn-default.focus,.btn-default:active,.btn-default:focus,.btn-default:hover,.open>.dropdown-toggle.btn-default{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default.active,.btn-default:active,.open>.dropdown-toggle.btn-default{background-image:none}.btn-default.disabled,.btn-default.disabled.active,.btn-default.disabled.focus,.btn-default.disabled:active,.btn-default.disabled:focus,.btn-default.disabled:hover,.btn-default[disabled],.btn-default[disabled].active,.btn-default[disabled].focus,.btn-default[disabled]:active,.btn-default[disabled]:focus,.btn-default[disabled]:hover,fieldset[disabled] .btn-default,fieldset[disabled] .btn-default.active,fieldset[disabled] .btn-default.focus,fieldset[disabled] .btn-default:active,fieldset[disabled] .btn-default:focus,fieldset[disabled] .btn-default:hover{background-color:#fff;border-color:#ccc}.btn-default .badge{color:#fff;background-color:#333}.btn-primary{color:#fff;background-color:#337ab7;border-color:#2e6da4}.btn-primary.active,.btn-primary.focus,.btn-primary:active,.btn-primary:focus,.btn-primary:hover,.open>.dropdown-toggle.btn-primary{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary.active,.btn-primary:active,.open>.dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled,.btn-primary.disabled.active,.btn-primary.disabled.focus,.btn-primary.disabled:active,.btn-primary.disabled:focus,.btn-primary.disabled:hover,.btn-primary[disabled],.btn-primary[disabled].active,.btn-primary[disabled].focus,.btn-primary[disabled]:active,.btn-primary[disabled]:focus,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary,fieldset[disabled] .btn-primary.active,fieldset[disabled] .btn-primary.focus,fieldset[disabled] .btn-primary:active,fieldset[disabled] .btn-primary:focus,fieldset[disabled] .btn-primary:hover{background-color:#337ab7;border-color:#2e6da4}.btn-primary .badge{color:#337ab7;background-color:#fff}.btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.btn-success.active,.btn-success.focus,.btn-success:active,.btn-success:focus,.btn-success:hover,.open>.dropdown-toggle.btn-success{color:#fff;background-color:#449d44;border-color:#398439}.btn-success.active,.btn-success:active,.open>.dropdown-toggle.btn-success{background-image:none}.btn-success.disabled,.btn-success.disabled.active,.btn-success.disabled.focus,.btn-success.disabled:active,.btn-success.disabled:focus,.btn-success.disabled:hover,.btn-success[disabled],.btn-success[disabled].active,.btn-success[disabled].focus,.btn-success[disabled]:active,.btn-success[disabled]:focus,.btn-success[disabled]:hover,fieldset[disabled] .btn-success,fieldset[disabled] .btn-success.active,fieldset[disabled] .btn-success.focus,fieldset[disabled] .btn-success:active,fieldset[disabled] .btn-success:focus,fieldset[disabled] .btn-success:hover{background-color:#5cb85c;border-color:#4cae4c}.btn-success .badge{color:#5cb85c;background-color:#fff}.btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da}.btn-info.active,.btn-info.focus,.btn-info:active,.btn-info:focus,.btn-info:hover,.open>.dropdown-toggle.btn-info{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info.active,.btn-info:active,.open>.dropdown-toggle.btn-info{background-image:none}.btn-info.disabled,.btn-info.disabled.active,.btn-info.disabled.focus,.btn-info.disabled:active,.btn-info.disabled:focus,.btn-info.disabled:hover,.btn-info[disabled],.btn-info[disabled].active,.btn-info[disabled].focus,.btn-info[disabled]:active,.btn-info[disabled]:focus,.btn-info[disabled]:hover,fieldset[disabled] .btn-info,fieldset[disabled] .btn-info.active,fieldset[disabled] .btn-info.focus,fieldset[disabled] .btn-info:active,fieldset[disabled] .btn-info:focus,fieldset[disabled] .btn-info:hover{background-color:#5bc0de;border-color:#46b8da}.btn-info .badge{color:#5bc0de;background-color:#fff}.btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}.btn-warning.active,.btn-warning.focus,.btn-warning:active,.btn-warning:focus,.btn-warning:hover,.open>.dropdown-toggle.btn-warning{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning.active,.btn-warning:active,.open>.dropdown-toggle.btn-warning{background-image:none}.btn-warning.disabled,.btn-warning.disabled.active,.btn-warning.disabled.focus,.btn-warning.disabled:active,.btn-warning.disabled:focus,.btn-warning.disabled:hover,.btn-warning[disabled],.btn-warning[disabled].active,.btn-warning[disabled].focus,.btn-warning[disabled]:active,.btn-warning[disabled]:focus,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning,fieldset[disabled] .btn-warning.active,fieldset[disabled] .btn-warning.focus,fieldset[disabled] .btn-warning:active,fieldset[disabled] .btn-warning:focus,fieldset[disabled] .btn-warning:hover{background-color:#f0ad4e;border-color:#eea236}.btn-warning .badge{color:#f0ad4e;background-color:#fff}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d43f3a}.btn-danger.active,.btn-danger.focus,.btn-danger:active,.btn-danger:focus,.btn-danger:hover,.open>.dropdown-toggle.btn-danger{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger.active,.btn-danger:active,.open>.dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled,.btn-danger.disabled.active,.btn-danger.disabled.focus,.btn-danger.disabled:active,.btn-danger.disabled:focus,.btn-danger.disabled:hover,.btn-danger[disabled],.btn-danger[disabled].active,.btn-danger[disabled].focus,.btn-danger[disabled]:active,.btn-danger[disabled]:focus,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger,fieldset[disabled] .btn-danger.active,fieldset[disabled] .btn-danger.focus,fieldset[disabled] .btn-danger:active,fieldset[disabled] .btn-danger:focus,fieldset[disabled] .btn-danger:hover{background-color:#d9534f;border-color:#d43f3a}.btn-danger .badge{color:#d9534f;background-color:#fff}.btn-link{color:#337ab7;font-weight:400;border-radius:0}.btn-link,.btn-link.active,.btn-link:active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:active,.btn-link:focus,.btn-link:hover{border-color:transparent}.btn-link:focus,.btn-link:hover{color:#23527c;text-decoration:underline;background-color:transparent}.btn-link[disabled]:focus,.btn-link[disabled]:hover,fieldset[disabled] .btn-link:focus,fieldset[disabled] .btn-link:hover{color:#777;text-decoration:none}.btn-group-lg>.btn,.btn-lg{padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.btn-group-sm>.btn,.btn-sm{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-group-xs>.btn,.btn-xs{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:5px}input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none;visibility:hidden}.collapse.in{display:block;visibility:visible}tr.collapse.in{display:table-row}tbody.collapse.in{display:table-row-group}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition-property:height,visibility;transition-property:height,visibility;-webkit-transition-duration:.35s;transition-duration:.35s;-webkit-transition-timing-function:ease;transition-timing-function:ease}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px solid;border-right:4px solid transparent;border-left:4px solid transparent}.dropdown,.dropup{position:relative}.dropdown-toggle:focus{outline:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;list-style:none;font-size:14px;text-align:left;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,.175);box-shadow:0 6px 12px rgba(0,0,0,.175);background-clip:padding-box}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:400;line-height:1.42857143;color:#333;white-space:nowrap}.dropdown-menu>li>a:focus,.dropdown-menu>li>a:hover{text-decoration:none;color:#262626;background-color:#f5f5f5}.dropdown-menu>.active>a,.dropdown-menu>.active>a:focus,.dropdown-menu>.active>a:hover{color:#fff;text-decoration:none;outline:0;background-color:#337ab7}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{color:#777}.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{text-decoration:none;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);cursor:not-allowed}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-menu-right{left:auto;right:0}.dropdown-menu-left{left:0;right:auto}.dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.42857143;color:#777;white-space:nowrap}.dropdown-backdrop{position:fixed;left:0;right:0;bottom:0;top:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{border-top:0;border-bottom:4px solid;content:""}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:2px}@media (min-width:768px){.navbar-right .dropdown-menu{left:auto;right:0}.navbar-right .dropdown-menu-left{left:0;right:auto}}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group-vertical>.btn,.btn-group>.btn{position:relative;float:left}.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group-vertical>.btn:hover,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus,.btn-group>.btn:hover{z-index:2}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-toolbar{margin-left:-5px}.btn-toolbar .btn-group,.btn-toolbar .input-group{float:left}.btn-toolbar>.btn,.btn-toolbar>.btn-group,.btn-toolbar>.input-group{margin-left:5px}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-bottom-right-radius:0;border-top-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-top-right-radius:0}.btn-group>.btn-group:last-child:not(:first-child)>.btn:first-child{border-bottom-left-radius:0;border-top-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{padding-left:8px;padding-right:8px}.btn-group>.btn-lg+.dropdown-toggle{padding-left:12px;padding-right:12px}.btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-group.open .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none}.btn .caret{margin-left:0}.btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}.dropup .btn-lg .caret{border-width:0 5px 5px}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group,.btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group>.btn{float:none}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-child){border-bottom-left-radius:4px;border-top-right-radius:0;border-top-left-radius:0}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group-vertical>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-right-radius:0;border-top-left-radius:0}.btn-group-justified{display:table;width:100%;table-layout:fixed;border-collapse:separate}.btn-group-justified>.btn,.btn-group-justified>.btn-group{float:none;display:table-cell;width:1%}.btn-group-justified>.btn-group .btn{width:100%}.btn-group-justified>.btn-group .dropdown-menu{left:auto}[data-toggle=buttons]>.btn-group>.btn input[type=checkbox],[data-toggle=buttons]>.btn-group>.btn input[type=radio],[data-toggle=buttons]>.btn input[type=checkbox],[data-toggle=buttons]>.btn input[type=radio]{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.input-group{position:relative;display:table;border-collapse:separate}.input-group[class*=col-]{float:none;padding-left:0;padding-right:0}.input-group .form-control{position:relative;z-index:2;float:left;width:100%;margin-bottom:0}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-group-lg>.form-control,select.input-group-lg>.input-group-addon,select.input-group-lg>.input-group-btn>.btn{height:46px;line-height:46px}select[multiple].input-group-lg>.form-control,select[multiple].input-group-lg>.input-group-addon,select[multiple].input-group-lg>.input-group-btn>.btn,textarea.input-group-lg>.form-control,textarea.input-group-lg>.input-group-addon,textarea.input-group-lg>.input-group-btn>.btn{height:auto}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-group-sm>.form-control,select.input-group-sm>.input-group-addon,select.input-group-sm>.input-group-btn>.btn{height:30px;line-height:30px}select[multiple].input-group-sm>.form-control,select[multiple].input-group-sm>.input-group-addon,select[multiple].input-group-sm>.input-group-btn>.btn,textarea.input-group-sm>.form-control,textarea.input-group-sm>.input-group-addon,textarea.input-group-sm>.input-group-btn>.btn{height:auto}.input-group-addon,.input-group-btn,.input-group .form-control{display:table-cell}.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child),.input-group .form-control:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:6px 12px;font-size:14px;font-weight:400;line-height:1;color:#555;text-align:center;background-color:#eee;border:1px solid #ccc;border-radius:4px}.input-group-addon.input-sm{padding:5px 10px;font-size:12px;border-radius:3px}.input-group-addon.input-lg{padding:10px 16px;font-size:18px;border-radius:6px}.input-group-addon input[type=checkbox],.input-group-addon input[type=radio]{margin-top:0}.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn-group:not(:last-child)>.btn,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle),.input-group .form-control:first-child{border-bottom-right-radius:0;border-top-right-radius:0}.input-group-addon:first-child{border-right:0}.input-group-addon:last-child,.input-group-btn:first-child>.btn-group:not(:first-child)>.btn,.input-group-btn:first-child>.btn:not(:first-child),.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group>.btn,.input-group-btn:last-child>.dropdown-toggle,.input-group .form-control:last-child{border-bottom-left-radius:0;border-top-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{font-size:0;white-space:nowrap}.input-group-btn,.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-1px}.input-group-btn>.btn:active,.input-group-btn>.btn:focus,.input-group-btn>.btn:hover{z-index:2}.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group{margin-right:-1px}.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group{margin-left:-1px}.nav{margin-bottom:0;padding-left:0;list-style:none}.nav>li,.nav>li>a{position:relative;display:block}.nav>li>a{padding:10px 15px}.nav>li>a:focus,.nav>li>a:hover{text-decoration:none;background-color:#eee}.nav>li.disabled>a{color:#777}.nav>li.disabled>a:focus,.nav>li.disabled>a:hover{color:#777;text-decoration:none;background-color:transparent;cursor:not-allowed}.nav .open>a,.nav .open>a:focus,.nav .open>a:hover{background-color:#eee;border-color:#337ab7}.nav .nav-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.42857143;border:1px solid transparent;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>li.active>a,.nav-tabs>li.active>a:focus,.nav-tabs>li.active>a:hover{color:#555;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent;cursor:default}.nav-tabs.nav-justified{width:100%;border-bottom:0}.nav-tabs.nav-justified>li{float:none}.nav-tabs.nav-justified>li>a{text-align:center;margin-bottom:5px}.nav-tabs.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%}.nav-tabs.nav-justified>li>a{margin-bottom:0}}.nav-tabs.nav-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border:1px solid #ddd}@media (min-width:768px){.nav-tabs.nav-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border-bottom-color:#fff}}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:4px}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:focus,.nav-pills>li.active>a:hover{color:#fff;background-color:#337ab7}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-justified{width:100%}.nav-justified>li{float:none}.nav-justified>li>a{text-align:center;margin-bottom:5px}.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-justified>li{display:table-cell;width:1%}.nav-justified>li>a{margin-bottom:0}}.nav-tabs-justified{border-bottom:0}.nav-tabs-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover{border:1px solid #ddd}@media (min-width:768px){.nav-tabs-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover{border-bottom-color:#fff}}.tab-content>.tab-pane{display:none;visibility:hidden}.tab-content>.active{display:block;visibility:visible}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-right-radius:0;border-top-left-radius:0}.navbar{position:relative;min-height:50px;margin-bottom:20px;border:1px solid transparent}@media (min-width:768px){.navbar{border-radius:4px}}@media (min-width:768px){.navbar-header{float:left}}.navbar-collapse{overflow-x:visible;padding-right:15px;padding-left:15px;border-top:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 hsla(0,0%,100%,.1);box-shadow:inset 0 1px 0 hsla(0,0%,100%,.1);-webkit-overflow-scrolling:touch}.navbar-collapse.in{overflow-y:auto}@media (min-width:768px){.navbar-collapse{width:auto;border-top:0;-webkit-box-shadow:none;box-shadow:none}.navbar-collapse.collapse{display:block!important;visibility:visible!important;height:auto!important;padding-bottom:0;overflow:visible!important}.navbar-collapse.in{overflow-y:visible}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse,.navbar-static-top .navbar-collapse{padding-left:0;padding-right:0}}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse{max-height:340px}@media (max-device-width:480px) and (orientation:landscape){.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse{max-height:200px}}.container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:0;margin-left:0}}.navbar-static-top{z-index:1000;border-width:0 0 1px}@media (min-width:768px){.navbar-static-top{border-radius:0}}.navbar-fixed-bottom,.navbar-fixed-top{position:fixed;right:0;left:0;z-index:1030}@media (min-width:768px){.navbar-fixed-bottom,.navbar-fixed-top{border-radius:0}}.navbar-fixed-top{top:0;border-width:0 0 1px}.navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0}.navbar-brand{float:left;padding:15px;font-size:18px;line-height:20px;height:50px}.navbar-brand:focus,.navbar-brand:hover{text-decoration:none}.navbar-brand>img{display:block}@media (min-width:768px){.navbar>.container-fluid .navbar-brand,.navbar>.container .navbar-brand{margin-left:-15px}}.navbar-toggle{position:relative;float:right;margin-right:15px;padding:9px 10px;margin-top:8px;margin-bottom:8px;background-color:transparent;background-image:none;border:1px solid transparent;border-radius:4px}.navbar-toggle:focus{outline:0}.navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media (min-width:768px){.navbar-toggle{display:none}}.navbar-nav{margin:7.5px -15px}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:20px}@media (max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;-webkit-box-shadow:none;box-shadow:none}.navbar-nav .open .dropdown-menu .dropdown-header,.navbar-nav .open .dropdown-menu>li>a{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:20px}.navbar-nav .open .dropdown-menu>li>a:focus,.navbar-nav .open .dropdown-menu>li>a:hover{background-image:none}}@media (min-width:768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:15px;padding-bottom:15px}}.navbar-form{margin:8px -15px;padding:10px 15px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 hsla(0,0%,100%,.1),0 1px 0 hsla(0,0%,100%,.1);box-shadow:inset 0 1px 0 hsla(0,0%,100%,.1),0 1px 0 hsla(0,0%,100%,.1)}@media (min-width:768px){.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.navbar-form .form-control{display:inline-block;width:auto;vertical-align:middle}.navbar-form .form-control-static{display:inline-block}.navbar-form .input-group{display:inline-table;vertical-align:middle}.navbar-form .input-group .form-control,.navbar-form .input-group .input-group-addon,.navbar-form .input-group .input-group-btn{width:auto}.navbar-form .input-group>.form-control{width:100%}.navbar-form .control-label{margin-bottom:0;vertical-align:middle}.navbar-form .checkbox,.navbar-form .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.navbar-form .checkbox label,.navbar-form .radio label{padding-left:0}.navbar-form .checkbox input[type=checkbox],.navbar-form .radio input[type=radio]{position:relative;margin-left:0}.navbar-form .has-feedback .form-control-feedback{top:0}}@media (max-width:767px){.navbar-form .form-group{margin-bottom:5px}.navbar-form .form-group:last-child{margin-bottom:0}}@media (min-width:768px){.navbar-form{width:auto;border:0;margin-left:0;margin-right:0;padding-top:0;padding-bottom:0;-webkit-box-shadow:none;box-shadow:none}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-right-radius:0;border-top-left-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{margin-bottom:0;border-top-right-radius:4px;border-top-left-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.navbar-btn{margin-top:8px;margin-bottom:8px}.navbar-btn.btn-sm{margin-top:10px;margin-bottom:10px}.navbar-btn.btn-xs{margin-top:14px;margin-bottom:14px}.navbar-text{margin-top:15px;margin-bottom:15px}@media (min-width:768px){.navbar-text{float:left;margin-left:15px;margin-right:15px}}@media (min-width:768px){.navbar-left{float:left!important}.navbar-right{float:right!important;margin-right:-15px}.navbar-right~.navbar-right{margin-right:0}}.navbar-default{background-color:#f8f8f8;border-color:#e7e7e7}.navbar-default .navbar-brand{color:#777}.navbar-default .navbar-brand:focus,.navbar-default .navbar-brand:hover{color:#5e5e5e;background-color:transparent}.navbar-default .navbar-nav>li>a,.navbar-default .navbar-text{color:#777}.navbar-default .navbar-nav>li>a:focus,.navbar-default .navbar-nav>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:focus,.navbar-default .navbar-nav>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:focus,.navbar-default .navbar-nav>.disabled>a:hover{color:#ccc;background-color:transparent}.navbar-default .navbar-toggle{border-color:#ddd}.navbar-default .navbar-toggle:focus,.navbar-default .navbar-toggle:hover{background-color:#ddd}.navbar-default .navbar-toggle .icon-bar{background-color:#888}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#e7e7e7}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:focus,.navbar-default .navbar-nav>.open>a:hover{background-color:#e7e7e7;color:#555}@media (max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#777}.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#ccc;background-color:transparent}}.navbar-default .navbar-link{color:#777}.navbar-default .navbar-link:hover{color:#333}.navbar-default .btn-link{color:#777}.navbar-default .btn-link:focus,.navbar-default .btn-link:hover{color:#333}.navbar-default .btn-link[disabled]:focus,.navbar-default .btn-link[disabled]:hover,fieldset[disabled] .navbar-default .btn-link:focus,fieldset[disabled] .navbar-default .btn-link:hover{color:#ccc}.navbar-inverse{background-color:#222;border-color:#080808}.navbar-inverse .navbar-brand{color:#9d9d9d}.navbar-inverse .navbar-brand:focus,.navbar-inverse .navbar-brand:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav>li>a,.navbar-inverse .navbar-text{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a:focus,.navbar-inverse .navbar-nav>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:focus,.navbar-inverse .navbar-nav>.active>a:hover{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:focus,.navbar-inverse .navbar-nav>.disabled>a:hover{color:#444;background-color:transparent}.navbar-inverse .navbar-toggle{border-color:#333}.navbar-inverse .navbar-toggle:focus,.navbar-inverse .navbar-toggle:hover{background-color:#333}.navbar-inverse .navbar-toggle .icon-bar{background-color:#fff}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#101010}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:focus,.navbar-inverse .navbar-nav>.open>a:hover{background-color:#080808;color:#fff}@media (max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu .divider{background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#444;background-color:transparent}}.navbar-inverse .navbar-link{color:#9d9d9d}.navbar-inverse .navbar-link:hover{color:#fff}.navbar-inverse .btn-link{color:#9d9d9d}.navbar-inverse .btn-link:focus,.navbar-inverse .btn-link:hover{color:#fff}.navbar-inverse .btn-link[disabled]:focus,.navbar-inverse .btn-link[disabled]:hover,fieldset[disabled] .navbar-inverse .btn-link:focus,fieldset[disabled] .navbar-inverse .btn-link:hover{color:#444}.breadcrumb{padding:8px 15px;margin-bottom:20px;list-style:none;background-color:#f5f5f5;border-radius:4px}.breadcrumb>li{display:inline-block}.breadcrumb>li+li:before{content:"/\A0";padding:0 5px;color:#ccc}.breadcrumb>.active{color:#777}.pagination{display:inline-block;padding-left:0;margin:20px 0;border-radius:4px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 12px;line-height:1.42857143;text-decoration:none;color:#337ab7;background-color:#fff;border:1px solid #ddd;margin-left:-1px}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-bottom-left-radius:4px;border-top-left-radius:4px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-bottom-right-radius:4px;border-top-right-radius:4px}.pagination>li>a:focus,.pagination>li>a:hover,.pagination>li>span:focus,.pagination>li>span:hover{color:#23527c;background-color:#eee;border-color:#ddd}.pagination>.active>a,.pagination>.active>a:focus,.pagination>.active>a:hover,.pagination>.active>span,.pagination>.active>span:focus,.pagination>.active>span:hover{z-index:2;color:#fff;background-color:#337ab7;border-color:#337ab7;cursor:default}.pagination>.disabled>a,.pagination>.disabled>a:focus,.pagination>.disabled>a:hover,.pagination>.disabled>span,.pagination>.disabled>span:focus,.pagination>.disabled>span:hover{color:#777;background-color:#fff;border-color:#ddd;cursor:not-allowed}.pagination-lg>li>a,.pagination-lg>li>span{padding:10px 16px;font-size:18px}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-bottom-left-radius:6px;border-top-left-radius:6px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-bottom-right-radius:6px;border-top-right-radius:6px}.pagination-sm>li>a,.pagination-sm>li>span{padding:5px 10px;font-size:12px}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-bottom-left-radius:3px;border-top-left-radius:3px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-bottom-right-radius:3px;border-top-right-radius:3px}.pager{padding-left:0;margin:20px 0;list-style:none;text-align:center}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;border-radius:15px}.pager li>a:focus,.pager li>a:hover{text-decoration:none;background-color:#eee}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:focus,.pager .disabled>a:hover,.pager .disabled>span{color:#777;background-color:#fff;cursor:not-allowed}.label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}a.label:focus,a.label:hover{color:#fff;text-decoration:none;cursor:pointer}.label:empty{display:none}.btn .label{position:relative;top:-1px}.label-default{background-color:#777}.label-default[href]:focus,.label-default[href]:hover{background-color:#5e5e5e}.label-primary{background-color:#337ab7}.label-primary[href]:focus,.label-primary[href]:hover{background-color:#286090}.label-success{background-color:#5cb85c}.label-success[href]:focus,.label-success[href]:hover{background-color:#449d44}.label-info{background-color:#5bc0de}.label-info[href]:focus,.label-info[href]:hover{background-color:#31b0d5}.label-warning{background-color:#f0ad4e}.label-warning[href]:focus,.label-warning[href]:hover{background-color:#ec971f}.label-danger{background-color:#d9534f}.label-danger[href]:focus,.label-danger[href]:hover{background-color:#c9302c}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:700;color:#fff;line-height:1;vertical-align:baseline;white-space:nowrap;text-align:center;background-color:#777;border-radius:10px}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.btn-xs .badge{top:0;padding:1px 5px}a.badge:focus,a.badge:hover{color:#fff;text-decoration:none;cursor:pointer}.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#337ab7;background-color:#fff}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}.nav-pills>li>a>.badge{margin-left:3px}.jumbotron{padding:30px 15px;margin-bottom:30px;background-color:#eee}.jumbotron,.jumbotron .h1,.jumbotron h1{color:inherit}.jumbotron p{margin-bottom:15px;font-size:21px;font-weight:200}.jumbotron>hr{border-top-color:#d5d5d5}.container-fluid .jumbotron,.container .jumbotron{border-radius:6px}.jumbotron .container{max-width:100%}@media screen and (min-width:768px){.jumbotron{padding:48px 0}.container-fluid .jumbotron,.container .jumbotron{padding-left:60px;padding-right:60px}.jumbotron .h1,.jumbotron h1{font-size:63px}}.thumbnail{display:block;padding:4px;margin-bottom:20px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:border .2s ease-in-out;transition:border .2s ease-in-out}.thumbnail>img,.thumbnail a>img{margin-left:auto;margin-right:auto}a.thumbnail.active,a.thumbnail:focus,a.thumbnail:hover{border-color:#337ab7}.thumbnail .caption{padding:9px;color:#333}.alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:700}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable,.alert-dismissible{padding-right:35px}.alert-dismissable .close,.alert-dismissible .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{background-color:#dff0d8;border-color:#d6e9c6;color:#3c763d}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#2b542c}.alert-info{background-color:#d9edf7;border-color:#bce8f1;color:#31708f}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#245269}.alert-warning{background-color:#fcf8e3;border-color:#faebcc;color:#8a6d3b}.alert-warning hr{border-top-color:#f7e1b5}.alert-warning .alert-link{color:#66512c}.alert-danger{background-color:#f2dede;border-color:#ebccd1;color:#a94442}.alert-danger hr{border-top-color:#e4b9c0}.alert-danger .alert-link{color:#843534}@-webkit-keyframes progress-bar-stripes{0%{background-position:40px 0}to{background-position:0 0}}@keyframes progress-bar-stripes{0%{background-position:40px 0}to{background-position:0 0}}.progress{overflow:hidden;height:20px;margin-bottom:20px;background-color:#f5f5f5;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,.1);box-shadow:inset 0 1px 2px rgba(0,0,0,.1)}.progress-bar{float:left;width:0;height:100%;font-size:12px;line-height:20px;color:#fff;text-align:center;background-color:#337ab7;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);-webkit-transition:width .6s ease;transition:width .6s ease}.progress-bar-striped,.progress-striped .progress-bar{background-image:linear-gradient(45deg,hsla(0,0%,100%,.15) 25%,transparent 0,transparent 50%,hsla(0,0%,100%,.15) 0,hsla(0,0%,100%,.15) 75%,transparent 0,transparent);background-size:40px 40px}.progress-bar.active,.progress.active .progress-bar{-webkit-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-bar-success{background-color:#5cb85c}.progress-striped .progress-bar-success{background-image:linear-gradient(45deg,hsla(0,0%,100%,.15) 25%,transparent 0,transparent 50%,hsla(0,0%,100%,.15) 0,hsla(0,0%,100%,.15) 75%,transparent 0,transparent)}.progress-bar-info{background-color:#5bc0de}.progress-striped .progress-bar-info{background-image:linear-gradient(45deg,hsla(0,0%,100%,.15) 25%,transparent 0,transparent 50%,hsla(0,0%,100%,.15) 0,hsla(0,0%,100%,.15) 75%,transparent 0,transparent)}.progress-bar-warning{background-color:#f0ad4e}.progress-striped .progress-bar-warning{background-image:linear-gradient(45deg,hsla(0,0%,100%,.15) 25%,transparent 0,transparent 50%,hsla(0,0%,100%,.15) 0,hsla(0,0%,100%,.15) 75%,transparent 0,transparent)}.progress-bar-danger{background-color:#d9534f}.progress-striped .progress-bar-danger{background-image:linear-gradient(45deg,hsla(0,0%,100%,.15) 25%,transparent 0,transparent 50%,hsla(0,0%,100%,.15) 0,hsla(0,0%,100%,.15) 75%,transparent 0,transparent)}.media{margin-top:15px}.media:first-child{margin-top:0}.media,.media-body{zoom:1;overflow:hidden}.media-body{width:10000px}.media-object{display:block}.media-right,.media>.pull-right{padding-left:10px}.media-left,.media>.pull-left{padding-right:10px}.media-body,.media-left,.media-right{display:table-cell;vertical-align:top}.media-middle{vertical-align:middle}.media-bottom{vertical-align:bottom}.media-heading{margin-top:0;margin-bottom:5px}.media-list{padding-left:0;list-style:none}.list-group{margin-bottom:20px;padding-left:0}.list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#fff;border:1px solid #ddd}.list-group-item:first-child{border-top-right-radius:4px;border-top-left-radius:4px}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}a.list-group-item{color:#555}a.list-group-item .list-group-item-heading{color:#333}a.list-group-item:focus,a.list-group-item:hover{text-decoration:none;color:#555;background-color:#f5f5f5}.list-group-item.disabled,.list-group-item.disabled:focus,.list-group-item.disabled:hover{background-color:#eee;color:#777;cursor:not-allowed}.list-group-item.disabled .list-group-item-heading,.list-group-item.disabled:focus .list-group-item-heading,.list-group-item.disabled:hover .list-group-item-heading{color:inherit}.list-group-item.disabled .list-group-item-text,.list-group-item.disabled:focus .list-group-item-text,.list-group-item.disabled:hover .list-group-item-text{color:#777}.list-group-item.active,.list-group-item.active:focus,.list-group-item.active:hover{z-index:2;color:#fff;background-color:#337ab7;border-color:#337ab7}.list-group-item.active .list-group-item-heading,.list-group-item.active .list-group-item-heading>.small,.list-group-item.active .list-group-item-heading>small,.list-group-item.active:focus .list-group-item-heading,.list-group-item.active:focus .list-group-item-heading>.small,.list-group-item.active:focus .list-group-item-heading>small,.list-group-item.active:hover .list-group-item-heading,.list-group-item.active:hover .list-group-item-heading>.small,.list-group-item.active:hover .list-group-item-heading>small{color:inherit}.list-group-item.active .list-group-item-text,.list-group-item.active:focus .list-group-item-text,.list-group-item.active:hover .list-group-item-text{color:#c7ddef}.list-group-item-success{color:#3c763d;background-color:#dff0d8}a.list-group-item-success{color:#3c763d}a.list-group-item-success .list-group-item-heading{color:inherit}a.list-group-item-success:focus,a.list-group-item-success:hover{color:#3c763d;background-color:#d0e9c6}a.list-group-item-success.active,a.list-group-item-success.active:focus,a.list-group-item-success.active:hover{color:#fff;background-color:#3c763d;border-color:#3c763d}.list-group-item-info{color:#31708f;background-color:#d9edf7}a.list-group-item-info{color:#31708f}a.list-group-item-info .list-group-item-heading{color:inherit}a.list-group-item-info:focus,a.list-group-item-info:hover{color:#31708f;background-color:#c4e3f3}a.list-group-item-info.active,a.list-group-item-info.active:focus,a.list-group-item-info.active:hover{color:#fff;background-color:#31708f;border-color:#31708f}.list-group-item-warning{color:#8a6d3b;background-color:#fcf8e3}a.list-group-item-warning{color:#8a6d3b}a.list-group-item-warning .list-group-item-heading{color:inherit}a.list-group-item-warning:focus,a.list-group-item-warning:hover{color:#8a6d3b;background-color:#faf2cc}a.list-group-item-warning.active,a.list-group-item-warning.active:focus,a.list-group-item-warning.active:hover{color:#fff;background-color:#8a6d3b;border-color:#8a6d3b}.list-group-item-danger{color:#a94442;background-color:#f2dede}a.list-group-item-danger{color:#a94442}a.list-group-item-danger .list-group-item-heading{color:inherit}a.list-group-item-danger:focus,a.list-group-item-danger:hover{color:#a94442;background-color:#ebcccc}a.list-group-item-danger.active,a.list-group-item-danger.active:focus,a.list-group-item-danger.active:hover{color:#fff;background-color:#a94442;border-color:#a94442}.list-group-item-heading{margin-top:0;margin-bottom:5px}.list-group-item-text{margin-bottom:0;line-height:1.3}.panel{margin-bottom:20px;background-color:#fff;border:1px solid transparent;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,.05);box-shadow:0 1px 1px rgba(0,0,0,.05)}.panel-body{padding:15px}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-right-radius:3px;border-top-left-radius:3px}.panel-heading>.dropdown .dropdown-toggle,.panel-title{color:inherit}.panel-title{margin-top:0;margin-bottom:0;font-size:16px}.panel-title>.small,.panel-title>.small>a,.panel-title>a,.panel-title>small,.panel-title>small>a{color:inherit}.panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid #ddd;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.list-group,.panel>.panel-collapse>.list-group{margin-bottom:0}.panel>.list-group .list-group-item,.panel>.panel-collapse>.list-group .list-group-item{border-width:1px 0;border-radius:0}.panel>.list-group:first-child .list-group-item:first-child,.panel>.panel-collapse>.list-group:first-child .list-group-item:first-child{border-top:0;border-top-right-radius:3px;border-top-left-radius:3px}.panel>.list-group:last-child .list-group-item:last-child,.panel>.panel-collapse>.list-group:last-child .list-group-item:last-child{border-bottom:0;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.list-group+.panel-footer,.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.panel>.panel-collapse>.table,.panel>.table,.panel>.table-responsive>.table{margin-bottom:0}.panel>.panel-collapse>.table caption,.panel>.table-responsive>.table caption,.panel>.table caption{padding-left:15px;padding-right:15px}.panel>.table-responsive:first-child>.table:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child,.panel>.table:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child,.panel>.table:first-child>thead:first-child>tr:first-child{border-top-right-radius:3px;border-top-left-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table:first-child>thead:first-child>tr:first-child th:first-child{border-top-left-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table:first-child>thead:first-child>tr:first-child th:last-child{border-top-right-radius:3px}.panel>.table-responsive:last-child>.table:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child,.panel>.table:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:first-child{border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child{border-bottom-right-radius:3px}.panel>.panel-body+.table,.panel>.panel-body+.table-responsive,.panel>.table+.panel-body,.panel>.table-responsive+.panel-body{border-top:1px solid #ddd}.panel>.table>tbody:first-child>tr:first-child td,.panel>.table>tbody:first-child>tr:first-child th{border-top:0}.panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0}.panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tfoot>tr>td:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.panel>.table-bordered>tbody>tr:first-child>td,.panel>.table-bordered>tbody>tr:first-child>th,.panel>.table-bordered>tbody>tr:last-child>td,.panel>.table-bordered>tbody>tr:last-child>th,.panel>.table-bordered>tfoot>tr:last-child>td,.panel>.table-bordered>tfoot>tr:last-child>th,.panel>.table-bordered>thead>tr:first-child>td,.panel>.table-bordered>thead>tr:first-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th,.panel>.table-responsive>.table-bordered>thead>tr:first-child>td,.panel>.table-responsive>.table-bordered>thead>tr:first-child>th{border-bottom:0}.panel>.table-responsive{border:0;margin-bottom:0}.panel-group{margin-bottom:20px}.panel-group .panel{margin-bottom:0;border-radius:4px}.panel-group .panel+.panel{margin-top:5px}.panel-group .panel-heading{border-bottom:0}.panel-group .panel-heading+.panel-collapse>.list-group,.panel-group .panel-heading+.panel-collapse>.panel-body{border-top:1px solid #ddd}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #ddd}.panel-default{border-color:#ddd}.panel-default>.panel-heading{color:#333;background-color:#f5f5f5;border-color:#ddd}.panel-default>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ddd}.panel-default>.panel-heading .badge{color:#f5f5f5;background-color:#333}.panel-default>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ddd}.panel-primary{border-color:#337ab7}.panel-primary>.panel-heading{color:#fff;background-color:#337ab7;border-color:#337ab7}.panel-primary>.panel-heading+.panel-collapse>.panel-body{border-top-color:#337ab7}.panel-primary>.panel-heading .badge{color:#337ab7;background-color:#fff}.panel-primary>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#337ab7}.panel-success{border-color:#d6e9c6}.panel-success>.panel-heading{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.panel-success>.panel-heading+.panel-collapse>.panel-body{border-top-color:#d6e9c6}.panel-success>.panel-heading .badge{color:#dff0d8;background-color:#3c763d}.panel-success>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#d6e9c6}.panel-info{border-color:#bce8f1}.panel-info>.panel-heading{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.panel-info>.panel-heading+.panel-collapse>.panel-body{border-top-color:#bce8f1}.panel-info>.panel-heading .badge{color:#d9edf7;background-color:#31708f}.panel-info>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#bce8f1}.panel-warning{border-color:#faebcc}.panel-warning>.panel-heading{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.panel-warning>.panel-heading+.panel-collapse>.panel-body{border-top-color:#faebcc}.panel-warning>.panel-heading .badge{color:#fcf8e3;background-color:#8a6d3b}.panel-warning>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#faebcc}.panel-danger{border-color:#ebccd1}.panel-danger>.panel-heading{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.panel-danger>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ebccd1}.panel-danger>.panel-heading .badge{color:#f2dede;background-color:#a94442}.panel-danger>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ebccd1}.embed-responsive{position:relative;display:block;height:0;padding:0;overflow:hidden}.embed-responsive .embed-responsive-item,.embed-responsive embed,.embed-responsive iframe,.embed-responsive object,.embed-responsive video{position:absolute;top:0;left:0;bottom:0;height:100%;width:100%;border:0}.embed-responsive.embed-responsive-16by9{padding-bottom:56.25%}.embed-responsive.embed-responsive-4by3{padding-bottom:75%}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.05);box-shadow:inset 0 1px 1px rgba(0,0,0,.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,.15)}.well-lg{padding:24px;border-radius:6px}.well-sm{padding:9px;border-radius:3px}.close{float:right;font-size:21px;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;opacity:.2;filter:alpha(opacity=20)}.close:focus,.close:hover{color:#000;text-decoration:none;cursor:pointer;opacity:.5;filter:alpha(opacity=50)}button.close{padding:0;cursor:pointer;background:transparent;border:0;-webkit-appearance:none}.modal,.modal-open{overflow:hidden}.modal{display:none;position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;-webkit-overflow-scrolling:touch;outline:0}.modal.fade .modal-dialog{-webkit-transform:translateY(-25%);transform:translateY(-25%);-webkit-transition:-webkit-transform .3s ease-out;transition:-webkit-transform .3s ease-out;transition:transform .3s ease-out;transition:transform .3s ease-out,-webkit-transform .3s ease-out}.modal.in .modal-dialog{-webkit-transform:translate(0);transform:translate(0)}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal-dialog{position:relative;width:auto;margin:10px}.modal-content{position:relative;background-color:#fff;border:1px solid #999;border:1px solid rgba(0,0,0,.2);border-radius:6px;-webkit-box-shadow:0 3px 9px rgba(0,0,0,.5);box-shadow:0 3px 9px rgba(0,0,0,.5);background-clip:padding-box;outline:0}.modal-backdrop{position:absolute;top:0;right:0;left:0;background-color:#000}.modal-backdrop.fade{opacity:0;filter:alpha(opacity=0)}.modal-backdrop.in{opacity:.5;filter:alpha(opacity=50)}.modal-header{padding:15px;border-bottom:1px solid #e5e5e5;min-height:16.42857143px}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.42857143}.modal-body{position:relative;padding:15px}.modal-footer{padding:15px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer .btn+.btn{margin-left:5px;margin-bottom:0}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:768px){.modal-dialog{width:600px;margin:30px auto}.modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,.5);box-shadow:0 5px 15px rgba(0,0,0,.5)}.modal-sm{width:300px}}@media (min-width:992px){.modal-lg{width:900px}}.tooltip{position:absolute;z-index:1070;display:block;visibility:visible;font-family:Helvetica Neue,Helvetica,Arial,sans-serif;font-size:12px;font-weight:400;line-height:1.4;opacity:0;filter:alpha(opacity=0)}.tooltip.in{opacity:.9;filter:alpha(opacity=90)}.tooltip.top{margin-top:-3px;padding:5px 0}.tooltip.right{margin-left:3px;padding:0 5px}.tooltip.bottom{margin-top:3px;padding:5px 0}.tooltip.left{margin-left:-3px;padding:0 5px}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;text-decoration:none;background-color:#000;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-left .tooltip-arrow{right:5px}.tooltip.top-left .tooltip-arrow,.tooltip.top-right .tooltip-arrow{bottom:0;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-right .tooltip-arrow{left:5px}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#000}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#000}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-left .tooltip-arrow{top:0;right:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-right .tooltip-arrow{top:0;left:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.popover{position:absolute;top:0;left:0;z-index:1060;display:none;max-width:276px;padding:1px;font-family:Helvetica Neue,Helvetica,Arial,sans-serif;font-size:14px;font-weight:400;line-height:1.42857143;text-align:left;background-color:#fff;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.2);border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2);white-space:normal}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{margin:0;padding:8px 14px;font-size:14px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:5px 5px 0 0}.popover-content{padding:9px 14px}.popover>.arrow,.popover>.arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover>.arrow{border-width:11px}.popover>.arrow:after{border-width:10px;content:""}.popover.top>.arrow{left:50%;margin-left:-11px;border-bottom-width:0;border-top-color:#999;border-top-color:rgba(0,0,0,.25);bottom:-11px}.popover.top>.arrow:after{content:" ";bottom:1px;margin-left:-10px;border-bottom-width:0;border-top-color:#fff}.popover.right>.arrow{top:50%;left:-11px;margin-top:-11px;border-left-width:0;border-right-color:#999;border-right-color:rgba(0,0,0,.25)}.popover.right>.arrow:after{content:" ";left:1px;bottom:-10px;border-left-width:0;border-right-color:#fff}.popover.bottom>.arrow{left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,.25);top:-11px}.popover.bottom>.arrow:after{content:" ";top:1px;margin-left:-10px;border-top-width:0;border-bottom-color:#fff}.popover.left>.arrow{top:50%;right:-11px;margin-top:-11px;border-right-width:0;border-left-color:#999;border-left-color:rgba(0,0,0,.25)}.popover.left>.arrow:after{content:" ";right:1px;border-right-width:0;border-left-color:#fff;bottom:-10px}.carousel,.carousel-inner{position:relative}.carousel-inner{overflow:hidden;width:100%}.carousel-inner>.item{display:none;position:relative;-webkit-transition:left .6s ease-in-out;transition:left .6s ease-in-out}.carousel-inner>.item>a>img,.carousel-inner>.item>img{line-height:1}@media (-webkit-transform-3d),(transform-3d){.carousel-inner>.item{-webkit-transition:-webkit-transform .6s ease-in-out;transition:-webkit-transform .6s ease-in-out;transition:transform .6s ease-in-out;transition:transform .6s ease-in-out,-webkit-transform .6s ease-in-out;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-perspective:1000;perspective:1000}.carousel-inner>.item.active.right,.carousel-inner>.item.next{-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0);left:0}.carousel-inner>.item.active.left,.carousel-inner>.item.prev{-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0);left:0}.carousel-inner>.item.active,.carousel-inner>.item.next.left,.carousel-inner>.item.prev.right{-webkit-transform:translateZ(0);transform:translateZ(0);left:0}}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:0;left:0;bottom:0;width:15%;opacity:.5;filter:alpha(opacity=50);font-size:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6)}.carousel-control.left{background-image:-webkit-gradient(linear,left top,right top,color-stop(0,rgba(0,0,0,.5)),to(rgba(0,0,0,.0001)));background-image:linear-gradient(90deg,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001));background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr="#80000000",endColorstr="#00000000",GradientType=1)}.carousel-control.right{left:auto;right:0;background-image:-webkit-gradient(linear,left top,right top,color-stop(0,rgba(0,0,0,.0001)),to(rgba(0,0,0,.5)));background-image:linear-gradient(90deg,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5));background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr="#00000000",endColorstr="#80000000",GradientType=1)}.carousel-control:focus,.carousel-control:hover{outline:0;color:#fff;text-decoration:none;opacity:.9;filter:alpha(opacity=90)}.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{position:absolute;top:50%;z-index:5;display:inline-block}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{left:50%;margin-left:-10px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{right:50%;margin-right:-10px}.carousel-control .icon-next,.carousel-control .icon-prev{width:20px;height:20px;margin-top:-10px;line-height:1;font-family:serif}.carousel-control .icon-prev:before{content:"\2039"}.carousel-control .icon-next:before{content:"\203A"}.carousel-indicators{position:absolute;bottom:10px;left:50%;z-index:15;width:60%;margin-left:-30%;padding-left:0;list-style:none;text-align:center}.carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;text-indent:-999px;border:1px solid #fff;border-radius:10px;cursor:pointer;background-color:#000\9;background-color:transparent}.carousel-indicators .active{margin:0;width:12px;height:12px;background-color:#fff}.carousel-caption{position:absolute;left:15%;right:15%;bottom:20px;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6)}.carousel-caption .btn{text-shadow:none}@media screen and (min-width:768px){.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{width:30px;height:30px;margin-top:-15px;font-size:30px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{margin-left:-15px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{margin-right:-15px}.carousel-caption{left:20%;right:20%;padding-bottom:30px}.carousel-indicators{bottom:20px}}.btn-group-vertical>.btn-group:after,.btn-group-vertical>.btn-group:before,.btn-toolbar:after,.btn-toolbar:before,.clearfix:after,.clearfix:before,.container-fluid:after,.container-fluid:before,.container:after,.container:before,.dl-horizontal dd:after,.dl-horizontal dd:before,.form-horizontal .form-group:after,.form-horizontal .form-group:before,.modal-footer:after,.modal-footer:before,.nav:after,.nav:before,.navbar-collapse:after,.navbar-collapse:before,.navbar-header:after,.navbar-header:before,.navbar:after,.navbar:before,.pager:after,.pager:before,.panel-body:after,.panel-body:before,.row:after,.row:before{content:" ";display:table}.btn-group-vertical>.btn-group:after,.btn-toolbar:after,.clearfix:after,.container-fluid:after,.container:after,.dl-horizontal dd:after,.form-horizontal .form-group:after,.modal-footer:after,.nav:after,.navbar-collapse:after,.navbar-header:after,.navbar:after,.pager:after,.panel-body:after,.row:after{clear:both}.center-block{display:block;margin-left:auto;margin-right:auto}.pull-right{float:right!important}.pull-left{float:left!important}.hide{display:none!important}.show{display:block!important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none!important;visibility:hidden!important}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-lg,.visible-lg-block,.visible-lg-inline,.visible-lg-inline-block,.visible-md,.visible-md-block,.visible-md-inline,.visible-md-inline-block,.visible-sm,.visible-sm-block,.visible-sm-inline,.visible-sm-inline-block,.visible-xs,.visible-xs-block,.visible-xs-inline,.visible-xs-inline-block{display:none!important}@media (max-width:767px){.visible-xs{display:block!important}table.visible-xs{display:table}tr.visible-xs{display:table-row!important}td.visible-xs,th.visible-xs{display:table-cell!important}}@media (max-width:767px){.visible-xs-block{display:block!important}}@media (max-width:767px){.visible-xs-inline{display:inline!important}}@media (max-width:767px){.visible-xs-inline-block{display:inline-block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm{display:block!important}table.visible-sm{display:table}tr.visible-sm{display:table-row!important}td.visible-sm,th.visible-sm{display:table-cell!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-block{display:block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline{display:inline!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline-block{display:inline-block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md{display:block!important}table.visible-md{display:table}tr.visible-md{display:table-row!important}td.visible-md,th.visible-md{display:table-cell!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-block{display:block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline{display:inline!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline-block{display:inline-block!important}}@media (min-width:1200px){.visible-lg{display:block!important}table.visible-lg{display:table}tr.visible-lg{display:table-row!important}td.visible-lg,th.visible-lg{display:table-cell!important}}@media (min-width:1200px){.visible-lg-block{display:block!important}}@media (min-width:1200px){.visible-lg-inline{display:inline!important}}@media (min-width:1200px){.visible-lg-inline-block{display:inline-block!important}}@media (max-width:767px){.hidden-xs{display:none!important}}@media (min-width:768px) and (max-width:991px){.hidden-sm{display:none!important}}@media (min-width:992px) and (max-width:1199px){.hidden-md{display:none!important}}@media (min-width:1200px){.hidden-lg{display:none!important}}.visible-print{display:none!important}@media print{.visible-print{display:block!important}table.visible-print{display:table}tr.visible-print{display:table-row!important}td.visible-print,th.visible-print{display:table-cell!important}}.visible-print-block{display:none!important}@media print{.visible-print-block{display:block!important}}.visible-print-inline{display:none!important}@media print{.visible-print-inline{display:inline!important}}.visible-print-inline-block{display:none!important}@media print{.visible-print-inline-block{display:inline-block!important}}@media print{.hidden-print{display:none!important}}.ekko-lightbox{display:-webkit-box!important;display:-ms-flexbox!important;display:flex!important;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;padding-right:0!important}.ekko-lightbox-container{position:relative}.ekko-lightbox-container>div.ekko-lightbox-item{position:absolute;top:0;left:0;bottom:0;right:0;width:100%}.ekko-lightbox iframe{width:100%;height:100%}.ekko-lightbox-nav-overlay{position:absolute;top:0;left:0;width:100%;height:100%}.ekko-lightbox-nav-overlay,.ekko-lightbox-nav-overlay a{z-index:100;display:-webkit-box;display:-ms-flexbox;display:flex}.ekko-lightbox-nav-overlay a{-webkit-box-flex:1;-ms-flex:1;flex:1;-webkit-box-align:center;-ms-flex-align:center;align-items:center;opacity:0;-webkit-transition:opacity .5s;transition:opacity .5s;color:#fff;font-size:30px}.ekko-lightbox-nav-overlay a>*{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1}.ekko-lightbox-nav-overlay a>:focus{outline:none}.ekko-lightbox-nav-overlay a span{padding:0 30px}.ekko-lightbox-nav-overlay a:last-child span{text-align:right}.ekko-lightbox-nav-overlay a:hover{text-decoration:none}.ekko-lightbox-nav-overlay a:focus{outline:none}.ekko-lightbox-nav-overlay a.disabled{cursor:default;visibility:hidden}.ekko-lightbox a:hover{opacity:1;text-decoration:none}.ekko-lightbox .modal-dialog{display:none}.ekko-lightbox .modal-footer{text-align:left}.ekko-lightbox-loader{position:absolute;top:0;left:0;bottom:0;right:0;width:100%;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.ekko-lightbox-loader>div{width:40px;height:40px;position:relative;text-align:center}.ekko-lightbox-loader>div>div{width:100%;height:100%;border-radius:50%;background-color:#fff;opacity:.6;position:absolute;top:0;left:0;-webkit-animation:sk-bounce 2s infinite ease-in-out;animation:sk-bounce 2s infinite ease-in-out}.ekko-lightbox-loader>div>div:last-child{-webkit-animation-delay:-1s;animation-delay:-1s}.modal-dialog .ekko-lightbox-loader>div>div{background-color:#333}@-webkit-keyframes sk-bounce{0%,to{-webkit-transform:scale(0)}50%{-webkit-transform:scale(1)}}@keyframes sk-bounce{0%,to{transform:scale(0);-webkit-transform:scale(0)}50%{transform:scale(1);-webkit-transform:scale(1)}}/*! - * Bootstrap Colorpicker v2.5.2 - * https://itsjavi.com/bootstrap-colorpicker/ - * - * Originally written by (c) 2012 Stefan Petre - * Licensed under the Apache License v2.0 - * http://www.apache.org/licenses/LICENSE-2.0.txt - * - */.colorpicker-saturation{width:100px;height:100px;background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAQAAADa613fAAAP9klEQVR4XnRWC47rNgwcKjlA0bv2VL1Qi/YELRav7203iS1ppqZoiXCAhuBHVLI74xFtG3/Hz2joIOjRGuR5eMYuRn9YA1fds859KX8ZvczLr9/pImiR3Rqky9/wlajRIdVE/1Rufeu/0No3/ASgBZAJUkwgi0iCaEatekJJoEqiTQncd67/gyOfRCZshTed0Nl8LbLj8D6qxtoq9/7kJz/aH/3Xfu8VwI5+AUH8DxE7gUyiIpZ5LwiGzUqE3CScJsCDQHAsvBnxWpkbC0QMHmBp6latWS0bnvrCN/x1+xPfce+Ij0GAyeAGGz15sOiax2UylPhKrFaMPnVWClwepKh07hdhkVDsK2uoyEIySergjdbY2VBtV8VLr8Mf9mF/4wMb7kR8FOhzFWZZe7HIZD9JRIbee28eJKBweTB6TwjYkAgWaUmtDveGw1Wx3zZ76YlPPfQd/+gTTUFkiGiJ+NQAszU1EPT/QJEgufolAMPkNU4CVOyUIBLg4xglEZHGQnTFOFV0VaulYddBhA986ge/7N/yQi/3flFgwfQq2ibLnTDBRl9TmUHyJASPV/eoN0UISIr+ICQKIFV4EpljSjV1uFVUq9hRtet5e9gXvuyHPW0zMhQxWaoBBa9Tg8vsCEhww23Smd0CKjIkmPIoxWrUBDgJqFCyESF43ctQxLUoHN7Q1KyVhqrNNm3cy2vMyQNPVKjc29Rh5SSU+giWdRJHkLnQG71FQEuNyNGBTDdBQQAKCuGiEUS/jcyGbkMPq931OIzb/dUPGuVlG7f+slqkO5NAAlzTMdcq0NkzmsEBmAQkbI+pSHbiqnuWIA6lijhvqwIxMyWxMGZiPU669XJE1tADDTs2HWpwKxuqdnTpOiOR42xlzLtm3pXGel3xd8/oTs8Xy0MV8GM1RlsC2Y3Wy3wut3M+2mEVux0Gt9fhzTWyLvGiiJYaqY5DWRFIwAiQ5r6gB9GpQihJw4I9j5Mkscj3BnzGjBhv8xna5P1Jo428o6IOPY5KFZtVOkEKqUjqQY9Gi+jrIOFwJUDzRtA9xyoIrGGmkNRmxVAnZoK+TkUIeUYni5wEzgOG5iZX5HCr2JyQNqdk++G0rgb1ochSIGutTj4P7F0PuRUAolmh5sCzAHn1BYyaADh6bgFeoBx6vst091CEvcSLWBBpqGq384jZ5llVHSwEShLx+D4d0mU3D5eEAJQ9KEhOZUYnDENV2qKgmIlQhWfdvcoXYaegPp/n1oKIOgYFqxrzQSciqNhv/5FqPpy6b0UcX2vf13DfWySRSEgkEYlEJJGQSyKJSEQSCYlEEpHexIVO3XOevffze2a+PfPv9x1rne1c3b3Mmlmz9mE++zuzngfnw/E+Dlc4LL4NwHdFy7u3KGPVmZ6/4eeMoDyre3i/KHADIHYO04w9zO0mAotuKnrc7XaPjvu66bNe5cDT7RlPepEnfS2X8dF1/utDvD+OwGDBxEgQywLCvIMYWBY+DShwAAORAdv9PswhDAqOUCi5+71AbFcDMR4xBDNfhySKXPXZ1+Vub+Q1Ltf5z7eC0AjVldHI26rIFdKIAyYBJCFVUhVDwttAnM52B3Ect1TFQXzJ0z33lOuib/QO8g+CuO0gKBRU80A8hkeJ0b1KRQWmFQVSh8mf3lpUpNaRulzN5NArrmKKGMijXgzk7w5ijdFVgT8f1IdFNjVWjDWicUYWEEMmSFDtILdzHW5XueHp7p+yuS54ep5/c5BE2Gw/gWPNYU4/PZaak2VGEsFjSbOf8irea6KQgojGCk0KxZY31tWWgzwayF8N5KYyo3VADVicWWrhwzr3ZqIOa5xW5zbqMPPMiyDURHDIHQTeWq7KFXcQPOqzPOL5Ov/iIDEDy7DHEwx0PTgjO8SS0fOEHcZNMt+XKEFMj8Q4QUSvPu6HPuvd4N9/x12RPwcIVRCAakSOUzHgsUSMFWYzDQ+PiOJqAOuYc9jh5TecnA+xHfFyOYhebeTH89P80wrCJzUjlsx7euIV0g4zQFUSiBPioIWBACFC7GgDj8P91ZSJOQmQP74MAnQo8H5RIe8kZ0kBcQCMAlEpRDiKROBxbR0ksdhWFq0gR9q9uQzkDzuIFQSPqAgRCAsCaVNF2ZAAhxvtzcqcnDk6tpXxSsayqXLIgSOb6zqeH+fvO0i9XEu5EVV+OZehRZJ6BGTeaRhCkTzVIZeAzaWGAFfErIPogQI5CuR3HQQx7DzBB16R3s7e0MBUPedjWutgG/JUTPqMeAQNEiytJRnJearWUgdwFNxN7rtBoECuj/O3BMHaTIxQ0a4GctireElTJHJvLTaalih5kvBCGMvkdESUMAdCFaI4yG8SpDfRWAptqkAJUwCG6B7lOREFSZBqKs57MEHqVJEBwHa2lp0OiKtiQ18gx9P89QrSXyc0vObBM4vPmBADqJZLAo/yzK7qPSZstCy+fDSZlhrm+Zkyjsf5q2otdC14zkLjHLf0me9wjNqQo0B1a6wBJRaIEgC2Qw9oby/cRHA+xHCQy/xlB1HVSV3Y/5yVhsc7dBi2UoIWCMcbELZWgxNCGUZ5y4ceBaLlE8dAfrEosrYT+z8ya3sxXndFBxuQivNGEHFCbLGBlBLKGYHZoeoQpcjtMn/uICPefcxecpuDOEemg9S/44cflZPIlWolyHkLrEpgbS9IQRlAgZgi0WDjsEiPh+PN/Fkogq4GdzPtarlRGW2tJwEK1RMTEvdVdmhAKHO1pdUuGQsVcX+rSfGzDbwGyE8NRPQc83HCaOkTZwPqABZBdFq8zAN1gue0FPO8wYUFBE1WkMwVzM1iQ4BItFh+H36Qy/yJg0DRQICmBl+tbKUC5cCj3yXI+SUFBS78ZAcBtHt+e9lBuiqpTNh9zTvIjzuIWxVYGQJpAZY+VWS3QKh84iSZbwuIdiDpc4KztQa/sjhMaDJEJDSZ8mZ+kCBdC0JpKVNQzZdKu+EsOeFCosrngVAkDS/uy6iGnW7UxmMpkB8FyFKo6iQW8z1HuBdMu1pdkZdB8jWTjlFtNaiJRYniIDcD+eECMqFLS9ED6DgxzCMKnRD3HYYA2uMCJUh70OK8G0EUnJV8lqe8nj84QdqLhdoJskNlEw1ivajM8LtPBhIeN99LESXI9xcQIHFQudHngZjUhXOQeGlUYmAddh5pxMhzV0M1vMAtMFIVmfp6fq+DgEWefjQVenstaqUy3bJQAiVlEihDghCDINFQg8oUhoQPkO8SBEM7SFQ72VYBwPuE7k8uYF5LNwg/TEd2zkuKjIIhTiJRlYrDfNS1QL7DYUcbcCyKJNwOwucVCVSwBBj/DwghXA2hQtACgCBBPprfXkAIFIYRXhONQARFU00Tsh6LEmmQUbkTImMi9me5qaHDIeBgHeRbdxAIqAJBCDSoCNVQglrciqX/ZCD9RRP6rgpBvhmKAFhg2ForBLXBYPtUjj7vCHPe8SXbYAY47gHB9mKeqjjIg/53fmMD0fR9Bug7SFcHI6EA1OC/E8QTL4NgBSGiCiyTChnI1zcQxmyfRZGM6w701KRybDvsIK3LWDx6mxGkcglEZQLkawnCdppZ6sgCh8trWWBUQaUWCEOlOs7HAenFE45QSu9RQQDAqchXNxDq4orQR44qRIFUQvM+mRJuB6GDEixgCbSBQGXghEEbdn1P/zO/QhAWCsWsmRhLa2VFkSZIgSVKmgEQhvk6K8YKMRZl7Dwg4amOUYvFBfLlE4RasOCB5S9PXKq0AqGDMiYIReXF0mYctITWBmqR5F38X5Y7yJfeCtKBzNbWYm5XpsMpf3dRZD3jPDesvdVCOs6KYQXIFw1E4fcE8dHWOepZBXpLJcACWUZVMRZbfvgXR4Ak8A7VVSKSVuu9p6/mFxyE7cOWavtLp952O8huK83+gmHzHaAsVXLgAvl8gPCvHzAFsM8GNXGKPH5cmN02sXTLa8QdKRXMzHv67/k5A9k1UIx36UH/VlWWtuKssNiRapB6BaLXl6MA+ayDcNS3v/sYXgCL620F1kk8QhKAEOvKu4DvajDO5zkHc4fBg76anyEIIcamBPex5EK8AoVHhMW7QAqWrYD1204CJB1hCfOAV/PTBPH0zBmJmsZZKCEaAmdqm4zMcYxYLN0JuHThIAjirAnp3px7TRgD+ZSD/K92M1CNIgbC8Ex7FkSEIlQEEUQEQQQBRBABEUQQEQTx3X0Evap9AhP39jL5OvuzAWuvbDaTTDIzX2aypUCJ0i7nAigoQAk9gUIUSxXEoCFyyVIuL9ZQcMZoArnwr4D0OLS8jGNGTgGnsZQWMYrcOARoIReAALBeWhf+RUCAIEsECFQHLkwR5zj4JW3t5WOUU5djvgQIawD53EDsctmYz8xGaZGPBUR3qNkiGwqDICUYIFpqBgRaayCfFiAWR2wWvoobmzxdF8N5kyxXmvap/sgGcLF/aoBosbG+lE395R8zCA4BqUYgOgYq+HtvBrT0LK15X8lZwx5f9klCX0rdgXzIIGbdhXMqZtHzJhuptEjmsFc4KzmN5IFPtfM7gWw2kPczSIqQSPUDYKYBMamsBCpKphW0iA5H8AbMDPJOQYjLZg1Vk4G49GlCYNYAkdOd0kwRQ8FCyAHydgLZ6Z2AqrVtjDUQ7hCEmrkEooDAsB2YnBCvkBpZ6yBvJpCd7Mn5zJ6C4QF2BUQPgHEIGUrGnHzQ8rlMekBeTyAzwDJksxwM4+w3BY02B8mIl0CmFRm+ZscxAuSnvwqQsECTIGSV6FEoJFTygVuzB5xAsKqBvAQE3+nkVoJDI1BJIaPBWik7ZSu5NIp5A3mRQaTFvLgkO9fVgEgMqqeVfb+p55tijWH+Kea71ubq4v8Sl8089sZKbKEZNq+VUfISJJF7j79WrbYgS994ZEf+nIz0pNFRWqapSmK6P45i3OQuItIiPDyg6RnxZ4D0g+CFPxAzluoRsWsaA6I6JOqVWCisDvJ0BgHTzMSRgMi0vmi8R+sR6tg/XUh7kCc7kMRqSNkTBDx0OkAUegFcMazciBXNpm798R6klXap/WZz49TQwBHqEcj4oCToUPjUuP9lfxcbyKMAwT6bTf1qqIIQDl3i5oCERNmVm0wgW4A8BGRxMX3hWh8bEV5Rvfp4DS5F3djWH2ztDNWKW7OBjgjIwsDWaKRknJjqMsh9QCa1p608lLovFkBE969DYtYelSzwSRcg535vAsFeNU9SzRCYZb4LDmxmFQKkwYGM+5y/G7b1uxMIylLdyE5yxIyYsoXWhQIpzQhYPi3JkJoKkB9+BxD0OMuyOEBe36DgyPSrxscmATldgKj8PxrkA/kA5PYMgkrocwIQ6GSRGmF0VaNqBKQZ5FYDEZSDzFTzq9mBQjAayE1A+ryDTzcQZe0Ibbxj7EwpAmTrJwEimZR9CCPtODhzxuNtY19Zd2Lf/fjCTnEiDAOg62j1utb/dv9mZ/aHCj4AyOHbsW3/As0BTzIgeJU7AAAAAElFTkSuQmCC");cursor:crosshair;float:left}.colorpicker-saturation i{display:block;height:5px;width:5px;border:1px solid #000;border-radius:5px;position:absolute;top:0;left:0;margin:-4px 0 0 -4px}.colorpicker-saturation i b{display:block;height:5px;width:5px;border:1px solid #fff;border-radius:5px}.colorpicker-alpha,.colorpicker-hue{width:15px;height:100px;float:left;cursor:row-resize;margin-left:4px;margin-bottom:4px}.colorpicker-alpha i,.colorpicker-hue i{display:block;height:1px;background:#000;border-top:1px solid #fff;position:absolute;top:0;left:0;width:100%;margin-top:-1px}.colorpicker-hue{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAABkCAMAAABw8qpSAAABLFBMVEXqFBb/ABH/ACL/ADH/AEH/AFD/AGD/AG7/AH7/AI3/AJ3/AKz/ALz/AMr/ANv/AOr/APr2AP/mAP/XAP/HAP+4AP+oAP+aAP+JAP97AP9rAP9cAP9MAP8+AP8tAP8fAP8PAP8BAv8AEP8AH/8AL/8APv8ATv8AXP8Abf8Ae/8Ai/8Amv8Aqv8AuP8Ayf8A1/8A5/8A9/8A//gA/+kA/9kA/8oA/7oA/6wA/5sA/40A/30A/24A/14A/1AA/z8A/zEA/yEA/xEB/wMN/wAd/wAs/wA8/wBK/wBb/wBp/wB5/wCI/wCY/wCm/wC3/wDF/wDV/wDk/wD1/wD/+gD/7AD/3AD/zAD/vgD/rQD/nwD/jgD/gAD/cAD/YgD/UQD/QwD/MgD/JAD/FAD4Eg42qAedAAAAh0lEQVR4XgXAg3EDAAAAwI9to7Zt27a1/w49BASFhEVExcQlJKWkZWTl5BUUlZRVVNXUNTS1tHXo1KVbj159+g0YNGTYiFFjxk2YNGXajFlz5i1YtGTZilVr1m3YtGXbjl179h04dOTYiVNnzl24dOXajVt37j149OTZi1dv3n349OXbj19//wOxE1dQ8reGAAAAAElFTkSuQmCC")}.colorpicker-alpha{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAABkCAQAAAAVxWkcAAABr0lEQVR4Xo2VwU0DQQxF7dmRuNIFlzlSAR3QAaXQQdIBJVABFXDcOVAAd67cjJLR07dkhcSrkZKfb/t7bG88rFo3B5gZPMNycItu2xloGV7MWHzM9zuzFWCkmA0nK6AszCUJDW6+mG6R03ncw5v8EMTEvZ2O3AliYjpslblc0RF9LmZYWxURU6aKytWZYsoWCAe+xwOZp1GsEukGiIkYxcQCHck99+gRgB7JncyIB5SGEhP3Yh5P6JwX+u6AnYot104d8DJT7uH7M9JH6OZbimj0vfMVaYnJIZFJDBW9kHlerL2C6JV4mSt7uuo2N57RxnZ+usQjn0R1jwBJBrNO3evJpVYUWsJ/E3UiXRlv24/7YZ04xmEdWlzcKS+B/eapeyMvFd2k0+hRk/T0AmTW8h69s2sjYMsdPntECiILhAeIMZAeH4QvUwfn6ijC0tTV+fT9ky8jM9nK2g7Ly1VjSpKYq6IvsAm7MtNu1orEqa/K3KNvgMFdhfquPfJmp2dbh0/8Gzb6Y22ViaNr6n5410zXdngVhbu6XqdOtWOuin5hjABGp4a2uotZ71MVCfwDBt2/v37yo6AAAAAASUVORK5CYII=");display:none}.colorpicker-alpha,.colorpicker-hue,.colorpicker-saturation{background-size:contain}.colorpicker{padding:4px;min-width:130px;margin-top:1px;border-radius:4px;z-index:2500}.colorpicker:after,.colorpicker:before{display:table;content:"";line-height:0}.colorpicker:after{clear:both}.colorpicker:before{border-left:7px solid transparent;border-right:7px solid transparent;border-bottom:7px solid #ccc;border-bottom-color:rgba(0,0,0,.2);top:-7px;left:6px}.colorpicker:after,.colorpicker:before{content:"";display:inline-block;position:absolute}.colorpicker:after{border-left:6px solid transparent;border-right:6px solid transparent;border-bottom:6px solid #fff;top:-6px;left:7px}.colorpicker div{position:relative}.colorpicker.colorpicker-with-alpha{min-width:140px}.colorpicker.colorpicker-with-alpha .colorpicker-alpha{display:block}.colorpicker-color{height:10px;margin-top:5px;clear:both;background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAABkCAQAAAAVxWkcAAABr0lEQVR4Xo2VwU0DQQxF7dmRuNIFlzlSAR3QAaXQQdIBJVABFXDcOVAAd67cjJLR07dkhcSrkZKfb/t7bG88rFo3B5gZPMNycItu2xloGV7MWHzM9zuzFWCkmA0nK6AszCUJDW6+mG6R03ncw5v8EMTEvZ2O3AliYjpslblc0RF9LmZYWxURU6aKytWZYsoWCAe+xwOZp1GsEukGiIkYxcQCHck99+gRgB7JncyIB5SGEhP3Yh5P6JwX+u6AnYot104d8DJT7uH7M9JH6OZbimj0vfMVaYnJIZFJDBW9kHlerL2C6JV4mSt7uuo2N57RxnZ+usQjn0R1jwBJBrNO3evJpVYUWsJ/E3UiXRlv24/7YZ04xmEdWlzcKS+B/eapeyMvFd2k0+hRk/T0AmTW8h69s2sjYMsdPntECiILhAeIMZAeH4QvUwfn6ijC0tTV+fT9ky8jM9nK2g7Ly1VjSpKYq6IvsAm7MtNu1orEqa/K3KNvgMFdhfquPfJmp2dbh0/8Gzb6Y22ViaNr6n5410zXdngVhbu6XqdOtWOuin5hjABGp4a2uotZ71MVCfwDBt2/v37yo6AAAAAASUVORK5CYII=");background-position:0 100%}.colorpicker-color div{height:10px}.colorpicker-selectors{display:none;height:10px;margin-top:5px;clear:both}.colorpicker-selectors i{cursor:pointer;float:left;height:10px;width:10px}.colorpicker-selectors i+i{margin-left:3px}.colorpicker-element .add-on i,.colorpicker-element .input-group-addon i{display:inline-block;cursor:pointer;height:16px;vertical-align:text-top;width:16px}.colorpicker.colorpicker-inline{position:relative;display:inline-block;float:none;z-index:auto}.colorpicker.colorpicker-horizontal{width:110px;min-width:110px;height:auto}.colorpicker.colorpicker-horizontal .colorpicker-saturation{margin-bottom:4px}.colorpicker.colorpicker-horizontal .colorpicker-color{width:100px}.colorpicker.colorpicker-horizontal .colorpicker-alpha,.colorpicker.colorpicker-horizontal .colorpicker-hue{width:100px;height:15px;float:left;cursor:col-resize;margin-left:0;margin-bottom:4px}.colorpicker.colorpicker-horizontal .colorpicker-alpha i,.colorpicker.colorpicker-horizontal .colorpicker-hue i{display:block;height:15px;background:#fff;position:absolute;top:0;left:0;width:1px;border:none;margin-top:0}.colorpicker.colorpicker-horizontal .colorpicker-hue{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAAABCAMAAAAfBfuPAAABLFBMVEXqFBb/ABH/ACL/ADH/AEH/AFD/AGD/AG7/AH7/AI3/AJ3/AKz/ALz/AMr/ANv/AOr/APr2AP/mAP/XAP/HAP+4AP+oAP+aAP+JAP97AP9rAP9cAP9MAP8+AP8tAP8fAP8PAP8BAv8AEP8AH/8AL/8APv8ATv8AXP8Abf8Ae/8Ai/8Amv8Aqv8AuP8Ayf8A1/8A5/8A9/8A//gA/+kA/9kA/8oA/7oA/6wA/5sA/40A/30A/24A/14A/1AA/z8A/zEA/yEA/xEB/wMN/wAd/wAs/wA8/wBK/wBb/wBp/wB5/wCI/wCY/wCm/wC3/wDF/wDV/wDk/wD1/wD/+gD/7AD/3AD/zAD/vgD/rQD/nwD/jgD/gAD/cAD/YgD/UQD/QwD/MgD/JAD/FAD4Eg42qAedAAAAbUlEQVR4XgXAghEDsbxtlrZt27ax/w49ACAYQTGcICmaYTleECVZUTXdMC1Wm93hdLk9Xp8/EAyFI9FYPJFMpTPZXL5QLJUr1Vq90Wy1O91efzAcjSfT2XyxXK03293+cDydL9fb/fF8vT/f3x+LfRNXARMbCAAAAABJRU5ErkJggg==")}.colorpicker.colorpicker-horizontal .colorpicker-alpha{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAAAKCAQAAADoFTP1AAAB9ElEQVR4XoWTQW4VMRBEu9qWEimL7DhEMp8NF+ASnJJLcAQgE1bcgBUSkYKUuHCrZ9pjeqSU5Yn9LPu7umJQBIIv+k7vIOrtK66L4lmr3pVOrOv3otp619KZ0/KjdNI79L52Uo09FBQWrU0vfe5trezU+hLsoUKd3Repovte+0vbq/7Lj5XbaHECKasR9G4MPlbp+gzZxd6koPEJCkAYC5SjcOTAIIOK90Dja1IfIZ8Z+zAY9jm3b5Ia+MT5sFcqRJrR2AYYA8Kua5BzYRrFPNmD4PQMegGJMOffJJUsWiI3nCHZZjInNdffLWOufzbc3JaboCAVxwmnRHbhLSPwRJ4wU0BRSc6HkECYYVw95nMKgJOcylxrJttE5Ibzf9Xq9GPvP+WX3MiV/MGHfRu/SentRQrfG1GzsIrytdNXucSRKxQNIGHM9YhGFQJcdjNcBZvfJayuYe4Sia1CzwW+19mWOhe37HsxJWKwbu/jluEU15QzAQjAqCEbhMJc78GYV2E0kooHDubUImWkTOhGpgv8PoT8DJG/bzxna4BZ0eOFSOaLADGeSpFsg5AzeaDZIDQQXjZ4y/8ryfzUXBwdELRjTjCNvOeT0rNlrJz90vwy6N9pXXQEluX0inElpPWokSdiLCfiNJJjMKQ8Qsh8GEKQKMo/eiHrNbI9UksAAAAASUVORK5CYII=")}.colorpicker-right:before{left:auto;right:6px}.colorpicker-right:after{left:auto;right:7px}.colorpicker-no-arrow:after,.colorpicker-no-arrow:before{border-right:0;border-left:0}.colorpicker-alpha.colorpicker-visible,.colorpicker-hue.colorpicker-visible,.colorpicker-saturation.colorpicker-visible,.colorpicker-selectors.colorpicker-visible,.colorpicker.colorpicker-visible{display:block}.colorpicker-alpha.colorpicker-hidden,.colorpicker-hue.colorpicker-hidden,.colorpicker-saturation.colorpicker-hidden,.colorpicker-selectors.colorpicker-hidden,.colorpicker.colorpicker-hidden{display:none}.colorpicker-inline.colorpicker-visible{display:inline-block} -/*# sourceMappingURL=app.css.map*/ \ No newline at end of file diff --git a/resources/assets/css/font-awesome/font-awesome.css b/resources/assets/css/font-awesome/font-awesome.css deleted file mode 100644 index ee906a8196..0000000000 --- a/resources/assets/css/font-awesome/font-awesome.css +++ /dev/null @@ -1,2337 +0,0 @@ -/*! - * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome - * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) - */ -/* FONT PATH - * -------------------------- */ -@font-face { - font-family: 'FontAwesome'; - src: url('../fonts/fontawesome-webfont.eot?v=4.7.0'); - src: url('../fonts/fontawesome-webfont.eot?#iefix&v=4.7.0') format('embedded-opentype'), url('../fonts/fontawesome-webfont.woff2?v=4.7.0') format('woff2'), url('../fonts/fontawesome-webfont.woff?v=4.7.0') format('woff'), url('../fonts/fontawesome-webfont.ttf?v=4.7.0') format('truetype'), url('../fonts/fontawesome-webfont.svg?v=4.7.0#fontawesomeregular') format('svg'); - font-weight: normal; - font-style: normal; -} -.fa { - display: inline-block; - font: normal normal normal 14px/1 FontAwesome; - font-size: inherit; - text-rendering: auto; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} -/* makes the font 33% larger relative to the icon container */ -.fa-lg { - font-size: 1.33333333em; - line-height: 0.75em; - vertical-align: -15%; -} -.fa-2x { - font-size: 2em; -} -.fa-3x { - font-size: 3em; -} -.fa-4x { - font-size: 4em; -} -.fa-5x { - font-size: 5em; -} -.fa-fw { - width: 1.28571429em; - text-align: center; -} -.fa-ul { - padding-left: 0; - margin-left: 2.14285714em; - list-style-type: none; -} -.fa-ul > li { - position: relative; -} -.fa-li { - position: absolute; - left: -2.14285714em; - width: 2.14285714em; - top: 0.14285714em; - text-align: center; -} -.fa-li.fa-lg { - left: -1.85714286em; -} -.fa-border { - padding: .2em .25em .15em; - border: solid 0.08em #eeeeee; - border-radius: .1em; -} -.fa-pull-left { - float: left; -} -.fa-pull-right { - float: right; -} -.fa.fa-pull-left { - margin-right: .3em; -} -.fa.fa-pull-right { - margin-left: .3em; -} -/* Deprecated as of 4.4.0 */ -.pull-right { - float: right; -} -.pull-left { - float: left; -} -.fa.pull-left { - margin-right: .3em; -} -.fa.pull-right { - margin-left: .3em; -} -.fa-spin { - -webkit-animation: fa-spin 2s infinite linear; - animation: fa-spin 2s infinite linear; -} -.fa-pulse { - -webkit-animation: fa-spin 1s infinite steps(8); - animation: fa-spin 1s infinite steps(8); -} -@-webkit-keyframes fa-spin { - 0% { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - } - 100% { - -webkit-transform: rotate(359deg); - transform: rotate(359deg); - } -} -@keyframes fa-spin { - 0% { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - } - 100% { - -webkit-transform: rotate(359deg); - transform: rotate(359deg); - } -} -.fa-rotate-90 { - -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=1)"; - -webkit-transform: rotate(90deg); - -ms-transform: rotate(90deg); - transform: rotate(90deg); -} -.fa-rotate-180 { - -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=2)"; - -webkit-transform: rotate(180deg); - -ms-transform: rotate(180deg); - transform: rotate(180deg); -} -.fa-rotate-270 { - -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=3)"; - -webkit-transform: rotate(270deg); - -ms-transform: rotate(270deg); - transform: rotate(270deg); -} -.fa-flip-horizontal { - -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)"; - -webkit-transform: scale(-1, 1); - -ms-transform: scale(-1, 1); - transform: scale(-1, 1); -} -.fa-flip-vertical { - -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)"; - -webkit-transform: scale(1, -1); - -ms-transform: scale(1, -1); - transform: scale(1, -1); -} -:root .fa-rotate-90, -:root .fa-rotate-180, -:root .fa-rotate-270, -:root .fa-flip-horizontal, -:root .fa-flip-vertical { - filter: none; -} -.fa-stack { - position: relative; - display: inline-block; - width: 2em; - height: 2em; - line-height: 2em; - vertical-align: middle; -} -.fa-stack-1x, -.fa-stack-2x { - position: absolute; - left: 0; - width: 100%; - text-align: center; -} -.fa-stack-1x { - line-height: inherit; -} -.fa-stack-2x { - font-size: 2em; -} -.fa-inverse { - color: #ffffff; -} -/* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen - readers do not read off random characters that represent icons */ -.fa-glass:before { - content: "\f000"; -} -.fa-music:before { - content: "\f001"; -} -.fa-search:before { - content: "\f002"; -} -.fa-envelope-o:before { - content: "\f003"; -} -.fa-heart:before { - content: "\f004"; -} -.fa-star:before { - content: "\f005"; -} -.fa-star-o:before { - content: "\f006"; -} -.fa-user:before { - content: "\f007"; -} -.fa-film:before { - content: "\f008"; -} -.fa-th-large:before { - content: "\f009"; -} -.fa-th:before { - content: "\f00a"; -} -.fa-th-list:before { - content: "\f00b"; -} -.fa-check:before { - content: "\f00c"; -} -.fa-remove:before, -.fa-close:before, -.fa-times:before { - content: "\f00d"; -} -.fa-search-plus:before { - content: "\f00e"; -} -.fa-search-minus:before { - content: "\f010"; -} -.fa-power-off:before { - content: "\f011"; -} -.fa-signal:before { - content: "\f012"; -} -.fa-gear:before, -.fa-cog:before { - content: "\f013"; -} -.fa-trash-o:before { - content: "\f014"; -} -.fa-home:before { - content: "\f015"; -} -.fa-file-o:before { - content: "\f016"; -} -.fa-clock-o:before { - content: "\f017"; -} -.fa-road:before { - content: "\f018"; -} -.fa-download:before { - content: "\f019"; -} -.fa-arrow-circle-o-down:before { - content: "\f01a"; -} -.fa-arrow-circle-o-up:before { - content: "\f01b"; -} -.fa-inbox:before { - content: "\f01c"; -} -.fa-play-circle-o:before { - content: "\f01d"; -} -.fa-rotate-right:before, -.fa-repeat:before { - content: "\f01e"; -} -.fa-refresh:before { - content: "\f021"; -} -.fa-list-alt:before { - content: "\f022"; -} -.fa-lock:before { - content: "\f023"; -} -.fa-flag:before { - content: "\f024"; -} -.fa-headphones:before { - content: "\f025"; -} -.fa-volume-off:before { - content: "\f026"; -} -.fa-volume-down:before { - content: "\f027"; -} -.fa-volume-up:before { - content: "\f028"; -} -.fa-qrcode:before { - content: "\f029"; -} -.fa-barcode:before { - content: "\f02a"; -} -.fa-tag:before { - content: "\f02b"; -} -.fa-tags:before { - content: "\f02c"; -} -.fa-book:before { - content: "\f02d"; -} -.fa-bookmark:before { - content: "\f02e"; -} -.fa-print:before { - content: "\f02f"; -} -.fa-camera:before { - content: "\f030"; -} -.fa-font:before { - content: "\f031"; -} -.fa-bold:before { - content: "\f032"; -} -.fa-italic:before { - content: "\f033"; -} -.fa-text-height:before { - content: "\f034"; -} -.fa-text-width:before { - content: "\f035"; -} -.fa-align-left:before { - content: "\f036"; -} -.fa-align-center:before { - content: "\f037"; -} -.fa-align-right:before { - content: "\f038"; -} -.fa-align-justify:before { - content: "\f039"; -} -.fa-list:before { - content: "\f03a"; -} -.fa-dedent:before, -.fa-outdent:before { - content: "\f03b"; -} -.fa-indent:before { - content: "\f03c"; -} -.fa-video-camera:before { - content: "\f03d"; -} -.fa-photo:before, -.fa-image:before, -.fa-picture-o:before { - content: "\f03e"; -} -.fa-pencil:before { - content: "\f040"; -} -.fa-map-marker:before { - content: "\f041"; -} -.fa-adjust:before { - content: "\f042"; -} -.fa-tint:before { - content: "\f043"; -} -.fa-edit:before, -.fa-pencil-square-o:before { - content: "\f044"; -} -.fa-share-square-o:before { - content: "\f045"; -} -.fa-check-square-o:before { - content: "\f046"; -} -.fa-arrows:before { - content: "\f047"; -} -.fa-step-backward:before { - content: "\f048"; -} -.fa-fast-backward:before { - content: "\f049"; -} -.fa-backward:before { - content: "\f04a"; -} -.fa-play:before { - content: "\f04b"; -} -.fa-pause:before { - content: "\f04c"; -} -.fa-stop:before { - content: "\f04d"; -} -.fa-forward:before { - content: "\f04e"; -} -.fa-fast-forward:before { - content: "\f050"; -} -.fa-step-forward:before { - content: "\f051"; -} -.fa-eject:before { - content: "\f052"; -} -.fa-chevron-left:before { - content: "\f053"; -} -.fa-chevron-right:before { - content: "\f054"; -} -.fa-plus-circle:before { - content: "\f055"; -} -.fa-minus-circle:before { - content: "\f056"; -} -.fa-times-circle:before { - content: "\f057"; -} -.fa-check-circle:before { - content: "\f058"; -} -.fa-question-circle:before { - content: "\f059"; -} -.fa-info-circle:before { - content: "\f05a"; -} -.fa-crosshairs:before { - content: "\f05b"; -} -.fa-times-circle-o:before { - content: "\f05c"; -} -.fa-check-circle-o:before { - content: "\f05d"; -} -.fa-ban:before { - content: "\f05e"; -} -.fa-arrow-left:before { - content: "\f060"; -} -.fa-arrow-right:before { - content: "\f061"; -} -.fa-arrow-up:before { - content: "\f062"; -} -.fa-arrow-down:before { - content: "\f063"; -} -.fa-mail-forward:before, -.fa-share:before { - content: "\f064"; -} -.fa-expand:before { - content: "\f065"; -} -.fa-compress:before { - content: "\f066"; -} -.fa-plus:before { - content: "\f067"; -} -.fa-minus:before { - content: "\f068"; -} -.fa-asterisk:before { - content: "\f069"; -} -.fa-exclamation-circle:before { - content: "\f06a"; -} -.fa-gift:before { - content: "\f06b"; -} -.fa-leaf:before { - content: "\f06c"; -} -.fa-fire:before { - content: "\f06d"; -} -.fa-eye:before { - content: "\f06e"; -} -.fa-eye-slash:before { - content: "\f070"; -} -.fa-warning:before, -.fa-exclamation-triangle:before { - content: "\f071"; -} -.fa-plane:before { - content: "\f072"; -} -.fa-calendar:before { - content: "\f073"; -} -.fa-random:before { - content: "\f074"; -} -.fa-comment:before { - content: "\f075"; -} -.fa-magnet:before { - content: "\f076"; -} -.fa-chevron-up:before { - content: "\f077"; -} -.fa-chevron-down:before { - content: "\f078"; -} -.fa-retweet:before { - content: "\f079"; -} -.fa-shopping-cart:before { - content: "\f07a"; -} -.fa-folder:before { - content: "\f07b"; -} -.fa-folder-open:before { - content: "\f07c"; -} -.fa-arrows-v:before { - content: "\f07d"; -} -.fa-arrows-h:before { - content: "\f07e"; -} -.fa-bar-chart-o:before, -.fa-bar-chart:before { - content: "\f080"; -} -.fa-twitter-square:before { - content: "\f081"; -} -.fa-facebook-square:before { - content: "\f082"; -} -.fa-camera-retro:before { - content: "\f083"; -} -.fa-key:before { - content: "\f084"; -} -.fa-gears:before, -.fa-cogs:before { - content: "\f085"; -} -.fa-comments:before { - content: "\f086"; -} -.fa-thumbs-o-up:before { - content: "\f087"; -} -.fa-thumbs-o-down:before { - content: "\f088"; -} -.fa-star-half:before { - content: "\f089"; -} -.fa-heart-o:before { - content: "\f08a"; -} -.fa-sign-out:before { - content: "\f08b"; -} -.fa-linkedin-square:before { - content: "\f08c"; -} -.fa-thumb-tack:before { - content: "\f08d"; -} -.fa-external-link:before { - content: "\f08e"; -} -.fa-sign-in:before { - content: "\f090"; -} -.fa-trophy:before { - content: "\f091"; -} -.fa-github-square:before { - content: "\f092"; -} -.fa-upload:before { - content: "\f093"; -} -.fa-lemon-o:before { - content: "\f094"; -} -.fa-phone:before { - content: "\f095"; -} -.fa-square-o:before { - content: "\f096"; -} -.fa-bookmark-o:before { - content: "\f097"; -} -.fa-phone-square:before { - content: "\f098"; -} -.fa-twitter:before { - content: "\f099"; -} -.fa-facebook-f:before, -.fa-facebook:before { - content: "\f09a"; -} -.fa-github:before { - content: "\f09b"; -} -.fa-unlock:before { - content: "\f09c"; -} -.fa-credit-card:before { - content: "\f09d"; -} -.fa-feed:before, -.fa-rss:before { - content: "\f09e"; -} -.fa-hdd-o:before { - content: "\f0a0"; -} -.fa-bullhorn:before { - content: "\f0a1"; -} -.fa-bell:before { - content: "\f0f3"; -} -.fa-certificate:before { - content: "\f0a3"; -} -.fa-hand-o-right:before { - content: "\f0a4"; -} -.fa-hand-o-left:before { - content: "\f0a5"; -} -.fa-hand-o-up:before { - content: "\f0a6"; -} -.fa-hand-o-down:before { - content: "\f0a7"; -} -.fa-arrow-circle-left:before { - content: "\f0a8"; -} -.fa-arrow-circle-right:before { - content: "\f0a9"; -} -.fa-arrow-circle-up:before { - content: "\f0aa"; -} -.fa-arrow-circle-down:before { - content: "\f0ab"; -} -.fa-globe:before { - content: "\f0ac"; -} -.fa-wrench:before { - content: "\f0ad"; -} -.fa-tasks:before { - content: "\f0ae"; -} -.fa-filter:before { - content: "\f0b0"; -} -.fa-briefcase:before { - content: "\f0b1"; -} -.fa-arrows-alt:before { - content: "\f0b2"; -} -.fa-group:before, -.fa-users:before { - content: "\f0c0"; -} -.fa-chain:before, -.fa-link:before { - content: "\f0c1"; -} -.fa-cloud:before { - content: "\f0c2"; -} -.fa-flask:before { - content: "\f0c3"; -} -.fa-cut:before, -.fa-scissors:before { - content: "\f0c4"; -} -.fa-copy:before, -.fa-files-o:before { - content: "\f0c5"; -} -.fa-paperclip:before { - content: "\f0c6"; -} -.fa-save:before, -.fa-floppy-o:before { - content: "\f0c7"; -} -.fa-square:before { - content: "\f0c8"; -} -.fa-navicon:before, -.fa-reorder:before, -.fa-bars:before { - content: "\f0c9"; -} -.fa-list-ul:before { - content: "\f0ca"; -} -.fa-list-ol:before { - content: "\f0cb"; -} -.fa-strikethrough:before { - content: "\f0cc"; -} -.fa-underline:before { - content: "\f0cd"; -} -.fa-table:before { - content: "\f0ce"; -} -.fa-magic:before { - content: "\f0d0"; -} -.fa-truck:before { - content: "\f0d1"; -} -.fa-pinterest:before { - content: "\f0d2"; -} -.fa-pinterest-square:before { - content: "\f0d3"; -} -.fa-google-plus-square:before { - content: "\f0d4"; -} -.fa-google-plus:before { - content: "\f0d5"; -} -.fa-money:before { - content: "\f0d6"; -} -.fa-caret-down:before { - content: "\f0d7"; -} -.fa-caret-up:before { - content: "\f0d8"; -} -.fa-caret-left:before { - content: "\f0d9"; -} -.fa-caret-right:before { - content: "\f0da"; -} -.fa-columns:before { - content: "\f0db"; -} -.fa-unsorted:before, -.fa-sort:before { - content: "\f0dc"; -} -.fa-sort-down:before, -.fa-sort-desc:before { - content: "\f0dd"; -} -.fa-sort-up:before, -.fa-sort-asc:before { - content: "\f0de"; -} -.fa-envelope:before { - content: "\f0e0"; -} -.fa-linkedin:before { - content: "\f0e1"; -} -.fa-rotate-left:before, -.fa-undo:before { - content: "\f0e2"; -} -.fa-legal:before, -.fa-gavel:before { - content: "\f0e3"; -} -.fa-dashboard:before, -.fa-tachometer:before { - content: "\f0e4"; -} -.fa-comment-o:before { - content: "\f0e5"; -} -.fa-comments-o:before { - content: "\f0e6"; -} -.fa-flash:before, -.fa-bolt:before { - content: "\f0e7"; -} -.fa-sitemap:before { - content: "\f0e8"; -} -.fa-umbrella:before { - content: "\f0e9"; -} -.fa-paste:before, -.fa-clipboard:before { - content: "\f0ea"; -} -.fa-lightbulb-o:before { - content: "\f0eb"; -} -.fa-exchange:before { - content: "\f0ec"; -} -.fa-cloud-download:before { - content: "\f0ed"; -} -.fa-cloud-upload:before { - content: "\f0ee"; -} -.fa-user-md:before { - content: "\f0f0"; -} -.fa-stethoscope:before { - content: "\f0f1"; -} -.fa-suitcase:before { - content: "\f0f2"; -} -.fa-bell-o:before { - content: "\f0a2"; -} -.fa-coffee:before { - content: "\f0f4"; -} -.fa-cutlery:before { - content: "\f0f5"; -} -.fa-file-text-o:before { - content: "\f0f6"; -} -.fa-building-o:before { - content: "\f0f7"; -} -.fa-hospital-o:before { - content: "\f0f8"; -} -.fa-ambulance:before { - content: "\f0f9"; -} -.fa-medkit:before { - content: "\f0fa"; -} -.fa-fighter-jet:before { - content: "\f0fb"; -} -.fa-beer:before { - content: "\f0fc"; -} -.fa-h-square:before { - content: "\f0fd"; -} -.fa-plus-square:before { - content: "\f0fe"; -} -.fa-angle-double-left:before { - content: "\f100"; -} -.fa-angle-double-right:before { - content: "\f101"; -} -.fa-angle-double-up:before { - content: "\f102"; -} -.fa-angle-double-down:before { - content: "\f103"; -} -.fa-angle-left:before { - content: "\f104"; -} -.fa-angle-right:before { - content: "\f105"; -} -.fa-angle-up:before { - content: "\f106"; -} -.fa-angle-down:before { - content: "\f107"; -} -.fa-desktop:before { - content: "\f108"; -} -.fa-laptop:before { - content: "\f109"; -} -.fa-tablet:before { - content: "\f10a"; -} -.fa-mobile-phone:before, -.fa-mobile:before { - content: "\f10b"; -} -.fa-circle-o:before { - content: "\f10c"; -} -.fa-quote-left:before { - content: "\f10d"; -} -.fa-quote-right:before { - content: "\f10e"; -} -.fa-spinner:before { - content: "\f110"; -} -.fa-circle:before { - content: "\f111"; -} -.fa-mail-reply:before, -.fa-reply:before { - content: "\f112"; -} -.fa-github-alt:before { - content: "\f113"; -} -.fa-folder-o:before { - content: "\f114"; -} -.fa-folder-open-o:before { - content: "\f115"; -} -.fa-smile-o:before { - content: "\f118"; -} -.fa-frown-o:before { - content: "\f119"; -} -.fa-meh-o:before { - content: "\f11a"; -} -.fa-gamepad:before { - content: "\f11b"; -} -.fa-keyboard-o:before { - content: "\f11c"; -} -.fa-flag-o:before { - content: "\f11d"; -} -.fa-flag-checkered:before { - content: "\f11e"; -} -.fa-terminal:before { - content: "\f120"; -} -.fa-code:before { - content: "\f121"; -} -.fa-mail-reply-all:before, -.fa-reply-all:before { - content: "\f122"; -} -.fa-star-half-empty:before, -.fa-star-half-full:before, -.fa-star-half-o:before { - content: "\f123"; -} -.fa-location-arrow:before { - content: "\f124"; -} -.fa-crop:before { - content: "\f125"; -} -.fa-code-fork:before { - content: "\f126"; -} -.fa-unlink:before, -.fa-chain-broken:before { - content: "\f127"; -} -.fa-question:before { - content: "\f128"; -} -.fa-info:before { - content: "\f129"; -} -.fa-exclamation:before { - content: "\f12a"; -} -.fa-superscript:before { - content: "\f12b"; -} -.fa-subscript:before { - content: "\f12c"; -} -.fa-eraser:before { - content: "\f12d"; -} -.fa-puzzle-piece:before { - content: "\f12e"; -} -.fa-microphone:before { - content: "\f130"; -} -.fa-microphone-slash:before { - content: "\f131"; -} -.fa-shield:before { - content: "\f132"; -} -.fa-calendar-o:before { - content: "\f133"; -} -.fa-fire-extinguisher:before { - content: "\f134"; -} -.fa-rocket:before { - content: "\f135"; -} -.fa-maxcdn:before { - content: "\f136"; -} -.fa-chevron-circle-left:before { - content: "\f137"; -} -.fa-chevron-circle-right:before { - content: "\f138"; -} -.fa-chevron-circle-up:before { - content: "\f139"; -} -.fa-chevron-circle-down:before { - content: "\f13a"; -} -.fa-html5:before { - content: "\f13b"; -} -.fa-css3:before { - content: "\f13c"; -} -.fa-anchor:before { - content: "\f13d"; -} -.fa-unlock-alt:before { - content: "\f13e"; -} -.fa-bullseye:before { - content: "\f140"; -} -.fa-ellipsis-h:before { - content: "\f141"; -} -.fa-ellipsis-v:before { - content: "\f142"; -} -.fa-rss-square:before { - content: "\f143"; -} -.fa-play-circle:before { - content: "\f144"; -} -.fa-ticket:before { - content: "\f145"; -} -.fa-minus-square:before { - content: "\f146"; -} -.fa-minus-square-o:before { - content: "\f147"; -} -.fa-level-up:before { - content: "\f148"; -} -.fa-level-down:before { - content: "\f149"; -} -.fa-check-square:before { - content: "\f14a"; -} -.fa-pencil-square:before { - content: "\f14b"; -} -.fa-external-link-square:before { - content: "\f14c"; -} -.fa-share-square:before { - content: "\f14d"; -} -.fa-compass:before { - content: "\f14e"; -} -.fa-toggle-down:before, -.fa-caret-square-o-down:before { - content: "\f150"; -} -.fa-toggle-up:before, -.fa-caret-square-o-up:before { - content: "\f151"; -} -.fa-toggle-right:before, -.fa-caret-square-o-right:before { - content: "\f152"; -} -.fa-euro:before, -.fa-eur:before { - content: "\f153"; -} -.fa-gbp:before { - content: "\f154"; -} -.fa-dollar:before, -.fa-usd:before { - content: "\f155"; -} -.fa-rupee:before, -.fa-inr:before { - content: "\f156"; -} -.fa-cny:before, -.fa-rmb:before, -.fa-yen:before, -.fa-jpy:before { - content: "\f157"; -} -.fa-ruble:before, -.fa-rouble:before, -.fa-rub:before { - content: "\f158"; -} -.fa-won:before, -.fa-krw:before { - content: "\f159"; -} -.fa-bitcoin:before, -.fa-btc:before { - content: "\f15a"; -} -.fa-file:before { - content: "\f15b"; -} -.fa-file-text:before { - content: "\f15c"; -} -.fa-sort-alpha-asc:before { - content: "\f15d"; -} -.fa-sort-alpha-desc:before { - content: "\f15e"; -} -.fa-sort-amount-asc:before { - content: "\f160"; -} -.fa-sort-amount-desc:before { - content: "\f161"; -} -.fa-sort-numeric-asc:before { - content: "\f162"; -} -.fa-sort-numeric-desc:before { - content: "\f163"; -} -.fa-thumbs-up:before { - content: "\f164"; -} -.fa-thumbs-down:before { - content: "\f165"; -} -.fa-youtube-square:before { - content: "\f166"; -} -.fa-youtube:before { - content: "\f167"; -} -.fa-xing:before { - content: "\f168"; -} -.fa-xing-square:before { - content: "\f169"; -} -.fa-youtube-play:before { - content: "\f16a"; -} -.fa-dropbox:before { - content: "\f16b"; -} -.fa-stack-overflow:before { - content: "\f16c"; -} -.fa-instagram:before { - content: "\f16d"; -} -.fa-flickr:before { - content: "\f16e"; -} -.fa-adn:before { - content: "\f170"; -} -.fa-bitbucket:before { - content: "\f171"; -} -.fa-bitbucket-square:before { - content: "\f172"; -} -.fa-tumblr:before { - content: "\f173"; -} -.fa-tumblr-square:before { - content: "\f174"; -} -.fa-long-arrow-down:before { - content: "\f175"; -} -.fa-long-arrow-up:before { - content: "\f176"; -} -.fa-long-arrow-left:before { - content: "\f177"; -} -.fa-long-arrow-right:before { - content: "\f178"; -} -.fa-apple:before { - content: "\f179"; -} -.fa-windows:before { - content: "\f17a"; -} -.fa-android:before { - content: "\f17b"; -} -.fa-linux:before { - content: "\f17c"; -} -.fa-dribbble:before { - content: "\f17d"; -} -.fa-skype:before { - content: "\f17e"; -} -.fa-foursquare:before { - content: "\f180"; -} -.fa-trello:before { - content: "\f181"; -} -.fa-female:before { - content: "\f182"; -} -.fa-male:before { - content: "\f183"; -} -.fa-gittip:before, -.fa-gratipay:before { - content: "\f184"; -} -.fa-sun-o:before { - content: "\f185"; -} -.fa-moon-o:before { - content: "\f186"; -} -.fa-archive:before { - content: "\f187"; -} -.fa-bug:before { - content: "\f188"; -} -.fa-vk:before { - content: "\f189"; -} -.fa-weibo:before { - content: "\f18a"; -} -.fa-renren:before { - content: "\f18b"; -} -.fa-pagelines:before { - content: "\f18c"; -} -.fa-stack-exchange:before { - content: "\f18d"; -} -.fa-arrow-circle-o-right:before { - content: "\f18e"; -} -.fa-arrow-circle-o-left:before { - content: "\f190"; -} -.fa-toggle-left:before, -.fa-caret-square-o-left:before { - content: "\f191"; -} -.fa-dot-circle-o:before { - content: "\f192"; -} -.fa-wheelchair:before { - content: "\f193"; -} -.fa-vimeo-square:before { - content: "\f194"; -} -.fa-turkish-lira:before, -.fa-try:before { - content: "\f195"; -} -.fa-plus-square-o:before { - content: "\f196"; -} -.fa-space-shuttle:before { - content: "\f197"; -} -.fa-slack:before { - content: "\f198"; -} -.fa-envelope-square:before { - content: "\f199"; -} -.fa-wordpress:before { - content: "\f19a"; -} -.fa-openid:before { - content: "\f19b"; -} -.fa-institution:before, -.fa-bank:before, -.fa-university:before { - content: "\f19c"; -} -.fa-mortar-board:before, -.fa-graduation-cap:before { - content: "\f19d"; -} -.fa-yahoo:before { - content: "\f19e"; -} -.fa-google:before { - content: "\f1a0"; -} -.fa-reddit:before { - content: "\f1a1"; -} -.fa-reddit-square:before { - content: "\f1a2"; -} -.fa-stumbleupon-circle:before { - content: "\f1a3"; -} -.fa-stumbleupon:before { - content: "\f1a4"; -} -.fa-delicious:before { - content: "\f1a5"; -} -.fa-digg:before { - content: "\f1a6"; -} -.fa-pied-piper-pp:before { - content: "\f1a7"; -} -.fa-pied-piper-alt:before { - content: "\f1a8"; -} -.fa-drupal:before { - content: "\f1a9"; -} -.fa-joomla:before { - content: "\f1aa"; -} -.fa-language:before { - content: "\f1ab"; -} -.fa-fax:before { - content: "\f1ac"; -} -.fa-building:before { - content: "\f1ad"; -} -.fa-child:before { - content: "\f1ae"; -} -.fa-paw:before { - content: "\f1b0"; -} -.fa-spoon:before { - content: "\f1b1"; -} -.fa-cube:before { - content: "\f1b2"; -} -.fa-cubes:before { - content: "\f1b3"; -} -.fa-behance:before { - content: "\f1b4"; -} -.fa-behance-square:before { - content: "\f1b5"; -} -.fa-steam:before { - content: "\f1b6"; -} -.fa-steam-square:before { - content: "\f1b7"; -} -.fa-recycle:before { - content: "\f1b8"; -} -.fa-automobile:before, -.fa-car:before { - content: "\f1b9"; -} -.fa-cab:before, -.fa-taxi:before { - content: "\f1ba"; -} -.fa-tree:before { - content: "\f1bb"; -} -.fa-spotify:before { - content: "\f1bc"; -} -.fa-deviantart:before { - content: "\f1bd"; -} -.fa-soundcloud:before { - content: "\f1be"; -} -.fa-database:before { - content: "\f1c0"; -} -.fa-file-pdf-o:before { - content: "\f1c1"; -} -.fa-file-word-o:before { - content: "\f1c2"; -} -.fa-file-excel-o:before { - content: "\f1c3"; -} -.fa-file-powerpoint-o:before { - content: "\f1c4"; -} -.fa-file-photo-o:before, -.fa-file-picture-o:before, -.fa-file-image-o:before { - content: "\f1c5"; -} -.fa-file-zip-o:before, -.fa-file-archive-o:before { - content: "\f1c6"; -} -.fa-file-sound-o:before, -.fa-file-audio-o:before { - content: "\f1c7"; -} -.fa-file-movie-o:before, -.fa-file-video-o:before { - content: "\f1c8"; -} -.fa-file-code-o:before { - content: "\f1c9"; -} -.fa-vine:before { - content: "\f1ca"; -} -.fa-codepen:before { - content: "\f1cb"; -} -.fa-jsfiddle:before { - content: "\f1cc"; -} -.fa-life-bouy:before, -.fa-life-buoy:before, -.fa-life-saver:before, -.fa-support:before, -.fa-life-ring:before { - content: "\f1cd"; -} -.fa-circle-o-notch:before { - content: "\f1ce"; -} -.fa-ra:before, -.fa-resistance:before, -.fa-rebel:before { - content: "\f1d0"; -} -.fa-ge:before, -.fa-empire:before { - content: "\f1d1"; -} -.fa-git-square:before { - content: "\f1d2"; -} -.fa-git:before { - content: "\f1d3"; -} -.fa-y-combinator-square:before, -.fa-yc-square:before, -.fa-hacker-news:before { - content: "\f1d4"; -} -.fa-tencent-weibo:before { - content: "\f1d5"; -} -.fa-qq:before { - content: "\f1d6"; -} -.fa-wechat:before, -.fa-weixin:before { - content: "\f1d7"; -} -.fa-send:before, -.fa-paper-plane:before { - content: "\f1d8"; -} -.fa-send-o:before, -.fa-paper-plane-o:before { - content: "\f1d9"; -} -.fa-history:before { - content: "\f1da"; -} -.fa-circle-thin:before { - content: "\f1db"; -} -.fa-header:before { - content: "\f1dc"; -} -.fa-paragraph:before { - content: "\f1dd"; -} -.fa-sliders:before { - content: "\f1de"; -} -.fa-share-alt:before { - content: "\f1e0"; -} -.fa-share-alt-square:before { - content: "\f1e1"; -} -.fa-bomb:before { - content: "\f1e2"; -} -.fa-soccer-ball-o:before, -.fa-futbol-o:before { - content: "\f1e3"; -} -.fa-tty:before { - content: "\f1e4"; -} -.fa-binoculars:before { - content: "\f1e5"; -} -.fa-plug:before { - content: "\f1e6"; -} -.fa-slideshare:before { - content: "\f1e7"; -} -.fa-twitch:before { - content: "\f1e8"; -} -.fa-yelp:before { - content: "\f1e9"; -} -.fa-newspaper-o:before { - content: "\f1ea"; -} -.fa-wifi:before { - content: "\f1eb"; -} -.fa-calculator:before { - content: "\f1ec"; -} -.fa-paypal:before { - content: "\f1ed"; -} -.fa-google-wallet:before { - content: "\f1ee"; -} -.fa-cc-visa:before { - content: "\f1f0"; -} -.fa-cc-mastercard:before { - content: "\f1f1"; -} -.fa-cc-discover:before { - content: "\f1f2"; -} -.fa-cc-amex:before { - content: "\f1f3"; -} -.fa-cc-paypal:before { - content: "\f1f4"; -} -.fa-cc-stripe:before { - content: "\f1f5"; -} -.fa-bell-slash:before { - content: "\f1f6"; -} -.fa-bell-slash-o:before { - content: "\f1f7"; -} -.fa-trash:before { - content: "\f1f8"; -} -.fa-copyright:before { - content: "\f1f9"; -} -.fa-at:before { - content: "\f1fa"; -} -.fa-eyedropper:before { - content: "\f1fb"; -} -.fa-paint-brush:before { - content: "\f1fc"; -} -.fa-birthday-cake:before { - content: "\f1fd"; -} -.fa-area-chart:before { - content: "\f1fe"; -} -.fa-pie-chart:before { - content: "\f200"; -} -.fa-line-chart:before { - content: "\f201"; -} -.fa-lastfm:before { - content: "\f202"; -} -.fa-lastfm-square:before { - content: "\f203"; -} -.fa-toggle-off:before { - content: "\f204"; -} -.fa-toggle-on:before { - content: "\f205"; -} -.fa-bicycle:before { - content: "\f206"; -} -.fa-bus:before { - content: "\f207"; -} -.fa-ioxhost:before { - content: "\f208"; -} -.fa-angellist:before { - content: "\f209"; -} -.fa-cc:before { - content: "\f20a"; -} -.fa-shekel:before, -.fa-sheqel:before, -.fa-ils:before { - content: "\f20b"; -} -.fa-meanpath:before { - content: "\f20c"; -} -.fa-buysellads:before { - content: "\f20d"; -} -.fa-connectdevelop:before { - content: "\f20e"; -} -.fa-dashcube:before { - content: "\f210"; -} -.fa-forumbee:before { - content: "\f211"; -} -.fa-leanpub:before { - content: "\f212"; -} -.fa-sellsy:before { - content: "\f213"; -} -.fa-shirtsinbulk:before { - content: "\f214"; -} -.fa-simplybuilt:before { - content: "\f215"; -} -.fa-skyatlas:before { - content: "\f216"; -} -.fa-cart-plus:before { - content: "\f217"; -} -.fa-cart-arrow-down:before { - content: "\f218"; -} -.fa-diamond:before { - content: "\f219"; -} -.fa-ship:before { - content: "\f21a"; -} -.fa-user-secret:before { - content: "\f21b"; -} -.fa-motorcycle:before { - content: "\f21c"; -} -.fa-street-view:before { - content: "\f21d"; -} -.fa-heartbeat:before { - content: "\f21e"; -} -.fa-venus:before { - content: "\f221"; -} -.fa-mars:before { - content: "\f222"; -} -.fa-mercury:before { - content: "\f223"; -} -.fa-intersex:before, -.fa-transgender:before { - content: "\f224"; -} -.fa-transgender-alt:before { - content: "\f225"; -} -.fa-venus-double:before { - content: "\f226"; -} -.fa-mars-double:before { - content: "\f227"; -} -.fa-venus-mars:before { - content: "\f228"; -} -.fa-mars-stroke:before { - content: "\f229"; -} -.fa-mars-stroke-v:before { - content: "\f22a"; -} -.fa-mars-stroke-h:before { - content: "\f22b"; -} -.fa-neuter:before { - content: "\f22c"; -} -.fa-genderless:before { - content: "\f22d"; -} -.fa-facebook-official:before { - content: "\f230"; -} -.fa-pinterest-p:before { - content: "\f231"; -} -.fa-whatsapp:before { - content: "\f232"; -} -.fa-server:before { - content: "\f233"; -} -.fa-user-plus:before { - content: "\f234"; -} -.fa-user-times:before { - content: "\f235"; -} -.fa-hotel:before, -.fa-bed:before { - content: "\f236"; -} -.fa-viacoin:before { - content: "\f237"; -} -.fa-train:before { - content: "\f238"; -} -.fa-subway:before { - content: "\f239"; -} -.fa-medium:before { - content: "\f23a"; -} -.fa-yc:before, -.fa-y-combinator:before { - content: "\f23b"; -} -.fa-optin-monster:before { - content: "\f23c"; -} -.fa-opencart:before { - content: "\f23d"; -} -.fa-expeditedssl:before { - content: "\f23e"; -} -.fa-battery-4:before, -.fa-battery:before, -.fa-battery-full:before { - content: "\f240"; -} -.fa-battery-3:before, -.fa-battery-three-quarters:before { - content: "\f241"; -} -.fa-battery-2:before, -.fa-battery-half:before { - content: "\f242"; -} -.fa-battery-1:before, -.fa-battery-quarter:before { - content: "\f243"; -} -.fa-battery-0:before, -.fa-battery-empty:before { - content: "\f244"; -} -.fa-mouse-pointer:before { - content: "\f245"; -} -.fa-i-cursor:before { - content: "\f246"; -} -.fa-object-group:before { - content: "\f247"; -} -.fa-object-ungroup:before { - content: "\f248"; -} -.fa-sticky-note:before { - content: "\f249"; -} -.fa-sticky-note-o:before { - content: "\f24a"; -} -.fa-cc-jcb:before { - content: "\f24b"; -} -.fa-cc-diners-club:before { - content: "\f24c"; -} -.fa-clone:before { - content: "\f24d"; -} -.fa-balance-scale:before { - content: "\f24e"; -} -.fa-hourglass-o:before { - content: "\f250"; -} -.fa-hourglass-1:before, -.fa-hourglass-start:before { - content: "\f251"; -} -.fa-hourglass-2:before, -.fa-hourglass-half:before { - content: "\f252"; -} -.fa-hourglass-3:before, -.fa-hourglass-end:before { - content: "\f253"; -} -.fa-hourglass:before { - content: "\f254"; -} -.fa-hand-grab-o:before, -.fa-hand-rock-o:before { - content: "\f255"; -} -.fa-hand-stop-o:before, -.fa-hand-paper-o:before { - content: "\f256"; -} -.fa-hand-scissors-o:before { - content: "\f257"; -} -.fa-hand-lizard-o:before { - content: "\f258"; -} -.fa-hand-spock-o:before { - content: "\f259"; -} -.fa-hand-pointer-o:before { - content: "\f25a"; -} -.fa-hand-peace-o:before { - content: "\f25b"; -} -.fa-trademark:before { - content: "\f25c"; -} -.fa-registered:before { - content: "\f25d"; -} -.fa-creative-commons:before { - content: "\f25e"; -} -.fa-gg:before { - content: "\f260"; -} -.fa-gg-circle:before { - content: "\f261"; -} -.fa-tripadvisor:before { - content: "\f262"; -} -.fa-odnoklassniki:before { - content: "\f263"; -} -.fa-odnoklassniki-square:before { - content: "\f264"; -} -.fa-get-pocket:before { - content: "\f265"; -} -.fa-wikipedia-w:before { - content: "\f266"; -} -.fa-safari:before { - content: "\f267"; -} -.fa-chrome:before { - content: "\f268"; -} -.fa-firefox:before { - content: "\f269"; -} -.fa-opera:before { - content: "\f26a"; -} -.fa-internet-explorer:before { - content: "\f26b"; -} -.fa-tv:before, -.fa-television:before { - content: "\f26c"; -} -.fa-contao:before { - content: "\f26d"; -} -.fa-500px:before { - content: "\f26e"; -} -.fa-amazon:before { - content: "\f270"; -} -.fa-calendar-plus-o:before { - content: "\f271"; -} -.fa-calendar-minus-o:before { - content: "\f272"; -} -.fa-calendar-times-o:before { - content: "\f273"; -} -.fa-calendar-check-o:before { - content: "\f274"; -} -.fa-industry:before { - content: "\f275"; -} -.fa-map-pin:before { - content: "\f276"; -} -.fa-map-signs:before { - content: "\f277"; -} -.fa-map-o:before { - content: "\f278"; -} -.fa-map:before { - content: "\f279"; -} -.fa-commenting:before { - content: "\f27a"; -} -.fa-commenting-o:before { - content: "\f27b"; -} -.fa-houzz:before { - content: "\f27c"; -} -.fa-vimeo:before { - content: "\f27d"; -} -.fa-black-tie:before { - content: "\f27e"; -} -.fa-fonticons:before { - content: "\f280"; -} -.fa-reddit-alien:before { - content: "\f281"; -} -.fa-edge:before { - content: "\f282"; -} -.fa-credit-card-alt:before { - content: "\f283"; -} -.fa-codiepie:before { - content: "\f284"; -} -.fa-modx:before { - content: "\f285"; -} -.fa-fort-awesome:before { - content: "\f286"; -} -.fa-usb:before { - content: "\f287"; -} -.fa-product-hunt:before { - content: "\f288"; -} -.fa-mixcloud:before { - content: "\f289"; -} -.fa-scribd:before { - content: "\f28a"; -} -.fa-pause-circle:before { - content: "\f28b"; -} -.fa-pause-circle-o:before { - content: "\f28c"; -} -.fa-stop-circle:before { - content: "\f28d"; -} -.fa-stop-circle-o:before { - content: "\f28e"; -} -.fa-shopping-bag:before { - content: "\f290"; -} -.fa-shopping-basket:before { - content: "\f291"; -} -.fa-hashtag:before { - content: "\f292"; -} -.fa-bluetooth:before { - content: "\f293"; -} -.fa-bluetooth-b:before { - content: "\f294"; -} -.fa-percent:before { - content: "\f295"; -} -.fa-gitlab:before { - content: "\f296"; -} -.fa-wpbeginner:before { - content: "\f297"; -} -.fa-wpforms:before { - content: "\f298"; -} -.fa-envira:before { - content: "\f299"; -} -.fa-universal-access:before { - content: "\f29a"; -} -.fa-wheelchair-alt:before { - content: "\f29b"; -} -.fa-question-circle-o:before { - content: "\f29c"; -} -.fa-blind:before { - content: "\f29d"; -} -.fa-audio-description:before { - content: "\f29e"; -} -.fa-volume-control-phone:before { - content: "\f2a0"; -} -.fa-braille:before { - content: "\f2a1"; -} -.fa-assistive-listening-systems:before { - content: "\f2a2"; -} -.fa-asl-interpreting:before, -.fa-american-sign-language-interpreting:before { - content: "\f2a3"; -} -.fa-deafness:before, -.fa-hard-of-hearing:before, -.fa-deaf:before { - content: "\f2a4"; -} -.fa-glide:before { - content: "\f2a5"; -} -.fa-glide-g:before { - content: "\f2a6"; -} -.fa-signing:before, -.fa-sign-language:before { - content: "\f2a7"; -} -.fa-low-vision:before { - content: "\f2a8"; -} -.fa-viadeo:before { - content: "\f2a9"; -} -.fa-viadeo-square:before { - content: "\f2aa"; -} -.fa-snapchat:before { - content: "\f2ab"; -} -.fa-snapchat-ghost:before { - content: "\f2ac"; -} -.fa-snapchat-square:before { - content: "\f2ad"; -} -.fa-pied-piper:before { - content: "\f2ae"; -} -.fa-first-order:before { - content: "\f2b0"; -} -.fa-yoast:before { - content: "\f2b1"; -} -.fa-themeisle:before { - content: "\f2b2"; -} -.fa-google-plus-circle:before, -.fa-google-plus-official:before { - content: "\f2b3"; -} -.fa-fa:before, -.fa-font-awesome:before { - content: "\f2b4"; -} -.fa-handshake-o:before { - content: "\f2b5"; -} -.fa-envelope-open:before { - content: "\f2b6"; -} -.fa-envelope-open-o:before { - content: "\f2b7"; -} -.fa-linode:before { - content: "\f2b8"; -} -.fa-address-book:before { - content: "\f2b9"; -} -.fa-address-book-o:before { - content: "\f2ba"; -} -.fa-vcard:before, -.fa-address-card:before { - content: "\f2bb"; -} -.fa-vcard-o:before, -.fa-address-card-o:before { - content: "\f2bc"; -} -.fa-user-circle:before { - content: "\f2bd"; -} -.fa-user-circle-o:before { - content: "\f2be"; -} -.fa-user-o:before { - content: "\f2c0"; -} -.fa-id-badge:before { - content: "\f2c1"; -} -.fa-drivers-license:before, -.fa-id-card:before { - content: "\f2c2"; -} -.fa-drivers-license-o:before, -.fa-id-card-o:before { - content: "\f2c3"; -} -.fa-quora:before { - content: "\f2c4"; -} -.fa-free-code-camp:before { - content: "\f2c5"; -} -.fa-telegram:before { - content: "\f2c6"; -} -.fa-thermometer-4:before, -.fa-thermometer:before, -.fa-thermometer-full:before { - content: "\f2c7"; -} -.fa-thermometer-3:before, -.fa-thermometer-three-quarters:before { - content: "\f2c8"; -} -.fa-thermometer-2:before, -.fa-thermometer-half:before { - content: "\f2c9"; -} -.fa-thermometer-1:before, -.fa-thermometer-quarter:before { - content: "\f2ca"; -} -.fa-thermometer-0:before, -.fa-thermometer-empty:before { - content: "\f2cb"; -} -.fa-shower:before { - content: "\f2cc"; -} -.fa-bathtub:before, -.fa-s15:before, -.fa-bath:before { - content: "\f2cd"; -} -.fa-podcast:before { - content: "\f2ce"; -} -.fa-window-maximize:before { - content: "\f2d0"; -} -.fa-window-minimize:before { - content: "\f2d1"; -} -.fa-window-restore:before { - content: "\f2d2"; -} -.fa-times-rectangle:before, -.fa-window-close:before { - content: "\f2d3"; -} -.fa-times-rectangle-o:before, -.fa-window-close-o:before { - content: "\f2d4"; -} -.fa-bandcamp:before { - content: "\f2d5"; -} -.fa-grav:before { - content: "\f2d6"; -} -.fa-etsy:before { - content: "\f2d7"; -} -.fa-imdb:before { - content: "\f2d8"; -} -.fa-ravelry:before { - content: "\f2d9"; -} -.fa-eercast:before { - content: "\f2da"; -} -.fa-microchip:before { - content: "\f2db"; -} -.fa-snowflake-o:before { - content: "\f2dc"; -} -.fa-superpowers:before { - content: "\f2dd"; -} -.fa-wpexplorer:before { - content: "\f2de"; -} -.fa-meetup:before { - content: "\f2e0"; -} -.sr-only { - position: absolute; - width: 1px; - height: 1px; - padding: 0; - margin: -1px; - overflow: hidden; - clip: rect(0, 0, 0, 0); - border: 0; -} -.sr-only-focusable:active, -.sr-only-focusable:focus { - position: static; - width: auto; - height: auto; - margin: 0; - overflow: visible; - clip: auto; -} diff --git a/resources/assets/css/font-awesome/font-awesome.min.css b/resources/assets/css/font-awesome/font-awesome.min.css deleted file mode 100644 index 540440ce89..0000000000 --- a/resources/assets/css/font-awesome/font-awesome.min.css +++ /dev/null @@ -1,4 +0,0 @@ -/*! - * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome - * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) - */@font-face{font-family:'FontAwesome';src:url('../fonts/fontawesome-webfont.eot?v=4.7.0');src:url('../fonts/fontawesome-webfont.eot?#iefix&v=4.7.0') format('embedded-opentype'),url('../fonts/fontawesome-webfont.woff2?v=4.7.0') format('woff2'),url('../fonts/fontawesome-webfont.woff?v=4.7.0') format('woff'),url('../fonts/fontawesome-webfont.ttf?v=4.7.0') format('truetype'),url('../fonts/fontawesome-webfont.svg?v=4.7.0#fontawesomeregular') format('svg');font-weight:normal;font-style:normal}.fa{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571429em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14285714em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14285714em;width:2.14285714em;top:.14285714em;text-align:center}.fa-li.fa-lg{left:-1.85714286em}.fa-border{padding:.2em .25em .15em;border:solid .08em #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left{margin-right:.3em}.fa.fa-pull-right{margin-left:.3em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}.fa-pulse{-webkit-animation:fa-spin 1s infinite steps(8);animation:fa-spin 1s infinite steps(8)}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scale(-1, 1);-ms-transform:scale(-1, 1);transform:scale(-1, 1)}.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";-webkit-transform:scale(1, -1);-ms-transform:scale(1, -1);transform:scale(1, -1)}:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270,:root .fa-flip-horizontal,:root .fa-flip-vertical{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\f000"}.fa-music:before{content:"\f001"}.fa-search:before{content:"\f002"}.fa-envelope-o:before{content:"\f003"}.fa-heart:before{content:"\f004"}.fa-star:before{content:"\f005"}.fa-star-o:before{content:"\f006"}.fa-user:before{content:"\f007"}.fa-film:before{content:"\f008"}.fa-th-large:before{content:"\f009"}.fa-th:before{content:"\f00a"}.fa-th-list:before{content:"\f00b"}.fa-check:before{content:"\f00c"}.fa-remove:before,.fa-close:before,.fa-times:before{content:"\f00d"}.fa-search-plus:before{content:"\f00e"}.fa-search-minus:before{content:"\f010"}.fa-power-off:before{content:"\f011"}.fa-signal:before{content:"\f012"}.fa-gear:before,.fa-cog:before{content:"\f013"}.fa-trash-o:before{content:"\f014"}.fa-home:before{content:"\f015"}.fa-file-o:before{content:"\f016"}.fa-clock-o:before{content:"\f017"}.fa-road:before{content:"\f018"}.fa-download:before{content:"\f019"}.fa-arrow-circle-o-down:before{content:"\f01a"}.fa-arrow-circle-o-up:before{content:"\f01b"}.fa-inbox:before{content:"\f01c"}.fa-play-circle-o:before{content:"\f01d"}.fa-rotate-right:before,.fa-repeat:before{content:"\f01e"}.fa-refresh:before{content:"\f021"}.fa-list-alt:before{content:"\f022"}.fa-lock:before{content:"\f023"}.fa-flag:before{content:"\f024"}.fa-headphones:before{content:"\f025"}.fa-volume-off:before{content:"\f026"}.fa-volume-down:before{content:"\f027"}.fa-volume-up:before{content:"\f028"}.fa-qrcode:before{content:"\f029"}.fa-barcode:before{content:"\f02a"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-book:before{content:"\f02d"}.fa-bookmark:before{content:"\f02e"}.fa-print:before{content:"\f02f"}.fa-camera:before{content:"\f030"}.fa-font:before{content:"\f031"}.fa-bold:before{content:"\f032"}.fa-italic:before{content:"\f033"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-align-left:before{content:"\f036"}.fa-align-center:before{content:"\f037"}.fa-align-right:before{content:"\f038"}.fa-align-justify:before{content:"\f039"}.fa-list:before{content:"\f03a"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-indent:before{content:"\f03c"}.fa-video-camera:before{content:"\f03d"}.fa-photo:before,.fa-image:before,.fa-picture-o:before{content:"\f03e"}.fa-pencil:before{content:"\f040"}.fa-map-marker:before{content:"\f041"}.fa-adjust:before{content:"\f042"}.fa-tint:before{content:"\f043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\f044"}.fa-share-square-o:before{content:"\f045"}.fa-check-square-o:before{content:"\f046"}.fa-arrows:before{content:"\f047"}.fa-step-backward:before{content:"\f048"}.fa-fast-backward:before{content:"\f049"}.fa-backward:before{content:"\f04a"}.fa-play:before{content:"\f04b"}.fa-pause:before{content:"\f04c"}.fa-stop:before{content:"\f04d"}.fa-forward:before{content:"\f04e"}.fa-fast-forward:before{content:"\f050"}.fa-step-forward:before{content:"\f051"}.fa-eject:before{content:"\f052"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-plus-circle:before{content:"\f055"}.fa-minus-circle:before{content:"\f056"}.fa-times-circle:before{content:"\f057"}.fa-check-circle:before{content:"\f058"}.fa-question-circle:before{content:"\f059"}.fa-info-circle:before{content:"\f05a"}.fa-crosshairs:before{content:"\f05b"}.fa-times-circle-o:before{content:"\f05c"}.fa-check-circle-o:before{content:"\f05d"}.fa-ban:before{content:"\f05e"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrow-down:before{content:"\f063"}.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-expand:before{content:"\f065"}.fa-compress:before{content:"\f066"}.fa-plus:before{content:"\f067"}.fa-minus:before{content:"\f068"}.fa-asterisk:before{content:"\f069"}.fa-exclamation-circle:before{content:"\f06a"}.fa-gift:before{content:"\f06b"}.fa-leaf:before{content:"\f06c"}.fa-fire:before{content:"\f06d"}.fa-eye:before{content:"\f06e"}.fa-eye-slash:before{content:"\f070"}.fa-warning:before,.fa-exclamation-triangle:before{content:"\f071"}.fa-plane:before{content:"\f072"}.fa-calendar:before{content:"\f073"}.fa-random:before{content:"\f074"}.fa-comment:before{content:"\f075"}.fa-magnet:before{content:"\f076"}.fa-chevron-up:before{content:"\f077"}.fa-chevron-down:before{content:"\f078"}.fa-retweet:before{content:"\f079"}.fa-shopping-cart:before{content:"\f07a"}.fa-folder:before{content:"\f07b"}.fa-folder-open:before{content:"\f07c"}.fa-arrows-v:before{content:"\f07d"}.fa-arrows-h:before{content:"\f07e"}.fa-bar-chart-o:before,.fa-bar-chart:before{content:"\f080"}.fa-twitter-square:before{content:"\f081"}.fa-facebook-square:before{content:"\f082"}.fa-camera-retro:before{content:"\f083"}.fa-key:before{content:"\f084"}.fa-gears:before,.fa-cogs:before{content:"\f085"}.fa-comments:before{content:"\f086"}.fa-thumbs-o-up:before{content:"\f087"}.fa-thumbs-o-down:before{content:"\f088"}.fa-star-half:before{content:"\f089"}.fa-heart-o:before{content:"\f08a"}.fa-sign-out:before{content:"\f08b"}.fa-linkedin-square:before{content:"\f08c"}.fa-thumb-tack:before{content:"\f08d"}.fa-external-link:before{content:"\f08e"}.fa-sign-in:before{content:"\f090"}.fa-trophy:before{content:"\f091"}.fa-github-square:before{content:"\f092"}.fa-upload:before{content:"\f093"}.fa-lemon-o:before{content:"\f094"}.fa-phone:before{content:"\f095"}.fa-square-o:before{content:"\f096"}.fa-bookmark-o:before{content:"\f097"}.fa-phone-square:before{content:"\f098"}.fa-twitter:before{content:"\f099"}.fa-facebook-f:before,.fa-facebook:before{content:"\f09a"}.fa-github:before{content:"\f09b"}.fa-unlock:before{content:"\f09c"}.fa-credit-card:before{content:"\f09d"}.fa-feed:before,.fa-rss:before{content:"\f09e"}.fa-hdd-o:before{content:"\f0a0"}.fa-bullhorn:before{content:"\f0a1"}.fa-bell:before{content:"\f0f3"}.fa-certificate:before{content:"\f0a3"}.fa-hand-o-right:before{content:"\f0a4"}.fa-hand-o-left:before{content:"\f0a5"}.fa-hand-o-up:before{content:"\f0a6"}.fa-hand-o-down:before{content:"\f0a7"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-globe:before{content:"\f0ac"}.fa-wrench:before{content:"\f0ad"}.fa-tasks:before{content:"\f0ae"}.fa-filter:before{content:"\f0b0"}.fa-briefcase:before{content:"\f0b1"}.fa-arrows-alt:before{content:"\f0b2"}.fa-group:before,.fa-users:before{content:"\f0c0"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-cloud:before{content:"\f0c2"}.fa-flask:before{content:"\f0c3"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-copy:before,.fa-files-o:before{content:"\f0c5"}.fa-paperclip:before{content:"\f0c6"}.fa-save:before,.fa-floppy-o:before{content:"\f0c7"}.fa-square:before{content:"\f0c8"}.fa-navicon:before,.fa-reorder:before,.fa-bars:before{content:"\f0c9"}.fa-list-ul:before{content:"\f0ca"}.fa-list-ol:before{content:"\f0cb"}.fa-strikethrough:before{content:"\f0cc"}.fa-underline:before{content:"\f0cd"}.fa-table:before{content:"\f0ce"}.fa-magic:before{content:"\f0d0"}.fa-truck:before{content:"\f0d1"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-square:before{content:"\f0d3"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-plus:before{content:"\f0d5"}.fa-money:before{content:"\f0d6"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-up:before{content:"\f0d8"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-columns:before{content:"\f0db"}.fa-unsorted:before,.fa-sort:before{content:"\f0dc"}.fa-sort-down:before,.fa-sort-desc:before{content:"\f0dd"}.fa-sort-up:before,.fa-sort-asc:before{content:"\f0de"}.fa-envelope:before{content:"\f0e0"}.fa-linkedin:before{content:"\f0e1"}.fa-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-legal:before,.fa-gavel:before{content:"\f0e3"}.fa-dashboard:before,.fa-tachometer:before{content:"\f0e4"}.fa-comment-o:before{content:"\f0e5"}.fa-comments-o:before{content:"\f0e6"}.fa-flash:before,.fa-bolt:before{content:"\f0e7"}.fa-sitemap:before{content:"\f0e8"}.fa-umbrella:before{content:"\f0e9"}.fa-paste:before,.fa-clipboard:before{content:"\f0ea"}.fa-lightbulb-o:before{content:"\f0eb"}.fa-exchange:before{content:"\f0ec"}.fa-cloud-download:before{content:"\f0ed"}.fa-cloud-upload:before{content:"\f0ee"}.fa-user-md:before{content:"\f0f0"}.fa-stethoscope:before{content:"\f0f1"}.fa-suitcase:before{content:"\f0f2"}.fa-bell-o:before{content:"\f0a2"}.fa-coffee:before{content:"\f0f4"}.fa-cutlery:before{content:"\f0f5"}.fa-file-text-o:before{content:"\f0f6"}.fa-building-o:before{content:"\f0f7"}.fa-hospital-o:before{content:"\f0f8"}.fa-ambulance:before{content:"\f0f9"}.fa-medkit:before{content:"\f0fa"}.fa-fighter-jet:before{content:"\f0fb"}.fa-beer:before{content:"\f0fc"}.fa-h-square:before{content:"\f0fd"}.fa-plus-square:before{content:"\f0fe"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angle-down:before{content:"\f107"}.fa-desktop:before{content:"\f108"}.fa-laptop:before{content:"\f109"}.fa-tablet:before{content:"\f10a"}.fa-mobile-phone:before,.fa-mobile:before{content:"\f10b"}.fa-circle-o:before{content:"\f10c"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-spinner:before{content:"\f110"}.fa-circle:before{content:"\f111"}.fa-mail-reply:before,.fa-reply:before{content:"\f112"}.fa-github-alt:before{content:"\f113"}.fa-folder-o:before{content:"\f114"}.fa-folder-open-o:before{content:"\f115"}.fa-smile-o:before{content:"\f118"}.fa-frown-o:before{content:"\f119"}.fa-meh-o:before{content:"\f11a"}.fa-gamepad:before{content:"\f11b"}.fa-keyboard-o:before{content:"\f11c"}.fa-flag-o:before{content:"\f11d"}.fa-flag-checkered:before{content:"\f11e"}.fa-terminal:before{content:"\f120"}.fa-code:before{content:"\f121"}.fa-mail-reply-all:before,.fa-reply-all:before{content:"\f122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\f123"}.fa-location-arrow:before{content:"\f124"}.fa-crop:before{content:"\f125"}.fa-code-fork:before{content:"\f126"}.fa-unlink:before,.fa-chain-broken:before{content:"\f127"}.fa-question:before{content:"\f128"}.fa-info:before{content:"\f129"}.fa-exclamation:before{content:"\f12a"}.fa-superscript:before{content:"\f12b"}.fa-subscript:before{content:"\f12c"}.fa-eraser:before{content:"\f12d"}.fa-puzzle-piece:before{content:"\f12e"}.fa-microphone:before{content:"\f130"}.fa-microphone-slash:before{content:"\f131"}.fa-shield:before{content:"\f132"}.fa-calendar-o:before{content:"\f133"}.fa-fire-extinguisher:before{content:"\f134"}.fa-rocket:before{content:"\f135"}.fa-maxcdn:before{content:"\f136"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-html5:before{content:"\f13b"}.fa-css3:before{content:"\f13c"}.fa-anchor:before{content:"\f13d"}.fa-unlock-alt:before{content:"\f13e"}.fa-bullseye:before{content:"\f140"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-rss-square:before{content:"\f143"}.fa-play-circle:before{content:"\f144"}.fa-ticket:before{content:"\f145"}.fa-minus-square:before{content:"\f146"}.fa-minus-square-o:before{content:"\f147"}.fa-level-up:before{content:"\f148"}.fa-level-down:before{content:"\f149"}.fa-check-square:before{content:"\f14a"}.fa-pencil-square:before{content:"\f14b"}.fa-external-link-square:before{content:"\f14c"}.fa-share-square:before{content:"\f14d"}.fa-compass:before{content:"\f14e"}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:"\f150"}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:"\f151"}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:"\f152"}.fa-euro:before,.fa-eur:before{content:"\f153"}.fa-gbp:before{content:"\f154"}.fa-dollar:before,.fa-usd:before{content:"\f155"}.fa-rupee:before,.fa-inr:before{content:"\f156"}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:"\f157"}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:"\f158"}.fa-won:before,.fa-krw:before{content:"\f159"}.fa-bitcoin:before,.fa-btc:before{content:"\f15a"}.fa-file:before{content:"\f15b"}.fa-file-text:before{content:"\f15c"}.fa-sort-alpha-asc:before{content:"\f15d"}.fa-sort-alpha-desc:before{content:"\f15e"}.fa-sort-amount-asc:before{content:"\f160"}.fa-sort-amount-desc:before{content:"\f161"}.fa-sort-numeric-asc:before{content:"\f162"}.fa-sort-numeric-desc:before{content:"\f163"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbs-down:before{content:"\f165"}.fa-youtube-square:before{content:"\f166"}.fa-youtube:before{content:"\f167"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-youtube-play:before{content:"\f16a"}.fa-dropbox:before{content:"\f16b"}.fa-stack-overflow:before{content:"\f16c"}.fa-instagram:before{content:"\f16d"}.fa-flickr:before{content:"\f16e"}.fa-adn:before{content:"\f170"}.fa-bitbucket:before{content:"\f171"}.fa-bitbucket-square:before{content:"\f172"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-long-arrow-down:before{content:"\f175"}.fa-long-arrow-up:before{content:"\f176"}.fa-long-arrow-left:before{content:"\f177"}.fa-long-arrow-right:before{content:"\f178"}.fa-apple:before{content:"\f179"}.fa-windows:before{content:"\f17a"}.fa-android:before{content:"\f17b"}.fa-linux:before{content:"\f17c"}.fa-dribbble:before{content:"\f17d"}.fa-skype:before{content:"\f17e"}.fa-foursquare:before{content:"\f180"}.fa-trello:before{content:"\f181"}.fa-female:before{content:"\f182"}.fa-male:before{content:"\f183"}.fa-gittip:before,.fa-gratipay:before{content:"\f184"}.fa-sun-o:before{content:"\f185"}.fa-moon-o:before{content:"\f186"}.fa-archive:before{content:"\f187"}.fa-bug:before{content:"\f188"}.fa-vk:before{content:"\f189"}.fa-weibo:before{content:"\f18a"}.fa-renren:before{content:"\f18b"}.fa-pagelines:before{content:"\f18c"}.fa-stack-exchange:before{content:"\f18d"}.fa-arrow-circle-o-right:before{content:"\f18e"}.fa-arrow-circle-o-left:before{content:"\f190"}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:"\f191"}.fa-dot-circle-o:before{content:"\f192"}.fa-wheelchair:before{content:"\f193"}.fa-vimeo-square:before{content:"\f194"}.fa-turkish-lira:before,.fa-try:before{content:"\f195"}.fa-plus-square-o:before{content:"\f196"}.fa-space-shuttle:before{content:"\f197"}.fa-slack:before{content:"\f198"}.fa-envelope-square:before{content:"\f199"}.fa-wordpress:before{content:"\f19a"}.fa-openid:before{content:"\f19b"}.fa-institution:before,.fa-bank:before,.fa-university:before{content:"\f19c"}.fa-mortar-board:before,.fa-graduation-cap:before{content:"\f19d"}.fa-yahoo:before{content:"\f19e"}.fa-google:before{content:"\f1a0"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-square:before{content:"\f1a2"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-stumbleupon:before{content:"\f1a4"}.fa-delicious:before{content:"\f1a5"}.fa-digg:before{content:"\f1a6"}.fa-pied-piper-pp:before{content:"\f1a7"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-drupal:before{content:"\f1a9"}.fa-joomla:before{content:"\f1aa"}.fa-language:before{content:"\f1ab"}.fa-fax:before{content:"\f1ac"}.fa-building:before{content:"\f1ad"}.fa-child:before{content:"\f1ae"}.fa-paw:before{content:"\f1b0"}.fa-spoon:before{content:"\f1b1"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-recycle:before{content:"\f1b8"}.fa-automobile:before,.fa-car:before{content:"\f1b9"}.fa-cab:before,.fa-taxi:before{content:"\f1ba"}.fa-tree:before{content:"\f1bb"}.fa-spotify:before{content:"\f1bc"}.fa-deviantart:before{content:"\f1bd"}.fa-soundcloud:before{content:"\f1be"}.fa-database:before{content:"\f1c0"}.fa-file-pdf-o:before{content:"\f1c1"}.fa-file-word-o:before{content:"\f1c2"}.fa-file-excel-o:before{content:"\f1c3"}.fa-file-powerpoint-o:before{content:"\f1c4"}.fa-file-photo-o:before,.fa-file-picture-o:before,.fa-file-image-o:before{content:"\f1c5"}.fa-file-zip-o:before,.fa-file-archive-o:before{content:"\f1c6"}.fa-file-sound-o:before,.fa-file-audio-o:before{content:"\f1c7"}.fa-file-movie-o:before,.fa-file-video-o:before{content:"\f1c8"}.fa-file-code-o:before{content:"\f1c9"}.fa-vine:before{content:"\f1ca"}.fa-codepen:before{content:"\f1cb"}.fa-jsfiddle:before{content:"\f1cc"}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-saver:before,.fa-support:before,.fa-life-ring:before{content:"\f1cd"}.fa-circle-o-notch:before{content:"\f1ce"}.fa-ra:before,.fa-resistance:before,.fa-rebel:before{content:"\f1d0"}.fa-ge:before,.fa-empire:before{content:"\f1d1"}.fa-git-square:before{content:"\f1d2"}.fa-git:before{content:"\f1d3"}.fa-y-combinator-square:before,.fa-yc-square:before,.fa-hacker-news:before{content:"\f1d4"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-qq:before{content:"\f1d6"}.fa-wechat:before,.fa-weixin:before{content:"\f1d7"}.fa-send:before,.fa-paper-plane:before{content:"\f1d8"}.fa-send-o:before,.fa-paper-plane-o:before{content:"\f1d9"}.fa-history:before{content:"\f1da"}.fa-circle-thin:before{content:"\f1db"}.fa-header:before{content:"\f1dc"}.fa-paragraph:before{content:"\f1dd"}.fa-sliders:before{content:"\f1de"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-bomb:before{content:"\f1e2"}.fa-soccer-ball-o:before,.fa-futbol-o:before{content:"\f1e3"}.fa-tty:before{content:"\f1e4"}.fa-binoculars:before{content:"\f1e5"}.fa-plug:before{content:"\f1e6"}.fa-slideshare:before{content:"\f1e7"}.fa-twitch:before{content:"\f1e8"}.fa-yelp:before{content:"\f1e9"}.fa-newspaper-o:before{content:"\f1ea"}.fa-wifi:before{content:"\f1eb"}.fa-calculator:before{content:"\f1ec"}.fa-paypal:before{content:"\f1ed"}.fa-google-wallet:before{content:"\f1ee"}.fa-cc-visa:before{content:"\f1f0"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-cc-discover:before{content:"\f1f2"}.fa-cc-amex:before{content:"\f1f3"}.fa-cc-paypal:before{content:"\f1f4"}.fa-cc-stripe:before{content:"\f1f5"}.fa-bell-slash:before{content:"\f1f6"}.fa-bell-slash-o:before{content:"\f1f7"}.fa-trash:before{content:"\f1f8"}.fa-copyright:before{content:"\f1f9"}.fa-at:before{content:"\f1fa"}.fa-eyedropper:before{content:"\f1fb"}.fa-paint-brush:before{content:"\f1fc"}.fa-birthday-cake:before{content:"\f1fd"}.fa-area-chart:before{content:"\f1fe"}.fa-pie-chart:before{content:"\f200"}.fa-line-chart:before{content:"\f201"}.fa-lastfm:before{content:"\f202"}.fa-lastfm-square:before{content:"\f203"}.fa-toggle-off:before{content:"\f204"}.fa-toggle-on:before{content:"\f205"}.fa-bicycle:before{content:"\f206"}.fa-bus:before{content:"\f207"}.fa-ioxhost:before{content:"\f208"}.fa-angellist:before{content:"\f209"}.fa-cc:before{content:"\f20a"}.fa-shekel:before,.fa-sheqel:before,.fa-ils:before{content:"\f20b"}.fa-meanpath:before{content:"\f20c"}.fa-buysellads:before{content:"\f20d"}.fa-connectdevelop:before{content:"\f20e"}.fa-dashcube:before{content:"\f210"}.fa-forumbee:before{content:"\f211"}.fa-leanpub:before{content:"\f212"}.fa-sellsy:before{content:"\f213"}.fa-shirtsinbulk:before{content:"\f214"}.fa-simplybuilt:before{content:"\f215"}.fa-skyatlas:before{content:"\f216"}.fa-cart-plus:before{content:"\f217"}.fa-cart-arrow-down:before{content:"\f218"}.fa-diamond:before{content:"\f219"}.fa-ship:before{content:"\f21a"}.fa-user-secret:before{content:"\f21b"}.fa-motorcycle:before{content:"\f21c"}.fa-street-view:before{content:"\f21d"}.fa-heartbeat:before{content:"\f21e"}.fa-venus:before{content:"\f221"}.fa-mars:before{content:"\f222"}.fa-mercury:before{content:"\f223"}.fa-intersex:before,.fa-transgender:before{content:"\f224"}.fa-transgender-alt:before{content:"\f225"}.fa-venus-double:before{content:"\f226"}.fa-mars-double:before{content:"\f227"}.fa-venus-mars:before{content:"\f228"}.fa-mars-stroke:before{content:"\f229"}.fa-mars-stroke-v:before{content:"\f22a"}.fa-mars-stroke-h:before{content:"\f22b"}.fa-neuter:before{content:"\f22c"}.fa-genderless:before{content:"\f22d"}.fa-facebook-official:before{content:"\f230"}.fa-pinterest-p:before{content:"\f231"}.fa-whatsapp:before{content:"\f232"}.fa-server:before{content:"\f233"}.fa-user-plus:before{content:"\f234"}.fa-user-times:before{content:"\f235"}.fa-hotel:before,.fa-bed:before{content:"\f236"}.fa-viacoin:before{content:"\f237"}.fa-train:before{content:"\f238"}.fa-subway:before{content:"\f239"}.fa-medium:before{content:"\f23a"}.fa-yc:before,.fa-y-combinator:before{content:"\f23b"}.fa-optin-monster:before{content:"\f23c"}.fa-opencart:before{content:"\f23d"}.fa-expeditedssl:before{content:"\f23e"}.fa-battery-4:before,.fa-battery:before,.fa-battery-full:before{content:"\f240"}.fa-battery-3:before,.fa-battery-three-quarters:before{content:"\f241"}.fa-battery-2:before,.fa-battery-half:before{content:"\f242"}.fa-battery-1:before,.fa-battery-quarter:before{content:"\f243"}.fa-battery-0:before,.fa-battery-empty:before{content:"\f244"}.fa-mouse-pointer:before{content:"\f245"}.fa-i-cursor:before{content:"\f246"}.fa-object-group:before{content:"\f247"}.fa-object-ungroup:before{content:"\f248"}.fa-sticky-note:before{content:"\f249"}.fa-sticky-note-o:before{content:"\f24a"}.fa-cc-jcb:before{content:"\f24b"}.fa-cc-diners-club:before{content:"\f24c"}.fa-clone:before{content:"\f24d"}.fa-balance-scale:before{content:"\f24e"}.fa-hourglass-o:before{content:"\f250"}.fa-hourglass-1:before,.fa-hourglass-start:before{content:"\f251"}.fa-hourglass-2:before,.fa-hourglass-half:before{content:"\f252"}.fa-hourglass-3:before,.fa-hourglass-end:before{content:"\f253"}.fa-hourglass:before{content:"\f254"}.fa-hand-grab-o:before,.fa-hand-rock-o:before{content:"\f255"}.fa-hand-stop-o:before,.fa-hand-paper-o:before{content:"\f256"}.fa-hand-scissors-o:before{content:"\f257"}.fa-hand-lizard-o:before{content:"\f258"}.fa-hand-spock-o:before{content:"\f259"}.fa-hand-pointer-o:before{content:"\f25a"}.fa-hand-peace-o:before{content:"\f25b"}.fa-trademark:before{content:"\f25c"}.fa-registered:before{content:"\f25d"}.fa-creative-commons:before{content:"\f25e"}.fa-gg:before{content:"\f260"}.fa-gg-circle:before{content:"\f261"}.fa-tripadvisor:before{content:"\f262"}.fa-odnoklassniki:before{content:"\f263"}.fa-odnoklassniki-square:before{content:"\f264"}.fa-get-pocket:before{content:"\f265"}.fa-wikipedia-w:before{content:"\f266"}.fa-safari:before{content:"\f267"}.fa-chrome:before{content:"\f268"}.fa-firefox:before{content:"\f269"}.fa-opera:before{content:"\f26a"}.fa-internet-explorer:before{content:"\f26b"}.fa-tv:before,.fa-television:before{content:"\f26c"}.fa-contao:before{content:"\f26d"}.fa-500px:before{content:"\f26e"}.fa-amazon:before{content:"\f270"}.fa-calendar-plus-o:before{content:"\f271"}.fa-calendar-minus-o:before{content:"\f272"}.fa-calendar-times-o:before{content:"\f273"}.fa-calendar-check-o:before{content:"\f274"}.fa-industry:before{content:"\f275"}.fa-map-pin:before{content:"\f276"}.fa-map-signs:before{content:"\f277"}.fa-map-o:before{content:"\f278"}.fa-map:before{content:"\f279"}.fa-commenting:before{content:"\f27a"}.fa-commenting-o:before{content:"\f27b"}.fa-houzz:before{content:"\f27c"}.fa-vimeo:before{content:"\f27d"}.fa-black-tie:before{content:"\f27e"}.fa-fonticons:before{content:"\f280"}.fa-reddit-alien:before{content:"\f281"}.fa-edge:before{content:"\f282"}.fa-credit-card-alt:before{content:"\f283"}.fa-codiepie:before{content:"\f284"}.fa-modx:before{content:"\f285"}.fa-fort-awesome:before{content:"\f286"}.fa-usb:before{content:"\f287"}.fa-product-hunt:before{content:"\f288"}.fa-mixcloud:before{content:"\f289"}.fa-scribd:before{content:"\f28a"}.fa-pause-circle:before{content:"\f28b"}.fa-pause-circle-o:before{content:"\f28c"}.fa-stop-circle:before{content:"\f28d"}.fa-stop-circle-o:before{content:"\f28e"}.fa-shopping-bag:before{content:"\f290"}.fa-shopping-basket:before{content:"\f291"}.fa-hashtag:before{content:"\f292"}.fa-bluetooth:before{content:"\f293"}.fa-bluetooth-b:before{content:"\f294"}.fa-percent:before{content:"\f295"}.fa-gitlab:before{content:"\f296"}.fa-wpbeginner:before{content:"\f297"}.fa-wpforms:before{content:"\f298"}.fa-envira:before{content:"\f299"}.fa-universal-access:before{content:"\f29a"}.fa-wheelchair-alt:before{content:"\f29b"}.fa-question-circle-o:before{content:"\f29c"}.fa-blind:before{content:"\f29d"}.fa-audio-description:before{content:"\f29e"}.fa-volume-control-phone:before{content:"\f2a0"}.fa-braille:before{content:"\f2a1"}.fa-assistive-listening-systems:before{content:"\f2a2"}.fa-asl-interpreting:before,.fa-american-sign-language-interpreting:before{content:"\f2a3"}.fa-deafness:before,.fa-hard-of-hearing:before,.fa-deaf:before{content:"\f2a4"}.fa-glide:before{content:"\f2a5"}.fa-glide-g:before{content:"\f2a6"}.fa-signing:before,.fa-sign-language:before{content:"\f2a7"}.fa-low-vision:before{content:"\f2a8"}.fa-viadeo:before{content:"\f2a9"}.fa-viadeo-square:before{content:"\f2aa"}.fa-snapchat:before{content:"\f2ab"}.fa-snapchat-ghost:before{content:"\f2ac"}.fa-snapchat-square:before{content:"\f2ad"}.fa-pied-piper:before{content:"\f2ae"}.fa-first-order:before{content:"\f2b0"}.fa-yoast:before{content:"\f2b1"}.fa-themeisle:before{content:"\f2b2"}.fa-google-plus-circle:before,.fa-google-plus-official:before{content:"\f2b3"}.fa-fa:before,.fa-font-awesome:before{content:"\f2b4"}.fa-handshake-o:before{content:"\f2b5"}.fa-envelope-open:before{content:"\f2b6"}.fa-envelope-open-o:before{content:"\f2b7"}.fa-linode:before{content:"\f2b8"}.fa-address-book:before{content:"\f2b9"}.fa-address-book-o:before{content:"\f2ba"}.fa-vcard:before,.fa-address-card:before{content:"\f2bb"}.fa-vcard-o:before,.fa-address-card-o:before{content:"\f2bc"}.fa-user-circle:before{content:"\f2bd"}.fa-user-circle-o:before{content:"\f2be"}.fa-user-o:before{content:"\f2c0"}.fa-id-badge:before{content:"\f2c1"}.fa-drivers-license:before,.fa-id-card:before{content:"\f2c2"}.fa-drivers-license-o:before,.fa-id-card-o:before{content:"\f2c3"}.fa-quora:before{content:"\f2c4"}.fa-free-code-camp:before{content:"\f2c5"}.fa-telegram:before{content:"\f2c6"}.fa-thermometer-4:before,.fa-thermometer:before,.fa-thermometer-full:before{content:"\f2c7"}.fa-thermometer-3:before,.fa-thermometer-three-quarters:before{content:"\f2c8"}.fa-thermometer-2:before,.fa-thermometer-half:before{content:"\f2c9"}.fa-thermometer-1:before,.fa-thermometer-quarter:before{content:"\f2ca"}.fa-thermometer-0:before,.fa-thermometer-empty:before{content:"\f2cb"}.fa-shower:before{content:"\f2cc"}.fa-bathtub:before,.fa-s15:before,.fa-bath:before{content:"\f2cd"}.fa-podcast:before{content:"\f2ce"}.fa-window-maximize:before{content:"\f2d0"}.fa-window-minimize:before{content:"\f2d1"}.fa-window-restore:before{content:"\f2d2"}.fa-times-rectangle:before,.fa-window-close:before{content:"\f2d3"}.fa-times-rectangle-o:before,.fa-window-close-o:before{content:"\f2d4"}.fa-bandcamp:before{content:"\f2d5"}.fa-grav:before{content:"\f2d6"}.fa-etsy:before{content:"\f2d7"}.fa-imdb:before{content:"\f2d8"}.fa-ravelry:before{content:"\f2d9"}.fa-eercast:before{content:"\f2da"}.fa-microchip:before{content:"\f2db"}.fa-snowflake-o:before{content:"\f2dc"}.fa-superpowers:before{content:"\f2dd"}.fa-wpexplorer:before{content:"\f2de"}.fa-meetup:before{content:"\f2e0"}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto} diff --git a/resources/assets/css/signature-pad.css b/resources/assets/css/signature-pad.css new file mode 100755 index 0000000000..218b9c2365 --- /dev/null +++ b/resources/assets/css/signature-pad.css @@ -0,0 +1,135 @@ + +#signature-pad { + padding-top: 250px; + margin: auto; +} +.m-signature-pad { + + position: relative; + font-size: 10px; + width: 100%; + height: 300px; + border: 1px solid #e8e8e8; + background-color: #fff; + box-shadow: 0 1px 4px rgba(0, 0, 0, 0.27), 0 0 40px rgba(0, 0, 0, 0.08) inset; + border-radius: 4px; +} + +.m-signature-pad:before, .m-signature-pad:after { + position: absolute; + z-index: -1; + content: ""; + width: 40%; + height: 10px; + left: 20px; + bottom: 10px; + background: transparent; + -webkit-transform: skew(-3deg) rotate(-3deg); + -moz-transform: skew(-3deg) rotate(-3deg); + -ms-transform: skew(-3deg) rotate(-3deg); + -o-transform: skew(-3deg) rotate(-3deg); + transform: skew(-3deg) rotate(-3deg); + box-shadow: 0 8px 12px rgba(0, 0, 0, 0.4); +} + +.m-signature-pad:after { + left: auto; + right: 20px; + -webkit-transform: skew(3deg) rotate(3deg); + -moz-transform: skew(3deg) rotate(3deg); + -ms-transform: skew(3deg) rotate(3deg); + -o-transform: skew(3deg) rotate(3deg); + transform: skew(3deg) rotate(3deg); +} + +.m-signature-pad--body { + position: absolute; + top: 20px; + bottom: 60px; + border: 1px solid #f4f4f4; + background-color: white; +} + +.m-signature-pad--body + canvas { + position: absolute; + left: 0; + top: 0; + width: 100%; + height: 100%; + border-radius: 4px; + box-shadow: 0 0 5px rgba(0, 0, 0, 0.02) inset; + } + +.m-signature-pad--footer { + position: absolute; + left: 20px; + right: 20px; + bottom: 20px; + height: 40px; +} + +.m-signature-pad--footer + .description { + color: #C3C3C3; + text-align: center; + font-size: 1.2em; + margin-top: 1.8em; + } + +.m-signature-pad--footer + .button { + position: absolute; + bottom: 0; + } + +.m-signature-pad--footer + .button.clear { + left: 0; + } + +.m-signature-pad--footer + .button.save { + right: 0; + } + +@media screen and (max-width: 1024px) { + .m-signature-pad { + top: 0; + left: 0; + right: 0; + bottom: 0; + width: auto; + height: auto; + min-width: 250px; + min-height: 140px; + margin: 5%; + } + +} + +@media screen and (min-device-width: 768px) and (max-device-width: 1024px) { + .m-signature-pad { + margin: 10%; + } +} + +@media screen and (max-height: 320px) { + .m-signature-pad--body { + left: 0; + right: 0; + top: 0; + bottom: 32px; + } + .m-signature-pad--footer { + left: 20px; + right: 20px; + bottom: 4px; + height: 28px; + } + .m-signature-pad--footer + .description { + font-size: 1em; + margin-top: 1em; + } +} diff --git a/public/assets/css/themes/dark-green.css b/resources/assets/css/skins/skin-green-dark.css similarity index 70% rename from public/assets/css/themes/dark-green.css rename to resources/assets/css/skins/skin-green-dark.css index caf5cc7610..0282e78e43 100644 --- a/public/assets/css/themes/dark-green.css +++ b/resources/assets/css/skins/skin-green-dark.css @@ -19,6 +19,9 @@ a, a:link, a:visited, .btn-primary.hover { #assetsListingTable>tbody>tr.selected>td { background-color: var(--back-main); } +body { + color: var(--text-main); +} .box, .box.box-default { border-top: 3px solid var(--header); border-top-color: var(--header); @@ -31,13 +34,17 @@ a, a:link, a:visited, .btn-primary.hover { background-color: var(--back-main); color: var(--header); } -.btn-default:active, .btn-default:focus, .btn-default:hover { +.btn-default:active, .btn-default:focus, .btn-default:hover, .btn-default.active { background-color: var(--back-sub); color: var(--header); } -.btn-primary, .btn-primary.hover, .btn-primary:active, .btn-primary:hover, .text-blue { +.btn-primary, .btn-primary.hover, .btn-primary:active, .text-blue { color: var(--text-main)!important; } +.btn-primary:hover { + background-color: var(--back-main); + color: var(--header)!important; +} #componentsTable>tbody>tr>td>nobr>a>i.fa { color: var(--text-main); } @@ -47,14 +54,17 @@ a, a:link, a:visited, .btn-primary.hover { .content-wrapper { background-color: var(--background); } -#create-form>div>div>div>span.input-group-addon { - background-color: var(--back-sub); - color: var(--text-main); -} #create-form>div>div>div>span>i.fa { background-color: var(--back-sub); color: var(--header); } +.datepicker .datepicker-switch:hover, .datepicker .next:hover, .datepicker .prev:hover, .datepicker tfoot tr th:hover, .datepicker table tr td.day.focused, .datepicker table tr td.day:hover { + background-color: var(--header); +} +.datepicker.dropdown-menu { + background-color: var(--back-main); + color: var(--text-main); +} #details>div>div>div>table { background-color: transparent; } @@ -70,7 +80,7 @@ a, a:link, a:visited, .btn-primary.hover { background-color: var(--back-main); color: var(--text-main); } -h1 { +h1, h2, h3, h4, h5, h6, p { color: var(--text-main); } .help-block { @@ -80,6 +90,10 @@ input[type=text], input[type=search] { background-color: var(--back-sub); color: var(--text-main); } +.input-group, .input-group-addon { + background-color: var(--back-sub)!important; + color: var(--text-main); +} #licensesTable>tbody>tr>td>nobr>a>i.fa { color: var(--text-main); } @@ -87,6 +101,16 @@ input[type=text], input[type=search] { background-color: var(--back-main); color: var(--text-main); } +.main-header .navbar, .main-header .logo { + background-color: var(--header); + background: -webkit-linear-gradient(top, var(--header) 0%,var(--header) 100%); + background: linear-gradient(to bottom, var(--header) 0%,var(--header) 100%); + border-color: var(--header); +} +.modal-content { + background-color: var(--back-main); + color: var(--text-main); +} .nav-tabs-custom>.nav-tabs>li>a, .nav-tabs-custom>.nav-tabs>li.active>a { color: var(--text-main); } @@ -119,13 +143,21 @@ input[type=text], input[type=search] { background-color: var(--back-main); color: var(--header); } -.select2-selection--single { - background-color: var(--back-sub)!important; - color: var(--text-main)!important; +.select2-container--default .select2-results__option[aria-selected=true], .select2-container--default .select2-results__option[aria-selected=true]:hover { + background-color: var(--back-sub); + color: var(--header); +} +.select2-container--default .select2-results__option--highlighted[aria-selected] { + background-color: var(--header); + color: var(--back-main); } .select2-container--default .select2-selection--single .select2-selection__rendered { color: var(--text-main); } +.select2-selection--single { + background-color: var(--back-sub)!important; + color: var(--text-main)!important; +} .select2-dropdown { background-color: var(--back-main); color: var(--text-main); @@ -143,3 +175,6 @@ input[type=text], input[type=search] { .table-striped>tbody>tr:nth-of-type(odd) { background-color: var(--back-sub); } +#webui>div>div>div>div>div>table>tbody>tr>td>a>i.fa { + color: var(--text-main); +} diff --git a/resources/assets/css/skins/skin-orange-dark.css b/resources/assets/css/skins/skin-orange-dark.css new file mode 100644 index 0000000000..270ff19581 --- /dev/null +++ b/resources/assets/css/skins/skin-orange-dark.css @@ -0,0 +1,181 @@ +:root { + --background: #222; + --back-main: #333; + --back-sub: #444; + --header: #FF8C00; /* Use same as Header picker */ + --text-main: #FFF; + --text-sub: #BBB; +} + +.main-header .navbar, .main-header .logo { + background-color: var(--header); + background: -webkit-linear-gradient(top, var(--header) 0%,var(--header) 100%); + background: linear-gradient(to bottom, var(--header) 0%,var(--header) 100%); + border-color: var(--header); +} +.modal-content { + background-color: var(--back-main); + color: var(--text-main); +} + +a, a:link, a:visited, .btn-primary.hover { + color: var(--header); +} +#accessoriesTable>tbody>tr>td>nobr>a>i.fa { + color: var(--text-main); +} +#assetsListingTable>tbody>tr>td>nobr>a>i.fa { + color: var(--text-main); +} +#assetsListingTable>tbody>tr.selected>td { + background-color: var(--back-main); +} +body { + color: var(--text-main); +} +.box, .box.box-default { + border-top: 3px solid var(--header); + border-top-color: var(--header); +} +.box-body, .box-footer, .box-header { + background-color: var(--back-sub); + color: var(--text-main); +} +.btn-default{ + background-color: var(--back-main); + color: var(--header); +} +.btn-default:active, .btn-default:focus, .btn-default:hover, .btn-default.active { + background-color: var(--back-sub); + color: var(--header); +} +.btn-primary, .btn-primary.hover, .btn-primary:active, .text-blue { + color: var(--text-main)!important; +} +.btn-primary:hover { + background-color: var(--back-main); + color: var(--header)!important; +} +#componentsTable>tbody>tr>td>nobr>a>i.fa { + color: var(--text-main); +} +#consumablesTable>tbody>tr>td>nobr>a>i.fa { + color: var(--text-main); +} +.content-wrapper { + background-color: var(--background); +} +#create-form>div>div>div>span>i.fa { + background-color: var(--back-sub); + color: var(--header); +} +.datepicker .datepicker-switch:hover, .datepicker .next:hover, .datepicker .prev:hover, .datepicker tfoot tr th:hover, .datepicker table tr td.day.focused, .datepicker table tr td.day:hover { + background-color: var(--header); +} +.datepicker.dropdown-menu { + background-color: var(--back-main); + color: var(--text-main); +} +#details>div>div>div>table { + background-color: transparent; +} +.dropdown-menu, .dropdown-menu>li>a { + background-color: var(--back-sub); + color: var(--header); +} +.dropdown-menu>li>a:hover { + background-color: var(--back-main); + color: var(--text-main); +} +.form-control { + background-color: var(--back-main); + color: var(--text-main); +} +h1, h2, h3, h4, h5, h6, p { + color: var(--text-main); +} +.help-block { + color: var(--text-sub); +} +input[type=text], input[type=search] { + background-color: var(--back-sub); + color: var(--text-main); +} +.input-group, .input-group-addon { + background-color: var(--back-sub)!important; + color: var(--text-main); +} +#licensesTable>tbody>tr>td>nobr>a>i.fa { + color: var(--text-main); +} +.main-footer { + background-color: var(--back-main); + color: var(--text-main); +} +.nav-tabs-custom>.nav-tabs>li>a, .nav-tabs-custom>.nav-tabs>li.active>a { + color: var(--text-main); +} +.nav-tabs-custom>.nav-tabs>li.active { + border-top-color: var(--header); +} +.nav-tabs-custom>.nav-tabs>li.active>a { + background-color: var(--back-main); +} +.nav-tabs-custom>.nav-tabs>li.active>a:hover { + background-color: var(--back-sub); + color: var(--text-main); +} +.nav-tabs-custom, .nav-tabs-custom>.tab-content { + background-color: var(--back-main); +} +.navbar-nav>.tasks-menu>.dropdown-menu>li.header { + background-color: var(--back-main); + color: var(--header); +} +.open>.dropdown-toggle.btn-default { + background-color: var(--back-sub); + color: var(--header); +} +.panel { + background-color: var(--back-sub); + color: var(--text-main); +} +.panel-default>.panel-heading { + background-color: var(--back-main); + color: var(--header); +} +.select2-container--default .select2-results__option[aria-selected=true], .select2-container--default .select2-results__option[aria-selected=true]:hover { + background-color: var(--back-sub); + color: var(--header); +} +.select2-container--default .select2-results__option--highlighted[aria-selected] { + background-color: var(--header); + color: var(--back-main); +} +.select2-container--default .select2-selection--single .select2-selection__rendered { + color: var(--text-main); +} +.select2-selection--single { + background-color: var(--back-sub)!important; + color: var(--text-main)!important; +} +.select2-dropdown { + background-color: var(--back-main); + color: var(--text-main); +} +.skin-blue .main-header .navbar .dropdown-menu li a { + color: var(--header); +} +.skin-blue .sidebar-menu>li.active>a, .skin-blue .sidebar-menu>li:hover>a, .sidebar-toggle:hover { + background-color: var(--header)!important; +} +.tab-content, .tab-pane { + background-color: var(--back-main); + color: var(--text-main); +} +.table-striped>tbody>tr:nth-of-type(odd) { + background-color: var(--back-sub); +} +#webui>div>div>div>div>div>table>tbody>tr>td>a>i.fa { + color: var(--text-main); +} diff --git a/resources/assets/css/skins/skin-red-dark.css b/resources/assets/css/skins/skin-red-dark.css new file mode 100644 index 0000000000..bb4d67f167 --- /dev/null +++ b/resources/assets/css/skins/skin-red-dark.css @@ -0,0 +1,182 @@ +:root { + --background: #222; + --back-main: #333; + --back-sub: #444; + --header: #ad0c0c; /* Use same as Header picker */ + --text-main: #FFF; + --text-sub: #BBB; +} + +.main-header .navbar, .main-header .logo { + background-color: var(--header); + background: -webkit-linear-gradient(top, var(--header) 0%,var(--header) 100%); + background: linear-gradient(to bottom, var(--header) 0%,var(--header) 100%); + border-color: var(--header); +} + +.modal-content { + background-color: var(--back-main); + color: var(--text-main); +} + +a, a:link, a:visited, .btn-primary.hover { + color: var(--header); +} +#accessoriesTable>tbody>tr>td>nobr>a>i.fa { + color: var(--text-main); +} +#assetsListingTable>tbody>tr>td>nobr>a>i.fa { + color: var(--text-main); +} +#assetsListingTable>tbody>tr.selected>td { + background-color: var(--back-main); +} +body { + color: var(--text-main); +} +.box, .box.box-default { + border-top: 3px solid var(--header); + border-top-color: var(--header); +} +.box-body, .box-footer, .box-header { + background-color: var(--back-sub); + color: var(--text-main); +} +.btn-default{ + background-color: var(--back-main); + color: var(--header); +} +.btn-default:active, .btn-default:focus, .btn-default:hover, .btn-default.active { + background-color: var(--back-sub); + color: var(--header); +} +.btn-primary, .btn-primary.hover, .btn-primary:active, .text-blue { + color: var(--text-main)!important; +} +.btn-primary:hover { + background-color: var(--back-main); + color: var(--header)!important; +} +#componentsTable>tbody>tr>td>nobr>a>i.fa { + color: var(--text-main); +} +#consumablesTable>tbody>tr>td>nobr>a>i.fa { + color: var(--text-main); +} +.content-wrapper { + background-color: var(--background); +} +#create-form>div>div>div>span>i.fa { + background-color: var(--back-sub); + color: var(--header); +} +.datepicker .datepicker-switch:hover, .datepicker .next:hover, .datepicker .prev:hover, .datepicker tfoot tr th:hover, .datepicker table tr td.day.focused, .datepicker table tr td.day:hover { + background-color: var(--header); +} +.datepicker.dropdown-menu { + background-color: var(--back-main); + color: var(--text-main); +} +#details>div>div>div>table { + background-color: transparent; +} +.dropdown-menu, .dropdown-menu>li>a { + background-color: var(--back-sub); + color: var(--header); +} +.dropdown-menu>li>a:hover { + background-color: var(--back-main); + color: var(--text-main); +} +.form-control { + background-color: var(--back-main); + color: var(--text-main); +} +h1, h2, h3, h4, h5, h6, p { + color: var(--text-main); +} +.help-block { + color: var(--text-sub); +} +input[type=text], input[type=search] { + background-color: var(--back-sub); + color: var(--text-main); +} +.input-group, .input-group-addon { + background-color: var(--back-sub)!important; + color: var(--text-main); +} +#licensesTable>tbody>tr>td>nobr>a>i.fa { + color: var(--text-main); +} +.main-footer { + background-color: var(--back-main); + color: var(--text-main); +} +.nav-tabs-custom>.nav-tabs>li>a, .nav-tabs-custom>.nav-tabs>li.active>a { + color: var(--text-main); +} +.nav-tabs-custom>.nav-tabs>li.active { + border-top-color: var(--header); +} +.nav-tabs-custom>.nav-tabs>li.active>a { + background-color: var(--back-main); +} +.nav-tabs-custom>.nav-tabs>li.active>a:hover { + background-color: var(--back-sub); + color: var(--text-main); +} +.nav-tabs-custom, .nav-tabs-custom>.tab-content { + background-color: var(--back-main); +} +.navbar-nav>.tasks-menu>.dropdown-menu>li.header { + background-color: var(--back-main); + color: var(--header); +} +.open>.dropdown-toggle.btn-default { + background-color: var(--back-sub); + color: var(--header); +} +.panel { + background-color: var(--back-sub); + color: var(--text-main); +} +.panel-default>.panel-heading { + background-color: var(--back-main); + color: var(--header); +} +.select2-container--default .select2-results__option[aria-selected=true], .select2-container--default .select2-results__option[aria-selected=true]:hover { + background-color: var(--back-sub); + color: var(--header); +} +.select2-container--default .select2-results__option--highlighted[aria-selected] { + background-color: var(--header); + color: var(--back-main); +} +.select2-container--default .select2-selection--single .select2-selection__rendered { + color: var(--text-main); +} +.select2-selection--single { + background-color: var(--back-sub)!important; + color: var(--text-main)!important; +} +.select2-dropdown { + background-color: var(--back-main); + color: var(--text-main); +} +.skin-blue .main-header .navbar .dropdown-menu li a { + color: var(--header); +} +.skin-blue .sidebar-menu>li.active>a, .skin-blue .sidebar-menu>li:hover>a, .sidebar-toggle:hover { + background-color: var(--header)!important; +} +.tab-content, .tab-pane { + background-color: var(--back-main); + color: var(--text-main); +} +.table-striped>tbody>tr:nth-of-type(odd) { + background-color: var(--back-sub); +} +#webui>div>div>div>div>div>table>tbody>tr>td>a>i.fa { + color: var(--text-main); +} diff --git a/resources/assets/js/app.js b/resources/assets/js/app.js deleted file mode 100755 index 6453fc7347..0000000000 --- a/resources/assets/js/app.js +++ /dev/null @@ -1,695 +0,0 @@ -/*! AdminLTE app.js - * ================ - * Main JS application file for AdminLTE v2. This file - * should be included in all pages. It controls some layout - * options and implements exclusive AdminLTE plugins. - * - * @Author Almsaeed Studio - * @Support - * @Email - * @version 2.3.0 - * @license MIT - */ - -//Make sure jQuery has been loaded before app.js -if (typeof jQuery === "undefined") { - throw new Error("AdminLTE requires jQuery"); -} - - -/* AdminLTE - * - * @type Object - * @description $.AdminLTE is the main object for the template's app. - * It's used for implementing functions and options related - * to the template. Keeping everything wrapped in an object - * prevents conflict with other plugins and is a better - * way to organize our code. - */ -$.AdminLTE = {}; - -/* -------------------- - * - AdminLTE Options - - * -------------------- - * Modify these options to suit your implementation - */ -$.AdminLTE.options = { - //Add slimscroll to navbar menus - //This requires you to load the slimscroll plugin - //in every page before app.js - navbarMenuSlimscroll: true, - navbarMenuSlimscrollWidth: "3px", //The width of the scroll bar - navbarMenuHeight: "200px", //The height of the inner menu - //General animation speed for JS animated elements such as box collapse/expand and - //sidebar treeview slide up/down. This options accepts an integer as milliseconds, - //'fast', 'normal', or 'slow' - animationSpeed: 500, - //Sidebar push menu toggle button selector - sidebarToggleSelector: "[data-toggle='offcanvas']", - //Activate sidebar push menu - sidebarPushMenu: true, - //Activate sidebar slimscroll if the fixed layout is set (requires SlimScroll Plugin) - sidebarSlimScroll: true, - //Enable sidebar expand on hover effect for sidebar mini - //This option is forced to true if both the fixed layout and sidebar mini - //are used together - sidebarExpandOnHover: false, - //BoxRefresh Plugin - enableBoxRefresh: true, - //Bootstrap.js tooltip - enableBSToppltip: true, - BSTooltipSelector: "[data-toggle='tooltip']", - //Enable Fast Click. Fastclick.js creates a more - //native touch experience with touch devices. If you - //choose to enable the plugin, make sure you load the script - //before AdminLTE's app.js - enableFastclick: false, - //Control Sidebar Options - enableControlSidebar: true, - controlSidebarOptions: { - //Which button should trigger the open/close event - toggleBtnSelector: "[data-toggle='control-sidebar']", - //The sidebar selector - selector: ".control-sidebar", - //Enable slide over content - slide: true - }, - //Box Widget Plugin. Enable this plugin - //to allow boxes to be collapsed and/or removed - enableBoxWidget: true, - //Box Widget plugin options - boxWidgetOptions: { - boxWidgetIcons: { - //Collapse icon - collapse: 'fa-minus', - //Open icon - open: 'fa-plus', - //Remove icon - remove: 'fa-times' - }, - boxWidgetSelectors: { - //Remove button selector - remove: '[data-widget="remove"]', - //Collapse button selector - collapse: '[data-widget="collapse"]' - } - }, - //Direct Chat plugin options - directChat: { - //Enable direct chat by default - enable: true, - //The button to open and close the chat contacts pane - contactToggleSelector: '[data-widget="chat-pane-toggle"]' - }, - //Define the set of colors to use globally around the website - colors: { - lightBlue: "#3c8dbc", - red: "#f56954", - green: "#00a65a", - aqua: "#00c0ef", - yellow: "#f39c12", - blue: "#0073b7", - navy: "#001F3F", - teal: "#39CCCC", - olive: "#3D9970", - lime: "#01FF70", - orange: "#FF851B", - fuchsia: "#F012BE", - purple: "#8E24AA", - maroon: "#D81B60", - black: "#222222", - gray: "#d2d6de" - }, - //The standard screen sizes that bootstrap uses. - //If you change these in the variables.less file, change - //them here too. - screenSizes: { - xs: 480, - sm: 768, - md: 992, - lg: 1200 - } -}; - -/* ------------------ - * - Implementation - - * ------------------ - * The next block of code implements AdminLTE's - * functions and plugins as specified by the - * options above. - */ -$(function () { - "use strict"; - - //Fix for IE page transitions - $("body").removeClass("hold-transition"); - - //Extend options if external options exist - if (typeof AdminLTEOptions !== "undefined") { - $.extend(true, - $.AdminLTE.options, - AdminLTEOptions); - } - - //Easy access to options - var o = $.AdminLTE.options; - - //Set up the object - _init(); - - //Activate the layout maker - $.AdminLTE.layout.activate(); - - //Enable sidebar tree view controls - $.AdminLTE.tree('.sidebar'); - - //Enable control sidebar - if (o.enableControlSidebar) { - $.AdminLTE.controlSidebar.activate(); - } - - //Add slimscroll to navbar dropdown - if (o.navbarMenuSlimscroll && typeof $.fn.slimscroll != 'undefined') { - $(".navbar .menu").slimscroll({ - height: o.navbarMenuHeight, - alwaysVisible: false, - size: o.navbarMenuSlimscrollWidth - }).css("width", "100%"); - } - - //Activate sidebar push menu - if (o.sidebarPushMenu) { - $.AdminLTE.pushMenu.activate(o.sidebarToggleSelector); - } - - //Activate Bootstrap tooltip - if (o.enableBSToppltip) { - $.widget.bridge('uitooltip', $.ui.tooltip); - $('body').tooltip({ - selector: o.BSTooltipSelector - }); - - } - - //Activate box widget - if (o.enableBoxWidget) { - $.AdminLTE.boxWidget.activate(); - } - - //Activate fast click - if (o.enableFastclick && typeof FastClick != 'undefined') { - FastClick.attach(document.body); - } - - //Activate direct chat widget - if (o.directChat.enable) { - $(document).on('click', o.directChat.contactToggleSelector, function () { - var box = $(this).parents('.direct-chat').first(); - box.toggleClass('direct-chat-contacts-open'); - }); - } - - /* - * INITIALIZE BUTTON TOGGLE - * ------------------------ - */ - $('.btn-group[data-toggle="btn-toggle"]').each(function () { - var group = $(this); - $(this).find(".btn").on('click', function (e) { - group.find(".btn.active").removeClass("active"); - $(this).addClass("active"); - e.preventDefault(); - }); - - }); -}); - -/* ---------------------------------- - * - Initialize the AdminLTE Object - - * ---------------------------------- - * All AdminLTE functions are implemented below. - */ -function _init() { - 'use strict'; - /* Layout - * ====== - * Fixes the layout height in case min-height fails. - * - * @type Object - * @usage $.AdminLTE.layout.activate() - * $.AdminLTE.layout.fix() - * $.AdminLTE.layout.fixSidebar() - */ - $.AdminLTE.layout = { - activate: function () { - var _this = this; - _this.fix(); - _this.fixSidebar(); - $(window, ".wrapper").resize(function () { - _this.fix(); - _this.fixSidebar(); - }); - }, - fix: function () { - //Get window height and the wrapper height - var neg = $('.main-header').outerHeight() + $('.main-footer').outerHeight(); - var window_height = $(window).height(); - var sidebar_height = $(".sidebar").height(); - //Set the min-height of the content and sidebar based on the - //the height of the document. - if ($("body").hasClass("fixed")) { - $(".content-wrapper, .right-side").css('min-height', window_height - $('.main-footer').outerHeight()); - } else { - var postSetWidth; - if (window_height >= sidebar_height) { - $(".content-wrapper, .right-side").css('min-height', window_height - neg); - postSetWidth = window_height - neg; - } else { - $(".content-wrapper, .right-side").css('min-height', sidebar_height); - postSetWidth = sidebar_height; - } - - //Fix for the control sidebar height - var controlSidebar = $($.AdminLTE.options.controlSidebarOptions.selector); - if (typeof controlSidebar !== "undefined") { - if (controlSidebar.height() > postSetWidth) - $(".content-wrapper, .right-side").css('min-height', controlSidebar.height()); - } - - } - }, - fixSidebar: function () { - //Make sure the body tag has the .fixed class - if (!$("body").hasClass("fixed")) { - if (typeof $.fn.slimScroll != 'undefined') { - $(".sidebar").slimScroll({destroy: true}).height("auto"); - } - return; - } else if (typeof $.fn.slimScroll == 'undefined' && window.console) { - window.console.error("Error: the fixed layout requires the slimscroll plugin!"); - } - //Enable slimscroll for fixed layout - if ($.AdminLTE.options.sidebarSlimScroll) { - if (typeof $.fn.slimScroll != 'undefined') { - //Destroy if it exists - $(".sidebar").slimScroll({destroy: true}).height("auto"); - //Add slimscroll - $(".sidebar").slimscroll({ - height: ($(window).height() - $(".main-header").height()) + "px", - color: "rgba(0,0,0,0.2)", - size: "3px" - }); - } - } - } - }; - - /* PushMenu() - * ========== - * Adds the push menu functionality to the sidebar. - * - * @type Function - * @usage: $.AdminLTE.pushMenu("[data-toggle='offcanvas']") - */ - $.AdminLTE.pushMenu = { - activate: function (toggleBtn) { - //Get the screen sizes - var screenSizes = $.AdminLTE.options.screenSizes; - - //Enable sidebar toggle - $(toggleBtn).on('click', function (e) { - e.preventDefault(); - - //Enable sidebar push menu - if ($(window).width() > (screenSizes.sm - 1)) { - if ($("body").hasClass('sidebar-collapse')) { - $("body").removeClass('sidebar-collapse').trigger('expanded.pushMenu'); - } else { - $("body").addClass('sidebar-collapse').trigger('collapsed.pushMenu'); - } - } - //Handle sidebar push menu for small screens - else { - if ($("body").hasClass('sidebar-open')) { - $("body").removeClass('sidebar-open').removeClass('sidebar-collapse').trigger('collapsed.pushMenu'); - } else { - $("body").addClass('sidebar-open').trigger('expanded.pushMenu'); - } - } - }); - - $(".content-wrapper").click(function () { - //Enable hide menu when clicking on the content-wrapper on small screens - if ($(window).width() <= (screenSizes.sm - 1) && $("body").hasClass("sidebar-open")) { - $("body").removeClass('sidebar-open'); - } - }); - - //Enable expand on hover for sidebar mini - if ($.AdminLTE.options.sidebarExpandOnHover - || ($('body').hasClass('fixed') - && $('body').hasClass('sidebar-mini'))) { - this.expandOnHover(); - } - }, - expandOnHover: function () { - var _this = this; - var screenWidth = $.AdminLTE.options.screenSizes.sm - 1; - //Expand sidebar on hover - $('.main-sidebar').hover(function () { - if ($('body').hasClass('sidebar-mini') - && $("body").hasClass('sidebar-collapse') - && $(window).width() > screenWidth) { - _this.expand(); - } - }, function () { - if ($('body').hasClass('sidebar-mini') - && $('body').hasClass('sidebar-expanded-on-hover') - && $(window).width() > screenWidth) { - _this.collapse(); - } - }); - }, - expand: function () { - $("body").removeClass('sidebar-collapse').addClass('sidebar-expanded-on-hover'); - }, - collapse: function () { - if ($('body').hasClass('sidebar-expanded-on-hover')) { - $('body').removeClass('sidebar-expanded-on-hover').addClass('sidebar-collapse'); - } - } - }; - - /* Tree() - * ====== - * Converts the sidebar into a multilevel - * tree view menu. - * - * @type Function - * @Usage: $.AdminLTE.tree('.sidebar') - */ - $.AdminLTE.tree = function (menu) { - var _this = this; - var animationSpeed = $.AdminLTE.options.animationSpeed; - $(document).on('click', menu + ' li a', function (e) { - //Get the clicked link and the next element - var $this = $(this); - var checkElement = $this.next(); - - //Check if the next element is a menu and is visible - if ((checkElement.is('.treeview-menu')) && (checkElement.is(':visible'))) { - //Close the menu - checkElement.slideUp(animationSpeed, function () { - checkElement.removeClass('menu-open'); - //Fix the layout in case the sidebar stretches over the height of the window - //_this.layout.fix(); - }); - checkElement.parent("li").removeClass("active"); - } - //If the menu is not visible - else if ((checkElement.is('.treeview-menu')) && (!checkElement.is(':visible'))) { - //Get the parent menu - var parent = $this.parents('ul').first(); - //Close all open menus within the parent - var ul = parent.find('ul:visible').slideUp(animationSpeed); - //Remove the menu-open class from the parent - ul.removeClass('menu-open'); - //Get the parent li - var parent_li = $this.parent("li"); - - //Open the target menu and add the menu-open class - checkElement.slideDown(animationSpeed, function () { - //Add the class active to the parent li - checkElement.addClass('menu-open'); - parent.find('li.active').removeClass('active'); - parent_li.addClass('active'); - //Fix the layout in case the sidebar stretches over the height of the window - _this.layout.fix(); - }); - } - //if this isn't a link, prevent the page from being redirected - if (checkElement.is('.treeview-menu')) { - e.preventDefault(); - } - }); - }; - - /* ControlSidebar - * ============== - * Adds functionality to the right sidebar - * - * @type Object - * @usage $.AdminLTE.controlSidebar.activate(options) - */ - $.AdminLTE.controlSidebar = { - //instantiate the object - activate: function () { - //Get the object - var _this = this; - //Update options - var o = $.AdminLTE.options.controlSidebarOptions; - //Get the sidebar - var sidebar = $(o.selector); - //The toggle button - var btn = $(o.toggleBtnSelector); - - //Listen to the click event - btn.on('click', function (e) { - e.preventDefault(); - //If the sidebar is not open - if (!sidebar.hasClass('control-sidebar-open') - && !$('body').hasClass('control-sidebar-open')) { - //Open the sidebar - _this.open(sidebar, o.slide); - } else { - _this.close(sidebar, o.slide); - } - }); - - //If the body has a boxed layout, fix the sidebar bg position - var bg = $(".control-sidebar-bg"); - _this._fix(bg); - - //If the body has a fixed layout, make the control sidebar fixed - if ($('body').hasClass('fixed')) { - _this._fixForFixed(sidebar); - } else { - //If the content height is less than the sidebar's height, force max height - if ($('.content-wrapper, .right-side').height() < sidebar.height()) { - _this._fixForContent(sidebar); - } - } - }, - //Open the control sidebar - open: function (sidebar, slide) { - //Slide over content - if (slide) { - sidebar.addClass('control-sidebar-open'); - } else { - //Push the content by adding the open class to the body instead - //of the sidebar itself - $('body').addClass('control-sidebar-open'); - } - }, - //Close the control sidebar - close: function (sidebar, slide) { - if (slide) { - sidebar.removeClass('control-sidebar-open'); - } else { - $('body').removeClass('control-sidebar-open'); - } - }, - _fix: function (sidebar) { - var _this = this; - if ($("body").hasClass('layout-boxed')) { - sidebar.css('position', 'absolute'); - sidebar.height($(".wrapper").height()); - $(window).resize(function () { - _this._fix(sidebar); - }); - } else { - sidebar.css({ - 'position': 'fixed', - 'height': 'auto' - }); - } - }, - _fixForFixed: function (sidebar) { - sidebar.css({ - 'position': 'fixed', - 'max-height': '100%', - 'overflow': 'auto', - 'padding-bottom': '50px' - }); - }, - _fixForContent: function (sidebar) { - $(".content-wrapper, .right-side").css('min-height', sidebar.height()); - } - }; - - /* BoxWidget - * ========= - * BoxWidget is a plugin to handle collapsing and - * removing boxes from the screen. - * - * @type Object - * @usage $.AdminLTE.boxWidget.activate() - * Set all your options in the main $.AdminLTE.options object - */ - $.AdminLTE.boxWidget = { - selectors: $.AdminLTE.options.boxWidgetOptions.boxWidgetSelectors, - icons: $.AdminLTE.options.boxWidgetOptions.boxWidgetIcons, - animationSpeed: $.AdminLTE.options.animationSpeed, - activate: function (_box) { - var _this = this; - if (!_box) { - _box = document; // activate all boxes per default - } - //Listen for collapse event triggers - $(_box).on('click', _this.selectors.collapse, function (e) { - e.preventDefault(); - _this.collapse($(this)); - }); - - //Listen for remove event triggers - $(_box).on('click', _this.selectors.remove, function (e) { - e.preventDefault(); - _this.remove($(this)); - }); - }, - collapse: function (element) { - var _this = this; - //Find the box parent - var box = element.parents(".box").first(); - //Find the body and the footer - var box_content = box.find("> .box-body, > .box-footer, > form >.box-body, > form > .box-footer"); - if (!box.hasClass("collapsed-box")) { - //Convert minus into plus - element.children(":first") - .removeClass(_this.icons.collapse) - .addClass(_this.icons.open); - //Hide the content - box_content.slideUp(_this.animationSpeed, function () { - box.addClass("collapsed-box"); - }); - } else { - //Convert plus into minus - element.children(":first") - .removeClass(_this.icons.open) - .addClass(_this.icons.collapse); - //Show the content - box_content.slideDown(_this.animationSpeed, function () { - box.removeClass("collapsed-box"); - }); - } - }, - remove: function (element) { - //Find the box parent - var box = element.parents(".box").first(); - box.slideUp(this.animationSpeed); - } - }; -} - -/* ------------------ - * - Custom Plugins - - * ------------------ - * All custom plugins are defined below. - */ - -/* - * BOX REFRESH BUTTON - * ------------------ - * This is a custom plugin to use with the component BOX. It allows you to add - * a refresh button to the box. It converts the box's state to a loading state. - * - * @type plugin - * @usage $("#box-widget").boxRefresh( options ); - */ -(function ($) { - - "use strict"; - - $.fn.boxRefresh = function (options) { - - // Render options - var settings = $.extend({ - //Refresh button selector - trigger: ".refresh-btn", - //File source to be loaded (e.g: ajax/src.php) - source: "", - //Callbacks - onLoadStart: function (box) { - return box; - }, //Right after the button has been clicked - onLoadDone: function (box) { - return box; - } //When the source has been loaded - - }, options); - - //The overlay - var overlay = $('
'); - - return this.each(function () { - //if a source is specified - if (settings.source === "") { - if (window.console) { - window.console.log("Please specify a source first - boxRefresh()"); - } - return; - } - //the box - var box = $(this); - //the button - var rBtn = box.find(settings.trigger).first(); - - //On trigger click - rBtn.on('click', function (e) { - e.preventDefault(); - //Add loading overlay - start(box); - - //Perform ajax call - box.find(".box-body").load(settings.source, function () { - done(box); - }); - }); - }); - - function start(box) { - //Add overlay and loading img - box.append(overlay); - - settings.onLoadStart.call(box); - } - - function done(box) { - //Remove overlay and loading img - box.find(overlay).remove(); - - settings.onLoadDone.call(box); - } - - }; - -})(jQuery); - -/* - * EXPLICIT BOX ACTIVATION - * ----------------------- - * This is a custom plugin to use with the component BOX. It allows you to activate - * a box inserted in the DOM after the app.js was loaded. - * - * @type plugin - * @usage $("#box-widget").activateBox(); - */ -(function ($) { - - 'use strict'; - - $.fn.activateBox = function () { - $.AdminLTE.boxWidget.activate(this); - }; - -})(jQuery); diff --git a/resources/assets/js/bootstrap-js.js b/resources/assets/js/bootstrap-js.js deleted file mode 100644 index 01fbbcbaa9..0000000000 --- a/resources/assets/js/bootstrap-js.js +++ /dev/null @@ -1,2363 +0,0 @@ -/*! - * Bootstrap v3.3.6 (http://getbootstrap.com) - * Copyright 2011-2015 Twitter, Inc. - * Licensed under the MIT license - */ - -if (typeof jQuery === 'undefined') { - throw new Error('Bootstrap\'s JavaScript requires jQuery') -} - -+function ($) { - 'use strict'; - var version = $.fn.jquery.split(' ')[0].split('.') - if ((version[0] < 2 && version[1] < 9) || (version[0] == 1 && version[1] == 9 && version[2] < 1) || (version[0] > 2)) { - throw new Error('Bootstrap\'s JavaScript requires jQuery version 1.9.1 or higher, but lower than version 3') - } -}(jQuery); - -/* ======================================================================== - * Bootstrap: transition.js v3.3.6 - * http://getbootstrap.com/javascript/#transitions - * ======================================================================== - * Copyright 2011-2015 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - * ======================================================================== */ - - -+function ($) { - 'use strict'; - - // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/) - // ============================================================ - - function transitionEnd() { - var el = document.createElement('bootstrap') - - var transEndEventNames = { - WebkitTransition : 'webkitTransitionEnd', - MozTransition : 'transitionend', - OTransition : 'oTransitionEnd otransitionend', - transition : 'transitionend' - } - - for (var name in transEndEventNames) { - if (el.style[name] !== undefined) { - return { end: transEndEventNames[name] } - } - } - - return false // explicit for ie8 ( ._.) - } - - // http://blog.alexmaccaw.com/css-transitions - $.fn.emulateTransitionEnd = function (duration) { - var called = false - var $el = this - $(this).one('bsTransitionEnd', function () { called = true }) - var callback = function () { if (!called) $($el).trigger($.support.transition.end) } - setTimeout(callback, duration) - return this - } - - $(function () { - $.support.transition = transitionEnd() - - if (!$.support.transition) return - - $.event.special.bsTransitionEnd = { - bindType: $.support.transition.end, - delegateType: $.support.transition.end, - handle: function (e) { - if ($(e.target).is(this)) return e.handleObj.handler.apply(this, arguments) - } - } - }) - -}(jQuery); - -/* ======================================================================== - * Bootstrap: alert.js v3.3.6 - * http://getbootstrap.com/javascript/#alerts - * ======================================================================== - * Copyright 2011-2015 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - * ======================================================================== */ - - -+function ($) { - 'use strict'; - - // ALERT CLASS DEFINITION - // ====================== - - var dismiss = '[data-dismiss="alert"]' - var Alert = function (el) { - $(el).on('click', dismiss, this.close) - } - - Alert.VERSION = '3.3.6' - - Alert.TRANSITION_DURATION = 150 - - Alert.prototype.close = function (e) { - var $this = $(this) - var selector = $this.attr('data-target') - - if (!selector) { - selector = $this.attr('href') - selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7 - } - - var $parent = $(selector) - - if (e) e.preventDefault() - - if (!$parent.length) { - $parent = $this.closest('.alert') - } - - $parent.trigger(e = $.Event('close.bs.alert')) - - if (e.isDefaultPrevented()) return - - $parent.removeClass('in') - - function removeElement() { - // detach from parent, fire event then clean up data - $parent.detach().trigger('closed.bs.alert').remove() - } - - $.support.transition && $parent.hasClass('fade') ? - $parent - .one('bsTransitionEnd', removeElement) - .emulateTransitionEnd(Alert.TRANSITION_DURATION) : - removeElement() - } - - - // ALERT PLUGIN DEFINITION - // ======================= - - function Plugin(option) { - return this.each(function () { - var $this = $(this) - var data = $this.data('bs.alert') - - if (!data) $this.data('bs.alert', (data = new Alert(this))) - if (typeof option == 'string') data[option].call($this) - }) - } - - var old = $.fn.alert - - $.fn.alert = Plugin - $.fn.alert.Constructor = Alert - - - // ALERT NO CONFLICT - // ================= - - $.fn.alert.noConflict = function () { - $.fn.alert = old - return this - } - - - // ALERT DATA-API - // ============== - - $(document).on('click.bs.alert.data-api', dismiss, Alert.prototype.close) - -}(jQuery); - -/* ======================================================================== - * Bootstrap: button.js v3.3.6 - * http://getbootstrap.com/javascript/#buttons - * ======================================================================== - * Copyright 2011-2015 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - * ======================================================================== */ - - -+function ($) { - 'use strict'; - - // BUTTON PUBLIC CLASS DEFINITION - // ============================== - - var Button = function (element, options) { - this.$element = $(element) - this.options = $.extend({}, Button.DEFAULTS, options) - this.isLoading = false - } - - Button.VERSION = '3.3.6' - - Button.DEFAULTS = { - loadingText: 'loading...' - } - - Button.prototype.setState = function (state) { - var d = 'disabled' - var $el = this.$element - var val = $el.is('input') ? 'val' : 'html' - var data = $el.data() - - state += 'Text' - - if (data.resetText == null) $el.data('resetText', $el[val]()) - - // push to event loop to allow forms to submit - setTimeout($.proxy(function () { - $el[val](data[state] == null ? this.options[state] : data[state]) - - if (state == 'loadingText') { - this.isLoading = true - $el.addClass(d).attr(d, d) - } else if (this.isLoading) { - this.isLoading = false - $el.removeClass(d).removeAttr(d) - } - }, this), 0) - } - - Button.prototype.toggle = function () { - var changed = true - var $parent = this.$element.closest('[data-toggle="buttons"]') - - if ($parent.length) { - var $input = this.$element.find('input') - if ($input.prop('type') == 'radio') { - if ($input.prop('checked')) changed = false - $parent.find('.active').removeClass('active') - this.$element.addClass('active') - } else if ($input.prop('type') == 'checkbox') { - if (($input.prop('checked')) !== this.$element.hasClass('active')) changed = false - this.$element.toggleClass('active') - } - $input.prop('checked', this.$element.hasClass('active')) - if (changed) $input.trigger('change') - } else { - this.$element.attr('aria-pressed', !this.$element.hasClass('active')) - this.$element.toggleClass('active') - } - } - - - // BUTTON PLUGIN DEFINITION - // ======================== - - function Plugin(option) { - return this.each(function () { - var $this = $(this) - var data = $this.data('bs.button') - var options = typeof option == 'object' && option - - if (!data) $this.data('bs.button', (data = new Button(this, options))) - - if (option == 'toggle') data.toggle() - else if (option) data.setState(option) - }) - } - - var old = $.fn.button - - $.fn.button = Plugin - $.fn.button.Constructor = Button - - - // BUTTON NO CONFLICT - // ================== - - $.fn.button.noConflict = function () { - $.fn.button = old - return this - } - - - // BUTTON DATA-API - // =============== - - $(document) - .on('click.bs.button.data-api', '[data-toggle^="button"]', function (e) { - var $btn = $(e.target) - if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn') - Plugin.call($btn, 'toggle') - if (!($(e.target).is('input[type="radio"]') || $(e.target).is('input[type="checkbox"]'))) e.preventDefault() - }) - .on('focus.bs.button.data-api blur.bs.button.data-api', '[data-toggle^="button"]', function (e) { - $(e.target).closest('.btn').toggleClass('focus', /^focus(in)?$/.test(e.type)) - }) - -}(jQuery); - -/* ======================================================================== - * Bootstrap: carousel.js v3.3.6 - * http://getbootstrap.com/javascript/#carousel - * ======================================================================== - * Copyright 2011-2015 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - * ======================================================================== */ - - -+function ($) { - 'use strict'; - - // CAROUSEL CLASS DEFINITION - // ========================= - - var Carousel = function (element, options) { - this.$element = $(element) - this.$indicators = this.$element.find('.carousel-indicators') - this.options = options - this.paused = null - this.sliding = null - this.interval = null - this.$active = null - this.$items = null - - this.options.keyboard && this.$element.on('keydown.bs.carousel', $.proxy(this.keydown, this)) - - this.options.pause == 'hover' && !('ontouchstart' in document.documentElement) && this.$element - .on('mouseenter.bs.carousel', $.proxy(this.pause, this)) - .on('mouseleave.bs.carousel', $.proxy(this.cycle, this)) - } - - Carousel.VERSION = '3.3.6' - - Carousel.TRANSITION_DURATION = 600 - - Carousel.DEFAULTS = { - interval: 5000, - pause: 'hover', - wrap: true, - keyboard: true - } - - Carousel.prototype.keydown = function (e) { - if (/input|textarea/i.test(e.target.tagName)) return - switch (e.which) { - case 37: this.prev(); break - case 39: this.next(); break - default: return - } - - e.preventDefault() - } - - Carousel.prototype.cycle = function (e) { - e || (this.paused = false) - - this.interval && clearInterval(this.interval) - - this.options.interval - && !this.paused - && (this.interval = setInterval($.proxy(this.next, this), this.options.interval)) - - return this - } - - Carousel.prototype.getItemIndex = function (item) { - this.$items = item.parent().children('.item') - return this.$items.index(item || this.$active) - } - - Carousel.prototype.getItemForDirection = function (direction, active) { - var activeIndex = this.getItemIndex(active) - var willWrap = (direction == 'prev' && activeIndex === 0) - || (direction == 'next' && activeIndex == (this.$items.length - 1)) - if (willWrap && !this.options.wrap) return active - var delta = direction == 'prev' ? -1 : 1 - var itemIndex = (activeIndex + delta) % this.$items.length - return this.$items.eq(itemIndex) - } - - Carousel.prototype.to = function (pos) { - var that = this - var activeIndex = this.getItemIndex(this.$active = this.$element.find('.item.active')) - - if (pos > (this.$items.length - 1) || pos < 0) return - - if (this.sliding) return this.$element.one('slid.bs.carousel', function () { that.to(pos) }) // yes, "slid" - if (activeIndex == pos) return this.pause().cycle() - - return this.slide(pos > activeIndex ? 'next' : 'prev', this.$items.eq(pos)) - } - - Carousel.prototype.pause = function (e) { - e || (this.paused = true) - - if (this.$element.find('.next, .prev').length && $.support.transition) { - this.$element.trigger($.support.transition.end) - this.cycle(true) - } - - this.interval = clearInterval(this.interval) - - return this - } - - Carousel.prototype.next = function () { - if (this.sliding) return - return this.slide('next') - } - - Carousel.prototype.prev = function () { - if (this.sliding) return - return this.slide('prev') - } - - Carousel.prototype.slide = function (type, next) { - var $active = this.$element.find('.item.active') - var $next = next || this.getItemForDirection(type, $active) - var isCycling = this.interval - var direction = type == 'next' ? 'left' : 'right' - var that = this - - if ($next.hasClass('active')) return (this.sliding = false) - - var relatedTarget = $next[0] - var slideEvent = $.Event('slide.bs.carousel', { - relatedTarget: relatedTarget, - direction: direction - }) - this.$element.trigger(slideEvent) - if (slideEvent.isDefaultPrevented()) return - - this.sliding = true - - isCycling && this.pause() - - if (this.$indicators.length) { - this.$indicators.find('.active').removeClass('active') - var $nextIndicator = $(this.$indicators.children()[this.getItemIndex($next)]) - $nextIndicator && $nextIndicator.addClass('active') - } - - var slidEvent = $.Event('slid.bs.carousel', { relatedTarget: relatedTarget, direction: direction }) // yes, "slid" - if ($.support.transition && this.$element.hasClass('slide')) { - $next.addClass(type) - $next[0].offsetWidth // force reflow - $active.addClass(direction) - $next.addClass(direction) - $active - .one('bsTransitionEnd', function () { - $next.removeClass([type, direction].join(' ')).addClass('active') - $active.removeClass(['active', direction].join(' ')) - that.sliding = false - setTimeout(function () { - that.$element.trigger(slidEvent) - }, 0) - }) - .emulateTransitionEnd(Carousel.TRANSITION_DURATION) - } else { - $active.removeClass('active') - $next.addClass('active') - this.sliding = false - this.$element.trigger(slidEvent) - } - - isCycling && this.cycle() - - return this - } - - - // CAROUSEL PLUGIN DEFINITION - // ========================== - - function Plugin(option) { - return this.each(function () { - var $this = $(this) - var data = $this.data('bs.carousel') - var options = $.extend({}, Carousel.DEFAULTS, $this.data(), typeof option == 'object' && option) - var action = typeof option == 'string' ? option : options.slide - - if (!data) $this.data('bs.carousel', (data = new Carousel(this, options))) - if (typeof option == 'number') data.to(option) - else if (action) data[action]() - else if (options.interval) data.pause().cycle() - }) - } - - var old = $.fn.carousel - - $.fn.carousel = Plugin - $.fn.carousel.Constructor = Carousel - - - // CAROUSEL NO CONFLICT - // ==================== - - $.fn.carousel.noConflict = function () { - $.fn.carousel = old - return this - } - - - // CAROUSEL DATA-API - // ================= - - var clickHandler = function (e) { - var href - var $this = $(this) - var $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) // strip for ie7 - if (!$target.hasClass('carousel')) return - var options = $.extend({}, $target.data(), $this.data()) - var slideIndex = $this.attr('data-slide-to') - if (slideIndex) options.interval = false - - Plugin.call($target, options) - - if (slideIndex) { - $target.data('bs.carousel').to(slideIndex) - } - - e.preventDefault() - } - - $(document) - .on('click.bs.carousel.data-api', '[data-slide]', clickHandler) - .on('click.bs.carousel.data-api', '[data-slide-to]', clickHandler) - - $(window).on('load', function () { - $('[data-ride="carousel"]').each(function () { - var $carousel = $(this) - Plugin.call($carousel, $carousel.data()) - }) - }) - -}(jQuery); - -/* ======================================================================== - * Bootstrap: collapse.js v3.3.6 - * http://getbootstrap.com/javascript/#collapse - * ======================================================================== - * Copyright 2011-2015 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - * ======================================================================== */ - - -+function ($) { - 'use strict'; - - // COLLAPSE PUBLIC CLASS DEFINITION - // ================================ - - var Collapse = function (element, options) { - this.$element = $(element) - this.options = $.extend({}, Collapse.DEFAULTS, options) - this.$trigger = $('[data-toggle="collapse"][href="#' + element.id + '"],' + - '[data-toggle="collapse"][data-target="#' + element.id + '"]') - this.transitioning = null - - if (this.options.parent) { - this.$parent = this.getParent() - } else { - this.addAriaAndCollapsedClass(this.$element, this.$trigger) - } - - if (this.options.toggle) this.toggle() - } - - Collapse.VERSION = '3.3.6' - - Collapse.TRANSITION_DURATION = 350 - - Collapse.DEFAULTS = { - toggle: true - } - - Collapse.prototype.dimension = function () { - var hasWidth = this.$element.hasClass('width') - return hasWidth ? 'width' : 'height' - } - - Collapse.prototype.show = function () { - if (this.transitioning || this.$element.hasClass('in')) return - - var activesData - var actives = this.$parent && this.$parent.children('.panel').children('.in, .collapsing') - - if (actives && actives.length) { - activesData = actives.data('bs.collapse') - if (activesData && activesData.transitioning) return - } - - var startEvent = $.Event('show.bs.collapse') - this.$element.trigger(startEvent) - if (startEvent.isDefaultPrevented()) return - - if (actives && actives.length) { - Plugin.call(actives, 'hide') - activesData || actives.data('bs.collapse', null) - } - - var dimension = this.dimension() - - this.$element - .removeClass('collapse') - .addClass('collapsing')[dimension](0) - .attr('aria-expanded', true) - - this.$trigger - .removeClass('collapsed') - .attr('aria-expanded', true) - - this.transitioning = 1 - - var complete = function () { - this.$element - .removeClass('collapsing') - .addClass('collapse in')[dimension]('') - this.transitioning = 0 - this.$element - .trigger('shown.bs.collapse') - } - - if (!$.support.transition) return complete.call(this) - - var scrollSize = $.camelCase(['scroll', dimension].join('-')) - - this.$element - .one('bsTransitionEnd', $.proxy(complete, this)) - .emulateTransitionEnd(Collapse.TRANSITION_DURATION)[dimension](this.$element[0][scrollSize]) - } - - Collapse.prototype.hide = function () { - if (this.transitioning || !this.$element.hasClass('in')) return - - var startEvent = $.Event('hide.bs.collapse') - this.$element.trigger(startEvent) - if (startEvent.isDefaultPrevented()) return - - var dimension = this.dimension() - - this.$element[dimension](this.$element[dimension]())[0].offsetHeight - - this.$element - .addClass('collapsing') - .removeClass('collapse in') - .attr('aria-expanded', false) - - this.$trigger - .addClass('collapsed') - .attr('aria-expanded', false) - - this.transitioning = 1 - - var complete = function () { - this.transitioning = 0 - this.$element - .removeClass('collapsing') - .addClass('collapse') - .trigger('hidden.bs.collapse') - } - - if (!$.support.transition) return complete.call(this) - - this.$element - [dimension](0) - .one('bsTransitionEnd', $.proxy(complete, this)) - .emulateTransitionEnd(Collapse.TRANSITION_DURATION) - } - - Collapse.prototype.toggle = function () { - this[this.$element.hasClass('in') ? 'hide' : 'show']() - } - - Collapse.prototype.getParent = function () { - return $(this.options.parent) - .find('[data-toggle="collapse"][data-parent="' + this.options.parent + '"]') - .each($.proxy(function (i, element) { - var $element = $(element) - this.addAriaAndCollapsedClass(getTargetFromTrigger($element), $element) - }, this)) - .end() - } - - Collapse.prototype.addAriaAndCollapsedClass = function ($element, $trigger) { - var isOpen = $element.hasClass('in') - - $element.attr('aria-expanded', isOpen) - $trigger - .toggleClass('collapsed', !isOpen) - .attr('aria-expanded', isOpen) - } - - function getTargetFromTrigger($trigger) { - var href - var target = $trigger.attr('data-target') - || (href = $trigger.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7 - - return $(target) - } - - - // COLLAPSE PLUGIN DEFINITION - // ========================== - - function Plugin(option) { - return this.each(function () { - var $this = $(this) - var data = $this.data('bs.collapse') - var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option) - - if (!data && options.toggle && /show|hide/.test(option)) options.toggle = false - if (!data) $this.data('bs.collapse', (data = new Collapse(this, options))) - if (typeof option == 'string') data[option]() - }) - } - - var old = $.fn.collapse - - $.fn.collapse = Plugin - $.fn.collapse.Constructor = Collapse - - - // COLLAPSE NO CONFLICT - // ==================== - - $.fn.collapse.noConflict = function () { - $.fn.collapse = old - return this - } - - - // COLLAPSE DATA-API - // ================= - - $(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) { - var $this = $(this) - - if (!$this.attr('data-target')) e.preventDefault() - - var $target = getTargetFromTrigger($this) - var data = $target.data('bs.collapse') - var option = data ? 'toggle' : $this.data() - - Plugin.call($target, option) - }) - -}(jQuery); - -/* ======================================================================== - * Bootstrap: dropdown.js v3.3.6 - * http://getbootstrap.com/javascript/#dropdowns - * ======================================================================== - * Copyright 2011-2015 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - * ======================================================================== */ - - -+function ($) { - 'use strict'; - - // DROPDOWN CLASS DEFINITION - // ========================= - - var backdrop = '.dropdown-backdrop' - var toggle = '[data-toggle="dropdown"]' - var Dropdown = function (element) { - $(element).on('click.bs.dropdown', this.toggle) - } - - Dropdown.VERSION = '3.3.6' - - function getParent($this) { - var selector = $this.attr('data-target') - - if (!selector) { - selector = $this.attr('href') - selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7 - } - - var $parent = selector && $(selector) - - return $parent && $parent.length ? $parent : $this.parent() - } - - function clearMenus(e) { - if (e && e.which === 3) return - $(backdrop).remove() - $(toggle).each(function () { - var $this = $(this) - var $parent = getParent($this) - var relatedTarget = { relatedTarget: this } - - if (!$parent.hasClass('open')) return - - if (e && e.type == 'click' && /input|textarea/i.test(e.target.tagName) && $.contains($parent[0], e.target)) return - - $parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget)) - - if (e.isDefaultPrevented()) return - - $this.attr('aria-expanded', 'false') - $parent.removeClass('open').trigger($.Event('hidden.bs.dropdown', relatedTarget)) - }) - } - - Dropdown.prototype.toggle = function (e) { - var $this = $(this) - - if ($this.is('.disabled, :disabled')) return - - var $parent = getParent($this) - var isActive = $parent.hasClass('open') - - clearMenus() - - if (!isActive) { - if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) { - // if mobile we use a backdrop because click events don't delegate - $(document.createElement('div')) - .addClass('dropdown-backdrop') - .insertAfter($(this)) - .on('click', clearMenus) - } - - var relatedTarget = { relatedTarget: this } - $parent.trigger(e = $.Event('show.bs.dropdown', relatedTarget)) - - if (e.isDefaultPrevented()) return - - $this - .trigger('focus') - .attr('aria-expanded', 'true') - - $parent - .toggleClass('open') - .trigger($.Event('shown.bs.dropdown', relatedTarget)) - } - - return false - } - - Dropdown.prototype.keydown = function (e) { - if (!/(38|40|27|32)/.test(e.which) || /input|textarea/i.test(e.target.tagName)) return - - var $this = $(this) - - e.preventDefault() - e.stopPropagation() - - if ($this.is('.disabled, :disabled')) return - - var $parent = getParent($this) - var isActive = $parent.hasClass('open') - - if (!isActive && e.which != 27 || isActive && e.which == 27) { - if (e.which == 27) $parent.find(toggle).trigger('focus') - return $this.trigger('click') - } - - var desc = ' li:not(.disabled):visible a' - var $items = $parent.find('.dropdown-menu' + desc) - - if (!$items.length) return - - var index = $items.index(e.target) - - if (e.which == 38 && index > 0) index-- // up - if (e.which == 40 && index < $items.length - 1) index++ // down - if (!~index) index = 0 - - $items.eq(index).trigger('focus') - } - - - // DROPDOWN PLUGIN DEFINITION - // ========================== - - function Plugin(option) { - return this.each(function () { - var $this = $(this) - var data = $this.data('bs.dropdown') - - if (!data) $this.data('bs.dropdown', (data = new Dropdown(this))) - if (typeof option == 'string') data[option].call($this) - }) - } - - var old = $.fn.dropdown - - $.fn.dropdown = Plugin - $.fn.dropdown.Constructor = Dropdown - - - // DROPDOWN NO CONFLICT - // ==================== - - $.fn.dropdown.noConflict = function () { - $.fn.dropdown = old - return this - } - - - // APPLY TO STANDARD DROPDOWN ELEMENTS - // =================================== - - $(document) - .on('click.bs.dropdown.data-api', clearMenus) - .on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() }) - .on('click.bs.dropdown.data-api', toggle, Dropdown.prototype.toggle) - .on('keydown.bs.dropdown.data-api', toggle, Dropdown.prototype.keydown) - .on('keydown.bs.dropdown.data-api', '.dropdown-menu', Dropdown.prototype.keydown) - -}(jQuery); - -/* ======================================================================== - * Bootstrap: modal.js v3.3.6 - * http://getbootstrap.com/javascript/#modals - * ======================================================================== - * Copyright 2011-2015 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - * ======================================================================== */ - - -+function ($) { - 'use strict'; - - // MODAL CLASS DEFINITION - // ====================== - - var Modal = function (element, options) { - this.options = options - this.$body = $(document.body) - this.$element = $(element) - this.$dialog = this.$element.find('.modal-dialog') - this.$backdrop = null - this.isShown = null - this.originalBodyPad = null - this.scrollbarWidth = 0 - this.ignoreBackdropClick = false - - if (this.options.remote) { - this.$element - .find('.modal-content') - .load(this.options.remote, $.proxy(function () { - this.$element.trigger('loaded.bs.modal') - }, this)) - } - } - - Modal.VERSION = '3.3.6' - - Modal.TRANSITION_DURATION = 300 - Modal.BACKDROP_TRANSITION_DURATION = 150 - - Modal.DEFAULTS = { - backdrop: true, - keyboard: true, - show: true - } - - Modal.prototype.toggle = function (_relatedTarget) { - return this.isShown ? this.hide() : this.show(_relatedTarget) - } - - Modal.prototype.show = function (_relatedTarget) { - var that = this - var e = $.Event('show.bs.modal', { relatedTarget: _relatedTarget }) - - this.$element.trigger(e) - - if (this.isShown || e.isDefaultPrevented()) return - - this.isShown = true - - this.checkScrollbar() - this.setScrollbar() - this.$body.addClass('modal-open') - - this.escape() - this.resize() - - this.$element.on('click.dismiss.bs.modal', '[data-dismiss="modal"]', $.proxy(this.hide, this)) - - this.$dialog.on('mousedown.dismiss.bs.modal', function () { - that.$element.one('mouseup.dismiss.bs.modal', function (e) { - if ($(e.target).is(that.$element)) that.ignoreBackdropClick = true - }) - }) - - this.backdrop(function () { - var transition = $.support.transition && that.$element.hasClass('fade') - - if (!that.$element.parent().length) { - that.$element.appendTo(that.$body) // don't move modals dom position - } - - that.$element - .show() - .scrollTop(0) - - that.adjustDialog() - - if (transition) { - that.$element[0].offsetWidth // force reflow - } - - that.$element.addClass('in') - - that.enforceFocus() - - var e = $.Event('shown.bs.modal', { relatedTarget: _relatedTarget }) - - transition ? - that.$dialog // wait for modal to slide in - .one('bsTransitionEnd', function () { - that.$element.trigger('focus').trigger(e) - }) - .emulateTransitionEnd(Modal.TRANSITION_DURATION) : - that.$element.trigger('focus').trigger(e) - }) - } - - Modal.prototype.hide = function (e) { - if (e) e.preventDefault() - - e = $.Event('hide.bs.modal') - - this.$element.trigger(e) - - if (!this.isShown || e.isDefaultPrevented()) return - - this.isShown = false - - this.escape() - this.resize() - - $(document).off('focusin.bs.modal') - - this.$element - .removeClass('in') - .off('click.dismiss.bs.modal') - .off('mouseup.dismiss.bs.modal') - - this.$dialog.off('mousedown.dismiss.bs.modal') - - $.support.transition && this.$element.hasClass('fade') ? - this.$element - .one('bsTransitionEnd', $.proxy(this.hideModal, this)) - .emulateTransitionEnd(Modal.TRANSITION_DURATION) : - this.hideModal() - } - - Modal.prototype.enforceFocus = function () { - $(document) - .off('focusin.bs.modal') // guard against infinite focus loop - .on('focusin.bs.modal', $.proxy(function (e) { - if (this.$element[0] !== e.target && !this.$element.has(e.target).length) { - this.$element.trigger('focus') - } - }, this)) - } - - Modal.prototype.escape = function () { - if (this.isShown && this.options.keyboard) { - this.$element.on('keydown.dismiss.bs.modal', $.proxy(function (e) { - e.which == 27 && this.hide() - }, this)) - } else if (!this.isShown) { - this.$element.off('keydown.dismiss.bs.modal') - } - } - - Modal.prototype.resize = function () { - if (this.isShown) { - $(window).on('resize.bs.modal', $.proxy(this.handleUpdate, this)) - } else { - $(window).off('resize.bs.modal') - } - } - - Modal.prototype.hideModal = function () { - var that = this - this.$element.hide() - this.backdrop(function () { - that.$body.removeClass('modal-open') - that.resetAdjustments() - that.resetScrollbar() - that.$element.trigger('hidden.bs.modal') - }) - } - - Modal.prototype.removeBackdrop = function () { - this.$backdrop && this.$backdrop.remove() - this.$backdrop = null - } - - Modal.prototype.backdrop = function (callback) { - var that = this - var animate = this.$element.hasClass('fade') ? 'fade' : '' - - if (this.isShown && this.options.backdrop) { - var doAnimate = $.support.transition && animate - - this.$backdrop = $(document.createElement('div')) - .addClass('modal-backdrop ' + animate) - .appendTo(this.$body) - - this.$element.on('click.dismiss.bs.modal', $.proxy(function (e) { - if (this.ignoreBackdropClick) { - this.ignoreBackdropClick = false - return - } - if (e.target !== e.currentTarget) return - this.options.backdrop == 'static' - ? this.$element[0].focus() - : this.hide() - }, this)) - - if (doAnimate) this.$backdrop[0].offsetWidth // force reflow - - this.$backdrop.addClass('in') - - if (!callback) return - - doAnimate ? - this.$backdrop - .one('bsTransitionEnd', callback) - .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) : - callback() - - } else if (!this.isShown && this.$backdrop) { - this.$backdrop.removeClass('in') - - var callbackRemove = function () { - that.removeBackdrop() - callback && callback() - } - $.support.transition && this.$element.hasClass('fade') ? - this.$backdrop - .one('bsTransitionEnd', callbackRemove) - .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) : - callbackRemove() - - } else if (callback) { - callback() - } - } - - // these following methods are used to handle overflowing modals - - Modal.prototype.handleUpdate = function () { - this.adjustDialog() - } - - Modal.prototype.adjustDialog = function () { - var modalIsOverflowing = this.$element[0].scrollHeight > document.documentElement.clientHeight - - this.$element.css({ - paddingLeft: !this.bodyIsOverflowing && modalIsOverflowing ? this.scrollbarWidth : '', - paddingRight: this.bodyIsOverflowing && !modalIsOverflowing ? this.scrollbarWidth : '' - }) - } - - Modal.prototype.resetAdjustments = function () { - this.$element.css({ - paddingLeft: '', - paddingRight: '' - }) - } - - Modal.prototype.checkScrollbar = function () { - var fullWindowWidth = window.innerWidth - if (!fullWindowWidth) { // workaround for missing window.innerWidth in IE8 - var documentElementRect = document.documentElement.getBoundingClientRect() - fullWindowWidth = documentElementRect.right - Math.abs(documentElementRect.left) - } - this.bodyIsOverflowing = document.body.clientWidth < fullWindowWidth - this.scrollbarWidth = this.measureScrollbar() - } - - Modal.prototype.setScrollbar = function () { - var bodyPad = parseInt((this.$body.css('padding-right') || 0), 10) - this.originalBodyPad = document.body.style.paddingRight || '' - if (this.bodyIsOverflowing) this.$body.css('padding-right', bodyPad + this.scrollbarWidth) - } - - Modal.prototype.resetScrollbar = function () { - this.$body.css('padding-right', this.originalBodyPad) - } - - Modal.prototype.measureScrollbar = function () { // thx walsh - var scrollDiv = document.createElement('div') - scrollDiv.className = 'modal-scrollbar-measure' - this.$body.append(scrollDiv) - var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth - this.$body[0].removeChild(scrollDiv) - return scrollbarWidth - } - - - // MODAL PLUGIN DEFINITION - // ======================= - - function Plugin(option, _relatedTarget) { - return this.each(function () { - var $this = $(this) - var data = $this.data('bs.modal') - var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == 'object' && option) - - if (!data) $this.data('bs.modal', (data = new Modal(this, options))) - if (typeof option == 'string') data[option](_relatedTarget) - else if (options.show) data.show(_relatedTarget) - }) - } - - var old = $.fn.modal - - $.fn.modal = Plugin - $.fn.modal.Constructor = Modal - - - // MODAL NO CONFLICT - // ================= - - $.fn.modal.noConflict = function () { - $.fn.modal = old - return this - } - - - // MODAL DATA-API - // ============== - - $(document).on('click.bs.modal.data-api', '[data-toggle="modal"]', function (e) { - var $this = $(this) - var href = $this.attr('href') - var $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, ''))) // strip for ie7 - var option = $target.data('bs.modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data()) - - if ($this.is('a')) e.preventDefault() - - $target.one('show.bs.modal', function (showEvent) { - if (showEvent.isDefaultPrevented()) return // only register focus restorer if modal will actually get shown - $target.one('hidden.bs.modal', function () { - $this.is(':visible') && $this.trigger('focus') - }) - }) - Plugin.call($target, option, this) - }) - -}(jQuery); - -/* ======================================================================== - * Bootstrap: tooltip.js v3.3.6 - * http://getbootstrap.com/javascript/#tooltip - * Inspired by the original jQuery.tipsy by Jason Frame - * ======================================================================== - * Copyright 2011-2015 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - * ======================================================================== */ - - -+function ($) { - 'use strict'; - - // TOOLTIP PUBLIC CLASS DEFINITION - // =============================== - - var Tooltip = function (element, options) { - this.type = null - this.options = null - this.enabled = null - this.timeout = null - this.hoverState = null - this.$element = null - this.inState = null - - this.init('tooltip', element, options) - } - - Tooltip.VERSION = '3.3.6' - - Tooltip.TRANSITION_DURATION = 150 - - Tooltip.DEFAULTS = { - animation: true, - placement: 'top', - selector: false, - template: '', - trigger: 'hover focus', - title: '', - delay: 0, - html: false, - container: false, - viewport: { - selector: 'body', - padding: 0 - } - } - - Tooltip.prototype.init = function (type, element, options) { - this.enabled = true - this.type = type - this.$element = $(element) - this.options = this.getOptions(options) - this.$viewport = this.options.viewport && $($.isFunction(this.options.viewport) ? this.options.viewport.call(this, this.$element) : (this.options.viewport.selector || this.options.viewport)) - this.inState = { click: false, hover: false, focus: false } - - if (this.$element[0] instanceof document.constructor && !this.options.selector) { - throw new Error('`selector` option must be specified when initializing ' + this.type + ' on the window.document object!') - } - - var triggers = this.options.trigger.split(' ') - - for (var i = triggers.length; i--;) { - var trigger = triggers[i] - - if (trigger == 'click') { - this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this)) - } else if (trigger != 'manual') { - var eventIn = trigger == 'hover' ? 'mouseenter' : 'focusin' - var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout' - - this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this)) - this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this)) - } - } - - this.options.selector ? - (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) : - this.fixTitle() - } - - Tooltip.prototype.getDefaults = function () { - return Tooltip.DEFAULTS - } - - Tooltip.prototype.getOptions = function (options) { - options = $.extend({}, this.getDefaults(), this.$element.data(), options) - - if (options.delay && typeof options.delay == 'number') { - options.delay = { - show: options.delay, - hide: options.delay - } - } - - return options - } - - Tooltip.prototype.getDelegateOptions = function () { - var options = {} - var defaults = this.getDefaults() - - this._options && $.each(this._options, function (key, value) { - if (defaults[key] != value) options[key] = value - }) - - return options - } - - Tooltip.prototype.enter = function (obj) { - var self = obj instanceof this.constructor ? - obj : $(obj.currentTarget).data('bs.' + this.type) - - if (!self) { - self = new this.constructor(obj.currentTarget, this.getDelegateOptions()) - $(obj.currentTarget).data('bs.' + this.type, self) - } - - if (obj instanceof $.Event) { - self.inState[obj.type == 'focusin' ? 'focus' : 'hover'] = true - } - - if (self.tip().hasClass('in') || self.hoverState == 'in') { - self.hoverState = 'in' - return - } - - clearTimeout(self.timeout) - - self.hoverState = 'in' - - if (!self.options.delay || !self.options.delay.show) return self.show() - - self.timeout = setTimeout(function () { - if (self.hoverState == 'in') self.show() - }, self.options.delay.show) - } - - Tooltip.prototype.isInStateTrue = function () { - for (var key in this.inState) { - if (this.inState[key]) return true - } - - return false - } - - Tooltip.prototype.leave = function (obj) { - var self = obj instanceof this.constructor ? - obj : $(obj.currentTarget).data('bs.' + this.type) - - if (!self) { - self = new this.constructor(obj.currentTarget, this.getDelegateOptions()) - $(obj.currentTarget).data('bs.' + this.type, self) - } - - if (obj instanceof $.Event) { - self.inState[obj.type == 'focusout' ? 'focus' : 'hover'] = false - } - - if (self.isInStateTrue()) return - - clearTimeout(self.timeout) - - self.hoverState = 'out' - - if (!self.options.delay || !self.options.delay.hide) return self.hide() - - self.timeout = setTimeout(function () { - if (self.hoverState == 'out') self.hide() - }, self.options.delay.hide) - } - - Tooltip.prototype.show = function () { - var e = $.Event('show.bs.' + this.type) - - if (this.hasContent() && this.enabled) { - this.$element.trigger(e) - - var inDom = $.contains(this.$element[0].ownerDocument.documentElement, this.$element[0]) - if (e.isDefaultPrevented() || !inDom) return - var that = this - - var $tip = this.tip() - - var tipId = this.getUID(this.type) - - this.setContent() - $tip.attr('id', tipId) - this.$element.attr('aria-describedby', tipId) - - if (this.options.animation) $tip.addClass('fade') - - var placement = typeof this.options.placement == 'function' ? - this.options.placement.call(this, $tip[0], this.$element[0]) : - this.options.placement - - var autoToken = /\s?auto?\s?/i - var autoPlace = autoToken.test(placement) - if (autoPlace) placement = placement.replace(autoToken, '') || 'top' - - $tip - .detach() - .css({ top: 0, left: 0, display: 'block' }) - .addClass(placement) - .data('bs.' + this.type, this) - - this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element) - this.$element.trigger('inserted.bs.' + this.type) - - var pos = this.getPosition() - var actualWidth = $tip[0].offsetWidth - var actualHeight = $tip[0].offsetHeight - - if (autoPlace) { - var orgPlacement = placement - var viewportDim = this.getPosition(this.$viewport) - - placement = placement == 'bottom' && pos.bottom + actualHeight > viewportDim.bottom ? 'top' : - placement == 'top' && pos.top - actualHeight < viewportDim.top ? 'bottom' : - placement == 'right' && pos.right + actualWidth > viewportDim.width ? 'left' : - placement == 'left' && pos.left - actualWidth < viewportDim.left ? 'right' : - placement - - $tip - .removeClass(orgPlacement) - .addClass(placement) - } - - var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight) - - this.applyPlacement(calculatedOffset, placement) - - var complete = function () { - var prevHoverState = that.hoverState - that.$element.trigger('shown.bs.' + that.type) - that.hoverState = null - - if (prevHoverState == 'out') that.leave(that) - } - - $.support.transition && this.$tip.hasClass('fade') ? - $tip - .one('bsTransitionEnd', complete) - .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) : - complete() - } - } - - Tooltip.prototype.applyPlacement = function (offset, placement) { - var $tip = this.tip() - var width = $tip[0].offsetWidth - var height = $tip[0].offsetHeight - - // manually read margins because getBoundingClientRect includes difference - var marginTop = parseInt($tip.css('margin-top'), 10) - var marginLeft = parseInt($tip.css('margin-left'), 10) - - // we must check for NaN for ie 8/9 - if (isNaN(marginTop)) marginTop = 0 - if (isNaN(marginLeft)) marginLeft = 0 - - offset.top += marginTop - offset.left += marginLeft - - // $.fn.offset doesn't round pixel values - // so we use setOffset directly with our own function B-0 - $.offset.setOffset($tip[0], $.extend({ - using: function (props) { - $tip.css({ - top: Math.round(props.top), - left: Math.round(props.left) - }) - } - }, offset), 0) - - $tip.addClass('in') - - // check to see if placing tip in new offset caused the tip to resize itself - var actualWidth = $tip[0].offsetWidth - var actualHeight = $tip[0].offsetHeight - - if (placement == 'top' && actualHeight != height) { - offset.top = offset.top + height - actualHeight - } - - var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight) - - if (delta.left) offset.left += delta.left - else offset.top += delta.top - - var isVertical = /top|bottom/.test(placement) - var arrowDelta = isVertical ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight - var arrowOffsetPosition = isVertical ? 'offsetWidth' : 'offsetHeight' - - $tip.offset(offset) - this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], isVertical) - } - - Tooltip.prototype.replaceArrow = function (delta, dimension, isVertical) { - this.arrow() - .css(isVertical ? 'left' : 'top', 50 * (1 - delta / dimension) + '%') - .css(isVertical ? 'top' : 'left', '') - } - - Tooltip.prototype.setContent = function () { - var $tip = this.tip() - var title = this.getTitle() - - $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title) - $tip.removeClass('fade in top bottom left right') - } - - Tooltip.prototype.hide = function (callback) { - var that = this - var $tip = $(this.$tip) - var e = $.Event('hide.bs.' + this.type) - - function complete() { - if (that.hoverState != 'in') $tip.detach() - that.$element - .removeAttr('aria-describedby') - .trigger('hidden.bs.' + that.type) - callback && callback() - } - - this.$element.trigger(e) - - if (e.isDefaultPrevented()) return - - $tip.removeClass('in') - - $.support.transition && $tip.hasClass('fade') ? - $tip - .one('bsTransitionEnd', complete) - .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) : - complete() - - this.hoverState = null - - return this - } - - Tooltip.prototype.fixTitle = function () { - var $e = this.$element - if ($e.attr('title') || typeof $e.attr('data-original-title') != 'string') { - $e.attr('data-original-title', $e.attr('title') || '').attr('title', '') - } - } - - Tooltip.prototype.hasContent = function () { - return this.getTitle() - } - - Tooltip.prototype.getPosition = function ($element) { - $element = $element || this.$element - - var el = $element[0] - var isBody = el.tagName == 'BODY' - - var elRect = el.getBoundingClientRect() - if (elRect.width == null) { - // width and height are missing in IE8, so compute them manually; see https://github.com/twbs/bootstrap/issues/14093 - elRect = $.extend({}, elRect, { width: elRect.right - elRect.left, height: elRect.bottom - elRect.top }) - } - var elOffset = isBody ? { top: 0, left: 0 } : $element.offset() - var scroll = { scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop() } - var outerDims = isBody ? { width: $(window).width(), height: $(window).height() } : null - - return $.extend({}, elRect, scroll, outerDims, elOffset) - } - - Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) { - return placement == 'bottom' ? { top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2 } : - placement == 'top' ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } : - placement == 'left' ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } : - /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width } - - } - - Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) { - var delta = { top: 0, left: 0 } - if (!this.$viewport) return delta - - var viewportPadding = this.options.viewport && this.options.viewport.padding || 0 - var viewportDimensions = this.getPosition(this.$viewport) - - if (/right|left/.test(placement)) { - var topEdgeOffset = pos.top - viewportPadding - viewportDimensions.scroll - var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight - if (topEdgeOffset < viewportDimensions.top) { // top overflow - delta.top = viewportDimensions.top - topEdgeOffset - } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow - delta.top = viewportDimensions.top + viewportDimensions.height - bottomEdgeOffset - } - } else { - var leftEdgeOffset = pos.left - viewportPadding - var rightEdgeOffset = pos.left + viewportPadding + actualWidth - if (leftEdgeOffset < viewportDimensions.left) { // left overflow - delta.left = viewportDimensions.left - leftEdgeOffset - } else if (rightEdgeOffset > viewportDimensions.right) { // right overflow - delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset - } - } - - return delta - } - - Tooltip.prototype.getTitle = function () { - var title - var $e = this.$element - var o = this.options - - title = $e.attr('data-original-title') - || (typeof o.title == 'function' ? o.title.call($e[0]) : o.title) - - return title - } - - Tooltip.prototype.getUID = function (prefix) { - do prefix += ~~(Math.random() * 1000000) - while (document.getElementById(prefix)) - return prefix - } - - Tooltip.prototype.tip = function () { - if (!this.$tip) { - this.$tip = $(this.options.template) - if (this.$tip.length != 1) { - throw new Error(this.type + ' `template` option must consist of exactly 1 top-level element!') - } - } - return this.$tip - } - - Tooltip.prototype.arrow = function () { - return (this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow')) - } - - Tooltip.prototype.enable = function () { - this.enabled = true - } - - Tooltip.prototype.disable = function () { - this.enabled = false - } - - Tooltip.prototype.toggleEnabled = function () { - this.enabled = !this.enabled - } - - Tooltip.prototype.toggle = function (e) { - var self = this - if (e) { - self = $(e.currentTarget).data('bs.' + this.type) - if (!self) { - self = new this.constructor(e.currentTarget, this.getDelegateOptions()) - $(e.currentTarget).data('bs.' + this.type, self) - } - } - - if (e) { - self.inState.click = !self.inState.click - if (self.isInStateTrue()) self.enter(self) - else self.leave(self) - } else { - self.tip().hasClass('in') ? self.leave(self) : self.enter(self) - } - } - - Tooltip.prototype.destroy = function () { - var that = this - clearTimeout(this.timeout) - this.hide(function () { - that.$element.off('.' + that.type).removeData('bs.' + that.type) - if (that.$tip) { - that.$tip.detach() - } - that.$tip = null - that.$arrow = null - that.$viewport = null - }) - } - - - // TOOLTIP PLUGIN DEFINITION - // ========================= - - function Plugin(option) { - return this.each(function () { - var $this = $(this) - var data = $this.data('bs.tooltip') - var options = typeof option == 'object' && option - - if (!data && /destroy|hide/.test(option)) return - if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options))) - if (typeof option == 'string') data[option]() - }) - } - - var old = $.fn.tooltip - - $.fn.tooltip = Plugin - $.fn.tooltip.Constructor = Tooltip - - - // TOOLTIP NO CONFLICT - // =================== - - $.fn.tooltip.noConflict = function () { - $.fn.tooltip = old - return this - } - -}(jQuery); - -/* ======================================================================== - * Bootstrap: popover.js v3.3.6 - * http://getbootstrap.com/javascript/#popovers - * ======================================================================== - * Copyright 2011-2015 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - * ======================================================================== */ - - -+function ($) { - 'use strict'; - - // POPOVER PUBLIC CLASS DEFINITION - // =============================== - - var Popover = function (element, options) { - this.init('popover', element, options) - } - - if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js') - - Popover.VERSION = '3.3.6' - - Popover.DEFAULTS = $.extend({}, $.fn.tooltip.Constructor.DEFAULTS, { - placement: 'right', - trigger: 'click', - content: '', - template: '' - }) - - - // NOTE: POPOVER EXTENDS tooltip.js - // ================================ - - Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype) - - Popover.prototype.constructor = Popover - - Popover.prototype.getDefaults = function () { - return Popover.DEFAULTS - } - - Popover.prototype.setContent = function () { - var $tip = this.tip() - var title = this.getTitle() - var content = this.getContent() - - $tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title) - $tip.find('.popover-content').children().detach().end()[ // we use append for html objects to maintain js events - this.options.html ? (typeof content == 'string' ? 'html' : 'append') : 'text' - ](content) - - $tip.removeClass('fade top bottom left right in') - - // IE8 doesn't accept hiding via the `:empty` pseudo selector, we have to do - // this manually by checking the contents. - if (!$tip.find('.popover-title').html()) $tip.find('.popover-title').hide() - } - - Popover.prototype.hasContent = function () { - return this.getTitle() || this.getContent() - } - - Popover.prototype.getContent = function () { - var $e = this.$element - var o = this.options - - return $e.attr('data-content') - || (typeof o.content == 'function' ? - o.content.call($e[0]) : - o.content) - } - - Popover.prototype.arrow = function () { - return (this.$arrow = this.$arrow || this.tip().find('.arrow')) - } - - - // POPOVER PLUGIN DEFINITION - // ========================= - - function Plugin(option) { - return this.each(function () { - var $this = $(this) - var data = $this.data('bs.popover') - var options = typeof option == 'object' && option - - if (!data && /destroy|hide/.test(option)) return - if (!data) $this.data('bs.popover', (data = new Popover(this, options))) - if (typeof option == 'string') data[option]() - }) - } - - var old = $.fn.popover - - $.fn.popover = Plugin - $.fn.popover.Constructor = Popover - - - // POPOVER NO CONFLICT - // =================== - - $.fn.popover.noConflict = function () { - $.fn.popover = old - return this - } - -}(jQuery); - -/* ======================================================================== - * Bootstrap: scrollspy.js v3.3.6 - * http://getbootstrap.com/javascript/#scrollspy - * ======================================================================== - * Copyright 2011-2015 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - * ======================================================================== */ - - -+function ($) { - 'use strict'; - - // SCROLLSPY CLASS DEFINITION - // ========================== - - function ScrollSpy(element, options) { - this.$body = $(document.body) - this.$scrollElement = $(element).is(document.body) ? $(window) : $(element) - this.options = $.extend({}, ScrollSpy.DEFAULTS, options) - this.selector = (this.options.target || '') + ' .nav li > a' - this.offsets = [] - this.targets = [] - this.activeTarget = null - this.scrollHeight = 0 - - this.$scrollElement.on('scroll.bs.scrollspy', $.proxy(this.process, this)) - this.refresh() - this.process() - } - - ScrollSpy.VERSION = '3.3.6' - - ScrollSpy.DEFAULTS = { - offset: 10 - } - - ScrollSpy.prototype.getScrollHeight = function () { - return this.$scrollElement[0].scrollHeight || Math.max(this.$body[0].scrollHeight, document.documentElement.scrollHeight) - } - - ScrollSpy.prototype.refresh = function () { - var that = this - var offsetMethod = 'offset' - var offsetBase = 0 - - this.offsets = [] - this.targets = [] - this.scrollHeight = this.getScrollHeight() - - if (!$.isWindow(this.$scrollElement[0])) { - offsetMethod = 'position' - offsetBase = this.$scrollElement.scrollTop() - } - - this.$body - .find(this.selector) - .map(function () { - var $el = $(this) - var href = $el.data('target') || $el.attr('href') - var $href = /^#./.test(href) && $(href) - - return ($href - && $href.length - && $href.is(':visible') - && [[$href[offsetMethod]().top + offsetBase, href]]) || null - }) - .sort(function (a, b) { return a[0] - b[0] }) - .each(function () { - that.offsets.push(this[0]) - that.targets.push(this[1]) - }) - } - - ScrollSpy.prototype.process = function () { - var scrollTop = this.$scrollElement.scrollTop() + this.options.offset - var scrollHeight = this.getScrollHeight() - var maxScroll = this.options.offset + scrollHeight - this.$scrollElement.height() - var offsets = this.offsets - var targets = this.targets - var activeTarget = this.activeTarget - var i - - if (this.scrollHeight != scrollHeight) { - this.refresh() - } - - if (scrollTop >= maxScroll) { - return activeTarget != (i = targets[targets.length - 1]) && this.activate(i) - } - - if (activeTarget && scrollTop < offsets[0]) { - this.activeTarget = null - return this.clear() - } - - for (i = offsets.length; i--;) { - activeTarget != targets[i] - && scrollTop >= offsets[i] - && (offsets[i + 1] === undefined || scrollTop < offsets[i + 1]) - && this.activate(targets[i]) - } - } - - ScrollSpy.prototype.activate = function (target) { - this.activeTarget = target - - this.clear() - - var selector = this.selector + - '[data-target="' + target + '"],' + - this.selector + '[href="' + target + '"]' - - var active = $(selector) - .parents('li') - .addClass('active') - - if (active.parent('.dropdown-menu').length) { - active = active - .closest('li.dropdown') - .addClass('active') - } - - active.trigger('activate.bs.scrollspy') - } - - ScrollSpy.prototype.clear = function () { - $(this.selector) - .parentsUntil(this.options.target, '.active') - .removeClass('active') - } - - - // SCROLLSPY PLUGIN DEFINITION - // =========================== - - function Plugin(option) { - return this.each(function () { - var $this = $(this) - var data = $this.data('bs.scrollspy') - var options = typeof option == 'object' && option - - if (!data) $this.data('bs.scrollspy', (data = new ScrollSpy(this, options))) - if (typeof option == 'string') data[option]() - }) - } - - var old = $.fn.scrollspy - - $.fn.scrollspy = Plugin - $.fn.scrollspy.Constructor = ScrollSpy - - - // SCROLLSPY NO CONFLICT - // ===================== - - $.fn.scrollspy.noConflict = function () { - $.fn.scrollspy = old - return this - } - - - // SCROLLSPY DATA-API - // ================== - - $(window).on('load.bs.scrollspy.data-api', function () { - $('[data-spy="scroll"]').each(function () { - var $spy = $(this) - Plugin.call($spy, $spy.data()) - }) - }) - -}(jQuery); - -/* ======================================================================== - * Bootstrap: tab.js v3.3.6 - * http://getbootstrap.com/javascript/#tabs - * ======================================================================== - * Copyright 2011-2015 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - * ======================================================================== */ - - -+function ($) { - 'use strict'; - - // TAB CLASS DEFINITION - // ==================== - - var Tab = function (element) { - // jscs:disable requireDollarBeforejQueryAssignment - this.element = $(element) - // jscs:enable requireDollarBeforejQueryAssignment - } - - Tab.VERSION = '3.3.6' - - Tab.TRANSITION_DURATION = 150 - - Tab.prototype.show = function () { - var $this = this.element - var $ul = $this.closest('ul:not(.dropdown-menu)') - var selector = $this.data('target') - - if (!selector) { - selector = $this.attr('href') - selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7 - } - - if ($this.parent('li').hasClass('active')) return - - var $previous = $ul.find('.active:last a') - var hideEvent = $.Event('hide.bs.tab', { - relatedTarget: $this[0] - }) - var showEvent = $.Event('show.bs.tab', { - relatedTarget: $previous[0] - }) - - $previous.trigger(hideEvent) - $this.trigger(showEvent) - - if (showEvent.isDefaultPrevented() || hideEvent.isDefaultPrevented()) return - - var $target = $(selector) - - this.activate($this.closest('li'), $ul) - this.activate($target, $target.parent(), function () { - $previous.trigger({ - type: 'hidden.bs.tab', - relatedTarget: $this[0] - }) - $this.trigger({ - type: 'shown.bs.tab', - relatedTarget: $previous[0] - }) - }) - } - - Tab.prototype.activate = function (element, container, callback) { - var $active = container.find('> .active') - var transition = callback - && $.support.transition - && ($active.length && $active.hasClass('fade') || !!container.find('> .fade').length) - - function next() { - $active - .removeClass('active') - .find('> .dropdown-menu > .active') - .removeClass('active') - .end() - .find('[data-toggle="tab"]') - .attr('aria-expanded', false) - - element - .addClass('active') - .find('[data-toggle="tab"]') - .attr('aria-expanded', true) - - if (transition) { - element[0].offsetWidth // reflow for transition - element.addClass('in') - } else { - element.removeClass('fade') - } - - if (element.parent('.dropdown-menu').length) { - element - .closest('li.dropdown') - .addClass('active') - .end() - .find('[data-toggle="tab"]') - .attr('aria-expanded', true) - } - - callback && callback() - } - - $active.length && transition ? - $active - .one('bsTransitionEnd', next) - .emulateTransitionEnd(Tab.TRANSITION_DURATION) : - next() - - $active.removeClass('in') - } - - - // TAB PLUGIN DEFINITION - // ===================== - - function Plugin(option) { - return this.each(function () { - var $this = $(this) - var data = $this.data('bs.tab') - - if (!data) $this.data('bs.tab', (data = new Tab(this))) - if (typeof option == 'string') data[option]() - }) - } - - var old = $.fn.tab - - $.fn.tab = Plugin - $.fn.tab.Constructor = Tab - - - // TAB NO CONFLICT - // =============== - - $.fn.tab.noConflict = function () { - $.fn.tab = old - return this - } - - - // TAB DATA-API - // ============ - - var clickHandler = function (e) { - e.preventDefault() - Plugin.call($(this), 'show') - } - - $(document) - .on('click.bs.tab.data-api', '[data-toggle="tab"]', clickHandler) - .on('click.bs.tab.data-api', '[data-toggle="pill"]', clickHandler) - -}(jQuery); - -/* ======================================================================== - * Bootstrap: affix.js v3.3.6 - * http://getbootstrap.com/javascript/#affix - * ======================================================================== - * Copyright 2011-2015 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - * ======================================================================== */ - - -+function ($) { - 'use strict'; - - // AFFIX CLASS DEFINITION - // ====================== - - var Affix = function (element, options) { - this.options = $.extend({}, Affix.DEFAULTS, options) - - this.$target = $(this.options.target) - .on('scroll.bs.affix.data-api', $.proxy(this.checkPosition, this)) - .on('click.bs.affix.data-api', $.proxy(this.checkPositionWithEventLoop, this)) - - this.$element = $(element) - this.affixed = null - this.unpin = null - this.pinnedOffset = null - - this.checkPosition() - } - - Affix.VERSION = '3.3.6' - - Affix.RESET = 'affix affix-top affix-bottom' - - Affix.DEFAULTS = { - offset: 0, - target: window - } - - Affix.prototype.getState = function (scrollHeight, height, offsetTop, offsetBottom) { - var scrollTop = this.$target.scrollTop() - var position = this.$element.offset() - var targetHeight = this.$target.height() - - if (offsetTop != null && this.affixed == 'top') return scrollTop < offsetTop ? 'top' : false - - if (this.affixed == 'bottom') { - if (offsetTop != null) return (scrollTop + this.unpin <= position.top) ? false : 'bottom' - return (scrollTop + targetHeight <= scrollHeight - offsetBottom) ? false : 'bottom' - } - - var initializing = this.affixed == null - var colliderTop = initializing ? scrollTop : position.top - var colliderHeight = initializing ? targetHeight : height - - if (offsetTop != null && scrollTop <= offsetTop) return 'top' - if (offsetBottom != null && (colliderTop + colliderHeight >= scrollHeight - offsetBottom)) return 'bottom' - - return false - } - - Affix.prototype.getPinnedOffset = function () { - if (this.pinnedOffset) return this.pinnedOffset - this.$element.removeClass(Affix.RESET).addClass('affix') - var scrollTop = this.$target.scrollTop() - var position = this.$element.offset() - return (this.pinnedOffset = position.top - scrollTop) - } - - Affix.prototype.checkPositionWithEventLoop = function () { - setTimeout($.proxy(this.checkPosition, this), 1) - } - - Affix.prototype.checkPosition = function () { - if (!this.$element.is(':visible')) return - - var height = this.$element.height() - var offset = this.options.offset - var offsetTop = offset.top - var offsetBottom = offset.bottom - var scrollHeight = Math.max($(document).height(), $(document.body).height()) - - if (typeof offset != 'object') offsetBottom = offsetTop = offset - if (typeof offsetTop == 'function') offsetTop = offset.top(this.$element) - if (typeof offsetBottom == 'function') offsetBottom = offset.bottom(this.$element) - - var affix = this.getState(scrollHeight, height, offsetTop, offsetBottom) - - if (this.affixed != affix) { - if (this.unpin != null) this.$element.css('top', '') - - var affixType = 'affix' + (affix ? '-' + affix : '') - var e = $.Event(affixType + '.bs.affix') - - this.$element.trigger(e) - - if (e.isDefaultPrevented()) return - - this.affixed = affix - this.unpin = affix == 'bottom' ? this.getPinnedOffset() : null - - this.$element - .removeClass(Affix.RESET) - .addClass(affixType) - .trigger(affixType.replace('affix', 'affixed') + '.bs.affix') - } - - if (affix == 'bottom') { - this.$element.offset({ - top: scrollHeight - height - offsetBottom - }) - } - } - - - // AFFIX PLUGIN DEFINITION - // ======================= - - function Plugin(option) { - return this.each(function () { - var $this = $(this) - var data = $this.data('bs.affix') - var options = typeof option == 'object' && option - - if (!data) $this.data('bs.affix', (data = new Affix(this, options))) - if (typeof option == 'string') data[option]() - }) - } - - var old = $.fn.affix - - $.fn.affix = Plugin - $.fn.affix.Constructor = Affix - - - // AFFIX NO CONFLICT - // ================= - - $.fn.affix.noConflict = function () { - $.fn.affix = old - return this - } - - - // AFFIX DATA-API - // ============== - - $(window).on('load', function () { - $('[data-spy="affix"]').each(function () { - var $spy = $(this) - var data = $spy.data() - - data.offset = data.offset || {} - - if (data.offsetBottom != null) data.offset.bottom = data.offsetBottom - if (data.offsetTop != null) data.offset.top = data.offsetTop - - Plugin.call($spy, data) - }) - }) - -}(jQuery); diff --git a/resources/assets/js/bootstrap-table.js b/resources/assets/js/bootstrap-table.js deleted file mode 100755 index f8715e9c4d..0000000000 --- a/resources/assets/js/bootstrap-table.js +++ /dev/null @@ -1,2690 +0,0 @@ -/** - * @author zhixin wen - * version: 1.9.1 - * https://github.com/wenzhixin/bootstrap-table/ - */ - -!function ($) { - 'use strict'; - - // TOOLS DEFINITION - // ====================== - - var cachedWidth = null; - - // it only does '%s', and return '' when arguments are undefined - var sprintf = function (str) { - var args = arguments, - flag = true, - i = 1; - - str = str.replace(/%s/g, function () { - var arg = args[i++]; - - if (typeof arg === 'undefined') { - flag = false; - return ''; - } - return arg; - }); - return flag ? str : ''; - }; - - var getPropertyFromOther = function (list, from, to, value) { - var result = ''; - $.each(list, function (i, item) { - if (item[from] === value) { - result = item[to]; - return false; - } - return true; - }); - return result; - }; - - var getFieldIndex = function (columns, field) { - var index = -1; - - $.each(columns, function (i, column) { - if (column.field === field) { - index = i; - return false; - } - return true; - }); - return index; - }; - - // http://jsfiddle.net/wenyi/47nz7ez9/3/ - var setFieldIndex = function (columns) { - var i, j, k, - totalCol = 0, - flag = []; - - for (i = 0; i < columns[0].length; i++) { - totalCol += columns[0][i].colspan || 1; - } - - for (i = 0; i < columns.length; i++) { - flag[i] = []; - for (j = 0; j < totalCol; j++) { - flag[i][j] = false; - } - } - - for (i = 0; i < columns.length; i++) { - for (j = 0; j < columns[i].length; j++) { - var r = columns[i][j], - rowspan = r.rowspan || 1, - colspan = r.colspan || 1, - index = $.inArray(false, flag[i]); - - if (colspan === 1) { - r.fieldIndex = index; - // when field is undefined, use index instead - if (typeof r.field === 'undefined') { - r.field = index; - } - } - - for (k = 0; k < rowspan; k++) { - flag[i + k][index] = true; - } - for (k = 0; k < colspan; k++) { - flag[i][index + k] = true; - } - } - } - }; - - var getScrollBarWidth = function () { - if (cachedWidth === null) { - var inner = $('

').addClass('fixed-table-scroll-inner'), - outer = $('

').addClass('fixed-table-scroll-outer'), - w1, w2; - - outer.append(inner); - $('body').append(outer); - - w1 = inner[0].offsetWidth; - outer.css('overflow', 'scroll'); - w2 = inner[0].offsetWidth; - - if (w1 === w2) { - w2 = outer[0].clientWidth; - } - - outer.remove(); - cachedWidth = w1 - w2; - } - return cachedWidth; - }; - - var calculateObjectValue = function (self, name, args, defaultValue) { - var func = name; - - if (typeof name === 'string') { - // support obj.func1.func2 - var names = name.split('.'); - - if (names.length > 1) { - func = window; - $.each(names, function (i, f) { - func = func[f]; - }); - } else { - func = window[name]; - } - } - if (typeof func === 'object') { - return func; - } - if (typeof func === 'function') { - return func.apply(self, args); - } - if (!func && typeof name === 'string' && sprintf.apply(this, [name].concat(args))) { - return sprintf.apply(this, [name].concat(args)); - } - return defaultValue; - }; - - var compareObjects = function (objectA, objectB, compareLength) { - // Create arrays of property names - var objectAProperties = Object.getOwnPropertyNames(objectA), - objectBProperties = Object.getOwnPropertyNames(objectB), - propName = ''; - - if (compareLength) { - // If number of properties is different, objects are not equivalent - if (objectAProperties.length !== objectBProperties.length) { - return false; - } - } - - for (var i = 0; i < objectAProperties.length; i++) { - propName = objectAProperties[i]; - - // If the property is not in the object B properties, continue with the next property - if ($.inArray(propName, objectBProperties) > -1) { - // If values of same property are not equal, objects are not equivalent - if (objectA[propName] !== objectB[propName]) { - return false; - } - } - } - - // If we made it this far, objects are considered equivalent - return true; - }; - - var escapeHTML = function (text) { - if (typeof text === 'string') { - return text - .replace(/&/g, "&") - .replace(//g, ">") - .replace(/"/g, """) - .replace(/'/g, "'"); - } - return text; - }; - - var getRealHeight = function ($el) { - var height = 0; - $el.children().each(function () { - if (height < $(this).outerHeight(true)) { - height = $(this).outerHeight(true); - } - }); - return height; - }; - - var getRealDataAttr = function (dataAttr) { - for (var attr in dataAttr) { - var auxAttr = attr.split(/(?=[A-Z])/).join('-').toLowerCase(); - if (auxAttr !== attr) { - dataAttr[auxAttr] = dataAttr[attr]; - delete dataAttr[attr]; - } - } - - return dataAttr; - }; - - var getItemField = function (item, field) { - var value = item; - - if (typeof field !== 'string' || item.hasOwnProperty(field)) { - return item[field]; - } - var props = field.split('.'); - for (var p in props) { - value = value[props[p]]; - } - return value; - }; - - // BOOTSTRAP TABLE CLASS DEFINITION - // ====================== - - var BootstrapTable = function (el, options) { - this.options = options; - this.$el = $(el); - this.$el_ = this.$el.clone(); - this.timeoutId_ = 0; - this.timeoutFooter_ = 0; - - this.init(); - }; - - BootstrapTable.DEFAULTS = { - classes: 'table table-hover', - locale: undefined, - height: undefined, - undefinedText: '-', - sortName: undefined, - sortOrder: 'asc', - striped: false, - columns: [[]], - data: [], - dataField: 'rows', - method: 'get', - url: undefined, - ajax: undefined, - cache: true, - contentType: 'application/json', - dataType: 'json', - ajaxOptions: {}, - queryParams: function (params) { - return params; - }, - queryParamsType: 'limit', // undefined - responseHandler: function (res) { - return res; - }, - pagination: false, - onlyInfoPagination: false, - sidePagination: 'client', // client or server - totalRows: 0, // server side need to set - pageNumber: 1, - pageSize: 10, - pageList: [10, 25, 50, 100], - paginationHAlign: 'right', //right, left - paginationVAlign: 'bottom', //bottom, top, both - paginationDetailHAlign: 'left', //right, left - paginationFirstText: '«', - paginationPreText: '‹', - paginationNextText: '›', - paginationLastText: '»', - search: false, - strictSearch: false, - searchAlign: 'right', - selectItemName: 'btSelectItem', - showHeader: true, - showFooter: false, - showColumns: false, - showPaginationSwitch: false, - showRefresh: false, - showToggle: false, - buttonsAlign: 'right', - smartDisplay: true, - minimumCountColumns: 1, - idField: undefined, - uniqueId: undefined, - cardView: false, - detailView: false, - detailFormatter: function (index, row) { - return ''; - }, - trimOnSearch: true, - clickToSelect: false, - singleSelect: false, - toolbar: undefined, - toolbarAlign: 'left', - checkboxHeader: true, - sortable: true, - silentSort: true, - maintainSelected: false, - searchTimeOut: 500, - searchText: '', - iconSize: undefined, - iconsPrefix: 'glyphicon', // glyphicon of fa (font awesome) - icons: { - paginationSwitchDown: 'glyphicon-collapse-down icon-chevron-down', - paginationSwitchUp: 'glyphicon-collapse-up icon-chevron-up', - refresh: 'glyphicon-refresh icon-refresh', - toggle: 'glyphicon-list-alt icon-list-alt', - columns: 'glyphicon-th icon-th', - detailOpen: 'glyphicon-plus icon-plus', - detailClose: 'glyphicon-minus icon-minus' - }, - - rowStyle: function (row, index) { - return {}; - }, - - rowAttributes: function (row, index) { - return {}; - }, - - onAll: function (name, args) { - return false; - }, - onClickCell: function (field, value, row, $element) { - return false; - }, - onDblClickCell: function (field, value, row, $element) { - return false; - }, - onClickRow: function (item, $element) { - return false; - }, - onDblClickRow: function (item, $element) { - return false; - }, - onSort: function (name, order) { - return false; - }, - onCheck: function (row) { - return false; - }, - onUncheck: function (row) { - return false; - }, - onCheckAll: function (rows) { - return false; - }, - onUncheckAll: function (rows) { - return false; - }, - onCheckSome: function (rows) { - return false; - }, - onUncheckSome: function (rows) { - return false; - }, - onLoadSuccess: function (data) { - return false; - }, - onLoadError: function (status) { - return false; - }, - onColumnSwitch: function (field, checked) { - return false; - }, - onPageChange: function (number, size) { - return false; - }, - onSearch: function (text) { - return false; - }, - onToggle: function (cardView) { - return false; - }, - onPreBody: function (data) { - return false; - }, - onPostBody: function () { - return false; - }, - onPostHeader: function () { - return false; - }, - onExpandRow: function (index, row, $detail) { - return false; - }, - onCollapseRow: function (index, row) { - return false; - }, - onRefreshOptions: function (options) { - return false; - }, - onResetView: function () { - return false; - } - }; - - BootstrapTable.LOCALES = []; - - BootstrapTable.LOCALES['en-US'] = BootstrapTable.LOCALES['en'] = { - formatLoadingMessage: function () { - return 'Loading, please wait...'; - }, - formatRecordsPerPage: function (pageNumber) { - return sprintf('%s records per page', pageNumber); - }, - formatShowingRows: function (pageFrom, pageTo, totalRows) { - return sprintf('Showing %s to %s of %s rows', pageFrom, pageTo, totalRows); - }, - formatDetailPagination: function (totalRows) { - return sprintf('Showing %s rows', totalRows); - }, - formatSearch: function () { - return 'Search'; - }, - formatNoMatches: function () { - return 'No matching records found'; - }, - formatPaginationSwitch: function () { - return 'Hide/Show pagination'; - }, - formatRefresh: function () { - return 'Refresh'; - }, - formatToggle: function () { - return 'Toggle'; - }, - formatColumns: function () { - return 'Columns'; - }, - formatAllRows: function () { - return 'All'; - } - }; - - $.extend(BootstrapTable.DEFAULTS, BootstrapTable.LOCALES['en-US']); - - BootstrapTable.COLUMN_DEFAULTS = { - radio: false, - checkbox: false, - checkboxEnabled: true, - field: undefined, - title: undefined, - titleTooltip: undefined, - 'class': undefined, - align: undefined, // left, right, center - halign: undefined, // left, right, center - falign: undefined, // left, right, center - valign: undefined, // top, middle, bottom - width: undefined, - sortable: false, - order: 'asc', // asc, desc - visible: true, - switchable: true, - clickToSelect: true, - formatter: undefined, - footerFormatter: undefined, - events: undefined, - sorter: undefined, - sortName: undefined, - cellStyle: undefined, - searchable: true, - searchFormatter: true, - cardVisible: true - }; - - BootstrapTable.EVENTS = { - 'all.bs.table': 'onAll', - 'click-cell.bs.table': 'onClickCell', - 'dbl-click-cell.bs.table': 'onDblClickCell', - 'click-row.bs.table': 'onClickRow', - 'dbl-click-row.bs.table': 'onDblClickRow', - 'sort.bs.table': 'onSort', - 'check.bs.table': 'onCheck', - 'uncheck.bs.table': 'onUncheck', - 'check-all.bs.table': 'onCheckAll', - 'uncheck-all.bs.table': 'onUncheckAll', - 'check-some.bs.table': 'onCheckSome', - 'uncheck-some.bs.table': 'onUncheckSome', - 'load-success.bs.table': 'onLoadSuccess', - 'load-error.bs.table': 'onLoadError', - 'column-switch.bs.table': 'onColumnSwitch', - 'page-change.bs.table': 'onPageChange', - 'search.bs.table': 'onSearch', - 'toggle.bs.table': 'onToggle', - 'pre-body.bs.table': 'onPreBody', - 'post-body.bs.table': 'onPostBody', - 'post-header.bs.table': 'onPostHeader', - 'expand-row.bs.table': 'onExpandRow', - 'collapse-row.bs.table': 'onCollapseRow', - 'refresh-options.bs.table': 'onRefreshOptions', - 'reset-view.bs.table': 'onResetView' - }; - - BootstrapTable.prototype.init = function () { - this.initLocale(); - this.initContainer(); - this.initTable(); - this.initHeader(); - this.initData(); - this.initFooter(); - this.initToolbar(); - this.initPagination(); - this.initBody(); - this.initSearchText(); - this.initServer(); - }; - - BootstrapTable.prototype.initLocale = function () { - if (this.options.locale) { - var parts = this.options.locale.split(/-|_/); - parts[0].toLowerCase(); - parts[1] && parts[1].toUpperCase(); - if ($.fn.bootstrapTable.locales[this.options.locale]) { - // locale as requested - $.extend(this.options, $.fn.bootstrapTable.locales[this.options.locale]); - } else if ($.fn.bootstrapTable.locales[parts.join('-')]) { - // locale with sep set to - (in case original was specified with _) - $.extend(this.options, $.fn.bootstrapTable.locales[parts.join('-')]); - } else if ($.fn.bootstrapTable.locales[parts[0]]) { - // short locale language code (i.e. 'en') - $.extend(this.options, $.fn.bootstrapTable.locales[parts[0]]); - } - } - }; - - BootstrapTable.prototype.initContainer = function () { - this.$container = $([ - '
', - '
', - this.options.paginationVAlign === 'top' || this.options.paginationVAlign === 'both' ? - '
' : - '', - '
', - '
', - '
', - '
', - this.options.formatLoadingMessage(), - '
', - '
', - '', - this.options.paginationVAlign === 'bottom' || this.options.paginationVAlign === 'both' ? - '
' : - '', - '
', - '
' - ].join('')); - - this.$container.insertAfter(this.$el); - this.$tableContainer = this.$container.find('.fixed-table-container'); - this.$tableHeader = this.$container.find('.fixed-table-header'); - this.$tableBody = this.$container.find('.fixed-table-body'); - this.$tableLoading = this.$container.find('.fixed-table-loading'); - this.$tableFooter = this.$container.find('.fixed-table-footer'); - this.$toolbar = this.$container.find('.fixed-table-toolbar'); - this.$pagination = this.$container.find('.fixed-table-pagination'); - - this.$tableBody.append(this.$el); - this.$container.after('
'); - - this.$el.addClass(this.options.classes); - if (this.options.striped) { - this.$el.addClass('table-striped'); - } - if ($.inArray('table-no-bordered', this.options.classes.split(' ')) !== -1) { - this.$tableContainer.addClass('table-no-bordered'); - } - }; - - BootstrapTable.prototype.initTable = function () { - var that = this, - columns = [], - data = []; - - this.$header = this.$el.find('>thead'); - if (!this.$header.length) { - this.$header = $('').appendTo(this.$el); - } - this.$header.find('tr').each(function () { - var column = []; - - $(this).find('th').each(function () { - column.push($.extend({}, { - title: $(this).html(), - 'class': $(this).attr('class'), - titleTooltip: $(this).attr('title'), - rowspan: $(this).attr('rowspan') ? +$(this).attr('rowspan') : undefined, - colspan: $(this).attr('colspan') ? +$(this).attr('colspan') : undefined - }, $(this).data())); - }); - columns.push(column); - }); - if (!$.isArray(this.options.columns[0])) { - this.options.columns = [this.options.columns]; - } - this.options.columns = $.extend(true, [], columns, this.options.columns); - this.columns = []; - - setFieldIndex(this.options.columns); - $.each(this.options.columns, function (i, columns) { - $.each(columns, function (j, column) { - column = $.extend({}, BootstrapTable.COLUMN_DEFAULTS, column); - - if (typeof column.fieldIndex !== 'undefined') { - that.columns[column.fieldIndex] = column; - } - - that.options.columns[i][j] = column; - }); - }); - - // if options.data is setting, do not process tbody data - if (this.options.data.length) { - return; - } - - this.$el.find('>tbody>tr').each(function () { - var row = {}; - - // save tr's id, class and data-* attributes - row._id = $(this).attr('id'); - row._class = $(this).attr('class'); - row._data = getRealDataAttr($(this).data()); - - $(this).find('td').each(function (i) { - var field = that.columns[i].field; - - row[field] = $(this).html(); - // save td's id, class and data-* attributes - row['_' + field + '_id'] = $(this).attr('id'); - row['_' + field + '_class'] = $(this).attr('class'); - row['_' + field + '_rowspan'] = $(this).attr('rowspan'); - row['_' + field + '_title'] = $(this).attr('title'); - row['_' + field + '_data'] = getRealDataAttr($(this).data()); - }); - data.push(row); - }); - this.options.data = data; - }; - - BootstrapTable.prototype.initHeader = function () { - var that = this, - visibleColumns = {}, - html = []; - - this.header = { - fields: [], - styles: [], - classes: [], - formatters: [], - events: [], - sorters: [], - sortNames: [], - cellStyles: [], - searchables: [] - }; - - $.each(this.options.columns, function (i, columns) { - html.push(''); - - if (i == 0 && !that.options.cardView && that.options.detailView) { - html.push(sprintf('
', - that.options.columns.length)); - } - - $.each(columns, function (j, column) { - var text = '', - halign = '', // header align style - align = '', // body align style - style = '', - class_ = sprintf(' class="%s"', column['class']), - order = that.options.sortOrder || column.order, - unitWidth = 'px', - width = column.width; - - if (column.width !== undefined && (!that.options.cardView)) { - if (typeof column.width === 'string') { - if (column.width.indexOf('%') !== -1) { - unitWidth = '%'; - } - } - } - if (column.width && typeof column.width === 'string') { - width = column.width.replace('%', '').replace('px', ''); - } - - halign = sprintf('text-align: %s; ', column.halign ? column.halign : column.align); - align = sprintf('text-align: %s; ', column.align); - style = sprintf('vertical-align: %s; ', column.valign); - style += sprintf('width: %s; ', (column.checkbox || column.radio) && !width ? - '36px' : (width ? width + unitWidth : undefined)); - - if (typeof column.fieldIndex !== 'undefined') { - that.header.fields[column.fieldIndex] = column.field; - that.header.styles[column.fieldIndex] = align + style; - that.header.classes[column.fieldIndex] = class_; - that.header.formatters[column.fieldIndex] = column.formatter; - that.header.events[column.fieldIndex] = column.events; - that.header.sorters[column.fieldIndex] = column.sorter; - that.header.sortNames[column.fieldIndex] = column.sortName; - that.header.cellStyles[column.fieldIndex] = column.cellStyle; - that.header.searchables[column.fieldIndex] = column.searchable; - - if (!column.visible) { - return; - } - - if (that.options.cardView && (!column.cardVisible)) { - return; - } - - visibleColumns[column.field] = column; - } - - html.push(''); - - html.push(sprintf('
', that.options.sortable && column.sortable ? - 'sortable both' : '')); - - text = column.title; - - if (column.checkbox) { - if (!that.options.singleSelect && that.options.checkboxHeader) { - text = ''; - } - that.header.stateField = column.field; - } - if (column.radio) { - text = ''; - that.header.stateField = column.field; - that.options.singleSelect = true; - } - - html.push(text); - html.push('
'); - html.push('
'); - html.push('
'); - html.push(''); - }); - html.push(''); - }); - - this.$header.html(html.join('')); - this.$header.find('th[data-field]').each(function (i) { - $(this).data(visibleColumns[$(this).data('field')]); - }); - this.$container.off('click', '.th-inner').on('click', '.th-inner', function (event) { - if (that.options.sortable && $(this).parent().data().sortable) { - that.onSort(event); - } - }); - - this.$header.children().children().off('keypress').on('keypress', function (event) { - if (that.options.sortable && $(this).data().sortable) { - var code = event.keyCode || event.which; - if (code == 13) { //Enter keycode - that.onSort(event); - } - } - }); - - if (!this.options.showHeader || this.options.cardView) { - this.$header.hide(); - this.$tableHeader.hide(); - this.$tableLoading.css('top', 0); - } else { - this.$header.show(); - this.$tableHeader.show(); - this.$tableLoading.css('top', this.$header.outerHeight() + 1); - // Assign the correct sortable arrow - this.getCaret(); - } - - this.$selectAll = this.$header.find('[name="btSelectAll"]'); - this.$container.off('click', '[name="btSelectAll"]') - .on('click', '[name="btSelectAll"]', function () { - var checked = $(this).prop('checked'); - that[checked ? 'checkAll' : 'uncheckAll'](); - that.updateSelected(); - }); - }; - - BootstrapTable.prototype.initFooter = function () { - if (!this.options.showFooter || this.options.cardView) { - this.$tableFooter.hide(); - } else { - this.$tableFooter.show(); - } - }; - - /** - * @param data - * @param type: append / prepend - */ - BootstrapTable.prototype.initData = function (data, type) { - if (type === 'append') { - this.data = this.data.concat(data); - } else if (type === 'prepend') { - this.data = [].concat(data).concat(this.data); - } else { - this.data = data || this.options.data; - } - - // Fix #839 Records deleted when adding new row on filtered table - if (type === 'append') { - this.options.data = this.options.data.concat(data); - } else if (type === 'prepend') { - this.options.data = [].concat(data).concat(this.options.data); - } else { - this.options.data = this.data; - } - - if (this.options.sidePagination === 'server') { - return; - } - this.initSort(); - }; - - BootstrapTable.prototype.initSort = function () { - var that = this, - name = this.options.sortName, - order = this.options.sortOrder === 'desc' ? -1 : 1, - index = $.inArray(this.options.sortName, this.header.fields); - - if (index !== -1) { - this.data.sort(function (a, b) { - if (that.header.sortNames[index]) { - name = that.header.sortNames[index]; - } - var aa = getItemField(a, name), - bb = getItemField(b, name), - value = calculateObjectValue(that.header, that.header.sorters[index], [aa, bb]); - - if (value !== undefined) { - return order * value; - } - - // Fix #161: undefined or null string sort bug. - if (aa === undefined || aa === null) { - aa = ''; - } - if (bb === undefined || bb === null) { - bb = ''; - } - - // IF both values are numeric, do a numeric comparison - if ($.isNumeric(aa) && $.isNumeric(bb)) { - // Convert numerical values form string to float. - aa = parseFloat(aa); - bb = parseFloat(bb); - if (aa < bb) { - return order * -1; - } - return order; - } - - if (aa === bb) { - return 0; - } - - // If value is not a string, convert to string - if (typeof aa !== 'string') { - aa = aa.toString(); - } - - if (aa.localeCompare(bb) === -1) { - return order * -1; - } - - return order; - }); - } - }; - - BootstrapTable.prototype.onSort = function (event) { - var $this = event.type === "keypress" ? $(event.currentTarget) : $(event.currentTarget).parent(), - $this_ = this.$header.find('th').eq($this.index()); - - this.$header.add(this.$header_).find('span.order').remove(); - - if (this.options.sortName === $this.data('field')) { - this.options.sortOrder = this.options.sortOrder === 'asc' ? 'desc' : 'asc'; - } else { - this.options.sortName = $this.data('field'); - this.options.sortOrder = $this.data('order') === 'asc' ? 'desc' : 'asc'; - } - this.trigger('sort', this.options.sortName, this.options.sortOrder); - - $this.add($this_).data('order', this.options.sortOrder); - - // Assign the correct sortable arrow - this.getCaret(); - - if (this.options.sidePagination === 'server') { - this.initServer(this.options.silentSort); - return; - } - - this.initSort(); - this.initBody(); - }; - - BootstrapTable.prototype.initToolbar = function () { - var that = this, - html = [], - timeoutId = 0, - $keepOpen, - $search, - switchableCount = 0; - - this.$toolbar.html(''); - - if (typeof this.options.toolbar === 'string' || typeof this.options.toolbar === 'object') { - $(sprintf('
', this.options.toolbarAlign)) - .appendTo(this.$toolbar) - .append($(this.options.toolbar)); - } - - // showColumns, showToggle, showRefresh - html = [sprintf('
', - this.options.buttonsAlign, this.options.buttonsAlign)]; - - if (typeof this.options.icons === 'string') { - this.options.icons = calculateObjectValue(null, this.options.icons); - } - - if (this.options.showPaginationSwitch) { - html.push(sprintf(''); - } - - if (this.options.showRefresh) { - html.push(sprintf(''); - } - - if (this.options.showToggle) { - html.push(sprintf(''); - } - - if (this.options.showColumns) { - html.push(sprintf('
', - this.options.formatColumns()), - '', - '', - '
'); - } - - html.push('
'); - - // Fix #188: this.showToolbar is for extentions - if (this.showToolbar || html.length > 2) { - this.$toolbar.append(html.join('')); - } - - if (this.options.showPaginationSwitch) { - this.$toolbar.find('button[name="paginationSwitch"]') - .off('click').on('click', $.proxy(this.togglePagination, this)); - } - - if (this.options.showRefresh) { - this.$toolbar.find('button[name="refresh"]') - .off('click').on('click', $.proxy(this.refresh, this)); - } - - if (this.options.showToggle) { - this.$toolbar.find('button[name="toggle"]') - .off('click').on('click', function () { - that.toggleView(); - }); - } - - if (this.options.showColumns) { - $keepOpen = this.$toolbar.find('.keep-open'); - - if (switchableCount <= this.options.minimumCountColumns) { - $keepOpen.find('input').prop('disabled', true); - } - - $keepOpen.find('li').off('click').on('click', function (event) { - event.stopImmediatePropagation(); - }); - $keepOpen.find('input').off('click').on('click', function () { - var $this = $(this); - - that.toggleColumn(getFieldIndex(that.columns, - $(this).data('field')), $this.prop('checked'), false); - that.trigger('column-switch', $(this).data('field'), $this.prop('checked')); - }); - } - - if (this.options.search) { - html = []; - html.push( - ''); - - this.$toolbar.append(html.join('')); - $search = this.$toolbar.find('.search input'); - $search.off('keyup drop').on('keyup drop', function (event) { - clearTimeout(timeoutId); // doesn't matter if it's 0 - timeoutId = setTimeout(function () { - that.onSearch(event); - }, that.options.searchTimeOut); - }); - } - }; - - BootstrapTable.prototype.onSearch = function (event) { - var text = $.trim($(event.currentTarget).val()); - - // trim search input - if (this.options.trimOnSearch && $(event.currentTarget).val() !== text) { - $(event.currentTarget).val(text); - } - - if (text === this.searchText) { - return; - } - this.searchText = text; - - this.options.pageNumber = 1; - this.initSearch(); - this.updatePagination(); - this.trigger('search', text); - }; - - BootstrapTable.prototype.initSearch = function () { - var that = this; - - if (this.options.sidePagination !== 'server') { - var s = this.searchText && this.searchText.toLowerCase(); - var f = $.isEmptyObject(this.filterColumns) ? null : this.filterColumns; - - // Check filter - this.data = f ? $.grep(this.options.data, function (item, i) { - for (var key in f) { - if ($.isArray(f[key])) { - if ($.inArray(item[key], f[key]) === -1) { - return false; - } - } else if (item[key] !== f[key]) { - return false; - } - } - return true; - }) : this.options.data; - - this.data = s ? $.grep(this.data, function (item, i) { - for (var key in item) { - key = $.isNumeric(key) ? parseInt(key, 10) : key; - var value = item[key], - column = that.columns[getFieldIndex(that.columns, key)], - j = $.inArray(key, that.header.fields); - - // Fix #142: search use formated data - if (column && column.searchFormatter) { - value = calculateObjectValue(column, - that.header.formatters[j], [value, item, i], value); - } - - var index = $.inArray(key, that.header.fields); - if (index !== -1 && that.header.searchables[index] && (typeof value === 'string' || typeof value === 'number')) { - if (that.options.strictSearch) { - if ((value + '').toLowerCase() === s) { - return true; - } - } else { - if ((value + '').toLowerCase().indexOf(s) !== -1) { - return true; - } - } - } - } - return false; - }) : this.data; - } - }; - - BootstrapTable.prototype.initPagination = function () { - if (!this.options.pagination) { - this.$pagination.hide(); - return; - } else { - this.$pagination.show(); - } - - var that = this, - html = [], - $allSelected = false, - i, from, to, - $pageList, - $first, $pre, - $next, $last, - $number, - data = this.getData(); - - if (this.options.sidePagination !== 'server') { - this.options.totalRows = data.length; - } - - this.totalPages = 0; - if (this.options.totalRows) { - if (this.options.pageSize === this.options.formatAllRows()) { - this.options.pageSize = this.options.totalRows; - $allSelected = true; - } else if (this.options.pageSize === this.options.totalRows) { - // Fix #667 Table with pagination, - // multiple pages and a search that matches to one page throws exception - var pageLst = typeof this.options.pageList === 'string' ? - this.options.pageList.replace('[', '').replace(']', '') - .replace(/ /g, '').toLowerCase().split(',') : this.options.pageList; - if ($.inArray(this.options.formatAllRows().toLowerCase(), pageLst) > -1) { - $allSelected = true; - } - } - - this.totalPages = ~~((this.options.totalRows - 1) / this.options.pageSize) + 1; - - this.options.totalPages = this.totalPages; - } - if (this.totalPages > 0 && this.options.pageNumber > this.totalPages) { - this.options.pageNumber = this.totalPages; - } - - this.pageFrom = (this.options.pageNumber - 1) * this.options.pageSize + 1; - this.pageTo = this.options.pageNumber * this.options.pageSize; - if (this.pageTo > this.options.totalRows) { - this.pageTo = this.options.totalRows; - } - - html.push( - '
', - '', - this.options.onlyInfoPagination ? this.options.formatDetailPagination(this.options.totalRows) : - this.options.formatShowingRows(this.pageFrom, this.pageTo, this.options.totalRows), - ''); - - if (!this.options.onlyInfoPagination) { - html.push(''); - - var pageNumber = [ - sprintf('', - this.options.paginationVAlign === 'top' || this.options.paginationVAlign === 'both' ? - 'dropdown' : 'dropup'), - '', - ''); - - html.push(this.options.formatRecordsPerPage(pageNumber.join(''))); - html.push(''); - - html.push('
', - ''); - - } - this.$pagination.html(html.join('')); - - if (!this.options.onlyInfoPagination) { - $pageList = this.$pagination.find('.page-list a'); - $first = this.$pagination.find('.page-first'); - $pre = this.$pagination.find('.page-pre'); - $next = this.$pagination.find('.page-next'); - $last = this.$pagination.find('.page-last'); - $number = this.$pagination.find('.page-number'); - - if (this.options.pageNumber <= 1) { - $first.addClass('disabled'); - $pre.addClass('disabled'); - } - if (this.options.pageNumber >= this.totalPages) { - $next.addClass('disabled'); - $last.addClass('disabled'); - } - if (this.options.smartDisplay) { - if (this.totalPages <= 1) { - this.$pagination.find('div.pagination').hide(); - } - if (pageList.length < 2 || this.options.totalRows <= pageList[0]) { - this.$pagination.find('span.page-list').hide(); - } - - // when data is empty, hide the pagination - this.$pagination[this.getData().length ? 'show' : 'hide'](); - } - if ($allSelected) { - this.options.pageSize = this.options.formatAllRows(); - } - $pageList.off('click').on('click', $.proxy(this.onPageListChange, this)); - $first.off('click').on('click', $.proxy(this.onPageFirst, this)); - $pre.off('click').on('click', $.proxy(this.onPagePre, this)); - $next.off('click').on('click', $.proxy(this.onPageNext, this)); - $last.off('click').on('click', $.proxy(this.onPageLast, this)); - $number.off('click').on('click', $.proxy(this.onPageNumber, this)); - } - }; - - BootstrapTable.prototype.updatePagination = function (event) { - // Fix #171: IE disabled button can be clicked bug. - if (event && $(event.currentTarget).hasClass('disabled')) { - return; - } - - if (!this.options.maintainSelected) { - this.resetRows(); - } - - this.initPagination(); - if (this.options.sidePagination === 'server') { - this.initServer(); - } else { - this.initBody(); - } - - this.trigger('page-change', this.options.pageNumber, this.options.pageSize); - }; - - BootstrapTable.prototype.onPageListChange = function (event) { - var $this = $(event.currentTarget); - - $this.parent().addClass('active').siblings().removeClass('active'); - this.options.pageSize = $this.text().toUpperCase() === this.options.formatAllRows().toUpperCase() ? - this.options.formatAllRows() : +$this.text(); - this.$toolbar.find('.page-size').text(this.options.pageSize); - - this.updatePagination(event); - }; - - BootstrapTable.prototype.onPageFirst = function (event) { - this.options.pageNumber = 1; - this.updatePagination(event); - }; - - BootstrapTable.prototype.onPagePre = function (event) { - this.options.pageNumber--; - this.updatePagination(event); - }; - - BootstrapTable.prototype.onPageNext = function (event) { - this.options.pageNumber++; - this.updatePagination(event); - }; - - BootstrapTable.prototype.onPageLast = function (event) { - this.options.pageNumber = this.totalPages; - this.updatePagination(event); - }; - - BootstrapTable.prototype.onPageNumber = function (event) { - if (this.options.pageNumber === +$(event.currentTarget).text()) { - return; - } - this.options.pageNumber = +$(event.currentTarget).text(); - this.updatePagination(event); - }; - - BootstrapTable.prototype.initBody = function (fixedScroll) { - var that = this, - html = [], - data = this.getData(); - - this.trigger('pre-body', data); - - this.$body = this.$el.find('>tbody'); - if (!this.$body.length) { - this.$body = $('').appendTo(this.$el); - } - - //Fix #389 Bootstrap-table-flatJSON is not working - - if (!this.options.pagination || this.options.sidePagination === 'server') { - this.pageFrom = 1; - this.pageTo = data.length; - } - - for (var i = this.pageFrom - 1; i < this.pageTo; i++) { - var key, - item = data[i], - style = {}, - csses = [], - data_ = '', - attributes = {}, - htmlAttributes = []; - - style = calculateObjectValue(this.options, this.options.rowStyle, [item, i], style); - - if (style && style.css) { - for (key in style.css) { - csses.push(key + ': ' + style.css[key]); - } - } - - attributes = calculateObjectValue(this.options, - this.options.rowAttributes, [item, i], attributes); - - if (attributes) { - for (key in attributes) { - htmlAttributes.push(sprintf('%s="%s"', key, escapeHTML(attributes[key]))); - } - } - - if (item._data && !$.isEmptyObject(item._data)) { - $.each(item._data, function (k, v) { - // ignore data-index - if (k === 'index') { - return; - } - data_ += sprintf(' data-%s="%s"', k, v); - }); - } - - html.push('' - ); - - if (this.options.cardView) { - html.push(sprintf('', this.header.fields.length)); - } - - if (!this.options.cardView && this.options.detailView) { - html.push('', - '', - sprintf('', this.options.iconsPrefix, this.options.icons.detailOpen), - '', - ''); - } - - $.each(this.header.fields, function (j, field) { - var text = '', - value = getItemField(item, field), - type = '', - cellStyle = {}, - id_ = '', - class_ = that.header.classes[j], - data_ = '', - rowspan_ = '', - title_ = '', - column = that.columns[getFieldIndex(that.columns, field)]; - - if (!column.visible) { - return; - } - - style = sprintf('style="%s"', csses.concat(that.header.styles[j]).join('; ')); - - value = calculateObjectValue(column, - that.header.formatters[j], [value, item, i], value); - - // handle td's id and class - if (item['_' + field + '_id']) { - id_ = sprintf(' id="%s"', item['_' + field + '_id']); - } - if (item['_' + field + '_class']) { - class_ = sprintf(' class="%s"', item['_' + field + '_class']); - } - if (item['_' + field + '_rowspan']) { - rowspan_ = sprintf(' rowspan="%s"', item['_' + field + '_rowspan']); - } - if (item['_' + field + '_title']) { - title_ = sprintf(' title="%s"', item['_' + field + '_title']); - } - cellStyle = calculateObjectValue(that.header, - that.header.cellStyles[j], [value, item, i], cellStyle); - if (cellStyle.classes) { - class_ = sprintf(' class="%s"', cellStyle.classes); - } - if (cellStyle.css) { - var csses_ = []; - for (var key in cellStyle.css) { - csses_.push(key + ': ' + cellStyle.css[key]); - } - style = sprintf('style="%s"', csses_.concat(that.header.styles[j]).join('; ')); - } - - if (item['_' + field + '_data'] && !$.isEmptyObject(item['_' + field + '_data'])) { - $.each(item['_' + field + '_data'], function (k, v) { - // ignore data-index - if (k === 'index') { - return; - } - data_ += sprintf(' data-%s="%s"', k, v); - }); - } - - if (column.checkbox || column.radio) { - type = column.checkbox ? 'checkbox' : type; - type = column.radio ? 'radio' : type; - - text = [that.options.cardView ? - '
' : '', - '', - that.header.formatters[j] && typeof value === 'string' ? value : '', - that.options.cardView ? '
' : '' - ].join(''); - - item[that.header.stateField] = value === true || (value && value.checked); - } else { - value = typeof value === 'undefined' || value === null ? - that.options.undefinedText : value; - - text = that.options.cardView ? ['
', - that.options.showHeader ? sprintf('%s', style, - getPropertyFromOther(that.columns, 'field', 'title', field)) : '', - sprintf('%s', value), - '
' - ].join('') : [sprintf('', id_, class_, style, data_, rowspan_, title_), - value, - '' - ].join(''); - - // Hide empty data on Card view when smartDisplay is set to true. - if (that.options.cardView && that.options.smartDisplay && value === '') { - // Should set a placeholder for event binding correct fieldIndex - text = '
'; - } - } - - html.push(text); - }); - - if (this.options.cardView) { - html.push(''); - } - - html.push(''); - } - - // show no records - if (!html.length) { - html.push('', - sprintf('%s', - this.$header.find('th').length, this.options.formatNoMatches()), - ''); - } - - this.$body.html(html.join('')); - - if (!fixedScroll) { - this.scrollTo(0); - } - - // click to select by column - this.$body.find('> tr[data-index] > td').off('click dblclick').on('click dblclick', function (e) { - var $td = $(this), - $tr = $td.parent(), - item = that.data[$tr.data('index')], - index = $td[0].cellIndex, - field = that.header.fields[that.options.detailView && !that.options.cardView ? index - 1 : index], - column = that.columns[getFieldIndex(that.columns, field)], - value = getItemField(item, field); - - if ($td.find('.detail-icon').length) { - return; - } - - that.trigger(e.type === 'click' ? 'click-cell' : 'dbl-click-cell', field, value, item, $td); - that.trigger(e.type === 'click' ? 'click-row' : 'dbl-click-row', item, $tr); - - // if click to select - then trigger the checkbox/radio click - if (e.type === 'click' && that.options.clickToSelect && column.clickToSelect) { - var $selectItem = $tr.find(sprintf('[name="%s"]', that.options.selectItemName)); - if ($selectItem.length) { - $selectItem[0].click(); // #144: .trigger('click') bug - } - } - }); - - this.$body.find('> tr[data-index] > td > .detail-icon').off('click').on('click', function () { - var $this = $(this), - $tr = $this.parent().parent(), - index = $tr.data('index'), - row = data[index]; // Fix #980 Detail view, when searching, returns wrong row - - // remove and update - if ($tr.next().is('tr.detail-view')) { - $this.find('i').attr('class', sprintf('%s %s', that.options.iconsPrefix, that.options.icons.detailOpen)); - $tr.next().remove(); - that.trigger('collapse-row', index, row); - } else { - $this.find('i').attr('class', sprintf('%s %s', that.options.iconsPrefix, that.options.icons.detailClose)); - $tr.after(sprintf('%s', - $tr.find('td').length, calculateObjectValue(that.options, - that.options.detailFormatter, [index, row], ''))); - that.trigger('expand-row', index, row, $tr.next().find('td')); - } - that.resetView(); - }); - - this.$selectItem = this.$body.find(sprintf('[name="%s"]', this.options.selectItemName)); - this.$selectItem.off('click').on('click', function (event) { - event.stopImmediatePropagation(); - - var $this = $(this), - checked = $this.prop('checked'), - row = that.data[$this.data('index')]; - - if (that.options.maintainSelected && $(this).is(':radio')) { - $.each(that.options.data, function (i, row) { - row[that.header.stateField] = false; - }); - } - - row[that.header.stateField] = checked; - - if (that.options.singleSelect) { - that.$selectItem.not(this).each(function () { - that.data[$(this).data('index')][that.header.stateField] = false; - }); - that.$selectItem.filter(':checked').not(this).prop('checked', false); - } - - that.updateSelected(); - that.trigger(checked ? 'check' : 'uncheck', row, $this); - }); - - $.each(this.header.events, function (i, events) { - if (!events) { - return; - } - // fix bug, if events is defined with namespace - if (typeof events === 'string') { - events = calculateObjectValue(null, events); - } - - var field = that.header.fields[i], - fieldIndex = $.inArray(field, that.getVisibleFields()); - - if (that.options.detailView && !that.options.cardView) { - fieldIndex += 1; - } - - for (var key in events) { - that.$body.find('>tr:not(.no-records-found)').each(function () { - var $tr = $(this), - $td = $tr.find(that.options.cardView ? '.card-view' : 'td').eq(fieldIndex), - index = key.indexOf(' '), - name = key.substring(0, index), - el = key.substring(index + 1), - func = events[key]; - - $td.find(el).off(name).on(name, function (e) { - var index = $tr.data('index'), - row = that.data[index], - value = row[field]; - - func.apply(this, [e, value, row, index]); - }); - }); - } - }); - - this.updateSelected(); - this.resetView(); - - this.trigger('post-body'); - }; - - BootstrapTable.prototype.initServer = function (silent, query) { - var that = this, - data = {}, - params = { - pageSize: this.options.pageSize === this.options.formatAllRows() ? - this.options.totalRows : this.options.pageSize, - pageNumber: this.options.pageNumber, - searchText: this.searchText, - sortName: this.options.sortName, - sortOrder: this.options.sortOrder - }, - request; - - if (!this.options.url && !this.options.ajax) { - return; - } - - if (this.options.queryParamsType === 'limit') { - params = { - search: params.searchText, - sort: params.sortName, - order: params.sortOrder - }; - if (this.options.pagination) { - params.limit = this.options.pageSize === this.options.formatAllRows() ? - this.options.totalRows : this.options.pageSize; - params.offset = this.options.pageSize === this.options.formatAllRows() ? - 0 : this.options.pageSize * (this.options.pageNumber - 1); - } - } - - if (!($.isEmptyObject(this.filterColumnsPartial))) { - params['filter'] = JSON.stringify(this.filterColumnsPartial, null); - } - - data = calculateObjectValue(this.options, this.options.queryParams, [params], data); - - $.extend(data, query || {}); - - // false to stop request - if (data === false) { - return; - } - - if (!silent) { - this.$tableLoading.show(); - } - request = $.extend({}, calculateObjectValue(null, this.options.ajaxOptions), { - type: this.options.method, - url: this.options.url, - data: this.options.contentType === 'application/json' && this.options.method === 'post' ? - JSON.stringify(data) : data, - cache: this.options.cache, - contentType: this.options.contentType, - dataType: this.options.dataType, - success: function (res) { - res = calculateObjectValue(that.options, that.options.responseHandler, [res], res); - - that.load(res); - that.trigger('load-success', res); - }, - error: function (res) { - that.trigger('load-error', res.status, res); - }, - complete: function () { - if (!silent) { - that.$tableLoading.hide(); - } - } - }); - - if (this.options.ajax) { - calculateObjectValue(this, this.options.ajax, [request], null); - } else { - $.ajax(request); - } - }; - - BootstrapTable.prototype.initSearchText = function () { - if (this.options.search) { - if (this.options.searchText !== '') { - var $search = this.$toolbar.find('.search input'); - $search.val(this.options.searchText); - this.onSearch({currentTarget: $search}); - } - } - }; - - BootstrapTable.prototype.getCaret = function () { - var that = this; - - $.each(this.$header.find('th'), function (i, th) { - $(th).find('.sortable').removeClass('desc asc').addClass($(th).data('field') === that.options.sortName ? that.options.sortOrder : 'both'); - }); - }; - - BootstrapTable.prototype.updateSelected = function () { - var checkAll = this.$selectItem.filter(':enabled').length && - this.$selectItem.filter(':enabled').length === - this.$selectItem.filter(':enabled').filter(':checked').length; - - this.$selectAll.add(this.$selectAll_).prop('checked', checkAll); - - this.$selectItem.each(function () { - $(this).closest('tr')[$(this).prop('checked') ? 'addClass' : 'removeClass']('selected'); - }); - }; - - BootstrapTable.prototype.updateRows = function () { - var that = this; - - this.$selectItem.each(function () { - that.data[$(this).data('index')][that.header.stateField] = $(this).prop('checked'); - }); - }; - - BootstrapTable.prototype.resetRows = function () { - var that = this; - - $.each(this.data, function (i, row) { - that.$selectAll.prop('checked', false); - that.$selectItem.prop('checked', false); - if (that.header.stateField) { - row[that.header.stateField] = false; - } - }); - }; - - BootstrapTable.prototype.trigger = function (name) { - var args = Array.prototype.slice.call(arguments, 1); - - name += '.bs.table'; - this.options[BootstrapTable.EVENTS[name]].apply(this.options, args); - this.$el.trigger($.Event(name), args); - - this.options.onAll(name, args); - this.$el.trigger($.Event('all.bs.table'), [name, args]); - }; - - BootstrapTable.prototype.resetHeader = function () { - // fix #61: the hidden table reset header bug. - // fix bug: get $el.css('width') error sometime (height = 500) - clearTimeout(this.timeoutId_); - this.timeoutId_ = setTimeout($.proxy(this.fitHeader, this), this.$el.is(':hidden') ? 100 : 0); - }; - - BootstrapTable.prototype.fitHeader = function () { - var that = this, - fixedBody, - scrollWidth, - focused, - focusedTemp; - - if (that.$el.is(':hidden')) { - that.timeoutId_ = setTimeout($.proxy(that.fitHeader, that), 100); - return; - } - fixedBody = this.$tableBody.get(0); - - scrollWidth = fixedBody.scrollWidth > fixedBody.clientWidth && - fixedBody.scrollHeight > fixedBody.clientHeight + this.$header.outerHeight() ? - getScrollBarWidth() : 0; - - this.$el.css('margin-top', -this.$header.outerHeight()); - - focused = $(':focus'); - if (focused.length > 0) { - var $th = focused.parents('th'); - if ($th.length > 0) { - var dataField = $th.attr('data-field'); - if (dataField !== undefined) { - var $headerTh = this.$header.find("[data-field='" + dataField + "']"); - if ($headerTh.length > 0) { - $headerTh.find(":input").addClass("focus-temp"); - } - } - } - } - - this.$header_ = this.$header.clone(true, true); - this.$selectAll_ = this.$header_.find('[name="btSelectAll"]'); - this.$tableHeader.css({ - 'margin-right': scrollWidth - }).find('table').css('width', this.$el.outerWidth()) - .html('').attr('class', this.$el.attr('class')) - .append(this.$header_); - - - focusedTemp = $('.focus-temp:visible:eq(0)'); - if (focusedTemp.length > 0) { - focusedTemp.focus(); - this.$header.find('.focus-temp').removeClass('focus-temp'); - } - - // fix bug: $.data() is not working as expected after $.append() - this.$header.find('th[data-field]').each(function (i) { - that.$header_.find(sprintf('th[data-field="%s"]', $(this).data('field'))).data($(this).data()); - }); - - var visibleFields = this.getVisibleFields(); - - this.$body.find('>tr:first-child:not(.no-records-found) > *').each(function (i) { - var $this = $(this), - index = i; - - if (that.options.detailView && !that.options.cardView) { - if (i === 0) { - that.$header_.find('th.detail').find('.fht-cell').width($this.innerWidth()); - } - index = i - 1; - } - - that.$header_.find(sprintf('th[data-field="%s"]', visibleFields[index])) - .find('.fht-cell').width($this.innerWidth()); - }); - // horizontal scroll event - // TODO: it's probably better improving the layout than binding to scroll event - this.$tableBody.off('scroll').on('scroll', function () { - that.$tableHeader.scrollLeft($(this).scrollLeft()); - - if (that.options.showFooter && !that.options.cardView) { - that.$tableFooter.scrollLeft($(this).scrollLeft()); - } - }); - that.trigger('post-header'); - }; - - BootstrapTable.prototype.resetFooter = function () { - var that = this, - data = that.getData(), - html = []; - - if (!this.options.showFooter || this.options.cardView) { //do nothing - return; - } - - if (!this.options.cardView && this.options.detailView) { - html.push('
 
'); - } - - $.each(this.columns, function (i, column) { - var falign = '', // footer align style - style = '', - class_ = sprintf(' class="%s"', column['class']); - - if (!column.visible) { - return; - } - - if (that.options.cardView && (!column.cardVisible)) { - return; - } - - falign = sprintf('text-align: %s; ', column.falign ? column.falign : column.align); - style = sprintf('vertical-align: %s; ', column.valign); - - html.push(''); - html.push('
'); - - html.push(calculateObjectValue(column, column.footerFormatter, [data], ' ') || ' '); - - html.push('
'); - html.push('
'); - html.push(''); - html.push(''); - }); - - this.$tableFooter.find('tr').html(html.join('')); - clearTimeout(this.timeoutFooter_); - this.timeoutFooter_ = setTimeout($.proxy(this.fitFooter, this), - this.$el.is(':hidden') ? 100 : 0); - }; - - BootstrapTable.prototype.fitFooter = function () { - var that = this, - $footerTd, - elWidth, - scrollWidth; - - clearTimeout(this.timeoutFooter_); - if (this.$el.is(':hidden')) { - this.timeoutFooter_ = setTimeout($.proxy(this.fitFooter, this), 100); - return; - } - - elWidth = this.$el.css('width'); - scrollWidth = elWidth > this.$tableBody.width() ? getScrollBarWidth() : 0; - - this.$tableFooter.css({ - 'margin-right': scrollWidth - }).find('table').css('width', elWidth) - .attr('class', this.$el.attr('class')); - - $footerTd = this.$tableFooter.find('td'); - - this.$body.find('>tr:first-child:not(.no-records-found) > *').each(function (i) { - var $this = $(this); - - $footerTd.eq(i).find('.fht-cell').width($this.innerWidth()); - }); - }; - - BootstrapTable.prototype.toggleColumn = function (index, checked, needUpdate) { - if (index === -1) { - return; - } - this.columns[index].visible = checked; - this.initHeader(); - this.initSearch(); - this.initPagination(); - this.initBody(); - - if (this.options.showColumns) { - var $items = this.$toolbar.find('.keep-open input').prop('disabled', false); - - if (needUpdate) { - $items.filter(sprintf('[value="%s"]', index)).prop('checked', checked); - } - - if ($items.filter(':checked').length <= this.options.minimumCountColumns) { - $items.filter(':checked').prop('disabled', true); - } - } - }; - - BootstrapTable.prototype.toggleRow = function (index, uniqueId, visible) { - if (index === -1) { - return; - } - - this.$body.find(typeof index !== 'undefined' ? - sprintf('tr[data-index="%s"]', index) : - sprintf('tr[data-uniqueid="%s"]', uniqueId)) - [visible ? 'show' : 'hide'](); - }; - - BootstrapTable.prototype.getVisibleFields = function () { - var that = this, - visibleFields = []; - - $.each(this.header.fields, function (j, field) { - var column = that.columns[getFieldIndex(that.columns, field)]; - - if (!column.visible) { - return; - } - visibleFields.push(field); - }); - return visibleFields; - }; - - // PUBLIC FUNCTION DEFINITION - // ======================= - - BootstrapTable.prototype.resetView = function (params) { - var padding = 0; - - if (params && params.height) { - this.options.height = params.height; - } - - this.$selectAll.prop('checked', this.$selectItem.length > 0 && - this.$selectItem.length === this.$selectItem.filter(':checked').length); - - if (this.options.height) { - var toolbarHeight = getRealHeight(this.$toolbar), - paginationHeight = getRealHeight(this.$pagination), - height = this.options.height - toolbarHeight - paginationHeight; - - this.$tableContainer.css('height', height + 'px'); - } - - if (this.options.cardView) { - // remove the element css - this.$el.css('margin-top', '0'); - this.$tableContainer.css('padding-bottom', '0'); - return; - } - - if (this.options.showHeader && this.options.height) { - this.$tableHeader.show(); - this.resetHeader(); - padding += this.$header.outerHeight(); - } else { - this.$tableHeader.hide(); - this.trigger('post-header'); - } - - if (this.options.showFooter) { - this.resetFooter(); - if (this.options.height) { - padding += this.$tableFooter.outerHeight() + 1; - } - } - - // Assign the correct sortable arrow - this.getCaret(); - this.$tableContainer.css('padding-bottom', padding + 'px'); - this.trigger('reset-view'); - }; - - BootstrapTable.prototype.getData = function (useCurrentPage) { - return (this.searchText || !$.isEmptyObject(this.filterColumns) || !$.isEmptyObject(this.filterColumnsPartial)) ? - (useCurrentPage ? this.data.slice(this.pageFrom - 1, this.pageTo) : this.data) : - (useCurrentPage ? this.options.data.slice(this.pageFrom - 1, this.pageTo) : this.options.data); - }; - - BootstrapTable.prototype.load = function (data) { - var fixedScroll = false; - - // #431: support pagination - if (this.options.sidePagination === 'server') { - this.options.totalRows = data.total; - fixedScroll = data.fixedScroll; - data = data[this.options.dataField]; - } else if (!$.isArray(data)) { // support fixedScroll - fixedScroll = data.fixedScroll; - data = data.data; - } - - this.initData(data); - this.initSearch(); - this.initPagination(); - this.initBody(fixedScroll); - }; - - BootstrapTable.prototype.append = function (data) { - this.initData(data, 'append'); - this.initSearch(); - this.initPagination(); - this.initBody(true); - }; - - BootstrapTable.prototype.prepend = function (data) { - this.initData(data, 'prepend'); - this.initSearch(); - this.initPagination(); - this.initBody(true); - }; - - BootstrapTable.prototype.remove = function (params) { - var len = this.options.data.length, - i, row; - - if (!params.hasOwnProperty('field') || !params.hasOwnProperty('values')) { - return; - } - - for (i = len - 1; i >= 0; i--) { - row = this.options.data[i]; - - if (!row.hasOwnProperty(params.field)) { - continue; - } - if ($.inArray(row[params.field], params.values) !== -1) { - this.options.data.splice(i, 1); - } - } - - if (len === this.options.data.length) { - return; - } - - this.initSearch(); - this.initPagination(); - this.initBody(true); - }; - - BootstrapTable.prototype.removeAll = function () { - if (this.options.data.length > 0) { - this.options.data.splice(0, this.options.data.length); - this.initSearch(); - this.initPagination(); - this.initBody(true); - } - }; - - BootstrapTable.prototype.getRowByUniqueId = function (id) { - var uniqueId = this.options.uniqueId, - len = this.options.data.length, - dataRow = null, - i, row, rowUniqueId; - - for (i = len - 1; i >= 0; i--) { - row = this.options.data[i]; - - if (row.hasOwnProperty(uniqueId)) { // uniqueId is a column - rowUniqueId = row[uniqueId]; - } else if(row._data.hasOwnProperty(uniqueId)) { // uniqueId is a row data property - rowUniqueId = row._data[uniqueId]; - } else { - continue; - } - - if (typeof rowUniqueId === 'string') { - id = id.toString(); - } else if (typeof rowUniqueId === 'number') { - if ((Number(rowUniqueId) === rowUniqueId) && (rowUniqueId % 1 === 0)) { - id = parseInt(id); - } else if ((rowUniqueId === Number(rowUniqueId)) && (rowUniqueId !== 0)) { - id = parseFloat(id); - } - } - - if (rowUniqueId === id) { - dataRow = row; - break; - } - } - - return dataRow; - }; - - BootstrapTable.prototype.removeByUniqueId = function (id) { - var len = this.options.data.length, - row = this.getRowByUniqueId(id); - - if (row) { - this.options.data.splice(this.options.data.indexOf(row), 1); - } - - if (len === this.options.data.length) { - return; - } - - this.initSearch(); - this.initPagination(); - this.initBody(true); - }; - - BootstrapTable.prototype.updateByUniqueId = function (params) { - var rowId; - - if (!params.hasOwnProperty('id') || !params.hasOwnProperty('row')) { - return; - } - - rowId = $.inArray(this.getRowByUniqueId(params.id), this.options.data); - - if (rowId === -1) { - return; - } - - $.extend(this.data[rowId], params.row); - this.initSort(); - this.initBody(true); - }; - - BootstrapTable.prototype.insertRow = function (params) { - if (!params.hasOwnProperty('index') || !params.hasOwnProperty('row')) { - return; - } - this.data.splice(params.index, 0, params.row); - this.initSearch(); - this.initPagination(); - this.initSort(); - this.initBody(true); - }; - - BootstrapTable.prototype.updateRow = function (params) { - if (!params.hasOwnProperty('index') || !params.hasOwnProperty('row')) { - return; - } - $.extend(this.data[params.index], params.row); - this.initSort(); - this.initBody(true); - }; - - BootstrapTable.prototype.showRow = function (params) { - if (!params.hasOwnProperty('index') || !params.hasOwnProperty('uniqueId')) { - return; - } - this.toggleRow(params.index, params.uniqueId, true); - }; - - BootstrapTable.prototype.hideRow = function (params) { - if (!params.hasOwnProperty('index') || !params.hasOwnProperty('uniqueId')) { - return; - } - this.toggleRow(params.index, params.uniqueId, false); - }; - - BootstrapTable.prototype.getRowsHidden = function (show) { - var rows = $(this.$body[0]).children().filter(':hidden'), - i = 0; - if (show) { - for (; i < rows.length; i++) { - $(rows[i]).show(); - } - } - return rows; - }; - - BootstrapTable.prototype.mergeCells = function (options) { - var row = options.index, - col = $.inArray(options.field, this.getVisibleFields()), - rowspan = options.rowspan || 1, - colspan = options.colspan || 1, - i, j, - $tr = this.$body.find('>tr'), - $td; - - if (this.options.detailView && !this.options.cardView) { - col += 1; - } - - $td = $tr.eq(row).find('>td').eq(col); - - if (row < 0 || col < 0 || row >= this.data.length) { - return; - } - - for (i = row; i < row + rowspan; i++) { - for (j = col; j < col + colspan; j++) { - $tr.eq(i).find('>td').eq(j).hide(); - } - } - - $td.attr('rowspan', rowspan).attr('colspan', colspan).show(); - }; - - BootstrapTable.prototype.updateCell = function (params) { - if (!params.hasOwnProperty('index') || - !params.hasOwnProperty('field') || - !params.hasOwnProperty('value')) { - return; - } - this.data[params.index][params.field] = params.value; - this.initSort(); - this.initBody(true); - }; - - BootstrapTable.prototype.getOptions = function () { - return this.options; - }; - - BootstrapTable.prototype.getSelections = function () { - var that = this; - - return $.grep(this.data, function (row) { - return row[that.header.stateField]; - }); - }; - - BootstrapTable.prototype.getAllSelections = function () { - var that = this; - - return $.grep(this.options.data, function (row) { - return row[that.header.stateField]; - }); - }; - - BootstrapTable.prototype.checkAll = function () { - this.checkAll_(true); - }; - - BootstrapTable.prototype.uncheckAll = function () { - this.checkAll_(false); - }; - - BootstrapTable.prototype.checkAll_ = function (checked) { - var rows; - if (!checked) { - rows = this.getSelections(); - } - this.$selectAll.add(this.$selectAll_).prop('checked', checked); - this.$selectItem.filter(':enabled').prop('checked', checked); - this.updateRows(); - if (checked) { - rows = this.getSelections(); - } - this.trigger(checked ? 'check-all' : 'uncheck-all', rows); - }; - - BootstrapTable.prototype.check = function (index) { - this.check_(true, index); - }; - - BootstrapTable.prototype.uncheck = function (index) { - this.check_(false, index); - }; - - BootstrapTable.prototype.check_ = function (checked, index) { - var $el = this.$selectItem.filter(sprintf('[data-index="%s"]', index)).prop('checked', checked); - this.data[index][this.header.stateField] = checked; - this.updateSelected(); - this.trigger(checked ? 'check' : 'uncheck', this.data[index], $el); - }; - - BootstrapTable.prototype.checkBy = function (obj) { - this.checkBy_(true, obj); - }; - - BootstrapTable.prototype.uncheckBy = function (obj) { - this.checkBy_(false, obj); - }; - - BootstrapTable.prototype.checkBy_ = function (checked, obj) { - if (!obj.hasOwnProperty('field') || !obj.hasOwnProperty('values')) { - return; - } - - var that = this, - rows = []; - $.each(this.options.data, function (index, row) { - if (!row.hasOwnProperty(obj.field)) { - return false; - } - if ($.inArray(row[obj.field], obj.values) !== -1) { - var $el = that.$selectItem.filter(':enabled') - .filter(sprintf('[data-index="%s"]', index)).prop('checked', checked); - row[that.header.stateField] = checked; - rows.push(row); - that.trigger(checked ? 'check' : 'uncheck', row, $el); - } - }); - this.updateSelected(); - this.trigger(checked ? 'check-some' : 'uncheck-some', rows); - }; - - BootstrapTable.prototype.destroy = function () { - this.$el.insertBefore(this.$container); - $(this.options.toolbar).insertBefore(this.$el); - this.$container.next().remove(); - this.$container.remove(); - this.$el.html(this.$el_.html()) - .css('margin-top', '0') - .attr('class', this.$el_.attr('class') || ''); // reset the class - }; - - BootstrapTable.prototype.showLoading = function () { - this.$tableLoading.show(); - }; - - BootstrapTable.prototype.hideLoading = function () { - this.$tableLoading.hide(); - }; - - BootstrapTable.prototype.togglePagination = function () { - this.options.pagination = !this.options.pagination; - var button = this.$toolbar.find('button[name="paginationSwitch"] i'); - if (this.options.pagination) { - button.attr("class", this.options.iconsPrefix + " " + this.options.icons.paginationSwitchDown); - } else { - button.attr("class", this.options.iconsPrefix + " " + this.options.icons.paginationSwitchUp); - } - this.updatePagination(); - }; - - BootstrapTable.prototype.refresh = function (params) { - if (params && params.url) { - this.options.url = params.url; - this.options.pageNumber = 1; - } - this.initServer(params && params.silent, params && params.query); - }; - - BootstrapTable.prototype.resetWidth = function () { - if (this.options.showHeader && this.options.height) { - this.fitHeader(); - } - if (this.options.showFooter) { - this.fitFooter(); - } - }; - - BootstrapTable.prototype.showColumn = function (field) { - this.toggleColumn(getFieldIndex(this.columns, field), true, true); - }; - - BootstrapTable.prototype.hideColumn = function (field) { - this.toggleColumn(getFieldIndex(this.columns, field), false, true); - }; - - BootstrapTable.prototype.getHiddenColumns = function () { - return $.grep(this.columns, function (column) { - return !column.visible; - }); - }; - - BootstrapTable.prototype.filterBy = function (columns) { - this.filterColumns = $.isEmptyObject(columns) ? {} : columns; - this.options.pageNumber = 1; - this.initSearch(); - this.updatePagination(); - }; - - BootstrapTable.prototype.scrollTo = function (value) { - if (typeof value === 'string') { - value = value === 'bottom' ? this.$tableBody[0].scrollHeight : 0; - } - if (typeof value === 'number') { - this.$tableBody.scrollTop(value); - } - if (typeof value === 'undefined') { - return this.$tableBody.scrollTop(); - } - }; - - BootstrapTable.prototype.getScrollPosition = function () { - return this.scrollTo(); - }; - - BootstrapTable.prototype.selectPage = function (page) { - if (page > 0 && page <= this.options.totalPages) { - this.options.pageNumber = page; - this.updatePagination(); - } - }; - - BootstrapTable.prototype.prevPage = function () { - if (this.options.pageNumber > 1) { - this.options.pageNumber--; - this.updatePagination(); - } - }; - - BootstrapTable.prototype.nextPage = function () { - if (this.options.pageNumber < this.options.totalPages) { - this.options.pageNumber++; - this.updatePagination(); - } - }; - - BootstrapTable.prototype.toggleView = function () { - this.options.cardView = !this.options.cardView; - this.initHeader(); - // Fixed remove toolbar when click cardView button. - //that.initToolbar(); - this.initBody(); - this.trigger('toggle', this.options.cardView); - }; - - BootstrapTable.prototype.refreshOptions = function (options) { - //If the objects are equivalent then avoid the call of destroy / init methods - if (compareObjects(this.options, options, false)) { - return; - } - this.options = $.extend(this.options, options); - this.trigger('refresh-options', this.options); - this.destroy(); - this.init(); - }; - - BootstrapTable.prototype.resetSearch = function (text) { - var $search = this.$toolbar.find('.search input'); - $search.val(text || ''); - this.onSearch({currentTarget: $search}); - }; - - BootstrapTable.prototype.expandRow_ = function (expand, index) { - var $tr = this.$body.find(sprintf('> tr[data-index="%s"]', index)); - if ($tr.next().is('tr.detail-view') === (expand ? false : true)) { - $tr.find('> td > .detail-icon').click(); - } - }; - - BootstrapTable.prototype.expandRow = function (index) { - this.expandRow_(true, index); - }; - - BootstrapTable.prototype.collapseRow = function (index) { - this.expandRow_(false, index); - }; - - BootstrapTable.prototype.expandAllRows = function (isSubTable) { - if (isSubTable) { - var $tr = this.$body.find(sprintf('> tr[data-index="%s"]', 0)), - that = this, - detailIcon = null, - executeInterval = false, - idInterval = -1; - - if (!$tr.next().is('tr.detail-view')) { - $tr.find('> td > .detail-icon').click(); - executeInterval = true; - } else if (!$tr.next().next().is('tr.detail-view')) { - $tr.next().find(".detail-icon").click(); - executeInterval = true; - } - - if (executeInterval) { - try { - idInterval = setInterval(function () { - detailIcon = that.$body.find("tr.detail-view").last().find(".detail-icon"); - if (detailIcon.length > 0) { - detailIcon.click(); - } else { - clearInterval(idInterval); - } - }, 1); - } catch (ex) { - clearInterval(idInterval); - } - } - } else { - var trs = this.$body.children(); - for (var i = 0; i < trs.length; i++) { - this.expandRow_(true, $(trs[i]).data("index")); - } - } - }; - - BootstrapTable.prototype.collapseAllRows = function (isSubTable) { - if (isSubTable) { - this.expandRow_(false, 0); - } else { - var trs = this.$body.children(); - for (var i = 0; i < trs.length; i++) { - this.expandRow_(false, $(trs[i]).data("index")); - } - } - }; - - // BOOTSTRAP TABLE PLUGIN DEFINITION - // ======================= - - var allowedMethods = [ - 'getOptions', - 'getSelections', 'getAllSelections', 'getData', - 'load', 'append', 'prepend', 'remove', 'removeAll', - 'insertRow', 'updateRow', 'updateCell', 'updateByUniqueId', 'removeByUniqueId', - 'getRowByUniqueId', 'showRow', 'hideRow', 'getRowsHidden', - 'mergeCells', - 'checkAll', 'uncheckAll', - 'check', 'uncheck', - 'checkBy', 'uncheckBy', - 'refresh', - 'resetView', - 'resetWidth', - 'destroy', - 'showLoading', 'hideLoading', - 'showColumn', 'hideColumn', 'getHiddenColumns', - 'filterBy', - 'scrollTo', - 'getScrollPosition', - 'selectPage', 'prevPage', 'nextPage', - 'togglePagination', - 'toggleView', - 'refreshOptions', - 'resetSearch', - 'expandRow', 'collapseRow', 'expandAllRows', 'collapseAllRows' - ]; - - $.fn.bootstrapTable = function (option) { - var value, - args = Array.prototype.slice.call(arguments, 1); - - this.each(function () { - var $this = $(this), - data = $this.data('bootstrap.table'), - options = $.extend({}, BootstrapTable.DEFAULTS, $this.data(), - typeof option === 'object' && option); - - if (typeof option === 'string') { - if ($.inArray(option, allowedMethods) < 0) { - throw new Error("Unknown method: " + option); - } - - if (!data) { - return; - } - - value = data[option].apply(data, args); - - if (option === 'destroy') { - $this.removeData('bootstrap.table'); - } - } - - if (!data) { - $this.data('bootstrap.table', (data = new BootstrapTable(this, options))); - } - }); - - return typeof value === 'undefined' ? this : value; - }; - - $.fn.bootstrapTable.Constructor = BootstrapTable; - $.fn.bootstrapTable.defaults = BootstrapTable.DEFAULTS; - $.fn.bootstrapTable.columnDefaults = BootstrapTable.COLUMN_DEFAULTS; - $.fn.bootstrapTable.locales = BootstrapTable.LOCALES; - $.fn.bootstrapTable.methods = allowedMethods; - $.fn.bootstrapTable.utils = { - sprintf: sprintf, - getFieldIndex: getFieldIndex, - compareObjects: compareObjects, - calculateObjectValue: calculateObjectValue - }; - - // BOOTSTRAP TABLE INIT - // ======================= - - $(function () { - $('[data-toggle="table"]').bootstrapTable(); - }); - -}(jQuery); diff --git a/resources/assets/js/bootstrap.datepicker.js b/resources/assets/js/bootstrap.datepicker.js deleted file mode 100755 index 4005b732b3..0000000000 --- a/resources/assets/js/bootstrap.datepicker.js +++ /dev/null @@ -1,989 +0,0 @@ -/* ========================================================= - * bootstrap-datepicker.js - * http://www.eyecon.ro/bootstrap-datepicker - * ========================================================= - * Copyright 2012 Stefan Petre - * Improvements by Andrew Rowls - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ========================================================= */ - -!function( $ ) { - - function UTCDate(){ - return new Date(Date.UTC.apply(Date, arguments)); - } - function UTCToday(){ - var today = new Date(); - return UTCDate(today.getUTCFullYear(), today.getUTCMonth(), today.getUTCDate()); - } - - // Picker object - - var Datepicker = function(element, options) { - var that = this; - - this.element = $(element); - this.language = options.language||this.element.data('date-language')||"en"; - this.language = this.language in dates ? this.language : this.language.split('-')[0]; //Check if "de-DE" style date is available, if not language should fallback to 2 letter code eg "de" - this.language = this.language in dates ? this.language : "en"; - this.isRTL = dates[this.language].rtl||false; - this.format = DPGlobal.parseFormat(options.format||this.element.data('date-format')||dates[this.language].format||'mm/dd/yyyy'); - this.isInline = false; - this.isInput = this.element.is('input'); - this.component = this.element.is('.date') ? this.element.find('.add-on') : false; - this.hasInput = this.component && this.element.find('input').length; - if(this.component && this.component.length === 0) - this.component = false; - - this._attachEvents(); - - this.forceParse = true; - if ('forceParse' in options) { - this.forceParse = options.forceParse; - } else if ('dateForceParse' in this.element.data()) { - this.forceParse = this.element.data('date-force-parse'); - } - - - this.picker = $(DPGlobal.template) - .appendTo(this.isInline ? this.element : 'body') - .on({ - click: $.proxy(this.click, this), - mousedown: $.proxy(this.mousedown, this) - }); - - if(this.isInline) { - this.picker.addClass('datepicker-inline'); - } else { - this.picker.addClass('datepicker-dropdown dropdown-menu'); - } - if (this.isRTL){ - this.picker.addClass('datepicker-rtl'); - this.picker.find('.prev i, .next i') - .toggleClass('icon-arrow-left icon-arrow-right'); - } - $(document).on('mousedown', function (e) { - // Clicked outside the datepicker, hide it - if ($(e.target).closest('.datepicker.datepicker-inline, .datepicker.datepicker-dropdown').length === 0) { - that.hide(); - } - }); - - this.autoclose = false; - if ('autoclose' in options) { - this.autoclose = options.autoclose; - } else if ('dateAutoclose' in this.element.data()) { - this.autoclose = this.element.data('date-autoclose'); - } - - this.keyboardNavigation = true; - if ('keyboardNavigation' in options) { - this.keyboardNavigation = options.keyboardNavigation; - } else if ('dateKeyboardNavigation' in this.element.data()) { - this.keyboardNavigation = this.element.data('date-keyboard-navigation'); - } - - this.viewMode = this.startViewMode = 0; - switch(options.startView || this.element.data('date-start-view')){ - case 2: - case 'decade': - this.viewMode = this.startViewMode = 2; - break; - case 1: - case 'year': - this.viewMode = this.startViewMode = 1; - break; - } - - this.todayBtn = (options.todayBtn||this.element.data('date-today-btn')||false); - this.todayHighlight = (options.todayHighlight||this.element.data('date-today-highlight')||false); - - this.calendarWeeks = false; - if ('calendarWeeks' in options) { - this.calendarWeeks = options.calendarWeeks; - } else if ('dateCalendarWeeks' in this.element.data()) { - this.calendarWeeks = this.element.data('date-calendar-weeks'); - } - if (this.calendarWeeks) - this.picker.find('tfoot th.today') - .attr('colspan', function(i, val){ - return parseInt(val) + 1; - }); - - this.weekStart = ((options.weekStart||this.element.data('date-weekstart')||dates[this.language].weekStart||0) % 7); - this.weekEnd = ((this.weekStart + 6) % 7); - this.startDate = -Infinity; - this.endDate = Infinity; - this.daysOfWeekDisabled = []; - this.setStartDate(options.startDate||this.element.data('date-startdate')); - this.setEndDate(options.endDate||this.element.data('date-enddate')); - this.setDaysOfWeekDisabled(options.daysOfWeekDisabled||this.element.data('date-days-of-week-disabled')); - this.fillDow(); - this.fillMonths(); - this.update(); - this.showMode(); - - if(this.isInline) { - this.show(); - } - }; - - Datepicker.prototype = { - constructor: Datepicker, - - _events: [], - _attachEvents: function(){ - this._detachEvents(); - if (this.isInput) { // single input - this._events = [ - [this.element, { - // focus: $.proxy(this.show, this), - keyup: $.proxy(this.update, this), - keydown: $.proxy(this.keydown, this), - click: $.proxy(this.show, this) - }] - ]; - } - else if (this.component && this.hasInput){ // component: input + button - this._events = [ - // For components that are not readonly, allow keyboard nav - [this.element.find('input'), { - focus: $.proxy(this.show, this), - keyup: $.proxy(this.update, this), - keydown: $.proxy(this.keydown, this) - }], - [this.component, { - click: $.proxy(this.show, this) - }] - ]; - } - else if (this.element.is('div')) { // inline datepicker - this.isInline = true; - } - else { - this._events = [ - [this.element, { - click: $.proxy(this.show, this) - }] - ]; - } - for (var i=0, el, ev; i this.endDate) { - this.viewDate = new Date(this.endDate); - } else { - this.viewDate = new Date(this.date); - } - this.fill(); - }, - - fillDow: function(){ - var dowCnt = this.weekStart, - html = ''; - if(this.calendarWeeks){ - var cell = ' '; - html += cell; - this.picker.find('.datepicker-days thead tr:first-child').prepend(cell); - } - while (dowCnt < this.weekStart + 7) { - html += ''+dates[this.language].daysMin[(dowCnt++)%7]+''; - } - html += ''; - this.picker.find('.datepicker-days thead').append(html); - }, - - fillMonths: function(){ - var html = '', - i = 0; - while (i < 12) { - html += ''+dates[this.language].monthsShort[i++]+''; - } - this.picker.find('.datepicker-months td').html(html); - }, - - fill: function() { - var d = new Date(this.viewDate), - year = d.getUTCFullYear(), - month = d.getUTCMonth(), - startYear = this.startDate !== -Infinity ? this.startDate.getUTCFullYear() : -Infinity, - startMonth = this.startDate !== -Infinity ? this.startDate.getUTCMonth() : -Infinity, - endYear = this.endDate !== Infinity ? this.endDate.getUTCFullYear() : Infinity, - endMonth = this.endDate !== Infinity ? this.endDate.getUTCMonth() : Infinity, - currentDate = this.date && this.date.valueOf(), - today = new Date(); - this.picker.find('.datepicker-days thead th.switch') - .text(dates[this.language].months[month]+' '+year); - this.picker.find('tfoot th.today') - .text(dates[this.language].today) - .toggle(this.todayBtn !== false); - this.updateNavArrows(); - this.fillMonths(); - var prevMonth = UTCDate(year, month-1, 28,0,0,0,0), - day = DPGlobal.getDaysInMonth(prevMonth.getUTCFullYear(), prevMonth.getUTCMonth()); - prevMonth.setUTCDate(day); - prevMonth.setUTCDate(day - (prevMonth.getUTCDay() - this.weekStart + 7)%7); - var nextMonth = new Date(prevMonth); - nextMonth.setUTCDate(nextMonth.getUTCDate() + 42); - nextMonth = nextMonth.valueOf(); - var html = []; - var clsName; - while(prevMonth.valueOf() < nextMonth) { - if (prevMonth.getUTCDay() == this.weekStart) { - html.push(''); - if(this.calendarWeeks){ - // ISO 8601: First week contains first thursday. - // ISO also states week starts on Monday, but we can be more abstract here. - var - // Start of current week: based on weekstart/current date - ws = new Date(+prevMonth + (this.weekStart - prevMonth.getUTCDay() - 7) % 7 * 864e5), - // Thursday of this week - th = new Date(+ws + (7 + 4 - ws.getUTCDay()) % 7 * 864e5), - // First Thursday of year, year from thursday - yth = new Date(+(yth = UTCDate(th.getUTCFullYear(), 0, 1)) + (7 + 4 - yth.getUTCDay())%7*864e5), - // Calendar week: ms between thursdays, div ms per day, div 7 days - calWeek = (th - yth) / 864e5 / 7 + 1; - html.push(''+ calWeek +''); - - } - } - clsName = ''; - if (prevMonth.getUTCFullYear() < year || (prevMonth.getUTCFullYear() == year && prevMonth.getUTCMonth() < month)) { - clsName += ' old'; - } else if (prevMonth.getUTCFullYear() > year || (prevMonth.getUTCFullYear() == year && prevMonth.getUTCMonth() > month)) { - clsName += ' new'; - } - // Compare internal UTC date with local today, not UTC today - if (this.todayHighlight && - prevMonth.getUTCFullYear() == today.getFullYear() && - prevMonth.getUTCMonth() == today.getMonth() && - prevMonth.getUTCDate() == today.getDate()) { - clsName += ' today'; - } - if (currentDate && prevMonth.valueOf() == currentDate) { - clsName += ' active'; - } - if (prevMonth.valueOf() < this.startDate || prevMonth.valueOf() > this.endDate || - $.inArray(prevMonth.getUTCDay(), this.daysOfWeekDisabled) !== -1) { - clsName += ' disabled'; - } - html.push(''+prevMonth.getUTCDate() + ''); - if (prevMonth.getUTCDay() == this.weekEnd) { - html.push(''); - } - prevMonth.setUTCDate(prevMonth.getUTCDate()+1); - } - this.picker.find('.datepicker-days tbody').empty().append(html.join('')); - var currentYear = this.date && this.date.getUTCFullYear(); - - var months = this.picker.find('.datepicker-months') - .find('th:eq(1)') - .text(year) - .end() - .find('span').removeClass('active'); - if (currentYear && currentYear == year) { - months.eq(this.date.getUTCMonth()).addClass('active'); - } - if (year < startYear || year > endYear) { - months.addClass('disabled'); - } - if (year == startYear) { - months.slice(0, startMonth).addClass('disabled'); - } - if (year == endYear) { - months.slice(endMonth+1).addClass('disabled'); - } - - html = ''; - year = parseInt(year/10, 10) * 10; - var yearCont = this.picker.find('.datepicker-years') - .find('th:eq(1)') - .text(year + '-' + (year + 9)) - .end() - .find('td'); - year -= 1; - for (var i = -1; i < 11; i++) { - html += ''+year+''; - year += 1; - } - yearCont.html(html); - }, - - updateNavArrows: function() { - var d = new Date(this.viewDate), - year = d.getUTCFullYear(), - month = d.getUTCMonth(); - switch (this.viewMode) { - case 0: - if (this.startDate !== -Infinity && year <= this.startDate.getUTCFullYear() && month <= this.startDate.getUTCMonth()) { - this.picker.find('.prev').css({visibility: 'hidden'}); - } else { - this.picker.find('.prev').css({visibility: 'visible'}); - } - if (this.endDate !== Infinity && year >= this.endDate.getUTCFullYear() && month >= this.endDate.getUTCMonth()) { - this.picker.find('.next').css({visibility: 'hidden'}); - } else { - this.picker.find('.next').css({visibility: 'visible'}); - } - break; - case 1: - case 2: - if (this.startDate !== -Infinity && year <= this.startDate.getUTCFullYear()) { - this.picker.find('.prev').css({visibility: 'hidden'}); - } else { - this.picker.find('.prev').css({visibility: 'visible'}); - } - if (this.endDate !== Infinity && year >= this.endDate.getUTCFullYear()) { - this.picker.find('.next').css({visibility: 'hidden'}); - } else { - this.picker.find('.next').css({visibility: 'visible'}); - } - break; - } - }, - - click: function(e) { - e.stopPropagation(); - e.preventDefault(); - var target = $(e.target).closest('span, td, th'); - if (target.length == 1) { - switch(target[0].nodeName.toLowerCase()) { - case 'th': - switch(target[0].className) { - case 'switch': - this.showMode(1); - break; - case 'prev': - case 'next': - var dir = DPGlobal.modes[this.viewMode].navStep * (target[0].className == 'prev' ? -1 : 1); - switch(this.viewMode){ - case 0: - this.viewDate = this.moveMonth(this.viewDate, dir); - break; - case 1: - case 2: - this.viewDate = this.moveYear(this.viewDate, dir); - break; - } - this.fill(); - break; - case 'today': - var date = new Date(); - date = UTCDate(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0); - - this.showMode(-2); - var which = this.todayBtn == 'linked' ? null : 'view'; - this._setDate(date, which); - break; - } - break; - case 'span': - if (!target.is('.disabled')) { - this.viewDate.setUTCDate(1); - if (target.is('.month')) { - var month = target.parent().find('span').index(target); - this.viewDate.setUTCMonth(month); - this.element.trigger({ - type: 'changeMonth', - date: this.viewDate - }); - } else { - var year = parseInt(target.text(), 10)||0; - this.viewDate.setUTCFullYear(year); - this.element.trigger({ - type: 'changeYear', - date: this.viewDate - }); - } - this.showMode(-1); - this.fill(); - } - break; - case 'td': - if (target.is('.day') && !target.is('.disabled')){ - var day = parseInt(target.text(), 10)||1; - var year = this.viewDate.getUTCFullYear(), - month = this.viewDate.getUTCMonth(); - if (target.is('.old')) { - if (month === 0) { - month = 11; - year -= 1; - } else { - month -= 1; - } - } else if (target.is('.new')) { - if (month == 11) { - month = 0; - year += 1; - } else { - month += 1; - } - } - this._setDate(UTCDate(year, month, day,0,0,0,0)); - } - break; - } - } - }, - - _setDate: function(date, which){ - if (!which || which == 'date') - this.date = date; - if (!which || which == 'view') - this.viewDate = date; - this.fill(); - this.setValue(); - this.element.trigger({ - type: 'changeDate', - date: this.date - }); - var element; - if (this.isInput) { - element = this.element; - } else if (this.component){ - element = this.element.find('input'); - } - if (element) { - element.change(); - if (this.autoclose && (!which || which == 'date')) { - this.hide(); - } - } - }, - - moveMonth: function(date, dir){ - if (!dir) return date; - var new_date = new Date(date.valueOf()), - day = new_date.getUTCDate(), - month = new_date.getUTCMonth(), - mag = Math.abs(dir), - new_month, test; - dir = dir > 0 ? 1 : -1; - if (mag == 1){ - test = dir == -1 - // If going back one month, make sure month is not current month - // (eg, Mar 31 -> Feb 31 == Feb 28, not Mar 02) - ? function(){ return new_date.getUTCMonth() == month; } - // If going forward one month, make sure month is as expected - // (eg, Jan 31 -> Feb 31 == Feb 28, not Mar 02) - : function(){ return new_date.getUTCMonth() != new_month; }; - new_month = month + dir; - new_date.setUTCMonth(new_month); - // Dec -> Jan (12) or Jan -> Dec (-1) -- limit expected date to 0-11 - if (new_month < 0 || new_month > 11) - new_month = (new_month + 12) % 12; - } else { - // For magnitudes >1, move one month at a time... - for (var i=0; i= this.startDate && date <= this.endDate; - }, - - keydown: function(e){ - if (this.picker.is(':not(:visible)')){ - if (e.keyCode == 27) // allow escape to hide and re-show picker - this.show(); - return; - } - var dateChanged = false, - dir, day, month, - newDate, newViewDate; - switch(e.keyCode){ - case 27: // escape - this.hide(); - e.preventDefault(); - break; - case 37: // left - case 39: // right - if (!this.keyboardNavigation) break; - dir = e.keyCode == 37 ? -1 : 1; - if (e.ctrlKey){ - newDate = this.moveYear(this.date, dir); - newViewDate = this.moveYear(this.viewDate, dir); - } else if (e.shiftKey){ - newDate = this.moveMonth(this.date, dir); - newViewDate = this.moveMonth(this.viewDate, dir); - } else { - newDate = new Date(this.date); - newDate.setUTCDate(this.date.getUTCDate() + dir); - newViewDate = new Date(this.viewDate); - newViewDate.setUTCDate(this.viewDate.getUTCDate() + dir); - } - if (this.dateWithinRange(newDate)){ - this.date = newDate; - this.viewDate = newViewDate; - this.setValue(); - this.update(); - e.preventDefault(); - dateChanged = true; - } - break; - case 38: // up - case 40: // down - if (!this.keyboardNavigation) break; - dir = e.keyCode == 38 ? -1 : 1; - if (e.ctrlKey){ - newDate = this.moveYear(this.date, dir); - newViewDate = this.moveYear(this.viewDate, dir); - } else if (e.shiftKey){ - newDate = this.moveMonth(this.date, dir); - newViewDate = this.moveMonth(this.viewDate, dir); - } else { - newDate = new Date(this.date); - newDate.setUTCDate(this.date.getUTCDate() + dir * 7); - newViewDate = new Date(this.viewDate); - newViewDate.setUTCDate(this.viewDate.getUTCDate() + dir * 7); - } - if (this.dateWithinRange(newDate)){ - this.date = newDate; - this.viewDate = newViewDate; - this.setValue(); - this.update(); - e.preventDefault(); - dateChanged = true; - } - break; - case 13: // enter - this.hide(); - e.preventDefault(); - break; - case 9: // tab - this.hide(); - break; - } - if (dateChanged){ - this.element.trigger({ - type: 'changeDate', - date: this.date - }); - var element; - if (this.isInput) { - element = this.element; - } else if (this.component){ - element = this.element.find('input'); - } - if (element) { - element.change(); - } - } - }, - - showMode: function(dir) { - if (dir) { - this.viewMode = Math.max(0, Math.min(2, this.viewMode + dir)); - } - /* - vitalets: fixing bug of very special conditions: - jquery 1.7.1 + webkit + show inline datepicker in bootstrap popover. - Method show() does not set display css correctly and datepicker is not shown. - Changed to .css('display', 'block') solve the problem. - See https://github.com/vitalets/x-editable/issues/37 - - In jquery 1.7.2+ everything works fine. - */ - //this.picker.find('>div').hide().filter('.datepicker-'+DPGlobal.modes[this.viewMode].clsName).show(); - this.picker.find('>div').hide().filter('.datepicker-'+DPGlobal.modes[this.viewMode].clsName).css('display', 'block'); - this.updateNavArrows(); - } - }; - - $.fn.datepicker = function ( option ) { - var args = Array.apply(null, arguments); - args.shift(); - return this.each(function () { - var $this = $(this), - data = $this.data('datepicker'), - options = typeof option == 'object' && option; - if (!data) { - $this.data('datepicker', (data = new Datepicker(this, $.extend({}, $.fn.datepicker.defaults,options)))); - } - if (typeof option == 'string' && typeof data[option] == 'function') { - data[option].apply(data, args); - } - }); - }; - - $.fn.datepicker.defaults = { - }; - $.fn.datepicker.Constructor = Datepicker; - var dates = $.fn.datepicker.dates = { - en: { - days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"], - daysShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"], - daysMin: ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"], - months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"], - monthsShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"], - today: "Today" - } - }; - - var DPGlobal = { - modes: [ - { - clsName: 'days', - navFnc: 'Month', - navStep: 1 - }, - { - clsName: 'months', - navFnc: 'FullYear', - navStep: 1 - }, - { - clsName: 'years', - navFnc: 'FullYear', - navStep: 10 - }], - isLeapYear: function (year) { - return (((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0)); - }, - getDaysInMonth: function (year, month) { - return [31, (DPGlobal.isLeapYear(year) ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month]; - }, - validParts: /dd?|DD?|mm?|MM?|yy(?:yy)?/g, - nonpunctuation: /[^ -\/:-@\[\u3400-\u9fff-`{-~\t\n\r]+/g, - parseFormat: function(format){ - // IE treats \0 as a string end in inputs (truncating the value), - // so it's a bad format delimiter, anyway - var separators = format.replace(this.validParts, '\0').split('\0'), - parts = format.match(this.validParts); - if (!separators || !separators.length || !parts || parts.length === 0){ - throw new Error("Invalid date format."); - } - return {separators: separators, parts: parts}; - }, - parseDate: function(date, format, language) { - if (date instanceof Date) return date; - if (/^[\-+]\d+[dmwy]([\s,]+[\-+]\d+[dmwy])*$/.test(date)) { - var part_re = /([\-+]\d+)([dmwy])/, - parts = date.match(/([\-+]\d+)([dmwy])/g), - part, dir; - date = new Date(); - for (var i=0; i'+ - ''+ - ''+ - ''+ - ''+ - ''+ - '', - contTemplate: '', - footTemplate: '' - }; - DPGlobal.template = '
'+ - '
'+ - ''+ - DPGlobal.headTemplate+ - ''+ - DPGlobal.footTemplate+ - '
'+ - '
'+ - '
'+ - ''+ - DPGlobal.headTemplate+ - DPGlobal.contTemplate+ - DPGlobal.footTemplate+ - '
'+ - '
'+ - '
'+ - ''+ - DPGlobal.headTemplate+ - DPGlobal.contTemplate+ - DPGlobal.footTemplate+ - '
'+ - '
'+ - '
'; - - $.fn.datepicker.DPGlobal = DPGlobal; - -}( window.jQuery ); diff --git a/resources/assets/js/bootstrap.js b/resources/assets/js/bootstrap.js index 3731604dbd..f0acf8860a 100755 --- a/resources/assets/js/bootstrap.js +++ b/resources/assets/js/bootstrap.js @@ -6,8 +6,18 @@ window._ = require('lodash'); * for JavaScript based Bootstrap features such as modals and tabs. This * code may be modified to fit the specific needs of your application. */ - window.$ = window.jQuery = require('jquery'); + +/** + * jQuery UI is loaded here and then the tooltip is assigned another funtion name + * This resolves the issue of jquery-ui & bootstrap tooltip conflict + */ +require('jquery-ui'); +jQuery.fn.uitooltip = jQuery.fn.tooltip; + +/** + * Load boostrap + */ require('bootstrap-less'); /** diff --git a/resources/assets/js/bootstrap.min.js b/resources/assets/js/bootstrap.min.js deleted file mode 100755 index e79c065134..0000000000 --- a/resources/assets/js/bootstrap.min.js +++ /dev/null @@ -1,7 +0,0 @@ -/*! - * Bootstrap v3.3.6 (http://getbootstrap.com) - * Copyright 2011-2015 Twitter, Inc. - * Licensed under the MIT license - */ -if("undefined"==typeof jQuery)throw new Error("Bootstrap's JavaScript requires jQuery");+function(a){"use strict";var b=a.fn.jquery.split(" ")[0].split(".");if(b[0]<2&&b[1]<9||1==b[0]&&9==b[1]&&b[2]<1||b[0]>2)throw new Error("Bootstrap's JavaScript requires jQuery version 1.9.1 or higher, but lower than version 3")}(jQuery),+function(a){"use strict";function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]};return!1}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one("bsTransitionEnd",function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b(),a.support.transition&&(a.event.special.bsTransitionEnd={bindType:a.support.transition.end,delegateType:a.support.transition.end,handle:function(b){return a(b.target).is(this)?b.handleObj.handler.apply(this,arguments):void 0}})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var c=a(this),e=c.data("bs.alert");e||c.data("bs.alert",e=new d(this)),"string"==typeof b&&e[b].call(c)})}var c='[data-dismiss="alert"]',d=function(b){a(b).on("click",c,this.close)};d.VERSION="3.3.6",d.TRANSITION_DURATION=150,d.prototype.close=function(b){function c(){g.detach().trigger("closed.bs.alert").remove()}var e=a(this),f=e.attr("data-target");f||(f=e.attr("href"),f=f&&f.replace(/.*(?=#[^\s]*$)/,""));var g=a(f);b&&b.preventDefault(),g.length||(g=e.closest(".alert")),g.trigger(b=a.Event("close.bs.alert")),b.isDefaultPrevented()||(g.removeClass("in"),a.support.transition&&g.hasClass("fade")?g.one("bsTransitionEnd",c).emulateTransitionEnd(d.TRANSITION_DURATION):c())};var e=a.fn.alert;a.fn.alert=b,a.fn.alert.Constructor=d,a.fn.alert.noConflict=function(){return a.fn.alert=e,this},a(document).on("click.bs.alert.data-api",c,d.prototype.close)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.button"),f="object"==typeof b&&b;e||d.data("bs.button",e=new c(this,f)),"toggle"==b?e.toggle():b&&e.setState(b)})}var c=function(b,d){this.$element=a(b),this.options=a.extend({},c.DEFAULTS,d),this.isLoading=!1};c.VERSION="3.3.6",c.DEFAULTS={loadingText:"loading..."},c.prototype.setState=function(b){var c="disabled",d=this.$element,e=d.is("input")?"val":"html",f=d.data();b+="Text",null==f.resetText&&d.data("resetText",d[e]()),setTimeout(a.proxy(function(){d[e](null==f[b]?this.options[b]:f[b]),"loadingText"==b?(this.isLoading=!0,d.addClass(c).attr(c,c)):this.isLoading&&(this.isLoading=!1,d.removeClass(c).removeAttr(c))},this),0)},c.prototype.toggle=function(){var a=!0,b=this.$element.closest('[data-toggle="buttons"]');if(b.length){var c=this.$element.find("input");"radio"==c.prop("type")?(c.prop("checked")&&(a=!1),b.find(".active").removeClass("active"),this.$element.addClass("active")):"checkbox"==c.prop("type")&&(c.prop("checked")!==this.$element.hasClass("active")&&(a=!1),this.$element.toggleClass("active")),c.prop("checked",this.$element.hasClass("active")),a&&c.trigger("change")}else this.$element.attr("aria-pressed",!this.$element.hasClass("active")),this.$element.toggleClass("active")};var d=a.fn.button;a.fn.button=b,a.fn.button.Constructor=c,a.fn.button.noConflict=function(){return a.fn.button=d,this},a(document).on("click.bs.button.data-api",'[data-toggle^="button"]',function(c){var d=a(c.target);d.hasClass("btn")||(d=d.closest(".btn")),b.call(d,"toggle"),a(c.target).is('input[type="radio"]')||a(c.target).is('input[type="checkbox"]')||c.preventDefault()}).on("focus.bs.button.data-api blur.bs.button.data-api",'[data-toggle^="button"]',function(b){a(b.target).closest(".btn").toggleClass("focus",/^focus(in)?$/.test(b.type))})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},c.DEFAULTS,d.data(),"object"==typeof b&&b),g="string"==typeof b?b:f.slide;e||d.data("bs.carousel",e=new c(this,f)),"number"==typeof b?e.to(b):g?e[g]():f.interval&&e.pause().cycle()})}var c=function(b,c){this.$element=a(b),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=null,this.sliding=null,this.interval=null,this.$active=null,this.$items=null,this.options.keyboard&&this.$element.on("keydown.bs.carousel",a.proxy(this.keydown,this)),"hover"==this.options.pause&&!("ontouchstart"in document.documentElement)&&this.$element.on("mouseenter.bs.carousel",a.proxy(this.pause,this)).on("mouseleave.bs.carousel",a.proxy(this.cycle,this))};c.VERSION="3.3.6",c.TRANSITION_DURATION=600,c.DEFAULTS={interval:5e3,pause:"hover",wrap:!0,keyboard:!0},c.prototype.keydown=function(a){if(!/input|textarea/i.test(a.target.tagName)){switch(a.which){case 37:this.prev();break;case 39:this.next();break;default:return}a.preventDefault()}},c.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},c.prototype.getItemIndex=function(a){return this.$items=a.parent().children(".item"),this.$items.index(a||this.$active)},c.prototype.getItemForDirection=function(a,b){var c=this.getItemIndex(b),d="prev"==a&&0===c||"next"==a&&c==this.$items.length-1;if(d&&!this.options.wrap)return b;var e="prev"==a?-1:1,f=(c+e)%this.$items.length;return this.$items.eq(f)},c.prototype.to=function(a){var b=this,c=this.getItemIndex(this.$active=this.$element.find(".item.active"));return a>this.$items.length-1||0>a?void 0:this.sliding?this.$element.one("slid.bs.carousel",function(){b.to(a)}):c==a?this.pause().cycle():this.slide(a>c?"next":"prev",this.$items.eq(a))},c.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},c.prototype.next=function(){return this.sliding?void 0:this.slide("next")},c.prototype.prev=function(){return this.sliding?void 0:this.slide("prev")},c.prototype.slide=function(b,d){var e=this.$element.find(".item.active"),f=d||this.getItemForDirection(b,e),g=this.interval,h="next"==b?"left":"right",i=this;if(f.hasClass("active"))return this.sliding=!1;var j=f[0],k=a.Event("slide.bs.carousel",{relatedTarget:j,direction:h});if(this.$element.trigger(k),!k.isDefaultPrevented()){if(this.sliding=!0,g&&this.pause(),this.$indicators.length){this.$indicators.find(".active").removeClass("active");var l=a(this.$indicators.children()[this.getItemIndex(f)]);l&&l.addClass("active")}var m=a.Event("slid.bs.carousel",{relatedTarget:j,direction:h});return a.support.transition&&this.$element.hasClass("slide")?(f.addClass(b),f[0].offsetWidth,e.addClass(h),f.addClass(h),e.one("bsTransitionEnd",function(){f.removeClass([b,h].join(" ")).addClass("active"),e.removeClass(["active",h].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger(m)},0)}).emulateTransitionEnd(c.TRANSITION_DURATION)):(e.removeClass("active"),f.addClass("active"),this.sliding=!1,this.$element.trigger(m)),g&&this.cycle(),this}};var d=a.fn.carousel;a.fn.carousel=b,a.fn.carousel.Constructor=c,a.fn.carousel.noConflict=function(){return a.fn.carousel=d,this};var e=function(c){var d,e=a(this),f=a(e.attr("data-target")||(d=e.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,""));if(f.hasClass("carousel")){var g=a.extend({},f.data(),e.data()),h=e.attr("data-slide-to");h&&(g.interval=!1),b.call(f,g),h&&f.data("bs.carousel").to(h),c.preventDefault()}};a(document).on("click.bs.carousel.data-api","[data-slide]",e).on("click.bs.carousel.data-api","[data-slide-to]",e),a(window).on("load",function(){a('[data-ride="carousel"]').each(function(){var c=a(this);b.call(c,c.data())})})}(jQuery),+function(a){"use strict";function b(b){var c,d=b.attr("data-target")||(c=b.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,"");return a(d)}function c(b){return this.each(function(){var c=a(this),e=c.data("bs.collapse"),f=a.extend({},d.DEFAULTS,c.data(),"object"==typeof b&&b);!e&&f.toggle&&/show|hide/.test(b)&&(f.toggle=!1),e||c.data("bs.collapse",e=new d(this,f)),"string"==typeof b&&e[b]()})}var d=function(b,c){this.$element=a(b),this.options=a.extend({},d.DEFAULTS,c),this.$trigger=a('[data-toggle="collapse"][href="#'+b.id+'"],[data-toggle="collapse"][data-target="#'+b.id+'"]'),this.transitioning=null,this.options.parent?this.$parent=this.getParent():this.addAriaAndCollapsedClass(this.$element,this.$trigger),this.options.toggle&&this.toggle()};d.VERSION="3.3.6",d.TRANSITION_DURATION=350,d.DEFAULTS={toggle:!0},d.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},d.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var b,e=this.$parent&&this.$parent.children(".panel").children(".in, .collapsing");if(!(e&&e.length&&(b=e.data("bs.collapse"),b&&b.transitioning))){var f=a.Event("show.bs.collapse");if(this.$element.trigger(f),!f.isDefaultPrevented()){e&&e.length&&(c.call(e,"hide"),b||e.data("bs.collapse",null));var g=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[g](0).attr("aria-expanded",!0),this.$trigger.removeClass("collapsed").attr("aria-expanded",!0),this.transitioning=1;var h=function(){this.$element.removeClass("collapsing").addClass("collapse in")[g](""),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return h.call(this);var i=a.camelCase(["scroll",g].join("-"));this.$element.one("bsTransitionEnd",a.proxy(h,this)).emulateTransitionEnd(d.TRANSITION_DURATION)[g](this.$element[0][i])}}}},d.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var b=a.Event("hide.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse in").attr("aria-expanded",!1),this.$trigger.addClass("collapsed").attr("aria-expanded",!1),this.transitioning=1;var e=function(){this.transitioning=0,this.$element.removeClass("collapsing").addClass("collapse").trigger("hidden.bs.collapse")};return a.support.transition?void this.$element[c](0).one("bsTransitionEnd",a.proxy(e,this)).emulateTransitionEnd(d.TRANSITION_DURATION):e.call(this)}}},d.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()},d.prototype.getParent=function(){return a(this.options.parent).find('[data-toggle="collapse"][data-parent="'+this.options.parent+'"]').each(a.proxy(function(c,d){var e=a(d);this.addAriaAndCollapsedClass(b(e),e)},this)).end()},d.prototype.addAriaAndCollapsedClass=function(a,b){var c=a.hasClass("in");a.attr("aria-expanded",c),b.toggleClass("collapsed",!c).attr("aria-expanded",c)};var e=a.fn.collapse;a.fn.collapse=c,a.fn.collapse.Constructor=d,a.fn.collapse.noConflict=function(){return a.fn.collapse=e,this},a(document).on("click.bs.collapse.data-api",'[data-toggle="collapse"]',function(d){var e=a(this);e.attr("data-target")||d.preventDefault();var f=b(e),g=f.data("bs.collapse"),h=g?"toggle":e.data();c.call(f,h)})}(jQuery),+function(a){"use strict";function b(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#[A-Za-z]/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}function c(c){c&&3===c.which||(a(e).remove(),a(f).each(function(){var d=a(this),e=b(d),f={relatedTarget:this};e.hasClass("open")&&(c&&"click"==c.type&&/input|textarea/i.test(c.target.tagName)&&a.contains(e[0],c.target)||(e.trigger(c=a.Event("hide.bs.dropdown",f)),c.isDefaultPrevented()||(d.attr("aria-expanded","false"),e.removeClass("open").trigger(a.Event("hidden.bs.dropdown",f)))))}))}function d(b){return this.each(function(){var c=a(this),d=c.data("bs.dropdown");d||c.data("bs.dropdown",d=new g(this)),"string"==typeof b&&d[b].call(c)})}var e=".dropdown-backdrop",f='[data-toggle="dropdown"]',g=function(b){a(b).on("click.bs.dropdown",this.toggle)};g.VERSION="3.3.6",g.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=b(e),g=f.hasClass("open");if(c(),!g){"ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a(document.createElement("div")).addClass("dropdown-backdrop").insertAfter(a(this)).on("click",c);var h={relatedTarget:this};if(f.trigger(d=a.Event("show.bs.dropdown",h)),d.isDefaultPrevented())return;e.trigger("focus").attr("aria-expanded","true"),f.toggleClass("open").trigger(a.Event("shown.bs.dropdown",h))}return!1}},g.prototype.keydown=function(c){if(/(38|40|27|32)/.test(c.which)&&!/input|textarea/i.test(c.target.tagName)){var d=a(this);if(c.preventDefault(),c.stopPropagation(),!d.is(".disabled, :disabled")){var e=b(d),g=e.hasClass("open");if(!g&&27!=c.which||g&&27==c.which)return 27==c.which&&e.find(f).trigger("focus"),d.trigger("click");var h=" li:not(.disabled):visible a",i=e.find(".dropdown-menu"+h);if(i.length){var j=i.index(c.target);38==c.which&&j>0&&j--,40==c.which&&jdocument.documentElement.clientHeight;this.$element.css({paddingLeft:!this.bodyIsOverflowing&&a?this.scrollbarWidth:"",paddingRight:this.bodyIsOverflowing&&!a?this.scrollbarWidth:""})},c.prototype.resetAdjustments=function(){this.$element.css({paddingLeft:"",paddingRight:""})},c.prototype.checkScrollbar=function(){var a=window.innerWidth;if(!a){var b=document.documentElement.getBoundingClientRect();a=b.right-Math.abs(b.left)}this.bodyIsOverflowing=document.body.clientWidth
',trigger:"hover focus",title:"",delay:0,html:!1,container:!1,viewport:{selector:"body",padding:0}},c.prototype.init=function(b,c,d){if(this.enabled=!0,this.type=b,this.$element=a(c),this.options=this.getOptions(d),this.$viewport=this.options.viewport&&a(a.isFunction(this.options.viewport)?this.options.viewport.call(this,this.$element):this.options.viewport.selector||this.options.viewport),this.inState={click:!1,hover:!1,focus:!1},this.$element[0]instanceof document.constructor&&!this.options.selector)throw new Error("`selector` option must be specified when initializing "+this.type+" on the window.document object!");for(var e=this.options.trigger.split(" "),f=e.length;f--;){var g=e[f];if("click"==g)this.$element.on("click."+this.type,this.options.selector,a.proxy(this.toggle,this));else if("manual"!=g){var h="hover"==g?"mouseenter":"focusin",i="hover"==g?"mouseleave":"focusout";this.$element.on(h+"."+this.type,this.options.selector,a.proxy(this.enter,this)),this.$element.on(i+"."+this.type,this.options.selector,a.proxy(this.leave,this))}}this.options.selector?this._options=a.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.getOptions=function(b){return b=a.extend({},this.getDefaults(),this.$element.data(),b),b.delay&&"number"==typeof b.delay&&(b.delay={show:b.delay,hide:b.delay}),b},c.prototype.getDelegateOptions=function(){var b={},c=this.getDefaults();return this._options&&a.each(this._options,function(a,d){c[a]!=d&&(b[a]=d)}),b},c.prototype.enter=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);return c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),b instanceof a.Event&&(c.inState["focusin"==b.type?"focus":"hover"]=!0),c.tip().hasClass("in")||"in"==c.hoverState?void(c.hoverState="in"):(clearTimeout(c.timeout),c.hoverState="in",c.options.delay&&c.options.delay.show?void(c.timeout=setTimeout(function(){"in"==c.hoverState&&c.show()},c.options.delay.show)):c.show())},c.prototype.isInStateTrue=function(){for(var a in this.inState)if(this.inState[a])return!0;return!1},c.prototype.leave=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);return c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),b instanceof a.Event&&(c.inState["focusout"==b.type?"focus":"hover"]=!1),c.isInStateTrue()?void 0:(clearTimeout(c.timeout),c.hoverState="out",c.options.delay&&c.options.delay.hide?void(c.timeout=setTimeout(function(){"out"==c.hoverState&&c.hide()},c.options.delay.hide)):c.hide())},c.prototype.show=function(){var b=a.Event("show.bs."+this.type);if(this.hasContent()&&this.enabled){this.$element.trigger(b);var d=a.contains(this.$element[0].ownerDocument.documentElement,this.$element[0]);if(b.isDefaultPrevented()||!d)return;var e=this,f=this.tip(),g=this.getUID(this.type);this.setContent(),f.attr("id",g),this.$element.attr("aria-describedby",g),this.options.animation&&f.addClass("fade");var h="function"==typeof this.options.placement?this.options.placement.call(this,f[0],this.$element[0]):this.options.placement,i=/\s?auto?\s?/i,j=i.test(h);j&&(h=h.replace(i,"")||"top"),f.detach().css({top:0,left:0,display:"block"}).addClass(h).data("bs."+this.type,this),this.options.container?f.appendTo(this.options.container):f.insertAfter(this.$element),this.$element.trigger("inserted.bs."+this.type);var k=this.getPosition(),l=f[0].offsetWidth,m=f[0].offsetHeight;if(j){var n=h,o=this.getPosition(this.$viewport);h="bottom"==h&&k.bottom+m>o.bottom?"top":"top"==h&&k.top-mo.width?"left":"left"==h&&k.left-lg.top+g.height&&(e.top=g.top+g.height-i)}else{var j=b.left-f,k=b.left+f+c;jg.right&&(e.left=g.left+g.width-k)}return e},c.prototype.getTitle=function(){var a,b=this.$element,c=this.options;return a=b.attr("data-original-title")||("function"==typeof c.title?c.title.call(b[0]):c.title)},c.prototype.getUID=function(a){do a+=~~(1e6*Math.random());while(document.getElementById(a));return a},c.prototype.tip=function(){if(!this.$tip&&(this.$tip=a(this.options.template),1!=this.$tip.length))throw new Error(this.type+" `template` option must consist of exactly 1 top-level element!");return this.$tip},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")},c.prototype.enable=function(){this.enabled=!0},c.prototype.disable=function(){this.enabled=!1},c.prototype.toggleEnabled=function(){this.enabled=!this.enabled},c.prototype.toggle=function(b){var c=this;b&&(c=a(b.currentTarget).data("bs."+this.type),c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c))),b?(c.inState.click=!c.inState.click,c.isInStateTrue()?c.enter(c):c.leave(c)):c.tip().hasClass("in")?c.leave(c):c.enter(c)},c.prototype.destroy=function(){var a=this;clearTimeout(this.timeout),this.hide(function(){a.$element.off("."+a.type).removeData("bs."+a.type),a.$tip&&a.$tip.detach(),a.$tip=null,a.$arrow=null,a.$viewport=null})};var d=a.fn.tooltip;a.fn.tooltip=b,a.fn.tooltip.Constructor=c,a.fn.tooltip.noConflict=function(){return a.fn.tooltip=d,this}}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.popover"),f="object"==typeof b&&b;(e||!/destroy|hide/.test(b))&&(e||d.data("bs.popover",e=new c(this,f)),"string"==typeof b&&e[b]())})}var c=function(a,b){this.init("popover",a,b)};if(!a.fn.tooltip)throw new Error("Popover requires tooltip.js");c.VERSION="3.3.6",c.DEFAULTS=a.extend({},a.fn.tooltip.Constructor.DEFAULTS,{placement:"right",trigger:"click",content:"",template:''}),c.prototype=a.extend({},a.fn.tooltip.Constructor.prototype),c.prototype.constructor=c,c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.setContent=function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(".popover-title")[this.options.html?"html":"text"](b),a.find(".popover-content").children().detach().end()[this.options.html?"string"==typeof c?"html":"append":"text"](c),a.removeClass("fade top bottom left right in"),a.find(".popover-title").html()||a.find(".popover-title").hide()},c.prototype.hasContent=function(){return this.getTitle()||this.getContent()},c.prototype.getContent=function(){var a=this.$element,b=this.options;return a.attr("data-content")||("function"==typeof b.content?b.content.call(a[0]):b.content)},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")};var d=a.fn.popover;a.fn.popover=b,a.fn.popover.Constructor=c,a.fn.popover.noConflict=function(){return a.fn.popover=d,this}}(jQuery),+function(a){"use strict";function b(c,d){this.$body=a(document.body),this.$scrollElement=a(a(c).is(document.body)?window:c),this.options=a.extend({},b.DEFAULTS,d),this.selector=(this.options.target||"")+" .nav li > a",this.offsets=[],this.targets=[],this.activeTarget=null,this.scrollHeight=0,this.$scrollElement.on("scroll.bs.scrollspy",a.proxy(this.process,this)),this.refresh(),this.process()}function c(c){return this.each(function(){var d=a(this),e=d.data("bs.scrollspy"),f="object"==typeof c&&c;e||d.data("bs.scrollspy",e=new b(this,f)),"string"==typeof c&&e[c]()})}b.VERSION="3.3.6",b.DEFAULTS={offset:10},b.prototype.getScrollHeight=function(){return this.$scrollElement[0].scrollHeight||Math.max(this.$body[0].scrollHeight,document.documentElement.scrollHeight)},b.prototype.refresh=function(){var b=this,c="offset",d=0;this.offsets=[],this.targets=[],this.scrollHeight=this.getScrollHeight(),a.isWindow(this.$scrollElement[0])||(c="position",d=this.$scrollElement.scrollTop()),this.$body.find(this.selector).map(function(){var b=a(this),e=b.data("target")||b.attr("href"),f=/^#./.test(e)&&a(e);return f&&f.length&&f.is(":visible")&&[[f[c]().top+d,e]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){b.offsets.push(this[0]),b.targets.push(this[1])})},b.prototype.process=function(){var a,b=this.$scrollElement.scrollTop()+this.options.offset,c=this.getScrollHeight(),d=this.options.offset+c-this.$scrollElement.height(),e=this.offsets,f=this.targets,g=this.activeTarget;if(this.scrollHeight!=c&&this.refresh(),b>=d)return g!=(a=f[f.length-1])&&this.activate(a);if(g&&b=e[a]&&(void 0===e[a+1]||b .dropdown-menu > .active").removeClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!1),b.addClass("active").find('[data-toggle="tab"]').attr("aria-expanded",!0),h?(b[0].offsetWidth,b.addClass("in")):b.removeClass("fade"),b.parent(".dropdown-menu").length&&b.closest("li.dropdown").addClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!0),e&&e()}var g=d.find("> .active"),h=e&&a.support.transition&&(g.length&&g.hasClass("fade")||!!d.find("> .fade").length);g.length&&h?g.one("bsTransitionEnd",f).emulateTransitionEnd(c.TRANSITION_DURATION):f(),g.removeClass("in")};var d=a.fn.tab;a.fn.tab=b,a.fn.tab.Constructor=c,a.fn.tab.noConflict=function(){return a.fn.tab=d,this};var e=function(c){c.preventDefault(),b.call(a(this),"show")};a(document).on("click.bs.tab.data-api",'[data-toggle="tab"]',e).on("click.bs.tab.data-api",'[data-toggle="pill"]',e)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.affix"),f="object"==typeof b&&b;e||d.data("bs.affix",e=new c(this,f)),"string"==typeof b&&e[b]()})}var c=function(b,d){this.options=a.extend({},c.DEFAULTS,d),this.$target=a(this.options.target).on("scroll.bs.affix.data-api",a.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",a.proxy(this.checkPositionWithEventLoop,this)),this.$element=a(b),this.affixed=null,this.unpin=null,this.pinnedOffset=null,this.checkPosition()};c.VERSION="3.3.6",c.RESET="affix affix-top affix-bottom",c.DEFAULTS={offset:0,target:window},c.prototype.getState=function(a,b,c,d){var e=this.$target.scrollTop(),f=this.$element.offset(),g=this.$target.height();if(null!=c&&"top"==this.affixed)return c>e?"top":!1;if("bottom"==this.affixed)return null!=c?e+this.unpin<=f.top?!1:"bottom":a-d>=e+g?!1:"bottom";var h=null==this.affixed,i=h?e:f.top,j=h?g:b;return null!=c&&c>=e?"top":null!=d&&i+j>=a-d?"bottom":!1},c.prototype.getPinnedOffset=function(){if(this.pinnedOffset)return this.pinnedOffset;this.$element.removeClass(c.RESET).addClass("affix");var a=this.$target.scrollTop(),b=this.$element.offset();return this.pinnedOffset=b.top-a},c.prototype.checkPositionWithEventLoop=function(){setTimeout(a.proxy(this.checkPosition,this),1)},c.prototype.checkPosition=function(){if(this.$element.is(":visible")){var b=this.$element.height(),d=this.options.offset,e=d.top,f=d.bottom,g=Math.max(a(document).height(),a(document.body).height());"object"!=typeof d&&(f=e=d),"function"==typeof e&&(e=d.top(this.$element)),"function"==typeof f&&(f=d.bottom(this.$element));var h=this.getState(g,b,e,f);if(this.affixed!=h){null!=this.unpin&&this.$element.css("top","");var i="affix"+(h?"-"+h:""),j=a.Event(i+".bs.affix");if(this.$element.trigger(j),j.isDefaultPrevented())return;this.affixed=h,this.unpin="bottom"==h?this.getPinnedOffset():null,this.$element.removeClass(c.RESET).addClass(i).trigger(i.replace("affix","affixed")+".bs.affix")}"bottom"==h&&this.$element.offset({top:g-b-f})}};var d=a.fn.affix;a.fn.affix=b,a.fn.affix.Constructor=c,a.fn.affix.noConflict=function(){return a.fn.affix=d,this},a(window).on("load",function(){a('[data-spy="affix"]').each(function(){var c=a(this),d=c.data();d.offset=d.offset||{},null!=d.offsetBottom&&(d.offset.bottom=d.offsetBottom),null!=d.offsetTop&&(d.offset.top=d.offsetTop),b.call(c,d)})})}(jQuery); \ No newline at end of file diff --git a/resources/assets/js/components/importer/importer-file.vue b/resources/assets/js/components/importer/importer-file.vue index 9dadf20e9c..7c18dba0c6 100644 --- a/resources/assets/js/components/importer/importer-file.vue +++ b/resources/assets/js/components/importer/importer-file.vue @@ -1,7 +1,7 @@