diff --git a/INSTALL/centos.sh b/INSTALL/centos.sh index 129822a..c762adb 100644 --- a/INSTALL/centos.sh +++ b/INSTALL/centos.sh @@ -27,7 +27,7 @@ if [ ! -e "./super.json" ]; then fi echo "Shinobi - Run yum update" sudo yum update -y -sudo yum install make -y +sudo yum install make zip -y echo "=============" echo "Shinobi - Do you want to Install FFMPEG?" echo "(y)es or (N)o" @@ -143,21 +143,14 @@ if [ "$mysqlDefaultData" = "y" ] || [ "$mysqlDefaultData" = "Y" ]; then echo "=====================================" echo "=====================================" fi -if [ ! "$sqliteormariadb" = "M" ] && [ ! "$sqliteormariadb" = "m" ]; then - echo "=====================================" - echo "||===== Install Completed =====||" - echo "=====================================" - echo "|| Login with the Superuser and create a new user!!" - echo "||===================================" - echo "|| Open http://$(ifconfig | sed -En 's/127.0.0.1//;s/.*inet (addr:)?(([0-9]*\.){3}[0-9]*).*/\2/p'):8080/super in your web browser." - echo "||===================================" - echo "|| Default Superuser : admin@shinobi.video" - echo "|| Default Password : admin" - echo "=====================================" - echo "=====================================" -else - echo "+=================================+" - echo "||===== Install Completed =====||" - echo "|| Access the main Shinobi panel at http://$(ifconfig | sed -En 's/127.0.0.1//;s/.*inet (addr:)?(([0-9]*\.){3}[0-9]*).*/\2/p'):8080 in your web browser." - echo "+=================================+" -fi +echo "=====================================" +echo "||===== Install Completed =====||" +echo "=====================================" +echo "|| Login with the Superuser and create a new user!!" +echo "||===================================" +echo "|| Open http://$(ifconfig | sed -En 's/127.0.0.1//;s/.*inet (addr:)?(([0-9]*\.){3}[0-9]*).*/\2/p'):8080/super in your web browser." +echo "||===================================" +echo "|| Default Superuser : admin@shinobi.video" +echo "|| Default Password : admin" +echo "=====================================" +echo "=====================================" diff --git a/INSTALL/openalpr-cpu-easy.sh b/INSTALL/openalpr-cpu-easy.sh new file mode 100644 index 0000000..56e54b7 --- /dev/null +++ b/INSTALL/openalpr-cpu-easy.sh @@ -0,0 +1,41 @@ +# Install prerequisites +DIR=`dirname $0` +INSTALLERS_DIR="$DIR" +echo "-----------------------------------" +if ! [ -x "$(command -v opencv_version)" ]; then + echo "Installing OpenCV" + dos2unix $INSTALLERS_DIR/opencv-cuda.sh + sh $INSTALLERS_DIR/opencv-cuda.sh +else + echo "OpenCV found... : $(opencv_version)" +fi +# this includes all the ones missing from OpenALPR's guide. +sudo apt install libtesseract-dev git cmake build-essential libleptonica-dev -y +sudo apt install liblog4cplus-dev libcurl3-dev -y +sudo apt install libleptonica-dev -y +sudo apt install libcurl4-openssl-dev -y +sudo apt install liblog4cplus-dev -y +sudo apt install beanstalkd -y +sudo apt install openjdk-8-jdk -y + +# Clone the latest code from GitHub +git clone https://github.com/openalpr/openalpr.git + +# Setup the build directory +cd openalpr/src +mkdir build +cd build + +# setup the compile environment +cmake -DCMAKE_INSTALL_PREFIX:PATH=/usr -DCMAKE_INSTALL_SYSCONFDIR:PATH=/etc .. + +# compile the library +make + +# Install the binaries/libraries to your local system (prefix is /usr) +sudo make install + +# Test the library +wget http://plates.openalpr.com/h786poj.jpg -O lp.jpg +alpr lp.jpg +rm lp.jpg diff --git a/INSTALL/openalpr-gpu-easy.sh b/INSTALL/openalpr-gpu-easy.sh index 0949629..06903f1 100644 --- a/INSTALL/openalpr-gpu-easy.sh +++ b/INSTALL/openalpr-gpu-easy.sh @@ -1,4 +1,17 @@ # Install prerequisites +DIR=`dirname $0` +INSTALLERS_DIR="$DIR" +echo "-----------------------------------" +if ! [ -x "$(command -v opencv_version)" ]; then + echo "Installing OpenCV" + dos2unix $INSTALLERS_DIR/opencv-cuda.sh + sh $INSTALLERS_DIR/opencv-cuda.sh +else + echo "OpenCV found... : $(opencv_version)" +fi +# get tesseract repo because ubuntu repo is serving a broken version +sudo add-apt-repository ppa:alex-p/tesseract-ocr -y +sudo apt-get update # this includes all the ones missing from OpenALPR's guide. sudo apt install libtesseract-dev git cmake build-essential libleptonica-dev -y sudo apt install liblog4cplus-dev libcurl3-dev -y @@ -28,4 +41,4 @@ sudo make install # Test the library wget http://plates.openalpr.com/h786poj.jpg -O lp.jpg alpr lp.jpg -rm lp.jpg \ No newline at end of file +rm lp.jpg diff --git a/INSTALL/opencv-cuda.sh b/INSTALL/opencv-cuda.sh index 0eb75e9..1a1ee50 100644 --- a/INSTALL/opencv-cuda.sh +++ b/INSTALL/opencv-cuda.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash # OpenCV CUDA if [ $(dpkg-query -W -f='${Status}' git 2>/dev/null | grep -c "ok installed") -eq 0 ]; then echo "Installing Git..." @@ -77,4 +77,4 @@ read opencvuninstall if [ "$opencvuninstall" = "y" ] || [ "$opencvuninstall" = "Y" ]; then rm -rf opencv rm -rf opencv_contrib -fi +fi \ No newline at end of file diff --git a/INSTALL/opensuse.sh b/INSTALL/opensuse.sh index db021be..3a10b3e 100644 --- a/INSTALL/opensuse.sh +++ b/INSTALL/opensuse.sh @@ -115,15 +115,6 @@ sudo chmod -R 755 . touch INSTALL/installed.txt dos2unix /home/Shinobi/INSTALL/shinobi ln -s /home/Shinobi/INSTALL/shinobi /usr/bin/shinobi -if [ "$mysqlDefaultData" = "y" ] || [ "$mysqlDefaultData" = "Y" ]; then - echo "=====================================" > INSTALL/installed.txt - echo "======= Login Credentials =======" >> INSTALL/installed.txt - echo "|| Username : $userEmail" >> INSTALL/installed.txt - echo "|| Password : $userPasswordPlain" >> INSTALL/installed.txt - echo "|| API Key : $apiKey" >> INSTALL/installed.txt - echo "=====================================" >> INSTALL/installed.txt - echo "=====================================" >> INSTALL/installed.txt -fi echo "Shinobi - Start Shinobi and set to start on boot?" echo "(y)es or (N)o" read startShinobi @@ -134,31 +125,14 @@ if [ "$startShinobi" = "y" ] || [ "$startShinobi" = "Y" ]; then sudo pm2 save sudo pm2 list fi -if [ "$mysqlDefaultData" = "y" ] || [ "$mysqlDefaultData" = "Y" ]; then - echo "details written to INSTALL/installed.txt" - echo "=====================================" - echo "======= Login Credentials =======" - echo "|| Username : $userEmail" - echo "|| Password : $userPasswordPlain" - echo "|| API Key : $apiKey" - echo "=====================================" - echo "=====================================" -fi -if [ ! "$sqliteormariadb" = "M" ] && [ ! "$sqliteormariadb" = "m" ]; then - echo "=====================================" - echo "||===== Install Completed =====||" - echo "=====================================" - echo "|| Login with the Superuser and create a new user!!" - echo "||===================================" - echo "|| Open http://$(/sbin/ip -o -4 addr list eth0 | awk '{print $4}' | cut -d/ -f1):8080/super in your web browser." - echo "||===================================" - echo "|| Default Superuser : admin@shinobi.video" - echo "|| Default Password : admin" - echo "=====================================" - echo "=====================================" -else - echo "+=================================+" - echo "||===== Install Completed =====||" - echo "|| Access the main Shinobi panel at http://$(/sbin/ip -o -4 addr list eth0 | awk '{print $4}' | cut -d/ -f1):8080 in your web browser." - echo "+=================================+" -fi +echo "=====================================" +echo "||===== Install Completed =====||" +echo "=====================================" +echo "|| Login with the Superuser and create a new user!!" +echo "||===================================" +echo "|| Open http://$(/sbin/ip -o -4 addr list eth0 | awk '{print $4}' | cut -d/ -f1):8080/super in your web browser." +echo "||===================================" +echo "|| Default Superuser : admin@shinobi.video" +echo "|| Default Password : admin" +echo "=====================================" +echo "=====================================" diff --git a/INSTALL/shinobi b/INSTALL/shinobi index 30b9401..ed17294 100644 --- a/INSTALL/shinobi +++ b/INSTALL/shinobi @@ -1,30 +1,68 @@ #!/bin/bash -installationDirectory="/home/Shinobi" -if [ ! "$1" ]; then +if [ ! -e "/etc/shinobisystems/path.txt" ]; then + installationDirectory="/home/Shinobi" +else + installationDirectory=$(cat /etc/shinobisystems/cctv.txt) +fi +cd $installationDirectory +currentBuild=$(git show --oneline -s) +gitOrigin=$(git remote show origin) +splitBuildString=($currentBuild) +currentCommitNumber=${splitBuildString[0]} +if [[ $gitOrigin == *'ShinobiCE'* ]]; then + repo="CE" +else + repo="Pro" +fi +if [[ $@ == *'help'* ]] || [ ! "$1" ]; then echo "=========================================================" echo "==!! Shinobi : The Open Source CCTV and NVR Solution !!==" echo "=========================================================" - echo "You are missing function parameters." - echo "Example : shinobi [command] .." - echo "Example : shinobi flush restart logs" + if [ ! "$1" ]; then + echo "You are missing function parameters." + echo "Example : shinobi [command] .." + echo "Example : shinobi flush restart logs" + else + echo "Hello there! if you need support come on over" + echo "to the Shinobi Community Chat! :)" + echo "https://discordapp.com/invite/mdhmvuH/" + fi echo "=========================================================" echo "Your available options for COMMAND are as follows" echo "=========================================================" - echo "| start or s :" + echo "| start :" echo "|--> Start camera.js and cron.js under PM2 (Process Manager)" echo "-" - echo "| restart or r :" + echo "| restart :" echo "|--> Restart all processes running under the PM2 daemon." echo "-" - echo "| stop, exit, or e :" + echo "| stop, exit :" echo "|--> Stop all processes running under the PM2 daemon." echo "-" + echo "| version :" + echo "|--> get version of your current build by git." + echo "-" echo "| logs :" echo "|--> Get PM2 log stream with last 100 lines." echo "-" - echo "| clear, flush, or f :" + echo "| update :" + echo "|--> Update via Git." + echo "-" + echo "| getMaster :" + echo "|--> Switch to the Master Branch (For Pro Repo only)." + echo "-" + echo "| getDev :" + echo "|--> Switch to the Development Branch (For Pro Repo only)." + echo "-" + echo "| clear, flush :" echo "|--> Clear all PM2 logs." echo "-" + echo "| bootupEnable :" + echo "|--> Start Shinobi on OS reboot." + echo "-" + echo "| bootupDisable :" + echo "|--> Disable starting Shinobi on OS reboot." + echo "-" echo "| kill :" echo "|--> Stop the entire PM2 daemon." fi @@ -34,7 +72,8 @@ fi if [[ $@ == *'restart'* ]]; then proccessAlive=$(pm2 list | grep camera) if [ "$proccessAlive" ]; then - pm2 restart all + pm2 restart $installationDirectory/camera.js + pm2 restart $installationDirectory/cron.js else echo "Shinobi process is not running." fi @@ -58,11 +97,64 @@ fi if [[ $@ == *'stop'* ]] || [[ $@ == *'exit'* ]]; then proccessAlive=$(pm2 list | grep camera) if [ "$proccessAlive" ]; then - pm2 kill + pm2 stop $installationDirectory/camera.js + pm2 stop $installationDirectory/cron.js else echo "Shinobi process is not running." fi fi +if [[ $@ == *'version'* ]]; then + echo "Build ID : $currentCommitNumber" + if [[ $repo == "Pro" ]]; then + echo "Repository : Shinobi Pro" + else + echo "Repository : Shinobi CE" + fi + echo $currentBuild +fi +if [[ $@ == *'bootupEnable'* ]] || [[ $@ == *'bootupenable'* ]]; then + pm2 startup + pm2 save +fi +if [[ $@ == *'bootupDisable'* ]] || [[ $@ == *'bootupdisable'* ]]; then + pm2 unstartup + pm2 save +fi +if [[ $@ == *'getDev'* ]] || [[ $@ == *'getdev'* ]]; then + if [[ $repo == "Pro" ]]; then + git checkout dev + echo "Shinobi - Restart Shinobi to make the changes take affect." + else + echo "Shinobi - Cannot use \"getDev\" with Shinobi CE" + fi +fi +if [[ $@ == *'getMaster'* ]] || [[ $@ == *'getmaster'* ]]; then + if [[ $repo == "Pro" ]]; then + git checkout master + echo "Shinobi - Restart Shinobi to make the changes take affect." + else + echo "Shinobi - Cannot use \"getMaster\" with Shinobi CE" + fi +fi +if [[ $@ == *'update'* ]]; then + echo "=============" + echo "Shinobi - Are you sure you want to update? This will restart Shinobi." + echo "(y)es or (N)o" + read updateshinobi + if [ "$updateshinobi" = "y" ] || [ "$updateshinobi" = "Y" ]; then + echo "Beginning Update Process..." + pm2 stop $installationDirectory/camera.js + pm2 stop $installationDirectory/cron.js + npm install --unsafe-perm + npm audit fix --force + git reset --hard + git pull + pm2 start $installationDirectory/camera.js + pm2 start $installationDirectory/cron.js + else + echo "Cancelled Update Process." + fi +fi if [[ $@ == *'kill'* ]]; then pm2 kill fi diff --git a/INSTALL/start.sh b/INSTALL/start.sh index a2439f7..64df53e 100644 --- a/INSTALL/start.sh +++ b/INSTALL/start.sh @@ -3,6 +3,7 @@ if [ -e "INSTALL/installed.txt" ]; then echo "Starting Shinobi" pm2 start camera.js pm2 start cron.js + pm2 logs fi if [ ! -e "INSTALL/installed.txt" ]; then chmod +x INSTALL/now.sh&&INSTALL/now.sh diff --git a/INSTALL/terminalCommands.js b/INSTALL/terminalCommands.js new file mode 100644 index 0000000..bc6e4e7 --- /dev/null +++ b/INSTALL/terminalCommands.js @@ -0,0 +1,41 @@ +var fs = require('fs'); +var moment = require('moment'); +var exec = require('child_process').exec; +var execSync = require('child_process').execSync; +s = { + isWin: (process.platform === 'win32' || process.platform === 'win64'), + mainDirectory: __dirname.split('/INSTALL')[0] +} +var createTerminalCommands = function(callback){ + var next = function(){ + if(callback)callback() + } + if(!s.isWin){ + var etcPath = '/etc/shinobisystems/' + console.log('Creating "' + etcPath + '"...') + var createPathFile = function(){ + var pathTxt = etcPath + 'cctv.txt' + console.log('Creating "' + pathTxt + '"...') + fs.writeFile(pathTxt,s.mainDirectory,function(err){ + if(err)console.log(err) + fs.chmod(pathTxt,0o777,function(err){ + if(err)console.log(err) + console.log('Linking "' + s.mainDirectory + '/INSTALL/shinobi" to "/usr/bin/shinobi"...') + fs.symlink(s.mainDirectory + '/INSTALL/shinobi', '/usr/bin/shinobi', next) + console.log('You can now use `shinobi` in terminal.') + }) + }) + } + fs.stat(etcPath,function(err,stat){ + if(!err && stat){ + createPathFile() + }else{ + fs.mkdir(etcPath,createPathFile) + } + }) + }else{ + //no commands for windows yet + next() + } +} +createTerminalCommands() diff --git a/INSTALL/ubuntu.sh b/INSTALL/ubuntu.sh index b033daf..87bd23f 100644 --- a/INSTALL/ubuntu.sh +++ b/INSTALL/ubuntu.sh @@ -30,12 +30,17 @@ if [ ! -e "./super.json" ]; then echo "* You can edit these settings in \"super.json\" located in the Shinobi directory." sudo cp super.sample.json super.json fi +if ! [ -x "$(command -v ifconfig)" ]; then + echo "=============" + echo "Shinobi - Installing Net-Tools" + sudo apt install net-tools -y +fi if ! [ -x "$(command -v node)" ]; then echo "=============" echo "Shinobi - Installing Node.js" - wget https://deb.nodesource.com/setup_9.x - chmod +x setup_9.x - ./setup_9.x + wget https://deb.nodesource.com/setup_8.x + chmod +x setup_8.x + ./setup_8.x sudo apt install nodejs -y else echo "Node.js Found..." @@ -44,7 +49,7 @@ fi if ! [ -x "$(command -v npm)" ]; then sudo apt install npm -y fi -sudo apt install make -y +sudo apt install make zip -y if ! [ -x "$(command -v ffmpeg)" ]; then if [ "$getubuntuversion" = "16" ] || [ "$getubuntuversion" < "16" ]; then echo "=============" @@ -132,21 +137,14 @@ if [ "$startShinobi" = "y" ] || [ "$startShinobi" = "y" ]; then sudo pm2 save sudo pm2 list fi -if [ ! "$sqliteormariadb" = "M" ] && [ ! "$sqliteormariadb" = "m" ]; then - echo "=====================================" - echo "||===== Install Completed =====||" - echo "=====================================" - echo "|| Login with the Superuser and create a new user!!" - echo "||===================================" - echo "|| Open http://$(ifconfig | sed -En 's/127.0.0.1//;s/.*inet (addr:)?(([0-9]*\.){3}[0-9]*).*/\2/p'):8080/super in your web browser." - echo "||===================================" - echo "|| Default Superuser : admin@shinobi.video" - echo "|| Default Password : admin" - echo "=====================================" - echo "=====================================" -else - echo "+=================================+" - echo "||===== Install Completed =====||" - echo "|| Access the main Shinobi panel at http://$(ifconfig | sed -En 's/127.0.0.1//;s/.*inet (addr:)?(([0-9]*\.){3}[0-9]*).*/\2/p'):8080 in your web browser." - echo "+=================================+" -fi +echo "=====================================" +echo "||===== Install Completed =====||" +echo "=====================================" +echo "|| Login with the Superuser and create a new user!!" +echo "||===================================" +echo "|| Open http://$(ifconfig | sed -En 's/127.0.0.1//;s/.*inet (addr:)?(([0-9]*\.){3}[0-9]*).*/\2/p'):8080/super in your web browser." +echo "||===================================" +echo "|| Default Superuser : admin@shinobi.video" +echo "|| Default Password : admin" +echo "=====================================" +echo "=====================================" diff --git a/camera.js b/camera.js index f5939a0..f5de80e 100644 --- a/camera.js +++ b/camera.js @@ -15,16 +15,20 @@ var loadLib = function(lib){ } //process handlers var s = loadLib('process')(process,__dirname) +//load extender functions +loadLib('extenders')(s) //configuration loader var config = loadLib('config')(s) //language loader var lang = loadLib('language')(s,config) +//code test module +loadLib('codeTester')(s,config,lang) //basic functions loadLib('basic')(s,config) -//load extender functions -loadLib('extenders')(s,config) //video processing engine -loadLib('ffmpeg')(s,config,function(){ +loadLib('ffmpeg')(s,config,function(ffmpeg){ + //ffmpeg coProcessor + loadLib('ffmpegCoProcessor')(s,config,lang,ffmpeg) //database connection : mysql, sqlite3.. loadLib('sql')(s,config) //working directories : videos, streams, fileBin.. @@ -60,9 +64,17 @@ loadLib('ffmpeg')(s,config,function(){ //cluster module loadLib('childNode')(s,config,lang,app,io) //cloud uploaders : amazon s3, webdav, backblaze b2.. - loadLib('cloudUploaders')(s,config,lang) + loadLib('uploaders')(s,config,lang) //notifiers : discord.. loadLib('notification')(s,config,lang) + //notifiers : discord.. + loadLib('rtmpserver')(s,config,lang) + //dropInEvents server (file manipulation to create event trigger) + loadLib('dropInEvents')(s,config,lang,app,io) + //custom module loader + loadLib('customAutoLoad')(s,config,lang,app,io) + //scheduling engine + loadLib('scheduler')(s,config,lang,app,io) //on-start actions, daemon(s) starter loadLib('startup')(s,config,lang) }) diff --git a/conf.sample.json b/conf.sample.json index 9a74575..5931061 100644 --- a/conf.sample.json +++ b/conf.sample.json @@ -1,6 +1,7 @@ { "port": 8080, "passwordType": "sha256", + "detectorMergePamRegionTriggers": true, "addStorage": [ {"name":"second","path":"__DIR__/videos2"} ], diff --git a/cron.js b/cron.js index 6856322..a9eb577 100644 --- a/cron.js +++ b/cron.js @@ -170,7 +170,7 @@ s.localToUtc = function(time){ return moment(time).utc() } s.nameToTime = function(x){x=x.replace('.webm','').replace('.mp4','').split('T'),x[1]=x[1].replace(/-/g,':');x=x.join(' ');return x;} -io = require('socket.io-client')('ws://'+config.ip+':'+config.port);//connect to master +io = require('socket.io-client')('ws://'+config.ip+':'+config.port,{transports:['websocket']});//connect to master s.cx = function(x){x.cronKey=config.cron.key;return io.emit('cron',x)} //emulate master socket emitter s.tx = function(x,y){s.cx({f:'s.tx',data:x,to:y})} diff --git a/definitions/en_CA.json b/definitions/en_CA.json index ab0e5af..d5ea281 100644 --- a/definitions/en_CA.json +++ b/definitions/en_CA.json @@ -766,6 +766,14 @@ "example": "", "possible": "" }, + { + "name": "detail=detector_send_video_length", + "field": "Notification Video Length", + "description": "In seconds. The length of the video that gets sent to your Notification service, like Email or Discord.", + "default": "10", + "example": "", + "possible": "" + }, { "name": "detail=watchdog_reset", "field": "Timeout Reset on Next Event", @@ -835,8 +843,16 @@ { "name": "detail=detector_fps", "field": "Detector Rate (FPS)", - "description": "How many frames a second to send to the motion detector; 1 is the default.", - "default": "1", + "description": "How many frames a second to send to the motion detector; 2 is the default.", + "default": "2", + "example": "", + "possible": "" + }, + { + "name": "detail=detector_buffer_seconds", + "field": "Recorded Buffer", + "description": "How many seconds before the event to include in the recorded video.", + "default": "5", "example": "", "possible": "" }, diff --git a/languages/cz.json b/languages/cz.json new file mode 100644 index 0000000..485ea71 --- /dev/null +++ b/languages/cz.json @@ -0,0 +1,857 @@ +{ + "Shinobi": "Shinobi", + "superAdminTitle": "Shinobi : Super Admin", + "failedLoginText1": "Příliš mnoho neúspěšných přihlášení. Vyčkejte 15minut před dalším pokusem.", + "failedLoginText2": "Prosím zkontrolujte přihlašovací údaje.", + "Time Left": "Zbývající čas", + "Login": "Uživatel", + "Authenticate": "Ověřit", + "Dashboard": "Dashboard", + "Streamer": "Streamer", + "Admin": "Admin", + "Superuser": "Superuser", + "Dashcam": "Dashcam", + "Email": "Email", + "Username": "Uživatel", + "Profile": "Profil", + "Password": "Heslo", + "Password Again": "Heslo znovu", + "Remember Me": "Zamapatovat si mě", + "RAM": "RAM", + "CPU": "CPU", + "on": "na", + "Power Viewer": "Power Viewer", + "Power Video Viewer": "Power Video Viewer", + "Time-lapse": "Time-lapse", + "Montage": "Montáž", + "Accounts": "Účty", + "Settings": "Nastavení", + "Recording FPS": "Recording FPS", + "Input Selector": "Výběr vstupu", + "Input Settings": "Nastavení vstupu", + "Connection": "Připojení", + "Video Set": "Video Set", + "API": "API", + "ONVIF": "ONVIF", + "FFprobe": "Sonda", + "Monitor States": "Monitorovat stavy", + "Schedule": "Plán", + "Schedules": "Plány", + "Monitor States and Schedules": "Monitorovat stavy a plány", + "Filters": "Filtry", + "Full URL Path": "Plná URL cesta", + "Logs": "Logy", + "Full Stream URL": "Full Stream URL", + "Manual": "Manuální", + "List Toggle": "Přepnout zobrazení", + "Hide List": "Skrýt seznam", + "Motion GUI": "Motion GUI", + "Motion": "Pohyb", + "Global Detector Settings": "Globální nastavení detekce", + "Motion Detection": "Detekce pohybu", + "Object Detection": "Detekce objektů", + "JPEG Mode": "Režim JPEG", + "Order Streams": "Řazení streamů", + "Hide Notes": "Skrýt poznámky", + "Example": "Příklad", + "Logout": "Odhlásit", + "Closed": "Uzavřeno", + "Ended": "Skončilo", + "Options": "Možnosti", + "Started": "Začalo", + "Monitor": "Monitor", + "Filename": "Soubor", + "Size (mb)": "Velikost (MB)", + "Watch": "Sledovat", + "Download": "Stáhnout", + "Delete": "Smazat", + "Fix": "Opravit", + "Use HTML5 Play Method": "Použít HTML5 Přehrávání", + "Connection timed out": "Připojení vypršelo", + "skipPingText1": "Zkuste Nastavit \"Vynechat Ping\" na Ano.", + "Ping Failed": "Ping Selhal", + "Zoom In": "Přiblížení URL Adresa", + "Zoom Out": "Oddálení URL Adresa", + "Enable Nightvision": "Zapni Noční Vidění", + "Disable Nightvision": "Vypni Noční Vidění", + "Current": "Aktuální", + "Monitors": "Monitory", + "Video": "Video", + "Themes": "Témata", + "Videos": "Videa", + "Events": "Události", + "Streams": "Streamy", + "Snapshot": "Snapshot", + "Snapshots": "Snapshoty", + "Date Range": "Časové období", + "Event Limit": "Limit Událostí", + "No Data": "Žádná Data", + "Live View": "Živý Pohled", + "New Monitor": "Nový Monitor", + "Please Check Your Settings": "Prosím Zkontrolujte Nastavení", + "migrateText1": "Typ Vstupu nelze parsovat. Prosím nastavte manuálně.", + "Add": "Přidat", + "Save": "Uložit", + "Close": "Zavřít", + "Secure": "Secure", + "Check": "Ověřit", + "Stop": "Stop", + "Confirm": "Potvrdit", + "Enable": "Povolit", + "Enabled": "Povoleno", + "API Key": "API Klíč", + "API Keys": "API Klíče", + "Group Key": "Klíč Skupiny", + "Allowed IPs": "Povolené IP", + "Separate with commas, no spaces": "Oddělit čárkami, bez mezer", + "Can Get Monitors": "Can Get Monitory", + "Can Get Logs": "Can Get Logs", + "Can Authenticate Websocket": "Can Authenticate Websocket", + "Can Control Monitors": "Can Control Monitory", + "Can View Snapshots": "Can View Snapshots", + "Can View Streams": "Can View Streams", + "Can View Videos": "Can View Videos", + "Can View Monitor": "Can View Monitor", + "Can Change User Settings": "Can Change User Settings", + "Can Create and Delete Monitors": "Can Create and Delete Monitory", + "Can Edit Monitor": "Can Edit Monitor", + "Can Delete Videos": "Can Delete Videos", + "Delete Video": "Delete Video", + "Can View Videos and Events": "Can View Videos and Events", + "Can Delete Videos and Events": "Can Delete Videos and Events", + "Saved Filters": "Uložené filtry", + "Saved Presets": "Uložené předvolby", + "Saved Schedules": "Uložené časovače", + "Filter Name": "Název filtru", + "Find Where": "Find Where", + "Reason": "Důvod", + "Detection Engine": "Detection Engine", + "X Point": "Bod X", + "Y Point": "Bod Y", + "Sort By": "Řadit dle", + "Start Time": "Start Time", + "End Time": "End Time", + "Time": "Čas", + "Monitor ID": "Monitor ID", + "File Type": "Typ souboru", + "Filesize": "Velikost souboru", + "Video Status": "Stav Videa", + "Preferences": "Možnosti", + "Equal to": "Rovno", + "Not Equal to": "Není rovno", + "Greater Than or Equal to": "Větší než nebo rovno", + "Greater Than": "Větší než", + "Less Than": "Menší než", + "Less Than or Equal to": "Menší než nebo rovno", + "Contains": "Obsahuje", + "Does Not Contain": "Neobsahuje", + "AND": "A", + "OR": "Nebo", + "Like": "Jako", + "Matches": "Odpovída", + "Not Matches": "Neodpovídá", + "In": "In", + "Not In": "Not In", + "ASC": "Vzestupně", + "DESC": "Sestupně", + "Action for Selected": "Action for Selected", + "Search": "Hledat", + "No": "Ne", + "Yes": "Ano", + "Start": "Start", + "End": "Konec", + "Archive": "Archiv", + "Email Details": "Email Details", + "Delete Matches": "Delete Matches", + "Delete selected": "Delete selected", + "Execute Command": "Execute Command", + "for Global Access": "for Global Access", + "Help": "Pomoc", + "Don't show this anymore": "Již nezobrazovat", + "Chat on Discord": "Chat on Discord", + "Documentation": "Dokumentace", + "All Monitors": "Všechny monitory", + "Motion Meter": "Motion Meter", + "FFmpegTip": "FFprobe is a simple multimedia streams analyzer. You can use it to output all kinds of information about an input including duration, frame rate, frame size, etc.", + "Complete Stream URL": "Complete Stream URL", + "ONVIF Scanner": "ONVIF Scanner", + "ONVIFEventsNotAvailable": "ONVIF události njesou dostupné", + "ONVIFnotCompliantProfileT": "Camera is not ONVIF Profile T Compliant", + "Scan Settings": "Nastavení scanu", + "ONVIFnote": "Discover ONVIF devices on networks outside your own or leave it blank to scan your current network.
Username and Password can be left blank.", + "Range or Single": "Range or Single", + "IP Address": "IP Addresa", + "Port": "Port", + "Camera Username": "CAM Uživatel", + "Camera Password": "CAM Heslo", + "Found Devices": "Zařízení nalezeno", + "Switch on for Still Image": "Switch on for Still Image", + "Live Stream Toggle": "Live Stream Toggle", + "RegionNote": "Points are only saved when you press Save on the Monitor Settings window.", + "Points": "Points When adding points click on the edge of the polygon.", + "Indifference": "Indifference", + "Max Indifference": "Max Indifference", + "Trigger Threshold": "Trigger Threshold", + "Color Threshold": "Color Threshold", + "Region Name": "Název Regionu", + "Regions": "Regiony", + "Again": "Znovu", + "Account Info": "Info o účtu", + "blankPassword": "Nechcete-li měnit heslo, ponechte prázdné", + "2-Factor Authentication": "Dvou-faktorové přihlášení", + "Use Max Storage Amount": "Použít max. velikost uložiště", + "Max Storage Amount": "Maximum uložiště v Megabajtech", + "Number of Days to keep": "Počet dní uchování", + "Monitor Groups": "Skupiny monitorů", + "Group Name": "Název skupiny", + "Show Thumbnails in Video List": "Show Thumbnails in Video List", + "WebDAV": "WebDAV", + "Backblaze B2": "Backblaze B2", + "Backblaze Error": "Backblaze Error", + "Could not create Bucket.": "Could not create Bucket.", + "Amazon S3": "Amazon S3", + "Database": "Databáze", + "Database Not Found": "Databáze nenalezena", + "User Not Found": "Uživatel nenalezen", + "Save Links to Database": "Save Links to Database", + "Upload File": "Nahrát soubor", + "Bucket": "Bucket", + "Region": "Region", + "Use Global Amazon S3 Video Storage": "Use Global Amazon S3 Video Storage", + "Use Global Backblaze B2 Video Storage": "Use Global Backblaze B2 Video Storage", + "Use Global WebDAV Video Storage": "Use Global WebDAV Video Storage", + "Amazon S3 Upload Error": "Amazon S3 Upload Error", + "accountId": "Account ID", + "applicationKey": "Application Key", + "aws_accessKeyId": "Access Key Id", + "aws_secretAccessKey": "Secret Access Key", + "Discord Bot": "Discord Bot", + "URL": "URL", + "Operating Hours": "Operating Hours", + "Autosave": "Autosave", + "Save Directory": "Save Directory", + "CSS": "CSS Style your dashboard.", + "Force Monitors Per Row": "Force Monitory Per Row", + "Monitors per row": "Monitory per row for Montage", + "Browser Console Log": "Browser Console Log", + "Log Stream": "Log Stream", + "Privileges": "Privileges", + "All Monitors and Privileges": "All Monitory and Privileges", + "Permissions": "Permissions", + "Time-lapse Tool": "Time-lapse Tool", + "total": "total", + "MB": "MB", + "Calendar": "Calendar", + "Leave blank for random.": "Leave blank for random.", + "Currently viewing": "Currently viewing", + "Status Indicator": "Status Indicator", + "Show Logs": "Show Logs", + "Videos List": "Videos List", + "Monitor Settings": "Monitor Settings", + "Enlarge": "Enlarge", + "Fullscreen": "Fullscreen", + "Value": "Value", + "Idle": "Idle", + "Disabled": "Disabled", + "Record": "Record", + "Watch Only": "Watch Only", + "Toggle Sidebar": "Toggle Sidebar", + "Add Monitor": "Add Monitor", + "Start Recording": "Start Recording", + "Set to Watch Only": "Set to Watch Only", + "Save as": "Ukládat jako", + "Add New": "Přidat", + "Zip and Download": "Stáhnout jako ZIP", + "Export Selected Videos": "Exportovat vybraná videa", + "Delete Selected Videos": "Smazat vybraná videa", + "DeleteSelectedVideosMsg": "Do you want to delete these videos? You cannot recover them.", + "ExportSelectedVideosMsg": "Do you want to export these videos? It may take some time to zip and download.", + "clientStreamFailedattemptingReconnect": "Client side ctream check failed, attempting reconnect.", + "Export Video": "Export Video", + "Delete Filter": "Delete Filter", + "confirmDeleteFilter": "Do you want to delete this filter? You cannot recover it.", + "Fix Video": "Fix Video", + "FixVideoMsg": "Do you want to fix this video? You cannot undo this action.", + "DeleteVideoMsg": "Do you want to delete this video? You cannot recover it.", + "dropBoxSuccess": "Success! Files saved to your Dropbox.", + "API Key Deleted": "API Key Deleted", + "APIKeyDeletedText": "Key has been deleted. It will no longer work.", + "API Key Added": "API Key Added", + "APIKeyAddedText": "You may use this key now.", + "Update": "Update", + "Update to Master": "Update to Master", + "Update to Development": "Update to Development", + "Filters Updated": "Filters Updated", + "FiltersUpdatedText": "Your changes have been saved and applied.", + "Settings Changed": "Settings Changed", + "SettingsChangedText": "Your settings have been saved and applied. Some settings may require a refresh of this page.", + "Are you sure?": "Are you sure?", + "Import Monitor Configuration": "Import Monitor Configuration", + "ImportMultiMonitorConfigurationText": "Doing this will overrwrite any monitory with IDs existing in the import file.", + "ImportMonitorConfigurationText": "Doing this will overrwrite any changes currently not saved. Imported changes will only be applied when you press Save.", + "Paste JSON here.": "Paste JSON here.", + "Delete Monitor": "Delete Monitor", + "DeleteMonitorText": "Do you want to delete this monitor? You cannot recover it. You can choose for the files to remain in the filesystem. If you choose to recreate a monitor with the same ID the videos and events will become visible in the dashboard.", + "DeleteMonitorsText": "Do you want to delete these monitory? You cannot recover them. You can choose to keep the files for these IDs in the filesystem. If you choose to recreate a monitor with one of the IDs the videos and events will become visible in the dashboard.", + "Invalid JSON": "Invalid JSON", + "Invalid Data": "Invalid Data", + "Name cannot be empty.": "Name cannot be empty.", + "Start Time cannot be empty.": "Start Time cannot be empty.", + "Must be atleast one row": "Must be atleast one row", + "InvalidJSONText": "Please ensure this is a valid JSON string for Shinobi monitor configuration.", + "Passwords don't match": "Passwords don't match", + "Email address is in use.": "Email address is in use.", + "Group Key is in use.": "Group Key is in use.", + "Create Sub-Accounts at /admin": "Create Sub-Accounts at /admin", + "No Events found for this video": "No Events found for this video", + "Video and Time Span (Minutes)": "Video and Time Span (Minutes)", + "Video Length (minutes) and Motion Count per video": "Video Length (minutes) and Motion Count per video", + "Counts of Motion": "Counts of Motion", + "Unable to Launch": "Unable to Launch", + "UnabletoLaunchText": "Please save new monitor first. Then attempt to launch the region editor.", + "NoVideosFoundForDateRange": "No Videos found in this date range. Try setting the start date further back.", + "NoLogsFoundForDateRange": "No Logs found in this date range. Try widening the date range.", + "monitorEditFailedMaxReached": "Your account has reached the maximum number of cameras that can be created. Speak to an administrator if you would like this changed.", + "in": "in", + "ago": "ago", + "a few seconds": "a few seconds", + "a minute": "a minute", + "minutes": "minutes", + "an hour": "an hour", + "hours": "hours", + "a day": "a day", + "days": "days", + "a month": "a month", + "months": "months", + "a year": "a year", + "years": "years", + "Identity": "Identity", + "Input": "Input", + "Input Feed": "Input Feed", + "Stream": "Stream", + "Stream Timestamp": "Stream Timestamp", + "Stream Watermark": "Stream Watermark", + "JPEG API": "JPEG API Snapshot (cgi-bin)", + "Raw H.264 Stream": "Raw H.264 Stream", + "Recording": "Recording", + "Recording Timestamp": "Recording Timestamp", + "Recording Watermark": "Recording Watermark", + "Region Editor": "Region Editor", + "Detector Filters": "Detector Filters", + "Filter for Objects only": "Filter for Objects only", + "Custom": "Custom", + "Detector": "Detector", + "Audio Detector": "Audio Detector", + "Audio Detection": "Audio Detection", + "Minimum dB": "Minimum dB", + "Maximum dB": "Maximum dB", + "Connected": "Connected", + "Not Saved": "Not Saved", + "Not Connected": "Not Connected", + "Lisence Plate Detector": "Lisence Plate Detector", + "OpenCV Cascades": "OpenCV Cascades", + "Refresh List of Cascades": "Refresh List of Cascades", + "\"No Motion\" Detector": "\"No Motion\" Detector", + "Control": "Control", + "Grouping": "Grouping Add groups in Settings", + "Detector Grouping": "Detector Grouping Add groups in Settings", + "Detector Recording Process Exited Prematurely. Restarting.": "Detector Recording Process Exited Prematurely. Restarting.", + "Detector Recording Complete": "Detector Recording Complete", + "Clear Recorder Process": "Clear Recorder Process", + "Logging": "Logging", + "IdentityText1": "This is how the system will identify the data for this stream. You cannot change the Monitor ID once you have pressed save. If you want you can make the Monitor ID more human readable before you continue.", + "IdentityText2": "You can duplicate a monitor by modifying the Monitor ID then pressing save. You cannot use the ID of a monitor that already exists or it will save over that monitor's database information.", + "noSpecialCharacters": "No spaces or special characters.", + "NotesPlacholder": "Comments you want to leave for this cameras settings.", + "InputText1": "This section tells Shinobi how to consume a stream. For optimal performance try tuning your camera's internal settings. Find the following options and set them as shown. To find your camera you can use the built in ONVIF Scanner of Shinobi. Some ONVIF cameras require the use of a management tool to modify their internal settings. If you can't find your cameras you can try ONVIF Device Manager for Windows.", + "InputText2": "", + "InputText3": "If you need help figuring out what input type your camera is you can take a look in the Camera URLs List on the Shinobi website.", + "StreamText": "

This section will designate the primary method of streaming out and its settings. This stream will be displayed in the dashboard. If you choose to use HLS, JPEG, or MJPEG then you can consume the stream through other programs.

Using JPEG stream essentially turns off the primary stream and uses the snapshot bin to get frames.

", + "DetectorText": "

When the Width and Height boxes are shown you should set them to 640x480 or below. This will optimize the read speed of frames.

", + "RecordingText": "It is recommended that you set Record File Type to WebMMP4 and Video Codec to libvpxcopy or libx264 because your Input Type is set to .", + "Mode": "Mód", + "Name": "Název", + "Skip Ping": "Vynechat Ping", + "Retry Connection": "Retry Connection Number of times allowed to fail", + "Notes": "Notes", + "Input Type": "Input Type", + "Connection Type": "Connection Type", + "RTSP Transport": "RTSP Transport", + "Host": "Host", + "Force Port": "Force Port", + "Path": "Path", + "Monitor Capture Rate": "Monitor Capture Rate (FPS)", + "Analyzation Duration": "Analyzation Duration", + "Probe Size": "Probe Size", + "Stream Type": "Stream Type", + "# of Allow MJPEG Clients": "# of Allow MJPEG Clients 0 for infinite", + "HLS Video Encoder": "Video Encoder", + "HLS Audio Encoder": "Audio Encoder", + "HLS Segment Length": "Segment Length in Seconds", + "HLS Preset": "Preset Template", + "HLS List Size": "List Size", + "Traditional Recording": "Traditional Recording", + "Buffer Preview": "Buffer Preview", + "HLS Start Number": "HLS Start Number", + "HLS Live Start Index": "HLS Live Start Index", + "Check Signal Interval": "Check Signal Interval in Minutes", + "Log Signal Event": "Log Signal Event Client side only", + "Quality": "Quality 1 is High, 23 is Low", + "Rate": "Rate (FPS)", + "Width": "Width", + "Height": "Height", + "Rotate": "Rotate", + "Primary Engine": "Primary Engine", + "Video Filter": "Video Filter", + "Font Path": "Font Path", + "Font Size": "Font Size", + "Text Color": "Text Color", + "Text Box Color": "Text Box Color", + "Position X": "Position X", + "Position Y": "Position Y", + "Image Location": "Image Location Absolute Path or leave blank to use global", + "Image Position": "Image Position", + "Frame Rate": "Frame Rate (FPS)", + "Image Width": "Image Width", + "Image Height": "Image Height", + "Record File Type": "Record File Type", + "Video Codec": "Video Codec", + "Delete Monitor States Preset": "Delete Monitor States Preset", + "Delete Monitor State?": "Delete Monitor State", + "deleteMonitorStateText1": "Do you want to delete this Monitor States Preset?", + "deleteMonitorStateText2": "Do you want to delete this Monitor's Preset?", + "Search Images": "Hledat Images", + "Launch in New Window": "Launch in New Window", + "Preset": "Preset", + "Presets": "Presets", + "possibleInternalError": "Possible Internal Error", + "sizePurgeLockedText": "The Size Purge Lock (deleteOverMax) appears to have failed to unlock. Unlocking now...", + "Use coProcessor": "Use coProcessor", + "Audio Codec": "Audio Codec", + "Video Record Rate": "Video Record Rate (FPS)", + "Record Width": "Record Width", + "Record Height": "Record Height", + "Double Quote Directory": "Double Quote Directory Some directories have spaces. Using this may crash some cameras.", + "Recording Segment Interval": "Recording Segment Interval in minutes", + "Record Video Filter": "Record Video Filter", + "Input Flags": "Input Flags", + "Snapshot Flags": "Snapshot Flags", + "Detector Flags": "Detector Flags", + "Stream Flags": "Stream Flags", + "Stream to YouTube": "Stream to YouTube", + "Stream to YouTube Flags": "Stream to YouTube Flags", + "Recording Flags": "Recording Flags", + "Traditional Recording Flags": "Traditional Recording Flags", + "Output Method": "Output Method", + "Webhook": "Webhook", + "Event Webhook Error": "Event Webhook Error", + "Webhook URL": "Webhook URL", + "Command on Trigger": "Command on Trigger", + "Command": "Command", + "Allow Next Command": "Allow Next Command in Minutes", + "Allow Next Trigger": "Allow Next Trigger in Milliseconds", + "Save Events to SQL": "Save Events to SQL", + "Email on Trigger": "Email on Trigger Emails go to the main account holder's login address.", + "Attach Video Clip": "Attach Video Clip", + "Error While Decoding": "Error While Decoding", + "ErrorWhileDecodingText": "Your hardware may have an unstable connection to the network. Check your network connections.", + "Discord": "Discord", + "Discord Alert on Trigger": "Discord Alert on Trigger", + "Allow Next Email": "Allow Next Email in Minutes", + "Allow Next Discord Alert": "Allow Next Discord Alert in Minutes", + "DiscordLoggedIn": "Discord Bot Authenticated", + "DiscordFailedText": "Sending to Discord Failed", + "DiscordErrorText": "Sending to Discord caused an Error", + "DiscordNotEnabledText": "Discord Bot Not Enabled, Enable it in your Account Settings.", + "How to Record": "How to Record", + "Trigger Record": "Trigger Record", + "Recording Timeout": "Recording Timeout in Minutes", + "Timeout Reset on Next Motion": "Timeout Reset on Next Motion", + "Timeout Reset on Next Event": "Timeout Reset on Next Event", + "Delete Motionless Video": "Delete Motionless Video", + "Send Frames": "Send Frames Push frames to be analyzed", + "Detector Rate": "Detector Rate (FPS)", + "Feed-in Image Width": "Feed-in Image Width", + "Feed-in Image Height": "Feed-in Image Height", + "Check for Motion First": "Check for Motion First", + "Detect Objects": "Detect Objects See below", + "Full Frame Detection": "Full Frame Detection", + "Country of Plates": "Country of Plates", + "Email on No Motion": "Email on \"No Motion\"", + "Timeout": "Timeout", + "Controllable": "Controllable", + "Custom Base URL": "Custom Base URL Leave blank to use Host URL", + "Stop URL": "Stop URL", + "Stop Command": "Stop Command", + "Digest Authentication": "Digest Authentication", + "URL Stop Timeout": "URL Stop Timeout Run stop URL after X milliseconds", + "Center": "Center URL Address", + "Left": "Left URL Address", + "Left Stop": "Left Stop URL Address", + "Right": "Right URL Address", + "Right Stop": "Right Stop URL Address", + "Up": "Up URL Address", + "Up Stop": "Up Stop URL Address", + "Down": "Down URL Address", + "Down Stop": "Down Stop URL Address", + "Enable Night Vision": "Enable Night Vision URL Address", + "Disable Night Vision": "Disable Night Vision URL Address", + "Zoom Out Stop": "Zoom Out Stop URL Address", + "Zoom In Stop": "Zoom In Stop URL Address", + "Log Level": "Log Level", + "Save Log in SQL": "Save Log in SQL This can fill up quickly.", + "JPEG": "JPEG", + "Web Page": "Web Page", + "MJPEG": "MJPEG", + "H.264 / H.265 / H.265+": "H.264 / H.265 / H.265+", + "HLS (.m3u8)": "HLS (.m3u8)", + "MPEG-4 (.mp4 / .ts)": "MPEG-4 (.mp4 / .ts)", + "Shinobi Streamer": "Shinobi Streamer", + "Dashcam (Streamer v2)": "Dashcam (Streamer v2)", + "Local": "Local", + "Raw": "Raw", + "HTTP": "HTTP", + "HTTPS": "HTTPS", + "RTSP": "RTSP", + "RTMP": "RTMP", + "RTMPS": "RTMPS", + "UDP": "UDP", + "Auto": "Auto", + "TCP": "TCP", + "Base64 over Websocket": "Base64 over Websocket", + "Websocket": "Websocket", + "JPEG (Auto Enables JPEG API)": "JPEG (Auto Enables JPEG API)", + "HLS (includes Audio)": "HLS (includes Audio)", + "MPEG-DASH (includes Audio)": "MPEG-DASH (includes Audio)", + "libx264": "libx264", + "libx265": "libx265", + "copy": "copy", + "Audio": "Audio", + "Mute Audio": "Vypnout zvuk", + "No Audio": "Bez Zvuku", + "Popout Monitor on Event": "Vyskakovací okno při události", + "aac": "aac", + "ac3": "ac3", + "libmp3lame": "libmp3lame", + "No Rotation": "No Rotation", + "180 Degrees": "180 Degrees", + "90 Counter Clockwise and Vertical Flip (default)": "90 Counter Clockwise and Vertical Flip (default)", + "90 Clockwise": "90 Clockwise", + "90 Clockwise and Vertical Flip": "90 Clockwise and Vertical Flip", + "Top Right": "Top Right", + "Top Left": "Top Left", + "Bottom Right": "Bottom Right", + "Bottom Left": "Bottom Left", + "WebM (libvpx)": "WebM (libvpx)", + "Poseidon": "Poseidon", + "HEVC (H.265)": "HEVC (H.265)", + "MP4 (copy, libx264, libx265)": "MP4 (copy, libx264, libx265)", + "Default": "Default", + "libvpx (Default)": "libvpx (Default)", + "libvpx-vp9": "libvpx-vp9", + "libx264 (Default)": "libx264 (Default)", + "libvorbis (Default)": "libvorbis (Default)", + "libopus": "libopus", + "aac (Default)": "aac (Default)", + "Traditional (Watch-Only, Includes Buffer)": "Traditional (Watch-Only, Includes Buffer)", + "Hotswap Modes (Watch-Only)": "Hotswap Modes (Watch-Only)", + "Delete Motionless Videos (Record)": "Delete Motionless Videos (Record)", + "US": "US", + "EU": "EU", + "Silent": "Silent", + "Fatal": "Fatal", + "on Error": "on Error", + "All Warnings": "All Warnings", + "Warning": "Warning", + "Debug": "Debug", + "Export": "Exportovat", + "Import": "Importovat", + "Simple": "Jednoduché", + "Advanced": "Rozšířené", + "Error Connecting": "Chyba připojení", + "DB Lost.. Retrying..": "Database Lost.. Retrying..", + "Retrying...": "Nový pokus...", + "Filter Matches": "Filter Matches", + "FilterMatchesText1": "This filter has met conditions.", + "FilterMatchesText2": "záznamů nalezeno.", + "Executed": "Executed", + "Deleted": "Deleted", + "Query": "Query", + "Request": "Request", + "System": "System", + "Restart Core": "Restart Core", + "Restart CRON": "Restart CRON", + "Flush PM2 Logs": "Flush PM2 Logs", + "Filter ID": "Filter ID", + "Webdav Error": "Chyba WebDAV", + "WebdavErrorTextTryCreatingDir": "Cannot save. Trying to create directory.", + "WebdavErrorTextCreatingDir": "Nelze vytvořit složku.", + "File Not Exist": "Soubor neexistuje", + "No Videos Found": "Nenalezena žádná videa", + "FileNotExistText": "Cannot save non existant file. Something went wrong.", + "CameraNotRecordingText": "Settings may be incompatible. Check encoders. Restarting...", + "Camera is not running": "Kamera neběží", + "Camera is not recording": "Kamera nenahrává", + "Camera is not streaming": "Kamera nestreamuje", + "Process Started": "Proces spuštěn", + "Restarting Process": "Restartuji proces", + "Restarting": "Restartuji", + "Starting": "Startuje", + "Watching": "Sledování", + "Recording": "Nahrávání", + "Stopped": "Zastaveno", + "Died": "Selhalo", + "Restart": "Restart", + "Monitor Stopped": "Monitor zastaven", + "MonitorStoppedText": "Monitor session has been ordered to stop.", + "Monitor Idling": "Monitor Idling", + "MonitorIdlingText": "Monitor session has been ordered to idle.", + "NoMotionEmailText1": "Nezaznamenán pohyb na", + "NoMotionEmailText2": "Nebyl detekován žádný pohyb detected na kameře pro", + "Monitor Name": "Název monitoru", + "Mp4Frag": "Mp4Frag", + "Status Changed": "Stav byl změněn", + "Monitor is now Idle": "Monitor je nečinný", + "Monitor is now Disabled": "Monitor neaktivní", + "Monitor is now Watching": "Monitor sleduje", + "Monitor is now Recording": "Monitor nahrává", + "Space Used": "Využité místo", + "Processor": "Procesor", + "coProcessor": "koprocesor", + "coProcessor Stopped": "koprocesor zastaven", + "coProcessor Started": "koprocesor spuštěn", + "coProcessorTextStarted": "coProcessor has started for CPU only outputs.", + "coProcessorTextStopped": "coProcessor has ended.", + "Process Unexpected Exit": "Process Unexpected Exit", + "coProcess Unexpected Exit": "coProcess Unexpected Exit", + "Process Crashed for Monitor": "Process Crashed for Monitor", + "coProcess Crashed for Monitor": "coProcess Crashed for Monitor", + "FFmpegCantStart": "FFmpeg Couldn't Start", + "FFmpegCantStartText": "The recording engine for this camera could not start. There may be something wrong with your camera configuration. If there are any logs other than this one please post them in the Issues on Github.", + "JPEG Error": "JPEG Error", + "JPEGErrorText": "There was an issue getting data from your camera.", + "Fatal Maximum Reached": "Fatal Maximum Reached, Stopping Camera.", + "FatalMaximumReachedText": "JPEG Error was fatal.", + "Incorrect Settings Chosen": "Incorrect Settings Chosen", + "Can't Connect": "Can't Connect", + "Video Finished": "Video Finished", + "No Monitors Selected": "No Monitory Selected", + "monSavedButNotCopied": "Your monitor was saved but not copied to any other monitor.", + "No Monitor Found, Ignoring Request": "No Monitor Found, Ignoring Request", + "Event": "Event", + "CPU used by this stream": "CPU used by this stream", + "Detector Buffer": "Detector Buffer", + "EventText1": "Triggered a motion event at", + "EventText2": "Could not email image, file was not accessible", + "MailError": "MAIL ERROR : Could not send email, Check conf.json. Skipping any features relying on mailing.", + "updateKeyText1": "\"updateKey\" is missing from \"conf.json\", cannot do updates this way until you add it.", + "updateKeyText2": "\"updateKey\" is incorrect.", + "Control Error": "Control Error", + "Database row does not exist": "Database row does not exist", + "File Delete Error": "File Delete Error", + "List of Videos Delete Error": "List of Videos Delete Error", + "postDataBroken": "Check the format of the JSON. Ensure it is stringified and defined under 'data'", + "ControlErrorText1": "Control is not enabled", + "ControlErrorText2": "Check your connection details. You may need to point the Base URL at port 8000 or 80. Check your authentication info.", + "NotAuthorizedText1": "Not Authorized, Submit init command with \"auth\",\"ke\", and \"uid\"", + "Fields cannot be empty": "Fields cannot be empty", + "Email and Password fields cannot be empty": "Email and Password fields cannot be empty", + "AccountEditText1": "Could not edit. Refresh page if problem continues.", + "Not an Administrator Account": "Not an Administrator Account", + "superAdminText": "\"super.json\" does not exist. Please rename \"super.sample.json\" to \"super.json\".", + "Enter this code to proceed": "Enter this code to proceed", + "FactorAuthText1": "The code will only be active for 15 minutes. If you login again the timer will be reset to 15 minutes with the same code.", + "monitorEditText1": "Invalid Data, Check to see this is a valid import string.", + "monitorEditText2": "Invalid Details String. Check to see it is a JSON string and not a regular object being passed.", + "Monitor Updated by user": "Monitor Updated by user.", + "Monitor Added by user": "Monitor Added by user.", + "monitorGetText1": "incomplete request, remove last slash in URL or put acceptable value.", + "Monitor mode changed": "Monitor mode changed", + "Reset Timer": "Reset Timer", + "Monitor mode is already": "Monitor mode is already", + "Monitor or Key does not exist.": "Monitor or Key does not exist.", + "No Group with this key exists": "No Group with this key exists", + "Success": "Success", + "Trigger Successful": "Trigger Successful", + "No such file": "No such file", + "h265BrowserText1": "If you are trying to play an H.265 file, you may need to download it and open it in another application like VLC.", + "modifyVideoText1": "Method doesn't exist. Check to make sure that the last value of the URL is not blank.", + "CPU indicator will not work. Continuing...": "CPU indicator will not work. Continuing...", + "startUpText0": "Checking Disk Used..", + "startUpText1": "Completed Checking Disk Used.", + "startUpText2": "all users checked, wait to close open files and remove files over user limit", + "startUpText3": "waiting to give unfinished video check some time. 3 seconds.", + "startUpText4": "Starting Monitory... Please Wait...", + "startUpText5": "Shinobi is ready.", + "startUpText6": "Orphaned Videos Found and Inserted", + "Migrator": "Migrator", + "Thumbnail": "Thumbnail", + "Host Type": "Host Type", + "Edit": "Edit", + "Show Matrices": "Show Matrices", + "Show Matrix": "Show Matrix", + "No Monitor ID Present in Form": "No Monitor ID Present in Form", + "State Configuration has no monitory associated": "State Configuration has no monitory associated", + "State Configuration Not Found": "State Configuration Not Found", + "Inserted State Configuration": "Inserted State Configuration", + "Edited State Configuration": "Edited State Configuration", + "Deleted State Configuration": "Deleted State Configuration", + "Schedule Configuration Not Found": "Schedule Configuration Not Found", + "Inserted Schedule Configuration": "Inserted Schedule Configuration", + "Edited Schedule Configuration": "Edited Schedule Configuration", + "Deleted Schedule Configuration": "Deleted Schedule Configuration", + "Dashboard Language": "Jazyk prostředí", + "Form Data Not Found": "Form Data Not Found", + "File Not Found": "File Not Found", + "File Not Found in Filesystem": "File Not Found in Filesystem", + "File Not Found in Database": "File Not Found in Database", + "No Monitor Exists with this ID.": "No Monitor Exists with this ID.", + "Cannot watch a monitor that isn't running.": "Cannot watch a monitor that isn't running.", + "Not Permitted": "Not Permitted", + "notPermitted1": "This action is not permitted by the administrator of your account.'", + "Not Authorized": "Not Authorized", + "Generate Subtitles": "Generate Subtitles", + "Video Limit":"Video Limit", + "Preview":"Preview", + "Websocket Connected":"Websocket Connected", + "Websocket Disconnected":"Websocket Disconnected", + "Token":"Token", + "Channel ID":"Channel ID", + "New Authentication Token":"New Authentication Token", + "All Logs":"All Logs", + "For Group":"For Group", + "Basic Authentication":"Basic Authentication", + "Superuser Logs":"Superuser Logs", + "Authentication Failed":"Authentication Failed", + "Max Number of Cameras":"Max Number of Cameras", + "Can edit Max Storage":"Can edit Max Storage", + "Can edit Max Days":"Can edit Max Days", + "in Days":"in Days", + "Can edit how long to keep Logs":"Can edit how long to keep Logs", + "Can use Admin Panel":"Can use Admin Panel", + "Can use Discord Bot":"Can use Discord Bot", + "Can use WebDAV":"Can use WebDAV", + "Can use Amazon S3":"Can use Amazon S3", + "Can use LDAP":"Can use LDAP", + "Can View Logs":"Can View Logs", + "Can edit how long to keep Events":"Can edit how long to keep Events", + "Leave blank for unlimited":"Leave blank for unlimited", + "Limited":"Limited", + "All Privileges":"All Privileges", + "LDAP":"LDAP", + "LDAP Success":"LDAP Success", + "LDAP User Authenticated":"LDAP User Authenticated", + "LDAP User is New":"LDAP User is New", + "Creating New Account":"Creating New Account", + "bindDN":"bindDN", + "Bind Credentials":"Bind Credentials (Password)", + "Search Base":"Search Base", + "Configuration":"Nastavení", + "Blank for No Change":"Blank for No Change", + "Pop":"Pop", + "Recording FPS Change on Start":"Recording FPS Change on Start", + "Save Frames to Events":"Save Frames to Events", + "Search Filter":"Search Filter", + "h264_cuvid": "H.264 CUVID", + "hevc_cuvid": "H.265 CUVID", + "mjpeg_cuvid": "MJPEG CUVID", + "mpeg4_cuvid": "MPEG4 CUVID", + "h264_qsv": "H.264 (Quick Sync Video)", + "hevc_qsv": "H.265 (Quick Sync Video)", + "vp8_qsv": "VP8 (Quick Sync Video)", + "mpeg2_qsv": "MPEG2 (Quick Sync Video)", + "h264_mmal": "H.264 (Raspberry Pi)", + "mpeg2_mmal": "MPEG-2 (Raspberry Pi)", + "mpeg4_mmal": "MPEG-4 (Raspberry Pi)", + "h264_omx": "H.264 openMAX (Raspberry Pi)", + "h264_vaapi": "H.264 VA-API (Intel HW Accel)", + "h264_nvenc": "H.264 NVENC (NVIDIA HW Accel)", + "hevc_nvenc": "H.265 NVENC (NVIDIA HW Accel)", + "hevc_vaapi": "H.265 VA-API (Intel HW Accel)", + "vp8_cuvid": "VP8 NVENC (NVIDIA HW Accel)", + "vp9_cuvid": "VP9 NVENC (NVIDIA HW Accel)", + "hwaccel": "Acceleration Engine", + "hwaccel_vcodec": "Video Decoder", + "hwaccel_device": "HWAccel Device", + "Get Logs to Client": "Get Logs to Client", + "Hardware Accelerated": "Hardware Accelerated", + "Accelerator": "Accelerator", + "drm": "DRM object sharing", + "qsv": "qsv", + "dxva2": "dxva2 (DirectX Video, Windows)", + "vdpau": "vdpau", + "vaapi": "vaapi (VA-API)", + "vda": "vda (Apple VDA Hardware Acceleration)", + "videotoolbox": "videotoolbox", + "cuvid": "cuvid (NVIDIA NVENC)", + "Main": "Main", + "Storage Location": "Storage Location", + "Recommended": "Recommended", + "Please Wait for Completion": "Please Wait for Completion, Depending on the number of files selected this may take some time. Refresh to check again.", + "flv": "flv", + "FLV": "FLV", + "FLV Stream Type": "FLV Stream Type", + "Link Shinobi": "Link Shinobi", + "Show Stream HUD":"Show Stream HUD", + "Call Method":"Call Method", + "Gender":"Gender", + "Emotion":"Emotion", + "Age":"Age", + "Object":"Object", + "Uniform":"Uniform", + "Pose":"Pose", + "Male":"Male", + "Female":"Female", + "Channel":"Channel", + "Stream Key":"Stream Key", + "Server URL":"Server URL", + "Video Bit Rate":"Video Bit Rate", + "Audio Bit Rate":"Audio Bit Rate", + "RTMP Stream Flags":"RTMP Stream Flags", + "RTMP Stream":"RTMP Stream", + "Stream Channel":"Stream Channel", + "Confidence":"Confidence", + "Trainer Engine":"Trainer Engine", + "Train":"Train", + "TrainConfirm":"Are you sure you want to begin training? This can take more than 12 hours with over 500 images. This will consume a large amount of resources, like RAM or CPU.", + "Batch":"Batch", + "Subdivision":"Subdivision", + "Map":"Map", + "Add Map":"Add Map", + "Add Input Feed":"Add Input Feed", + "Add Channel":"Add Channel", + "Automatic":"Automatic", + "Max Latency":"Max Latency", + "Loop Stream":"Loop Stream", + "Object Tag":"Object Tag", + "Noise Filter":"Noise Filter", + "Noise Filter Range":"Noise Filter Range", + "TV Channel":"TV Channel", + "Channel ID":"Channel ID", + "TV Channel ID":"TV Channel ID", + "TV Channel Group":"TV Channel Group", + "Emotion Average":"Emotion Average", + "Require Object to be in Region":"Require Object to be in Region", + "Show Regions of Interest":"Show Regions of Interest", + "Confidence of Detection":"Confidence of Detection", + "Edit Selected":"Edit Selected", + "Copy Settings":"Copy Settings", + "Copy to Settings":"Copy to Settings", + "Copy Group Settings":"Copy Group Settings", + "Copy Connection Settings":"Copy Connection Settings", + "Copy Custom Settings":"Copy Custom Settings", + "Copy Logging Settings":"Copy Logging Settings", + "Copy JPEG API Settings":"Copy JPEG API Settings", + "Copy Input Settings":"Copy Input Settings", + "Copy Stream Settings":"Copy Stream Settings", + "Copy Stream Channel Settings":"Copy Stream Channel Settings", + "Copy Recording Settings":"Copy Recording Settings", + "Copy Detector Settings":"Copy Detector Settings", + "Monitors to Copy to":"Monitory to Copy to", + "Notification Sound":"Zvuk notifikace", + "Alert Sound":"Zvuk upozornění", + "Alert Sound Delay":"Zpoždění zvukového upozornění", + "powerVideoEventLimit":"You have set a high event limit. Are you sure you want to make this request?", + "There are no monitors that you can view with this account.":"There are no monitory that you can view with this account.", + "Use Built-In":"Použít vestavěné" +} diff --git a/languages/en_CA.json b/languages/en_CA.json index 896b779..fed1739 100644 --- a/languages/en_CA.json +++ b/languages/en_CA.json @@ -34,6 +34,10 @@ "API": "API", "ONVIF": "ONVIF", "FFprobe": "Probe", + "Monitor States": "Monitor States", + "Schedule": "Schedule", + "Schedules": "Schedules", + "Monitor States and Schedules": "Monitor States and Schedules", "Filters": "Filters", "Full URL Path": "Full URL Path", "Logs": "Logs", @@ -44,6 +48,8 @@ "Motion GUI": "Motion GUI", "Motion": "Motion", "Global Detector Settings": "Global Detector Settings", + "Trigger Group to Record": "Trigger Group to Record", + "Trigger Camera Groups": "Trigger Camera Groups", "Motion Detection": "Motion Detection", "Object Detection": "Object Detection", "JPEG Mode": "JPEG Mode", @@ -116,6 +122,8 @@ "Can View Videos and Events": "Can View Videos and Events", "Can Delete Videos and Events": "Can Delete Videos and Events", "Saved Filters": "Saved Filters", + "Saved Presets": "Saved Presets", + "Saved Schedules": "Saved Schedules", "Filter Name": "Filter Name", "Find Where": "Find Where", "Reason": "Reason", @@ -168,6 +176,15 @@ "Motion Meter": "Motion Meter", "FFmpegTip": "FFprobe is a simple multimedia streams analyzer. You can use it to output all kinds of information about an input including duration, frame rate, frame size, etc.", "Complete Stream URL": "Complete Stream URL", + "Primary Input": "Primary Input", + "All streams in first feed": "All streams in first feed", + "First stream in feed": "First stream in feed", + "Second stream in feed": "Second stream in feed", + "Video streams only": "Video streams only", + "Video stream only from first feed": "Video stream only from first feed", + "Audio streams only": "Audio streams only", + "Audio stream only from first feed": "Audio stream only from first feed", + "ONVIF Port": "ONVIF Port", "ONVIF Scanner": "ONVIF Scanner", "ONVIFEventsNotAvailable": "ONVIF Events not Available", "ONVIFnotCompliantProfileT": "Camera is not ONVIF Profile T Compliant", @@ -198,18 +215,29 @@ "Number of Days to keep": "Number of Days to keep", "Monitor Groups": "Monitor Groups", "Group Name": "Group Name", + "Show Thumbnails in Video List": "Show Thumbnails in Video List", "WebDAV": "WebDAV", "Backblaze B2": "Backblaze B2", "Backblaze Error": "Backblaze Error", + "SFTP (SSH File Transfer)": "SFTP (SSH File Transfer)", + "SFTP Error": "SFTP Error", + "SFTP": "SFTP", "Could not create Bucket.": "Could not create Bucket.", "Amazon S3": "Amazon S3", + "Wasabi Hot Cloud Storage": "Wasabi Hot Cloud Storage", + "Database": "Database", + "Database Not Found": "Database Not Found", + "User Not Found": "User Not Found", "Save Links to Database": "Save Links to Database", + "Upload File": "Upload File", "Bucket": "Bucket", "Region": "Region", "Use Global Amazon S3 Video Storage": "Use Global Amazon S3 Video Storage", + "Use Global Wasabi Hot Cloud Storage Video Storage": "Use Global Wasabi Hot Cloud Storage Video Storage", "Use Global Backblaze B2 Video Storage": "Use Global Backblaze B2 Video Storage", "Use Global WebDAV Video Storage": "Use Global WebDAV Video Storage", "Amazon S3 Upload Error": "Amazon S3 Upload Error", + "Wasabi Hot Cloud Storage Upload Error": "Wasabi Hot Cloud Storage Upload Error", "accountId": "Account ID", "applicationKey": "Application Key", "aws_accessKeyId": "Access Key Id", @@ -250,13 +278,17 @@ "Set to Watch Only": "Set to Watch Only", "Save as": "Save as", "Add New": "Add New", + "Merge and Download": "Merge and Download", "Zip and Download": "Zip and Download", + "Merge Selected Videos": "Merge Selected Videos", "Export Selected Videos": "Export Selected Videos", "Delete Selected Videos": "Delete Selected Videos", "DeleteSelectedVideosMsg": "Do you want to delete these videos? You cannot recover them.", "ExportSelectedVideosMsg": "Do you want to export these videos? It may take some time to zip and download.", + "MergeSelectedVideosMsg": "Do you want to merge these videos? It may take some time to merge and download. The moment the connection is closed the file will be deleted. Ensure you keep the browser open until it is complete.", "clientStreamFailedattemptingReconnect": "Client side ctream check failed, attempting reconnect.", "Export Video": "Export Video", + "Merge Video": "Merge Video", "Delete Filter": "Delete Filter", "confirmDeleteFilter": "Do you want to delete this filter? You cannot recover it.", "Fix Video": "Fix Video", @@ -283,9 +315,15 @@ "DeleteMonitorText": "Do you want to delete this monitor? You cannot recover it. You can choose for the files to remain in the filesystem. If you choose to recreate a monitor with the same ID the videos and events will become visible in the dashboard.", "DeleteMonitorsText": "Do you want to delete these monitors? You cannot recover them. You can choose to keep the files for these IDs in the filesystem. If you choose to recreate a monitor with one of the IDs the videos and events will become visible in the dashboard.", "Invalid JSON": "Invalid JSON", + "Invalid Data": "Invalid Data", + "Name cannot be empty.": "Name cannot be empty.", + "Start Time cannot be empty.": "Start Time cannot be empty.", + "Must be atleast one row": "Must be atleast one row", "InvalidJSONText": "Please ensure this is a valid JSON string for Shinobi monitor configuration.", "Passwords don't match": "Passwords don't match", "Email address is in use.": "Email address is in use.", + "Group Key is in use.": "Group Key is in use.", + "Create Sub-Accounts at /admin": "Create Sub-Accounts at /admin", "No Events found for this video": "No Events found for this video", "Video and Time Span (Minutes)": "Video and Time Span (Minutes)", "Video Length (minutes) and Motion Count per video": "Video Length (minutes) and Motion Count per video", @@ -324,16 +362,23 @@ "Filter for Objects only": "Filter for Objects only", "Custom": "Custom", "Detector": "Detector", + "Audio Detector": "Audio Detector", + "Audio Detection": "Audio Detection", + "Minimum dB": "Minimum dB", + "Maximum dB": "Maximum dB", "Connected": "Connected", "Not Saved": "Not Saved", "Not Connected": "Not Connected", - "Lisence Plate Detector": "Lisence Plate Detector", + "License Plate Detector": "License Plate Detector", "OpenCV Cascades": "OpenCV Cascades", "Refresh List of Cascades": "Refresh List of Cascades", "\"No Motion\" Detector": "\"No Motion\" Detector", "Control": "Control", "Grouping": "Grouping Add groups in Settings", "Detector Grouping": "Detector Grouping Add groups in Settings", + "Detector Recording Process Exited Prematurely. Restarting.": "Detector Recording Process Exited Prematurely. Restarting.", + "Detector Recording Complete": "Detector Recording Complete", + "Clear Recorder Process": "Clear Recorder Process", "Logging": "Logging", "IdentityText1": "This is how the system will identify the data for this stream. You cannot change the Monitor ID once you have pressed save. If you want you can make the Monitor ID more human readable before you continue.", "IdentityText2": "You can duplicate a monitor by modifying the Monitor ID then pressing save. You cannot use the ID of a monitor that already exists or it will save over that monitor's database information.", @@ -367,6 +412,7 @@ "HLS Preset": "Preset Template", "HLS List Size": "List Size", "Traditional Recording": "Traditional Recording", + "Recorded Buffer": "Recorded Buffer", "Buffer Preview": "Buffer Preview", "HLS Start Number": "HLS Start Number", "HLS Live Start Index": "HLS Live Start Index", @@ -391,8 +437,19 @@ "Image Width": "Image Width", "Image Height": "Image Height", "Record File Type": "Record File Type", + "Notification Video Length": "Notification Video Length", "Video Codec": "Video Codec", + "Delete Monitor States Preset": "Delete Monitor States Preset", + "Delete Monitor State?": "Delete Monitor State", + "deleteMonitorStateText1": "Do you want to delete this Monitor States Preset?", + "deleteMonitorStateText2": "Do you want to delete this Monitor's Preset?", + "Search Images": "Search Images", + "Launch in New Window": "Launch in New Window", "Preset": "Preset", + "Presets": "Presets", + "possibleInternalError": "Possible Internal Error", + "sizePurgeLockedText": "The Size Purge Lock (deleteOverMax) appears to have failed to unlock. Unlocking now...", + "Use coProcessor": "Use coProcessor", "Audio Codec": "Audio Codec", "Video Record Rate": "Video Record Rate (FPS)", "Record Width": "Record Width", @@ -407,6 +464,7 @@ "Stream to YouTube": "Stream to YouTube", "Stream to YouTube Flags": "Stream to YouTube Flags", "Recording Flags": "Recording Flags", + "Traditional Recording Flags": "Traditional Recording Flags", "Output Method": "Output Method", "Webhook": "Webhook", "Event Webhook Error": "Event Webhook Error", @@ -418,10 +476,13 @@ "Save Events to SQL": "Save Events to SQL", "Email on Trigger": "Email on Trigger Emails go to the main account holder's login address.", "Attach Video Clip": "Attach Video Clip", + "Error While Decoding": "Error While Decoding", + "ErrorWhileDecodingText": "Your hardware may have an unstable connection to the network. Check your network connections.", "Discord": "Discord", "Discord Alert on Trigger": "Discord Alert on Trigger", "Allow Next Email": "Allow Next Email in Minutes", "Allow Next Discord Alert": "Allow Next Discord Alert in Minutes", + "DiscordLoggedIn": "Discord Bot Authenticated", "DiscordFailedText": "Sending to Discord Failed", "DiscordErrorText": "Sending to Discord caused an Error", "DiscordNotEnabledText": "Discord Bot Not Enabled, Enable it in your Account Settings.", @@ -633,6 +694,7 @@ "Monitor mode is already": "Monitor mode is already", "Monitor or Key does not exist.": "Monitor or Key does not exist.", "No Group with this key exists": "No Group with this key exists", + "Success": "Success", "Trigger Successful": "Trigger Successful", "No such file": "No such file", "h265BrowserText1": "If you are trying to play an H.265 file, you may need to download it and open it in another application like VLC.", @@ -657,6 +719,10 @@ "Inserted State Configuration": "Inserted State Configuration", "Edited State Configuration": "Edited State Configuration", "Deleted State Configuration": "Deleted State Configuration", + "Schedule Configuration Not Found": "Schedule Configuration Not Found", + "Inserted Schedule Configuration": "Inserted Schedule Configuration", + "Edited Schedule Configuration": "Edited Schedule Configuration", + "Deleted Schedule Configuration": "Deleted Schedule Configuration", "Dashboard Language": "Dashboard Language", "Form Data Not Found": "Form Data Not Found", "File Not Found": "File Not Found", @@ -672,6 +738,7 @@ "Preview":"Preview", "Websocket Connected":"Websocket Connected", "Websocket Disconnected":"Websocket Disconnected", + "Videos Merge":"Videos Merge", "Token":"Token", "Channel ID":"Channel ID", "New Authentication Token":"New Authentication Token", @@ -689,10 +756,13 @@ "Can use Discord Bot":"Can use Discord Bot", "Can use WebDAV":"Can use WebDAV", "Can use Amazon S3":"Can use Amazon S3", + "Can use SFTP":"Can use SFTP", + "Can use Wasabi Hot Cloud Storage":"Can use Wasabi Hot Cloud Storage", "Can use LDAP":"Can use LDAP", "Can View Logs":"Can View Logs", "Can edit how long to keep Events":"Can edit how long to keep Events", "Leave blank for unlimited":"Leave blank for unlimited", + "privateKey":"Private Key", "Limited":"Limited", "All Privileges":"All Privileges", "LDAP":"LDAP", @@ -768,6 +838,11 @@ "RTMP Stream":"RTMP Stream", "Stream Channel":"Stream Channel", "Confidence":"Confidence", + "Trainer Engine":"Trainer Engine", + "Train":"Train", + "TrainConfirm":"Are you sure you want to begin training? This can take more than 12 hours with over 500 images. This will consume a large amount of resources, like RAM or CPU.", + "Batch":"Batch", + "Subdivision":"Subdivision", "Map":"Map", "Add Map":"Add Map", "Add Input Feed":"Add Input Feed", @@ -783,6 +858,7 @@ "TV Channel ID":"TV Channel ID", "TV Channel Group":"TV Channel Group", "Emotion Average":"Emotion Average", + "Require Object to be in Region":"Require Object to be in Region", "Show Regions of Interest":"Show Regions of Interest", "Confidence of Detection":"Confidence of Detection", "Edit Selected":"Edit Selected", diff --git a/languages/fr.json b/languages/fr.json index f8ce5eb..b6846d6 100644 --- a/languages/fr.json +++ b/languages/fr.json @@ -1,10 +1,10 @@ { - "\"No Motion\" Detector": "\"Aucun Mouvement\" Détecteur De", - "# of Allow MJPEG Clients": "# of Allow MJPEG Clients 0 for infinite", + "\"No Motion\" Detector": "\"Aucun Mouvement\" Détecteur", + "# of Allow MJPEG Clients": "# d'autoriser les clients MJPEG 0 pour l'infini", "180 Degrees": "180 Degrés", - "2-Factor Authentication": "Une Authentification À 2 Facteurs", + "2-Factor Authentication": "Authentification À 2 Facteurs", "90 Clockwise": "90 dans le sens des Aiguilles", - "90 Clockwise and Vertical Flip": "90 vers la gauche et Vertical Flip", + "90 Clockwise and Vertical Flip": "90 vers la gauche et rotation Vertical", "90 Counter Clockwise and Vertical Flip (default)": "90 dans le sens antihoraire et la rotation Verticale (par défaut)", "API": "API", "API Key": "Clé API", @@ -15,30 +15,30 @@ "APIKeyDeletedText": "Clé a été supprimé. Elle ne fonctionnera plus.", "ASC": "ASC", "Accelerator": "Accélérateur", - "Account Info": "Les Informations De Compte", + "Account Info": "Les Informations Du Compte", "AccountEditText1": "Ne pouvait pas modifier. Actualiser la page si le problème persiste.", "Accounts": "Comptes", "Action for Selected": "Action Sélectionnés", "Add": "Ajouter", "Add Channel": "Ajouter Un Canal", - "Add Input Feed": "Ajoutez D'Entrée D'Alimentation", + "Add Input Feed": "Ajouter un flux d'entrée", "Add Map": "Ajouter La Carte", "Add Monitor": "Ajouter Moniteur", - "Add New": "Ajouter De Nouveaux", + "Add New": "Ajouter Nouveau", "Admin": "Admin", "Advanced": "Avancé", "Again": "Encore", - "Age": "L'âge", + "Age": "Age", "All Logs": "Tous Les Journaux", "All Monitors": "Tous Les Moniteurs", "All Monitors and Privileges": "Tous les Moniteurs et Privilèges", "All Privileges": "Tous Les Privilèges", "All Warnings": "Tous Les Avertissements", - "Allow Next Command": "Permettre Prochaine Commande en quelques Minutes", - "Allow Next Email": "Permettre Prochain Email en quelques Minutes", - "Allow Next Trigger": "Permettre à Côté de Déclenchement en Millisecondes", - "Allowed IPs": "Permis IPs", - "Analyzation Duration": "Analyzation Durée", + "Allow Next Command": "Autoriser la commande suivante en quelques Minutes", + "Allow Next Email": "Autoriser le prochain Email en quelques Minutes", + "Allow Next Trigger": "Autoriser le déclencheur suivant en Millisecondes", + "Allowed IPs": "IPs autorisés", + "Analyzation Duration": "Durée d'analyse", "Archive": "Archive", "Are you sure?": "Êtes-vous sûr?", "Audio Bit Rate": "Le Débit Binaire Audio", @@ -51,49 +51,49 @@ "Base64 over Websocket": "Base64 sur Websocket", "Basic Authentication": "L'Authentification De Base", "Bind Credentials": "Lier Les Informations D'Identification (Mot De Passe)", - "Blank for No Change": "Vide pour Pas Changer", + "Blank for No Change": "Vide pour aucun changement", "Bottom Left": "En Bas À Gauche", "Bottom Right": "En Bas À Droite", - "Browser Console Log": "Le Navigateur De La Console De Log", - "Buffer Preview": "Tampon Aperçu", + "Browser Console Log": "Journal de la console du navigateur", + "Buffer Preview": "Aperçu de la mémoire tampon", "CPU": "CPU", - "CPU indicator will not work. Continuing...": "CPU indicateur ne fonctionnera pas. Continue...", + "CPU indicator will not work. Continuing...": "L'indicateur du CPU ne fonctionnera pas. En continuant ...", "CSS": "CSS Style de votre tableau de bord.", "Calendar": "Calendrier", - "Call Method": "Appel De La Méthode", + "Call Method": "Méthode d'appel", "Camera Password": "Mot De Passe De La Caméra", "Camera Username": "Nom D'Utilisateur De La Caméra", - "Camera is not recording": "Appareil photo n'est pas de l'enregistrement", + "Camera is not recording": "La caméra n'enregistre pas", "Camera is not streaming": "La caméra n'est pas en streaming", "CameraNotRecordingText": "Les paramètres peuvent être incompatibles. Vérifier les encodeurs. Le redémarrage...", "Can Authenticate Websocket": "Peut Authentifier Websocket", - "Can Control Monitors": "Peut Moniteurs De Contrôle", - "Can Delete Videos": "Pouvez Supprimer Des Vidéos", - "Can Delete Videos and Events": "Pouvez Supprimer des Vidéos et des Événements", - "Can Edit Monitor": "Pouvez Modifier Moniteur", - "Can Get Logs": "Pouvez Obtenir Les Journaux", - "Can Get Monitors": "Pouvez Obtenir Des Moniteurs", - "Can View Monitor": "Peut Moniteur De Vue", + "Can Control Monitors": "Peut contrôler les moniteurs", + "Can Delete Videos": "Peut supprimer des vidéos", + "Can Delete Videos and Events": "Peut supprimer des vidéos et des événements", + "Can Edit Monitor": "Peut modifier le moniteur", + "Can Get Logs": "Peut Obtenir Les Journaux", + "Can Get Monitors": "Peut Obtenir Des Moniteurs", + "Can View Monitor": "Peut afficher le moniteur", "Can View Snapshots": "Peut Afficher Des Instantanés", "Can View Streams": "Peut Afficher Des Flux", "Can View Videos": "Peut Visionner Des Vidéos", "Can View Videos and Events": "Pouvez Visualiser des Vidéos et des Événements", - "Can edit Max Days": "Pouvez éditer Max Jours", - "Can edit Max Storage": "Pouvez éditer Max de Stockage", - "Can edit how long to keep Events": "Pouvez modifier la durée de conservation des Événements", - "Can edit how long to keep Logs": "Pouvez modifier la durée de conservation des Journaux d'", - "Can use Admin Panel": "Pouvez utiliser le Panneau d'administration", + "Can edit Max Days": "Peut éditer le maximum de Jours", + "Can edit Max Storage": "Peut éditer maximum de Stockage", + "Can edit how long to keep Events": "Peut modifier la durée de conservation des Événements", + "Can edit how long to keep Logs": "Peut modifier la durée de conservation des Journaux d'", + "Can use Admin Panel": "Peut utiliser le Panneau d'administration", "Can use LDAP": "Peut utiliser le protocole LDAP", - "Can use WebDAV": "Pouvez utiliser WebDAV", + "Can use WebDAV": "Peut utiliser WebDAV", "Can't Connect": "Ne peut pas se Connecter", "Cannot watch a monitor that isn't running.": "Impossible de regarder un moniteur qui n'est pas en cours d'exécution.", "Center": "Centre d' Adresse URL", "Channel": "Canal", "Channel ID": "ID de canal", - "Chat on Discord": "Chat sur la Discorde", + "Chat on Discord": "Discuter sur Discord", "Check": "Vérifier", - "Check Signal Interval": "Vérifier le Signal de l'Intervalle en Minutes", - "Check for Motion First": "Vérifier le Mouvement de la Première", + "Check Signal Interval": "Vérifier l'intervalle du signal en Minutes", + "Check for Motion First": "Vérifier le Mouvement d'abord", "Close": "Fermer", "Closed": "Fermé", "Command": "Commande", @@ -107,42 +107,42 @@ "Connection": "Connexion", "Connection Type": "Type De Connexion", "Control": "Contrôle", - "Control Error": "Erreur De Contrôle De La", + "Control Error": "Erreur De Contrôle", "ControlErrorText1": "Le contrôle n'est pas activé", "Controllable": "Contrôlable", - "Copy Connection Settings": "Copie Des Paramètres De Connexion", - "Copy Custom Settings": "Copie Des Paramètres Personnalisés", - "Copy Detector Settings": "Copie Réglages Du Détecteur", - "Copy Group Settings": "Copier Les Paramètres De Groupe", + "Copy Connection Settings": "Copier les paramètres de connexion", + "Copy Custom Settings": "Copier les paramètres personnalisés", + "Copy Detector Settings": "Copier les réglages de Détection", + "Copy Group Settings": "Copier Les Paramètres Du Groupe", "Copy Input Settings": "Copier Les Paramètres D'Entrée", "Copy Logging Settings": "Copie Des Paramètres De Journalisation", "Copy Recording Settings": "Copier Les Paramètres D'Enregistrement", "Copy Settings": "Paramètres De Copie", - "Copy Stream Channel Settings": "Copie De Flux De Paramètres De Canal", + "Copy Stream Channel Settings": "Copier les réglages du canal", "Copy Stream Settings": "Copier Les Paramètres De Flux", - "Copy to Settings": "Copie des Paramètres de", - "Country of Plates": "Pays de Plaques", - "Counts of Motion": "Comtes de Mouvement", - "Creating New Account": "La Création D'Un Nouveau Compte", + "Copy to Settings": "Copier dans les paramètres", + "Country of Plates": "Pays de Plaques d'immatriculation", + "Counts of Motion": "Comptes de mouvement", + "Creating New Account": "Créer un nouveau compte", "Current": "Actuel", - "Currently viewing": "Visualisez actuellement", + "Currently viewing": "En cours de visionnage", "Custom": "Personnalisé", "Custom Base URL": "Base d'URL personnalisée Laissez le champ vide pour utiliser l'Hôte de l'URL", "DB Lost.. Retrying..": "Base De Données Perdues.. Réessayer..", "DESC": "DESC", "Dashboard": "Tableau de bord", - "Dashboard Language": "Langue Du Tableau De Bord", + "Dashboard Language": "Langue du Tableau De Bord", "Dashcam": "Dashcam", "Dashcam (Streamer v2)": "Dashcam (Streamer v2)", - "Date Range": "La Plage De Dates", + "Date Range": "Plage De Dates", "Debug": "Debug", "Default": "Par défaut", "Delete": "Supprimer", - "Delete Filter": "Supprimer Le Filtre", - "Delete Matches": "Supprimer Les Matchs", - "Delete Monitor": "Supprimer Moniteur", - "Delete Motionless Video": "Supprimer Immobile Vidéo", - "Delete Motionless Videos (Record)": "Supprimer Immobile Vidéos (Enregistrement)", + "Delete Filter": "Supprimer le Filtre", + "Delete Matches": "Supprimer les correspondances", + "Delete Monitor": "Supprimer le Moniteur", + "Delete Motionless Video": "Supprimer la vidéo immobile", + "Delete Motionless Videos (Record)": "Supprimer des vidéos immobiles (Enregistrer)", "Delete Selected Videos": "Supprimer La Sélection Des Vidéos", "Delete Video": "Supprimer La Vidéo", "Delete selected": "Supprimer la sélection", @@ -152,30 +152,30 @@ "DeleteVideoMsg": "Voulez-vous supprimer cette vidéo? Vous ne pouvez pas le récupérer.", "Deleted": "Supprimé", "Detect Objects": "Détecter les Objets Voir ci-dessous", - "Detector": "Détecteur de", + "Detector": "Détecteur", "Detector Buffer": "Détecteur De Tampon", "Detector Flags": "Détecteur De Drapeaux", - "Detector Grouping": "Détecteur de Groupement d'Ajouter des groupes de Paramètres", - "Detector Rate": "Détecteur de Taux (FPS)", + "Detector Grouping": "Groupement de détecteurs d'Ajouter des groupes de Paramètres", + "Detector Rate": "Taux de détecteur (FPS)", "DetectorText": "

Lorsque les zones Largeur et Hauteur sont affichés, vous devriez les mettre à 640x480 ou ci-dessous. Cela permettra d'optimiser la vitesse de lecture d'images.

", - "Disable Night Vision": "Désactiver la Vision de Nuit Adresse URL", - "Disable Nightvision": "Désactiver Nightvision", + "Disable Night Vision": "Désactiver la vision nocturne Adresse URL", + "Disable Nightvision": "Désactiver la vision nocturne", "Disabled": "Désactivé", - "Documentation": "La Documentation", + "Documentation": "Documentation", "Don't show this anymore": "Ne pas afficher plus", - "Double Quote Directory": "Devis Double Répertoire de Certains répertoires sont séparés par des espaces. L'utilisation de ce peut se bloquer certains appareils photo.", + "Double Quote Directory": "Devis Double Répertoire Certains répertoires sont séparés par des espaces. L'utilisation de ce peut se bloquer certaines cameras.", "Down": "Bas Adresse URL", - "Down Stop": "Vers le bas Arrêter Adresse URL", + "Down Stop": "Arrêt bas Adresse URL", "Download": "Télécharger", - "EU": "L'UE", + "EU": "UE", "Edit": "Modifier", - "Edit Selected": "Modifier Les", + "Edit Selected": "Modifier la sélection", "Email": "E-mail", - "Email Details": "E-Mail Les Détails", + "Email Details": "Détails de l'e-mail", "Email on No Motion": "E-mail sur \"Aucun Mouvement\"", "Email on Trigger": "E-mail sur la Gâchette e-Mails passent à la principale du titulaire de compte de connexion l'adresse.", "Emotion": "L'émotion", - "Emotion Average": "L'Émotion De La Moyenne", + "Emotion Average": "Emotion Moyenne", "Enable": "Activer", "Enable Night Vision": "Activer la Vision Nocturne Adresse URL", "Enable Nightvision": "Activer La Vision Nocturne", @@ -184,13 +184,13 @@ "End Time": "Heure De Fin", "Ended": "Terminé", "Enlarge": "Agrandir", - "Enter this code to proceed": "Entrez ce code pour procéder", + "Enter this code to proceed": "Entrez ce code pour continuer", "Equal to": "Égal à", "Error Connecting": "Erreur Lors De La Connexion", "Event": "L'événement", - "Event Limit": "Cas Limite", - "EventText1": "Déclenché un mouvement à", - "EventText2": "Pourrait pas l'email de l'image, le fichier n'est pas accessible", + "Event Limit": "Limite d'événement", + "EventText1": "Mouvement détectée à", + "EventText2": "Impossible d'envoyer l'image par l'email, le fichier n'est pas accessible", "Events": "Les événements", "Example": "Exemple", "Execute Command": "Exécuter La Commande", @@ -198,22 +198,22 @@ "Export": "L'exportation", "FFmpegCantStart": "FFmpeg ne Pouvait pas Commencer", "FFmpegCantStartText": "Le moteur d'enregistrement pour cette caméra n'a pas pu démarrer. Il y a peut être quelque chose de mal avec votre configuration de la caméra. S'il y a des journaux autres que celui-ci, veuillez les poster dans les Questions sur Github.", - "FFmpegTip": "FFprobe est un simple flux multimédias de l'analyseur. Vous pouvez l'utiliser pour afficher toutes sortes d'informations sur les intrants, y compris la durée, taux d'armature, taille de l'image, etc.", + "FFmpegTip": "FFprobe est un analyseur de flux multimédia simple. Vous pouvez l’utiliser pour générer toutes sortes d’informations sur une entrée, notamment la durée, la cadence, la taille, etc.", "FFprobe": "Sonde", "FLV": "FLV", "FLV Stream Type": "FLV Type de Flux", - "FactorAuthText1": "Le code ne sera actif pendant 15 minutes. Si vous vous connectez de nouveau la minuterie est réinitialisée à 15 minutes avec le même code.", - "Fatal": "Fatale", - "Fatal Maximum Reached": "Fatale Maximum Atteint, L'Arrêt De La Caméra.", - "FatalMaximumReachedText": "JPEG Erreur a été fatale.", - "Feed-in Image Height": "De rachat à la Hauteur de l'Image", - "Feed-in Image Width": "Alimentation sur la Largeur de l'Image", + "FactorAuthText1": "Le code ne sera actif que pendant 15 minutes. Si vous vous reconnectez, le chronomètre sera réinitialisé à 15 minutes avec le même code.", + "Fatal": "Fatal", + "Fatal Maximum Reached": "Maximum fatal atteint, L'Arrêt De La Caméra.", + "FatalMaximumReachedText": "Erreur JPEG fatale.", + "Feed-in Image Height": "Hauteur de l'image d'alimentation", + "Feed-in Image Width": "Largeur de l'image d'alimentation", "Female": "Femelle", "Fields cannot be empty": "Les champs ne peut pas être vide", - "File Not Exist": "Le Fichier N'Existe Pas", + "File Not Exist": "Fichier non existant", "File Not Found": "Fichier Non Trouvé", "File Type": "Type De Fichier", - "FileNotExistText": "Impossible d'enregistrer non existant fichier. Quelque chose s'est mal passé.", + "FileNotExistText": "Impossible de sauvegarder le fichier non existant. Quelque chose s'est mal passé.", "Filename": "Filename", "Filesize": "La taille du fichier", "Filter ID": "Filtre ID", @@ -228,7 +228,7 @@ "Fix": "Fix", "Fix Video": "Corriger La Vidéo", "FixVideoMsg": "Voulez-vous corriger cette vidéo? Vous ne pouvez pas annuler cette action.", - "Flush PM2 Logs": "Rincer les PM2 Journaux", + "Flush PM2 Logs": "Nettoyer les Journaux PM2", "Font Path": "Le Chemin De Police", "Font Size": "Taille De La Police", "For Group": "Pour Le Groupe", @@ -242,20 +242,20 @@ "Gender": "Genre", "Generate Subtitles": "Générer Des Sous-Titres", "Get Logs to Client": "Obtenir les Journaux du Client", - "Greater Than": "Plus De", + "Greater Than": "Plus grand que", "Greater Than or Equal to": "Supérieure ou Égale à", - "Group Key": "La Clé De Groupe", + "Group Key": "Clé de groupe", "Group Name": "Nom Du Groupe", "Grouping": "Groupement d'Ajouter des groupes de Paramètres", "H.264 / H.265 / H.265+": "H. 264 / H. 265 / H. 265 ", "HLS (.m3u8)": "HLS (.m3u8)", - "HLS (includes Audio)": "HLS (Audio)", + "HLS (includes Audio)": "HLS (inclut l'audio)", "HLS Audio Encoder": "Encodeur Audio", - "HLS List Size": "La Taille De La Liste", + "HLS List Size": "Taille de la liste HLS", "HLS Live Start Index": "HLS Vivre Index de Début", "HLS Preset": "Modèle Préréglé", "HLS Segment Length": "La Longueur du Segment en quelques Secondes", - "HLS Start Number": "HLS Nombre de Départ", + "HLS Start Number": "Numéro de départ HLS", "HLS Video Encoder": "Encodeur Vidéo", "HTTP": "HTTP", "HTTPS": "HTTPS", @@ -265,47 +265,47 @@ "Hide List": "Masquer La Liste", "Hide Notes": "Masquer Les Notes", "Host": "Accueil", - "Hotswap Modes (Watch-Only)": "Hotswap Modes (Watch)", - "How to Record": "Comment faire pour Enregistrer", + "Hotswap Modes (Watch-Only)": "Modes Hotswap (Regarder Uniquement)", + "How to Record": "Comment enregistrer", "IP Address": "Adresse IP", "Identity": "Identité", - "IdentityText1": "C'est la façon dont le système permettra d'identifier les données pour ce flux. Vous ne pouvez pas modifier le Moniteur ID une fois que vous avez appuyé sur la touche enregistrer. Si vous le souhaitez, vous pouvez faire le Moniteur ID plus lisible par l'homme avant de continuer.", - "IdentityText2": "Vous pouvez dupliquer l'écran en modifiant le Moniteur ID , puis appuyez sur save. Vous ne peut pas utiliser l'ID d'un moniteur qui existe déjà ou qu'il permettra d'économiser plus que surveiller les informations de base de données.", + "IdentityText1": "Voici comment le système identifiera les données pour ce flux. Vous ne pouvez pas changer l'identifiant du moniteur une fois que vous avez appuyé sur Enregistrer. Si vous le souhaitez, vous pouvez rendre l'identifiant du moniteur plus lisible par l'homme avant de continuer.", + "IdentityText2": "Vous pouvez dupliquer l'écran en modifiant l'ID du moniteur , puis appuyez sur save. Vous ne pouvez pas utiliser l'ID d'un moniteur existant, sinon les informations de la base de données de ce moniteur seront sauvegardées.", "Idle": "Inactif", "Image Height": "La Hauteur De L'Image", - "Image Location": "Emplacement de l'Image de Chemin d'accès Absolu ou laissez le champ vide pour utiliser mondiale", + "Image Location": "Emplacement de l'Image Chemin absolu ou laisser vide pour utiliser global", "Image Position": "La Position De L'Image", "Image Width": "La Largeur De L'Image", "Import": "L'importation", - "Import Monitor Configuration": "L'Importation De Configuration Du Moniteur De", - "ImportMonitorConfigurationText": "En faisant cela, vous overrwrite toutes les modifications ne sont pas enregistrées. Les modifications importées ne sera appliquée que lorsque vous appuyez sur Enregistrer.", - "ImportMultiMonitorConfigurationText": "En faisant cela, vous overrwrite tous les moniteurs avec des Id existant dans le fichier d'importation.", + "Import Monitor Configuration": "Importer la configuration du moniteur", + "ImportMonitorConfigurationText": "Cela écrasera toutes les modifications actuellement non enregistrées. Les modifications importées ne seront appliquées que si vous appuyez sur Enregistrer .", + "ImportMultiMonitorConfigurationText": "Cela écrasera tous les moniteurs dont l'ID existe dans le fichier d'importation.", "In": "Dans", - "Incorrect Settings Chosen": "Des Paramètres Incorrects Choisi", - "Indifference": "L'indifférence", + "Incorrect Settings Chosen": "Réglages incorrects choisis", + "Indifference": "Indifférence", "Input": "Entrée", - "Input Feed": "Entrée D'Alimentation", - "Input Flags": "Entrée Des Drapeaux", + "Input Feed": "Flux d'entrée", + "Input Flags": "Drapeaux d'entrée", "Input Selector": "Sélecteur D'Entrée", - "Input Settings": "Les Paramètres D'Entrée", + "Input Settings": "Paramètres D'Entrée", "Input Type": "Type D'Entrée", - "InputText1": "Cette section indique Shinobi comment utiliser un flux. Pour des performances optimales, essayez de régler votre appareil photo les réglages internes. Trouvez les options suivantes et de les définir comme illustré. Pour trouver votre appareil photo vous pouvez utiliser le construit en ONVIF Scanner de Shinobi. Certaines caméras ONVIF nécessitent l'utilisation d'un outil de gestion pour modifier leurs paramètres internes. Si vous ne trouvez pas votre appareil, vous pouvez essayer ONVIF le Gestionnaire de Périphériques de Windows.", - "InputText2": "
  • Framerate (FPS) : Haut : 10 - 15 FPS, Faible : 2 à 5 FPS
  • I-frame interval : 80
  • Taux de bits Type : CBR (Constant Bit rate)
  • Débit binaire : entre 256kbps - 500kbps
", - "InputText3": "Si vous avez besoin d'aide pour déterminer ce type d'entrée de votre appareil photo vous pouvez prendre un coup d'oeil à la Caméra Liste d'URLs sur le Shinobi site web.", - "Invalid JSON": "Invalid JSON", - "InvalidJSONText": "Veuillez vous assurer que c'est une chaîne JSON valide pour les Shinobi de configuration du moniteur.", + "InputText1": "Cette section explique à Shinobi comment utiliser un flux. Pour des performances optimales, essayez de régler les paramètres internes de votre appareil photo. Recherchez les options suivantes et configurez-les comme indiqué. Pour trouver votre appareil photo, vous pouvez utiliser le scanner ONVIF intégré de Shinobi. Certaines caméras ONVIF nécessitent l'utilisation d'un outil de gestion pour modifier leurs paramètres internes. Si vous ne trouvez pas vos caméras, vous pouvez utiliser le gestionnaire de périphériques ONVIF pour Windows .", + "InputText2": "
  • Fréquence d'image (FPS) : Haut : 10 - 15 FPS, Faible : 2 à 5 FPS
  • Intervalle I-frame : 80
  • Type de débit : CBR (débit binaire constant)
  • Débit binaire : entre 256kbps - 500kbps
", + "InputText3": "Si vous avez besoin d'aide pour déterminer le type d'entrée de votre caméra, consultez la Liste des URL de la caméra s le site Web de Shinobi.", + "Invalid JSON": "JSON invalide", + "InvalidJSONText": "Assurez-vous qu'il s'agit d'une chaîne JSON valide pour la configuration du moniteur Shinobi.", "JPEG": "JPEG", - "JPEG (Auto Enables JPEG API)": "JPEG (Auto Permet JPEG API)", + "JPEG (Auto Enables JPEG API)": "JPEG (Activation automatique de l'API JPEG)", "JPEG API": "JPEG API Instantané (cgi-bin)", - "JPEG Error": "JPEG Erreur", - "JPEG Mode": "Le Mode JPEG", - "JPEGErrorText": "Il y avait un problème dans l'obtention de données de votre appareil photo.", + "JPEG Error": "Erreur JPEG", + "JPEG Mode": "Mode JPEG", + "JPEGErrorText": "Il y avait un problème dans l'obtention de données de votre camera.", "LDAP": "LDAP", "LDAP Success": "LDAP Succès", - "LDAP User Authenticated": "LDAP de l'Utilisateur Authentifié", + "LDAP User Authenticated": "Utilisateur LDAP authentifié", "LDAP User is New": "Utilisateur LDAP est Nouveau", "Leave blank for random.": "Laissez vide pour aléatoire.", - "Leave blank for unlimited": "Laissez vide pour un nombre illimité de", + "Leave blank for unlimited": "Laissez vide pour illimité", "Left": "Gauche Adresse URL", "Left Stop": "Butée gauche, Adresse URL", "Less Than": "Moins De", @@ -313,14 +313,14 @@ "Like": "Comme", "Limited": "Limitée", "Link Shinobi": "Lien Shinobi", - "Lisence Plate Detector": "Lisence Détecteur De Plaque", + "Lisence Plate Detector": "Détecteur de plaques Lisence", "List Toggle": "Liste De Bascule", - "Live Stream Toggle": "Live Stream De La Bascule", + "Live Stream Toggle": "Flux en direct bascule", "Live View": "Vue En Direct", "Local": "Local", - "Log Level": "Le Niveau De Journal", - "Log Signal Event": "Journal du Signal d'Événements côté Client seulement", - "Logging": "La journalisation", + "Log Level": "Niveau de journalisation", + "Log Signal Event": "Consigner un événement de signal Côté client uniquement", + "Logging": "Journalisation", "Login": "Connexion", "Logout": "Déconnexion", "Logs": "Les journaux", @@ -336,24 +336,24 @@ "Manual": "Manuel", "Map": "Carte", "Matches": "Matchs", - "Max Latency": "Max Latence", - "Max Number of Cameras": "Le Nombre maximum de Caméras", - "Max Storage Amount": "Max de la Quantité de Stockage en mo", + "Max Latency": "Latence maximale", + "Max Number of Cameras": "Nombre maximum de caméras", + "Max Storage Amount": "Quantité de stockage maximum en mo", "Mode": "Mode", "Monitor": "Moniteur", "Monitor Added by user": "Moniteur Ajoutés par l'utilisateur.", "Monitor Capture Rate": "Surveiller les Taux de Capture (FPS)", - "Monitor Groups": "La Surveillance De Groupes", + "Monitor Groups": "Groupes de surveillance", "Monitor ID": "Moniteur ID", "Monitor Idling": "Surveiller La Marche Au Ralenti", "Monitor Name": "Nom De Moniteur", "Monitor Settings": "Paramètres Du Moniteur", "Monitor Stopped": "Moniteur Arrêté", - "Monitor Updated by user": "Surveiller les mises à Jour par l'utilisateur.", - "Monitor mode changed": "Le mode moniteur changé", + "Monitor Updated by user": "Moniteur mis à jour par l'utilisateur.", + "Monitor mode changed": "Le mode moniteur a changé", "Monitor mode is already": "Le mode Monitor est déjà", "Monitor or Key does not exist.": "Le moniteur ou la Clé n'existe pas.", - "MonitorIdlingText": "Surveiller la session a été commandé au ralenti.", + "MonitorIdlingText": "La session du moniteur a été commandée pour être inactive.", "MonitorStoppedText": "Surveiller la session a été ordonné d'arrêter.", "Monitors": "Les moniteurs", "Monitors per row": "Surveille par ligne de Montage", @@ -364,41 +364,41 @@ "Name": "Nom", "New Authentication Token": "Nouveau Jeton D'Authentification", "New Monitor": "Nouveau Moniteur", - "No": "Pas de", + "No": "Non", "No Audio": "Pas D'Audio", "No Data": "Pas De Données", "No Events found for this video": "Aucun événement trouvé pour cette vidéo", - "No Group with this key exists": "Pas de Groupe avec cette clé existe", - "No Monitor Exists with this ID.": "Pas de Moniteur Existe à cet ID.", - "No Monitor Found, Ignoring Request": "Pas De Moniteur Trouvé, En Ignorant La Demande", - "No Monitors Selected": "Pas De Moniteurs Sélectionnés", + "No Group with this key exists": "Aucun groupe avec cette clé n'existe", + "No Monitor Exists with this ID.": "Aucun moniteur n'existe avec cet ID.", + "No Monitor Found, Ignoring Request": "Aucun moniteur trouvé, demande ignorée", + "No Monitors Selected": "Aucun moniteur sélectionné", "No Rotation": "Pas De Rotation", "No Videos Found": "Pas De Vidéos Trouvées", - "No such file": "Pas de tel fichier", + "No such file": "Ce fichier n'existe pas", "NoMotionEmailText1": "Pas de Mouvement pour", - "NoMotionEmailText2": "Il n'y a pas été de tout mouvement détecté sur l'appareil photo pour", - "NoVideosFoundForDateRange": "Pas de Vidéos trouvées dans cette plage de dates. Essayez de définir la date de début de la plus en arrière.", + "NoMotionEmailText2": "Aucun mouvement n'a été détecté sur la caméra depuis", + "NoVideosFoundForDateRange": "Aucune vidéo trouvée dans cette plage de dates. Essayez de définir la date de début plus en arrière.", "Noise Filter": "Filtre De Bruit", "Not Authorized": "Pas Autorisé", "Not Connected": "Pas Connecté", "Not Equal to": "Pas Égal à", "Not In": "Pas Dans", - "Not Matches": "Pas De Matchs", + "Not Matches": "Pas de correspondance", "Not Permitted": "Pas Autorisés", - "Not Saved": "Pas Enregistrées", + "Not Saved": "Non enregistré", "Not an Administrator Account": "Pas un Compte d'Administrateur", - "NotAuthorizedText1": "Pas Autorisé, Soumettre commande init avec \"auth\",\"ke\", et \"uid\"", + "NotAuthorizedText1": "Non autorisé, soumettre la commande init avec \"auth\",\"ke\", et \"uid\"", "Notes": "Notes", - "NotesPlacholder": "Les commentaires que vous voulez quitter pour ce caméras de paramètres.", + "NotesPlacholder": "Commentaires que vous souhaitez laisser pour les paramètres de cette caméra.", "Number of Days to keep": "Nombre de Jours de conservation", "ONVIF": "ONVIF", "ONVIF Scanner": "ONVIF Scanner", - "ONVIFnote": "Découvrez ONVIF appareils sur les réseaux à l'extérieur de votre propre ou la laisser vide pour analyser votre réseau actuel.
Nom d'utilisateur et le Mot de passe peut être laissé en blanc.", + "ONVIFnote": "Découvrez les périphériques ONVIF sur des réseaux extérieurs aux vôtres ou laissez-le vide pour analyser votre réseau actuel.
Le Nom d'utilisateur et le Mot de passe peut être laissé vide.", "Object": "Objet", "Object Tag": "Balise Object", "OpenCV Cascades": "OpenCV Cascades", "Options": "Options", - "Order Streams": "Afin De Ruisseaux", + "Order Streams": "Ordre des flux", "Output Method": "Méthode De Sortie", "Password": "Mot de passe", "Password Again": "Mot De Passe À Nouveau", @@ -407,7 +407,7 @@ "Path": "Chemin", "Permissions": "Les autorisations", "Please Wait for Completion": "Veuillez Attendre la fin, Selon le nombre de fichiers sélectionnés, cela peut prendre un certain temps. Actualiser pour vérifier de nouveau.", - "Points": "Des Points Lors de l'ajout de points de cliquer sur le bord du polygone.", + "Points": "Points Lorsque vous ajoutez des points, cliquez sur le bord du polygone.", "Pop": "Pop", "Port": "Port", "Pose": "Poser", @@ -419,38 +419,38 @@ "Preferences": "Préférences", "Preset": "Preset", "Preview": "Aperçu", - "Probe Size": "Longueur De La Sonde", + "Probe Size": "Taille de la Sonde", "Process Crashed for Monitor": "Le processus s'est Écrasé pour Surveiller", "Process Unexpected Exit": "Processus Inattendu De Sortie", "Profile": "Profil", - "Quality": "La qualité de l' 1 est Élevée, 23 est Faible", + "Quality": "Qualité 1 est Élevée, 23 est Faible", "Query": "Requête", "RAM": "RAM", "RTMP Stream": "Flux RTMP", "RTMP Stream Flags": "Flux RTMP Drapeaux", "RTSP": "RTSP", - "RTSP Transport": "RTSP de Transport", + "RTSP Transport": "Transport RTSP", "Range or Single": "Gamme ou Seul", "Rate": "Taux (FPS)", "Raw": "Raw", "Raw H.264 Stream": "Raw H. 264 Flux", "Recommended": "Recommandé", "Record": "Enregistrement", - "Record File Type": "Enregistrement De Type De Fichier", - "Record Height": "Record De Hauteur", - "Record Video Filter": "Enregistrement Vidéo De Filtre", - "Record Width": "Enregistrement De Largeur", + "Record File Type": "Type de fichier d'enregistrement", + "Record Height": "Enregistrer Hauteur", + "Record Video Filter": "Enregistrer le filtre vidéo", + "Record Width": "Enregistrer Largeur", "Recording": "Enregistrement", - "Recording FPS": "L'enregistrement de FPS", - "Recording FPS Change on Start": "Enregistrement FPS Changement sur Démarrer", - "Recording Flags": "L'Enregistrement Des Drapeaux", - "Recording Segment Interval": "Enregistrement Segment de l'Intervalle en minutes", - "Recording Timeout": "L'enregistrement de Délai d'attente en Minutes", - "Recording Timestamp": "L'Enregistrement D'Horodatage", - "Recording Watermark": "Enregistrement Filigrane", - "RecordingText": "Il est recommandé que vous définissez Enregistrement de Type de Fichier pour WebMMP4 et Vidéo Codec pour libvpxcopie ou libx264 parce que votre Type d'Entrée est définie sur .", + "Recording FPS": "L'enregistrement FPS", + "Recording FPS Change on Start": "Enregistrer le changement de FPS au démarrage", + "Recording Flags": "Drapeaux d'enregistrement", + "Recording Segment Interval": "Enregistrement de l'intervalle de segment en minutes", + "Recording Timeout": "Délai d'enregistrement en Minutes", + "Recording Timestamp": "Enregistrement de l'horodatage", + "Recording Watermark": "Filigrane d'enregistrement", + "RecordingText": "Il est recommandé de définir Type de fichier d'enregistrement sur WebMMP4 et Vidéo Codec pour libvpxou copie libx264 parce que votre Type d'Entrée est définie sur .", "Refresh List of Cascades": "Actualiser la Liste des Cascades", - "Region Editor": "Région De L'Éditeur", + "Region Editor": "Éditeur de région", "Region Name": "Nom De La Région", "RegionNote": "Les Points ne sont enregistrées que lorsque vous appuyez sur Enregistrer sur les Paramètres du Moniteur de la fenêtre.", "Regions": "Les régions", @@ -458,14 +458,14 @@ "Request": "Demande", "Reset Timer": "Réinitialiser La Minuterie", "Restart": "Redémarrer", - "Restart CRON": "Redémarrage du CRON", - "Restart Core": "Le Redémarrage De Base", - "Restarting Process": "Le Redémarrage Du Processus De", - "Retry Connection": "Nouvelle tentative de Connexion Nombre de fois que le droit à l'échec", + "Restart CRON": "Redémarrer CRON", + "Restart Core": "Redémarrer le noyau", + "Restarting Process": "Processus de redémarrage", + "Retry Connection": "Nouvelle tentative de Connexion Nombre d'échecs autorisés", "Retrying...": "Réessayer...", "Right": "Droit de l' Adresse URL", "Right Stop": "Droit d'Arrêter Adresse URL", - "Rotate": "Faites tourner", + "Rotate": "Tourner", "Save": "Enregistrer", "Save Directory": "Répertoire De Sauvegarde", "Save Events to SQL": "Enregistrer les Événements dans le SQL", @@ -481,20 +481,20 @@ "Send Frames": "Envoyer des Images Pousser images à analyser", "Separate with commas, no spaces": "Séparés par des virgules, sans espace", "Server URL": "URL du serveur", - "Set to Watch Only": "Mis à Regarder Seulement", + "Set to Watch Only": "Définir pour regarder uniquement", "Settings": "Paramètres", - "Settings Changed": "La Modification Des Réglages", + "Settings Changed": "Paramètres modifiés", "SettingsChangedText": "Vos paramètres sont enregistrés et appliqués. Certains paramètres peuvent nécessiter une actualisation de cette page.", "Shinobi": "Shinobi", "Shinobi Streamer": "Shinobi Streamer", - "Show Logs": "Afficher Les Journaux D'", - "Show Regions of Interest": "Montrer les Régions d'Intérêt", + "Show Logs": "Afficher Les Journaux", + "Show Regions of Interest": "Afficher les Régions d'Intérêt", "Show Stream HUD": "Afficher les Flux de PALETTE", "Silent": "Silencieux", "Simple": "Simple", "Size (mb)": "Taille (mo)", "Snapshot": "Instantané", - "Snapshot Flags": "Instantané De Drapeaux", + "Snapshot Flags": "Drapeaux Instantanés", "Snapshots": "Instantanés", "Sort By": "Trier Par", "Start": "Démarrer", @@ -508,12 +508,12 @@ "Stream": "Flux", "Stream Channel": "Canal De Flux De Données", "Stream Flags": "Flux De Drapeaux", - "Stream Key": "Flux De Clé", - "Stream Timestamp": "Flux D'Horodatage", + "Stream Key": "Clé de Flux", + "Stream Timestamp": "Horodatage du Flux", "Stream Type": "Type De Flux", "Stream Watermark": "Flux De Filigrane", "Stream to YouTube": "Stream sur YouTube", - "Stream to YouTube Flags": "Stream sur YouTube Drapeaux", + "Stream to YouTube Flags": "Diffuser vers des drapeaux YouTube", "StreamText": "

Cette section permettra de désigner le flux primaire, de méthode et de ses paramètres. Ce flux sera affiché dans le tableau de bord. Si vous choisissez d'utiliser HLS, JPEG, MJPEG, alors vous pouvez consommer du courant à travers d'autres programmes.

JPEG flux essentiellement désactive le principal cours d'eau et les utilisations de l'instantané bin pour obtenir des images.

", "Streamer": "Streamer", "Streams": "Flux", @@ -522,49 +522,49 @@ "Switch on for Still Image": "Interrupteur pour Toujours à l'Image", "System": "Système", "TCP": "TCP", - "TV Channel": "Chaîne de TÉLÉVISION", - "TV Channel Group": "Chaîne de TÉLÉVISION du Groupe", - "TV Channel ID": "Chaîne de TÉLÉVISION ID", - "Text Box Color": "Texte De La Boîte De Couleur", - "Text Color": "La Couleur Du Texte", + "TV Channel": "Chaîne TV", + "TV Channel Group": "Groupe de chaînes TV", + "TV Channel ID": "Identifiant de chaîne TV", + "Text Box Color": "Couleur de la Zone de Texte", + "Text Color": "Couleur du Texte", "Themes": "Thèmes", "There are no monitors that you can view with this account.": "Il n'y a pas les moniteurs que vous pouvez afficher avec ce compte.", "Time-lapse": "Time-lapse", - "Time-lapse Tool": "Time-lapse de l'Outil", - "Timeout": "Timeout", - "Timeout Reset on Next Motion": "Délai de Réinitialisation sur le Prochain Mouvement", + "Time-lapse Tool": "Outil Time-lapse", + "Timeout": "Délai d'attente", + "Timeout Reset on Next Motion": "Délai d'attente réinitialisé à au prochain mouvement", "Toggle Sidebar": "Basculer La Barre Latérale", "Top Left": "En Haut À Gauche", "Top Right": "En Haut À Droite", - "Traditional (Watch-Only, Includes Buffer)": "Traditionnel (Watch-Seulement, Comprend Tampon)", - "Traditional Recording": "Traditionnelle Enregistrement", - "Trigger Record": "Déclencheur D'Enregistrement", - "Trigger Successful": "Déclencheur De Succès", + "Traditional (Watch-Only, Includes Buffer)": "Traditionnel (Regarder uniquement, tampon inclus)", + "Traditional Recording": "Enregistrement Traditionnel", + "Trigger Record": "Enregistrement de Déclenchement", + "Trigger Successful": "Déclencheur Réussi", "UDP": "UDP", "URL": "URL", - "URL Stop Timeout": "URL Arrêter Délai Run stop URL après X millisecondes", + "URL Stop Timeout": "URL Arrêter le délai d'attente Run stop URL après X millisecondes", "US": "NOUS", "Unable to Launch": "Impossible de Lancer", - "UnabletoLaunchText": "Veuillez enregistrer le nouveau moniteur en premier. Tentez ensuite de lancer la région de l'éditeur.", + "UnabletoLaunchText": "Enregistrez d'abord le nouveau moniteur. Essayez ensuite de lancer l'éditeur de région.", "Uniform": "Uniforme", "Up": "Jusqu' Adresse URL", "Up Stop": "D'Arrêter Adresse URL", "Update": "Mise à jour", "Update to Development": "Mise à jour pour le Développement", - "Update to Master": "Mise à jour de Maître", - "Use Built-In": "Utilisez La Fonction De", + "Update to Master": "Mise à jour du Maître", + "Use Built-In": "Utilisez La Fonction intégré", "Username": "Nom d'utilisateur", "Value": "Valeur", "Video": "Vidéo", - "Video Bit Rate": "Le Débit Binaire Vidéo", + "Video Bit Rate": "Bitrate vidéo", "Video Codec": "Codec Vidéo", "Video Filter": "Filtre Vidéo", - "Video Finished": "Vidéo Fini", - "Video Length (minutes) and Motion Count per video": "Durée de la vidéo (en minutes) et le Mouvement Comte par vidéo", - "Video Limit": "Vidéo Limite", - "Video Record Rate": "Vidéo vitesse d'Enregistrement (IPS)", + "Video Finished": "Vidéo Terminée", + "Video Length (minutes) and Motion Count per video": "Durée de la vidéo (minutes) et nombre de mouvements par vidéo", + "Video Limit": "Limite Vidéo", + "Video Record Rate": "Taux d'enregistrement vidéo (IPS)", "Video Status": "État De La Vidéo", - "Video and Time Span (Minutes)": "La vidéo et la Durée (en Minutes)", + "Video and Time Span (Minutes)": "Vidéo et Durée (minutes)", "Videos": "Vidéos", "Videos List": "Liste Des Vidéos", "Warning": "Avertissement", @@ -573,7 +573,7 @@ "WebDAV": "WebDAV", "WebM (libvpx)": "WebM (libvpx)", "Webdav Error": "Webdav Erreur", - "WebdavErrorText": "Impossible d'enregistrer. Avez-vous rendre l'appareil dossiers à l'intérieur de votre choisi répertoire de sauvegarde?", + "WebdavErrorText": "Impossible de sauvegarder. Essayer de créer un répertoire dans votre dossier de sauvegarde", "Webhook": "Webhook", "Webhook URL": "Webhook URL", "Websocket": "Websocket", @@ -581,10 +581,10 @@ "Websocket Disconnected": "Websocket Déconnecté", "Width": "Largeur", "Yes": "Oui", - "Zoom In": "Zoom Dans l' Adresse URL", - "Zoom In Stop": "Zoom Arrêter Adresse URL", - "Zoom Out": "Zoom Adresse URL", - "Zoom Out Stop": "Zoom Arrêter Adresse URL", + "Zoom In": "Agrandir Adresse URL", + "Zoom In Stop": "Agrandir Arrêter Adresse URL", + "Zoom Out": "Dézoomer Adresse URL", + "Zoom Out Stop": "Dézoomer Arrêter Adresse URL", "a day": "un jour", "a few seconds": "quelques secondes", "a minute": "une minute", @@ -639,7 +639,7 @@ "monitorEditFailedMaxReached": "Votre compte a atteint le nombre maximum de caméras qui peuvent être créés. Parler à un administrateur si vous souhaitez que cela a changé.", "monitorEditText1": "Des Données non valides, Vérifiez la validité de l'importation de la chaîne.", "monitorEditText2": "Non Valide Les Détails De La Chaîne. Vérifiez pour voir c'est une chaîne JSON et non pas un objet normal d'être passé.", - "monitorGetText1": "demande incomplète, supprimer le dernier slash dans l'URL ou mettre valeur acceptable.", + "monitorGetText1": "demande incomplète, supprimer la dernière barre oblique de l'URL ou saisir une valeur acceptable", "months": "mois", "mpeg2_qsv": "MPEG2 (Quick Sync Video)", "mpeg4_cuvid": "MPEG4 CUVID", @@ -666,5 +666,5 @@ "vp8_cuvid": "VP8 NVENC (NVIDIA HW Accel)", "vp8_qsv": "VP8 (Quick Sync Video)", "vp9_cuvid": "VP9 NVENC (NVIDIA HW Accel)", - "years": "ans" + "years": "années" } diff --git a/libs/.gitignore b/libs/.gitignore new file mode 100644 index 0000000..df89f8a --- /dev/null +++ b/libs/.gitignore @@ -0,0 +1 @@ +customAutoLoad diff --git a/libs/auth.js b/libs/auth.js index bbc39a9..8db7804 100644 --- a/libs/auth.js +++ b/libs/auth.js @@ -35,6 +35,10 @@ module.exports = function(s,config,lang){ //check IP address of connecting user var finish=function(user){ if(s.api[params.auth].ip.indexOf('0.0.0.0')>-1||s.api[params.auth].ip.indexOf(params.ip)>-1){ + if(!user.lang){ + var details = s.parseJSON(user.details).lang + user.lang = s.getDefinitonFile(user.details.lang) || s.copySystemDefaultLanguage() + } cb(user); }else{ failed(); @@ -43,7 +47,10 @@ module.exports = function(s,config,lang){ //check if auth key is user's temporary session key if(s.group[params.ke]&&s.group[params.ke].users&&s.group[params.ke].users[params.auth]){ s.group[params.ke].users[params.auth].permissions={}; - cb(s.group[params.ke].users[params.auth]); + if(!s.group[params.ke].users[params.auth].lang){ + s.group[params.ke].users[params.auth].lang = s.copySystemDefaultLanguage() + } + cb(s.group[params.ke].users[params.auth]) }else{ //check if key is already in memory to save query time if(s.api[params.auth]&&s.api[params.auth].details){ @@ -185,6 +192,10 @@ module.exports = function(s,config,lang){ if(userFound === true){ return true }else{ + if(res)res.end(s.prettyPrint({ + ok: false, + msg: lang['Not Authorized'] + })) return false } } diff --git a/libs/basic.js b/libs/basic.js index 58c558c..250d238 100644 --- a/libs/basic.js +++ b/libs/basic.js @@ -12,7 +12,7 @@ module.exports = function(s,config){ if(s.isWin===true){ cmd = "Taskkill /IM ffmpeg.exe /F" }else{ - cmd = "ps aux | grep -ie ffmpeg | awk '{print $2}' | xargs kill -9" + cmd = "pkill -9 ffmpeg" } exec(cmd,{detached: true}) }; @@ -31,12 +31,14 @@ module.exports = function(s,config){ } } s.parseJSON = function(string){ + var parsed try{ - string = JSON.parse(string) + parsed = JSON.parse(string) }catch(err){ } - return string + if(!parsed)parsed = string + return parsed } s.stringJSON = function(json){ try{ @@ -224,4 +226,30 @@ module.exports = function(s,config){ break; } } + s.createTimeout = function(timeoutVar,timeoutLength,defaultLength,multiplier,callback){ + var theTimeout + if(!multiplier)multiplier = 1000 * 60 + if(!timeoutLength || timeoutLength === ''){ + theTimeout = defaultLength + }else{ + theTimeout = parseFloat(timeoutLength) * multiplier + } + clearTimeout(timeoutVar) + timeoutVar = setTimeout(function(){ + clearTimeout(timeoutVar) + delete(timeoutVar) + if(callback)callback() + },theTimeout) + } + Object.defineProperty(Array.prototype, 'chunk', { + value: function(chunkSize){ + var temporal = []; + + for (var i = 0; i < this.length; i+= chunkSize){ + temporal.push(this.slice(i,i+chunkSize)); + } + + return temporal; + } + }); } diff --git a/libs/cloudUploaders.js b/libs/cloudUploaders.js index cbc4128..f3a8ff9 100644 --- a/libs/cloudUploaders.js +++ b/libs/cloudUploaders.js @@ -2,7 +2,26 @@ var fs = require('fs'); var exec = require('child_process').exec; var spawn = require('child_process').spawn; var webdav = require("webdav-fs"); +var ssh2SftpClient = require('node-ssh') module.exports = function(s,config,lang){ + var addCloudUploader = function(opt){ + s.loadGroupAppExtender(opt.loadGroupAppExtender) + s.unloadGroupAppExtender(opt.unloadGroupAppExtender) + s.insertCompletedVideoExtender(opt.insertCompletedVideoExtender) + s.deleteVideoFromCloudExtensions[opt.name] = opt.deleteVideoFromCloudExtensions + s.cloudDiskUseStartupExtensions[opt.name] = opt.cloudDiskUseStartupExtensions + s.beforeAccountSave(opt.beforeAccountSave) + s.onAccountSave(opt.onAccountSave) + s.cloudDisksLoader(opt.name) + } + var addSimpleUploader = function(opt){ + s.loadGroupAppExtender(opt.loadGroupAppExtender) + s.unloadGroupAppExtender(opt.unloadGroupAppExtender) + s.insertCompletedVideoExtender(opt.insertCompletedVideoExtender) + s.beforeAccountSave(opt.beforeAccountSave) + s.onAccountSave(opt.onAccountSave) + s.onMonitorSave(opt.onMonitorSave) + } // WebDAV var beforeAccountSaveForWebDav = function(d){ //d = save event @@ -20,33 +39,33 @@ module.exports = function(s,config,lang){ } var loadWebDavForUser = function(e){ // e = user - var ar = JSON.parse(e.details); - if(ar.webdav_use_global === '1' && config.cloudUploaders && config.cloudUploaders.WebDAV){ + var userDetails = JSON.parse(e.details); + if(userDetails.webdav_use_global === '1' && config.cloudUploaders && config.cloudUploaders.WebDAV){ // { // webdav_user: "", // webdav_pass: "", // webdav_url: "", // webdav_dir: "", // } - ar = Object.assign(ar,config.cloudUploaders.WebDAV) + userDetails = Object.assign(userDetails,config.cloudUploaders.WebDAV) } //owncloud/webdav if(!s.group[e.ke].webdav && - ar.webdav_user&& - ar.webdav_user!==''&& - ar.webdav_pass&& - ar.webdav_pass!==''&& - ar.webdav_url&& - ar.webdav_url!=='' + userDetails.webdav_user&& + userDetails.webdav_user!==''&& + userDetails.webdav_pass&& + userDetails.webdav_pass!==''&& + userDetails.webdav_url&& + userDetails.webdav_url!=='' ){ - if(!ar.webdav_dir||ar.webdav_dir===''){ - ar.webdav_dir='/' + if(!userDetails.webdav_dir||userDetails.webdav_dir===''){ + userDetails.webdav_dir='/' } - ar.webdav_dir = s.checkCorrectPathEnding(ar.webdav_dir) + userDetails.webdav_dir = s.checkCorrectPathEnding(userDetails.webdav_dir) s.group[e.ke].webdav = webdav( - ar.webdav_url, - ar.webdav_user, - ar.webdav_pass + userDetails.webdav_url, + userDetails.webdav_user, + userDetails.webdav_pass ) } } @@ -174,8 +193,8 @@ module.exports = function(s,config,lang){ } var loadAmazonS3ForUser = function(e){ // e = user - var ar = JSON.parse(e.details) - if(ar.aws_use_global === '1' && config.cloudUploaders && config.cloudUploaders.AmazonS3){ + var userDetails = JSON.parse(e.details) + if(userDetails.aws_use_global === '1' && config.cloudUploaders && config.cloudUploaders.AmazonS3){ // { // aws_accessKeyId: "", // aws_secretAccessKey: "", @@ -183,30 +202,30 @@ module.exports = function(s,config,lang){ // aws_s3_bucket: "", // aws_s3_dir: "", // } - ar = Object.assign(ar,config.cloudUploaders.AmazonS3) + userDetails = Object.assign(userDetails,config.cloudUploaders.AmazonS3) } //Amazon S3 if(!s.group[e.ke].aws && !s.group[e.ke].aws_s3 && - ar.aws_s3 !== '0' && - ar.aws_accessKeyId !== ''&& - ar.aws_secretAccessKey && - ar.aws_secretAccessKey !== ''&& - ar.aws_region && - ar.aws_region !== ''&& - ar.aws_s3_bucket !== '' + userDetails.aws_s3 !== '0' && + userDetails.aws_accessKeyId !== ''&& + userDetails.aws_secretAccessKey && + userDetails.aws_secretAccessKey !== ''&& + userDetails.aws_region && + userDetails.aws_region !== ''&& + userDetails.aws_s3_bucket !== '' ){ - if(!ar.aws_s3_dir || ar.aws_s3_dir === '/'){ - ar.aws_s3_dir = '' + if(!userDetails.aws_s3_dir || userDetails.aws_s3_dir === '/'){ + userDetails.aws_s3_dir = '' } - if(ar.aws_s3_dir !== ''){ - ar.aws_s3_dir = s.checkCorrectPathEnding(ar.aws_s3_dir) + if(userDetails.aws_s3_dir !== ''){ + userDetails.aws_s3_dir = s.checkCorrectPathEnding(userDetails.aws_s3_dir) } s.group[e.ke].aws = new require("aws-sdk") s.group[e.ke].aws.config = new s.group[e.ke].aws.Config({ - accessKeyId: ar.aws_accessKeyId, - secretAccessKey: ar.aws_secretAccessKey, - region: ar.aws_region + accessKeyId: userDetails.aws_accessKeyId, + secretAccessKey: userDetails.aws_secretAccessKey, + region: userDetails.aws_region }) s.group[e.ke].aws_s3 = new s.group[e.ke].aws.S3(); } @@ -296,63 +315,67 @@ module.exports = function(s,config,lang){ } } var loadBackblazeB2ForUser = function(e){ - var ar = JSON.parse(e.details); + var userDetails = JSON.parse(e.details); try{ - if(ar.b2_use_global === '1' && config.cloudUploaders && config.cloudUploaders.BackblazeB2){ + if(userDetails.b2_use_global === '1' && config.cloudUploaders && config.cloudUploaders.BackblazeB2){ // { // bb_b2_accountId: "", // bb_b2_applicationKey: "", // bb_b2_bucket: "", // bb_b2_dir: "", // } - ar = Object.assign(ar,config.cloudUploaders.BackblazeB2) + userDetails = Object.assign(userDetails,config.cloudUploaders.BackblazeB2) } if(!s.group[e.ke].bb_b2 && - ar.bb_b2_accountId && - ar.bb_b2_accountId !=='' && - ar.bb_b2_applicationKey && - ar.bb_b2_applicationKey !=='' && - ar.bb_b2_bucket && - ar.bb_b2_bucket !== '' + userDetails.bb_b2_accountId && + userDetails.bb_b2_accountId !=='' && + userDetails.bb_b2_applicationKey && + userDetails.bb_b2_applicationKey !=='' && + userDetails.bb_b2_bucket && + userDetails.bb_b2_bucket !== '' ){ var B2 = require('backblaze-b2') - if(!ar.bb_b2_dir || ar.bb_b2_dir === '/'){ - ar.bb_b2_dir = '' + if(!userDetails.bb_b2_dir || userDetails.bb_b2_dir === '/'){ + userDetails.bb_b2_dir = '' } - if(ar.bb_b2_dir !== ''){ - ar.bb_b2_dir = s.checkCorrectPathEnding(ar.bb_b2_dir) + if(userDetails.bb_b2_dir !== ''){ + userDetails.bb_b2_dir = s.checkCorrectPathEnding(userDetails.bb_b2_dir) } - var b2 = new B2({ - accountId: ar.bb_b2_accountId, - applicationKey: ar.bb_b2_applicationKey - }) - s.group[e.ke].bb_b2 = b2 var backblazeErr = function(err){ // console.log(err) - s.userLog({mid:'$USER',ke:e.ke},{type:lang['Backblaze Error'],msg:err.data}) + s.userLog({mid:'$USER',ke:e.ke},{type:lang['Backblaze Error'],msg:err.data || err}) } - b2.authorize().then(function(resp){ - s.group[e.ke].bb_b2_downloadUrl = resp.data.downloadUrl - b2.listBuckets().then(function(resp){ - var buckets = resp.data.buckets - var bucketN = -2 - buckets.forEach(function(item,n){ - if(item.bucketName === ar.bb_b2_bucket){ - bucketN = n + var createB2Connection = function(){ + var b2 = new B2({ + accountId: userDetails.bb_b2_accountId, + applicationKey: userDetails.bb_b2_applicationKey + }) + b2.authorize().then(function(resp){ + s.group[e.ke].bb_b2_downloadUrl = resp.data.downloadUrl + b2.listBuckets().then(function(resp){ + var buckets = resp.data.buckets + var bucketN = -2 + buckets.forEach(function(item,n){ + if(item.bucketName === userDetails.bb_b2_bucket){ + bucketN = n + } + }) + if(bucketN > -1){ + s.group[e.ke].bb_b2_bucketId = buckets[bucketN].bucketId + }else{ + b2.createBucket( + userDetails.bb_b2_bucket, + 'allPublic' + ).then(function(resp){ + s.group[e.ke].bb_b2_bucketId = resp.data.bucketId + }).catch(backblazeErr) } - }) - if(bucketN > -1){ - s.group[e.ke].bb_b2_bucketId = buckets[bucketN].bucketId - }else{ - b2.createBucket( - ar.bb_b2_bucket, - 'allPublic' - ).then(function(resp){ - s.group[e.ke].bb_b2_bucketId = resp.data.bucketId - }).catch(backblazeErr) - } + }).catch(backblazeErr) }).catch(backblazeErr) - }).catch(backblazeErr) + s.group[e.ke].bb_b2 = b2 + } + createB2Connection() + s.group[e.ke].bb_b2_refreshTimer = setTimeout(createB2Connection,1000 * 60 * 60) } }catch(err){ s.debugLog(err) @@ -360,6 +383,7 @@ module.exports = function(s,config,lang){ } var unloadBackblazeB2ForUser = function(user){ s.group[user.ke].bb_b2 = null + clearTimeout(s.group[user.ke].bb_b2_refreshTimer) } var deleteVideoFromBackblazeB2 = function(e,video,callback){ // e = user @@ -431,156 +455,259 @@ module.exports = function(s,config,lang){ }) } } + //Wasabi Hot Cloud Storage + var beforeAccountSaveForWasabiHotCloudStorage = function(d){ + //d = save event + d.form.details.whcs_use_global=d.d.whcs_use_global + d.form.details.use_whcs=d.d.use_whcs + } + var cloudDiskUseStartupForWasabiHotCloudStorage = function(group,userDetails){ + group.cloudDiskUse['whcs'].name = 'Wasabi Hot Cloud Storage' + group.cloudDiskUse['whcs'].sizeLimitCheck = (userDetails.use_whcs_size_limit === '1') + if(!userDetails.whcs_size_limit || userDetails.whcs_size_limit === ''){ + group.cloudDiskUse['whcs'].sizeLimit = 10000 + }else{ + group.cloudDiskUse['whcs'].sizeLimit = parseFloat(userDetails.whcs_size_limit) + } + } + var loadWasabiHotCloudStorageForUser = function(e){ + // e = user + var userDetails = JSON.parse(e.details) + if(userDetails.whcs_use_global === '1' && config.cloudUploaders && config.cloudUploaders.WasabiHotCloudStorage){ + // { + // whcs_accessKeyId: "", + // whcs_secretAccessKey: "", + // whcs_region: "", + // whcs_bucket: "", + // whcs_dir: "", + // } + userDetails = Object.assign(userDetails,config.cloudUploaders.WasabiHotCloudStorage) + } + //Wasabi Hot Cloud Storage + if(!s.group[e.ke].whcs && + userDetails.whcs !== '0' && + userDetails.whcs_accessKeyId !== ''&& + userDetails.whcs_secretAccessKey && + userDetails.whcs_secretAccessKey !== ''&& + userDetails.whcs_region && + userDetails.whcs_region !== ''&& + userDetails.whcs_bucket !== '' + ){ + if(!userDetails.whcs_dir || userDetails.whcs_dir === '/'){ + userDetails.whcs_dir = '' + } + if(userDetails.whcs_dir !== ''){ + userDetails.whcs_dir = s.checkCorrectPathEnding(userDetails.whcs_dir) + } + var AWS = new require("aws-sdk") + s.group[e.ke].whcs = AWS + var wasabiEndpoint = new AWS.Endpoint('s3.wasabisys.com') + s.group[e.ke].whcs.config = new s.group[e.ke].whcs.Config({ + endpoint: wasabiEndpoint, + accessKeyId: userDetails.whcs_accessKeyId, + secretAccessKey: userDetails.whcs_secretAccessKey, + region: userDetails.whcs_region + }) + s.group[e.ke].whcs = new s.group[e.ke].whcs.S3(); + } + } + var unloadWasabiHotCloudStorageForUser = function(user){ + s.group[user.ke].whcs = null + } + var deleteVideoFromWasabiHotCloudStorage = function(e,video,callback){ + // e = user + try{ + var videoDetails = JSON.parse(video.details) + }catch(err){ + var videoDetails = video.details + } + if(!videoDetails.location){ + videoDetails.location = video.href.split('wasabisys.com')[1] + } + s.group[e.ke].whcs.deleteObject({ + Bucket: s.group[e.ke].init.whcs_bucket, + Key: videoDetails.location, + }, function(err, data) { + if (err) console.log(err); + callback() + }); + } + var uploadVideoToWasabiHotCloudStorage = function(e,k){ + //e = video object + //k = temporary values + if(!k)k={}; + //cloud saver - Wasabi Hot Cloud Storage + if(s.group[e.ke].whcs && s.group[e.ke].init.use_whcs !== '0' && s.group[e.ke].init.whcs_save === '1'){ + var ext = k.filename.split('.') + ext = ext[ext.length - 1] + var fileStream = fs.createReadStream(k.dir+k.filename); + fileStream.on('error', function (err) { + console.error(err) + }) + var saveLocation = s.group[e.ke].init.whcs_dir+e.ke+'/'+e.mid+'/'+k.filename + s.group[e.ke].whcs.upload({ + Bucket: s.group[e.ke].init.whcs_bucket, + Key: saveLocation, + Body:fileStream, + ACL:'public-read', + ContentType:'video/'+ext + },function(err,data){ + if(err){ + s.userLog(e,{type:lang['Wasabi Hot Cloud Storage Upload Error'],msg:err}) + } + if(s.group[e.ke].init.whcs_log === '1' && data && data.Location){ + var save = [ + e.mid, + e.ke, + k.startTime, + 1, + s.s({ + type : 'whcs', + location : saveLocation + }), + k.filesize, + k.endTime, + data.Location + ] + s.sqlQuery('INSERT INTO `Cloud Videos` (mid,ke,time,status,details,size,end,href) VALUES (?,?,?,?,?,?,?,?)',save) + s.setCloudDiskUsedForGroup(e,{ + amount : k.filesizeMB, + storageType : 'whcs' + }) + s.purgeCloudDiskForGroup(e,'whcs') + } + }) + } + } //SFTP - // var beforeAccountSaveForSftp = function(d){ - // //d = save event - // d.form.details.use_sftp = d.d.use_sftp - // } - // var cloudDiskUseStartupForSftp = function(group,userDetails){ - // group.cloudDiskUse['sftp'].name = 'SFTP' - // group.cloudDiskUse['sftp'].sizeLimitCheck = (userDetails.use_aws_s3_size_limit === '1') - // if(!userDetails.aws_s3_size_limit || userDetails.aws_s3_size_limit === ''){ - // group.cloudDiskUse['sftp'].sizeLimit = 10000 - // }else{ - // group.cloudDiskUse['sftp'].sizeLimit = parseFloat(userDetails.aws_s3_size_limit) - // } - // } - // var loadSftpForUser = function(e){ - // // e = user - // var ar = JSON.parse(e.details); - // //SFTP - // if(!s.group[e.ke].sftp && - // !s.group[e.ke].sftp && - // ar.sftp !== '0' && - // ar.sftp_accessKeyId !== ''&& - // ar.sftp_secretAccessKey && - // ar.sftp_secretAccessKey !== ''&& - // ar.sftp_region && - // ar.sftp_region !== ''&& - // ar.sftp_bucket !== '' - // ){ - // if(!ar.sftp_dir || ar.sftp_dir === '/'){ - // ar.sftp_dir = '' - // } - // if(ar.sftp_dir !== ''){ - // ar.sftp_dir = s.checkCorrectPathEnding(ar.sftp_dir) - // } - // s.group[e.ke].sftp = new s.group[e.ke].sftp.S3(); - // s.group[e.ke].sftp = new require('ssh2-sftp-client')(); - // var connectionDetails = { - // host: ar.sftp_host, - // port: ar.sftp_port - // } - // if(!ar.sftp_port)ar.sftp_port = 22 - // if(ar.sftp_username)connectionDetails.username = ar.sftp_username - // if(ar.sftp_password)connectionDetails.password = ar.sftp_password - // if(ar.sftp_privateKey)connectionDetails.privateKey = ar.sftp_privateKey - // sftp.connect(connectionDetails).then(() => { - // return sftp.list('/pathname'); - // }).then((data) => { - // console.log(data, 'the data info'); - // }).catch((err) => { - // console.log(err, 'catch error'); - // }); - // } - // } - // var unloadSftpForUser = function(user){ - // s.group[user.ke].sftp = null - // } - // var deleteVideoFromSftp = function(e,video,callback){ - // // e = user - // try{ - // var videoDetails = JSON.parse(video.details) - // }catch(err){ - // var videoDetails = video.details - // } - // s.group[e.ke].sftp.deleteObject({ - // Bucket: s.group[e.ke].init.sftp_bucket, - // Key: videoDetails.location, - // }, function(err, data) { - // if (err) console.log(err); - // callback() - // }); - // } - // var uploadVideoToSftp = function(e,k){ - // //e = video object - // //k = temporary values - // if(!k)k={}; - // //cloud saver - SFTP - // if(s.group[e.ke].sftp && s.group[e.ke].init.use_sftp !== '0' && s.group[e.ke].init.sftp_save === '1'){ - // var fileStream = fs.createReadStream(k.dir+k.filename); - // fileStream.on('error', function (err) { - // console.error(err) - // }) - // var saveLocation = s.group[e.ke].init.sftp_dir+e.ke+'/'+e.mid+'/'+k.filename - // s.group[e.ke].sftp.upload({ - // Bucket: s.group[e.ke].init.sftp_bucket, - // Key: saveLocation, - // Body:fileStream, - // ACL:'public-read' - // },function(err,data){ - // if(err){ - // s.userLog(e,{type:lang['SFTP Upload Error'],msg:err}) - // } - // if(s.group[e.ke].init.sftp_log === '1' && data && data.Location){ - // var save = [ - // e.mid, - // e.ke, - // k.startTime, - // 1, - // s.s({ - // type : 'sftp', - // location : saveLocation - // }), - // k.filesize, - // k.endTime, - // data.Location - // ] - // s.sqlQuery('INSERT INTO `Cloud Videos` (mid,ke,time,status,details,size,end,href) VALUES (?,?,?,?,?,?,?,?)',save) - // s.setCloudDiskUsedForGroup(e,{ - // amount : k.filesizeMB, - // storageType : 'sftp' - // }) - // s.purgeCloudDiskForGroup(e,'sftp') - // } - // }) - // } - // } + var sftpErr = function(err){ + // console.log(err) + s.userLog({mid:'$USER',ke:e.ke},{type:lang['SFTP Error'],msg:err.data || err}) + } + var beforeAccountSaveForSftp = function(d){ + //d = save event + d.form.details.use_sftp = d.d.use_sftp + } + var loadSftpForUser = function(e){ + // e = user + var userDetails = JSON.parse(e.details); + //SFTP + if(!s.group[e.ke].sftp && + !s.group[e.ke].sftp && + userDetails.sftp !== '0' && + userDetails.sftp_host && + userDetails.sftp_host !== ''&& + userDetails.sftp_port && + userDetails.sftp_port !== '' + ){ + if(!userDetails.sftp_dir || userDetails.sftp_dir === '/'){ + userDetails.sftp_dir = '' + } + if(userDetails.sftp_dir !== ''){ + userDetails.sftp_dir = s.checkCorrectPathEnding(userDetails.sftp_dir) + } + var sftp = new ssh2SftpClient() + var connectionDetails = { + host: userDetails.sftp_host, + port: userDetails.sftp_port + } + if(!userDetails.sftp_port)connectionDetails.port = 22 + if(userDetails.sftp_username && userDetails.sftp_username !== '')connectionDetails.username = userDetails.sftp_username + if(userDetails.sftp_password && userDetails.sftp_password !== '')connectionDetails.password = userDetails.sftp_password + if(userDetails.sftp_privateKey && userDetails.sftp_privateKey !== '')connectionDetails.privateKey = userDetails.sftp_privateKey + sftp.connect(connectionDetails).catch(sftpErr) + s.group[e.ke].sftp = sftp + } + } + var unloadSftpForUser = function(user){ + if(s.group[user.ke].sftp && s.group[user.ke].sftp.end)s.group[user.ke].sftp.end().then(function(){ + s.group[user.ke].sftp = null + }) + } + var uploadVideoToSftp = function(e,k){ + //e = video object + //k = temporary values + if(!k)k={}; + //cloud saver - SFTP + if(s.group[e.ke].sftp && s.group[e.ke].init.use_sftp !== '0' && s.group[e.ke].init.sftp_save === '1'){ + var localPath = k.dir + k.filename + var saveLocation = s.group[e.ke].init.sftp_dir + e.ke + '/' + e.mid + '/' + k.filename + s.group[e.ke].sftp.putFile(localPath, saveLocation).catch(sftpErr) + } + } + var createSftpDirectory = function(monitorConfig){ + var monitorSaveDirectory = s.group[monitorConfig.ke].init.sftp_dir + monitorConfig.ke + '/' + monitorConfig.mid + s.group[monitorConfig.ke].sftp.mkdir(monitorSaveDirectory, true).catch(function(err){ + if(err.code !== 'ERR_ASSERTION'){ + sftpErr(err) + } + }) + } + var onMonitorSaveForSftp = function(monitorConfig){ + if(s.group[monitorConfig.ke].sftp && s.group[monitorConfig.ke].init.use_sftp !== '0' && s.group[monitorConfig.ke].init.sftp_save === '1'){ + createSftpDirectory(monitorConfig) + } + } + var onAccountSaveForSftp = function(group,userDetails,user){ + if(s.group[user.ke] && s.group[user.ke].sftp && s.group[user.ke].init.use_sftp !== '0' && s.group[user.ke].init.sftp_save === '1'){ + Object.keys(s.group[user.ke].mon_conf).forEach(function(monitorId){ + createSftpDirectory(s.group[user.ke].mon_conf[monitorId]) + }) + } + } //add the extenders //webdav - s.loadGroupAppExtender(loadWebDavForUser) - s.unloadGroupAppExtender(unloadWebDavForUser) - s.insertCompletedVideoExtender(uploadVideoToWebDav) - s.deleteVideoFromCloudExtensions['webdav'] = deleteVideoFromWebDav - s.cloudDiskUseStartupExtensions['webdav'] = cloudDiskUseStartupForWebDav - s.beforeAccountSave(beforeAccountSaveForWebDav) - s.onAccountSave(cloudDiskUseStartupForWebDav) - s.cloudDisksLoader('webdav') + addCloudUploader({ + name: 'webdav', + loadGroupAppExtender: loadWebDavForUser, + unloadGroupAppExtender: unloadWebDavForUser, + insertCompletedVideoExtender: uploadVideoToWebDav, + deleteVideoFromCloudExtensions: deleteVideoFromWebDav, + cloudDiskUseStartupExtensions: cloudDiskUseStartupForWebDav, + beforeAccountSave: beforeAccountSaveForWebDav, + onAccountSave: cloudDiskUseStartupForWebDav, + }) //amazon s3 - s.loadGroupAppExtender(loadAmazonS3ForUser) - s.unloadGroupAppExtender(unloadAmazonS3ForUser) - s.insertCompletedVideoExtender(uploadVideoToAmazonS3) - s.deleteVideoFromCloudExtensions['s3'] = deleteVideoFromAmazonS3 - s.cloudDiskUseStartupExtensions['s3'] = cloudDiskUseStartupForAmazonS3 - s.beforeAccountSave(beforeAccountSaveForAmazonS3) - s.onAccountSave(cloudDiskUseStartupForAmazonS3) - s.cloudDisksLoader('s3') + addCloudUploader({ + name: 's3', + loadGroupAppExtender: loadAmazonS3ForUser, + unloadGroupAppExtender: unloadAmazonS3ForUser, + insertCompletedVideoExtender: uploadVideoToAmazonS3, + deleteVideoFromCloudExtensions: deleteVideoFromAmazonS3, + cloudDiskUseStartupExtensions: cloudDiskUseStartupForAmazonS3, + beforeAccountSave: beforeAccountSaveForAmazonS3, + onAccountSave: cloudDiskUseStartupForAmazonS3, + }) //backblaze b2 - s.loadGroupAppExtender(loadBackblazeB2ForUser) - s.unloadGroupAppExtender(unloadBackblazeB2ForUser) - s.insertCompletedVideoExtender(uploadVideoToBackblazeB2) - s.deleteVideoFromCloudExtensions['b2'] = deleteVideoFromBackblazeB2 - s.cloudDiskUseStartupExtensions['b2'] = cloudDiskUseStartupForBackblazeB2 - s.beforeAccountSave(beforeAccountSaveForBackblazeB2) - s.onAccountSave(cloudDiskUseStartupForBackblazeB2) - s.cloudDisksLoader('b2') - //SFTP - // s.loadGroupAppExtender(loadSftpForUser) - // s.unloadGroupAppExtender(unloadSftpForUser) - // s.insertCompletedVideoExtender(uploadVideoToSftp) - // s.deleteVideoFromCloudExtensions['sftp'] = deleteVideoFromSftp - // s.cloudDiskUseStartupExtensions['sftp'] = cloudDiskUseStartupForSftp - // s.beforeAccountSave(beforeAccountSaveForSftp) - // s.onAccountSave(cloudDiskUseStartupForSftp) - // s.cloudDisksLoader('sftp') + addCloudUploader({ + name: 'b2', + loadGroupAppExtender: loadBackblazeB2ForUser, + unloadGroupAppExtender: unloadBackblazeB2ForUser, + insertCompletedVideoExtender: uploadVideoToBackblazeB2, + deleteVideoFromCloudExtensions: deleteVideoFromBackblazeB2, + cloudDiskUseStartupExtensions: cloudDiskUseStartupForBackblazeB2, + beforeAccountSave: beforeAccountSaveForBackblazeB2, + onAccountSave: cloudDiskUseStartupForBackblazeB2, + }) + //wasabi + addCloudUploader({ + name: 'whcs', + loadGroupAppExtender: loadWasabiHotCloudStorageForUser, + unloadGroupAppExtender: unloadWasabiHotCloudStorageForUser, + insertCompletedVideoExtender: uploadVideoToWasabiHotCloudStorage, + deleteVideoFromCloudExtensions: deleteVideoFromWasabiHotCloudStorage, + cloudDiskUseStartupExtensions: cloudDiskUseStartupForWasabiHotCloudStorage, + beforeAccountSave: beforeAccountSaveForWasabiHotCloudStorage, + onAccountSave: cloudDiskUseStartupForWasabiHotCloudStorage, + }) + //SFTP (Simple Uploader) + addSimpleUploader({ + name: 'sftp', + loadGroupAppExtender: loadSftpForUser, + unloadGroupAppExtender: unloadSftpForUser, + insertCompletedVideoExtender: uploadVideoToSftp, + beforeAccountSave: beforeAccountSaveForSftp, + onAccountSave: onAccountSaveForSftp, + onMonitorSave: onMonitorSaveForSftp, + }) } diff --git a/libs/codeTester.js b/libs/codeTester.js new file mode 100644 index 0000000..94d596f --- /dev/null +++ b/libs/codeTester.js @@ -0,0 +1,67 @@ +var fs = require('fs'); +var execSync = require('child_process').execSync; +module.exports = function(s,config,lang){ + var onFFmpegLoaded = function(ffmpeg){ + if(process.argv[2] && process.argv[2].indexOf('test') > -1){ + config.testMode = true + } + if(config.testMode === true){ + config.videosDir = s.mainDirectory + '/videosTest/' + config.port = 9999 + if(config.childNodes && config.childNodes.enabled === true && config.childNodes.mode === 'master'){ + config.childNodes.port = 9998 + } + s.ffmpegFunctions = ffmpeg + } + } + var onBeforeDatabaseLoad = function(ffmpeg){ + if(config.testMode === true){ + try{ + execSync('rm ' + s.mainDirectory + '/shinobi-test.sqlite') + }catch(err){ + + } + try{ + require('sqlite3') + }catch(err){ + execSync('npm install sqlite3 --unsafe-perm') + } + execSync('cp ' + s.mainDirectory + '/sql/shinobi.sample.sqlite ' + s.mainDirectory + '/shinobi-test.sqlite') + config.databaseType = 'sqlite3' + config.db = { + filename: s.mainDirectory + "/shinobi-test.sqlite" + } + } + } + var onProcessReady = function(){ + if(config.testMode === true){ + s.location.super = s.mainDirectory + '/super-test.json' + fs.writeFileSync(s.location.super,s.s([ + { + "mail":"admin@shinobi.video", + "pass":"21232f297a57a5a743894a0e4a801fc3", + "tokens":[ + "111" + ] + } + ],null,3)) + setTimeout(function(){ + require(s.mainDirectory + '/test/run.js')(s,config,lang,io) + },500) + } + } + var onProcessExit = function(){ + if(config.testMode === true){ + execSync('rm ' + s.mainDirectory + '/shinobi-test.sqlite') + execSync('rm ' + s.location.super) + execSync('rm -rf ' + config.videosDir) + console.log('---- Temporary Files Cleaned Up') + process.exit() + } + } + //attach event handlers + s.onFFmpegLoaded(onFFmpegLoaded) + s.onBeforeDatabaseLoad(onBeforeDatabaseLoad) + s.onProcessReady(onProcessReady) + s.onProcessExit(onProcessExit) +} diff --git a/libs/config.js b/libs/config.js index 185daf0..05e03bb 100644 --- a/libs/config.js +++ b/libs/config.js @@ -34,10 +34,11 @@ module.exports = function(s){ if(config.databaseLogs === undefined){config.databaseLogs=false} if(config.useUTC === undefined){config.useUTC=false} if(config.iconURL === undefined){config.iconURL = "https://shinobi.video/libs/assets/icon/apple-touch-icon-152x152.png"} - if(config.pipeAddition === undefined){config.pipeAddition=7}else{config.pipeAddition=parseInt(config.pipeAddition)} + if(config.pipeAddition === undefined){config.pipeAddition=10}else{config.pipeAddition=parseInt(config.pipeAddition)} if(config.hideCloudSaveUrls === undefined){config.hideCloudSaveUrls = true} if(config.insertOrphans === undefined){config.insertOrphans = true} if(config.orphanedVideoCheckMax === undefined){config.orphanedVideoCheckMax = 20} + if(config.detectorMergePamRegionTriggers === undefined){config.detectorMergePamRegionTriggers = false} //Child Nodes if(config.childNodes === undefined)config.childNodes = {}; //enabled @@ -50,6 +51,12 @@ module.exports = function(s){ if(config.childNodes.key === undefined)config.childNodes.key = [ '3123asdasdf1dtj1hjk23sdfaasd12asdasddfdbtnkkfgvesra3asdsd3123afdsfqw345' ]; - + if(config.cron.key === 'change_this_to_something_very_random__just_anything_other_than_this'){ + console.error('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!') + console.error('!! Change your cron key in your conf.json. !!') + console.error(`!! If you're running Shinobi remotely you should do this now. !!`) + console.error('!! You can do this in the Super User panel or from terminal. !!') + console.error('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!') + } return config } diff --git a/libs/customAutoLoad.js b/libs/customAutoLoad.js new file mode 100644 index 0000000..70b6b86 --- /dev/null +++ b/libs/customAutoLoad.js @@ -0,0 +1,134 @@ +var fs = require('fs') +var express = require('express') +module.exports = function(s,config,lang,app,io){ + s.customAutoLoadModules = {} + s.customAutoLoadTree = { + pages: [], + PageBlocks: [], + LibsJs: [], + LibsCss: [], + adminPageBlocks: [], + adminLibsJs: [], + adminLibsCss: [], + superPageBlocks: [], + superLibsJs: [], + superLibsCss: [] + } + var folderPath = __dirname + '/customAutoLoad' + var search = function(searchFor,searchIn){return searchIn.indexOf(searchFor) > -1} + fs.readdir(folderPath,function(err,folderContents){ + if(!err && folderContents){ + folderContents.forEach(function(filename){ + s.customAutoLoadModules[filename] = {} + var customModulePath = folderPath + '/' + filename + if(filename.indexOf('.js') > -1){ + s.customAutoLoadModules[filename].type = 'file' + try{ + require(customModulePath)(s,config,lang,app,io) + }catch(err){ + console.log('Failed to Load Module : ' + filename) + console.log(err) + } + }else{ + if(fs.lstatSync(customModulePath).isDirectory()){ + s.customAutoLoadModules[filename].type = 'folder' + try{ + require(customModulePath)(s,config,lang,app,io) + fs.readdir(customModulePath,function(err,folderContents){ + folderContents.forEach(function(name){ + switch(name){ + case'web': + var webFolder = s.checkCorrectPathEnding(customModulePath) + 'web/' + fs.readdir(webFolder,function(err,webFolderContents){ + webFolderContents.forEach(function(name){ + switch(name){ + case'libs': + case'pages': + if(name === 'libs'){ + if(config.webPaths.home !== '/'){ + app.use('/libs',express.static(webFolder + '/libs')) + } + app.use(s.checkCorrectPathEnding(config.webPaths.home)+'libs',express.static(webFolder + '/libs')) + app.use(s.checkCorrectPathEnding(config.webPaths.admin)+'libs',express.static(webFolder + '/libs')) + app.use(s.checkCorrectPathEnding(config.webPaths.super)+'libs',express.static(webFolder + '/libs')) + } + var libFolder = webFolder + name + '/' + fs.readdir(libFolder,function(err,webFolderContents){ + webFolderContents.forEach(function(libName){ + var thirdLevelName = libFolder + libName + switch(libName){ + case'js': + case'css': + case'blocks': + fs.readdir(thirdLevelName,function(err,webFolderContents){ + webFolderContents.forEach(function(filename){ + var fullPath = thirdLevelName + '/' + filename + var blockPrefix = '' + switch(true){ + case search('super.',filename): + blockPrefix = 'super' + break; + case search('admin.',filename): + blockPrefix = 'admin' + break; + } + switch(libName){ + case'js': + s.customAutoLoadTree[blockPrefix + 'LibsJs'].push(filename) + break; + case'css': + s.customAutoLoadTree[blockPrefix + 'LibsCss'].push(filename) + break; + case'blocks': + s.customAutoLoadTree[blockPrefix + 'PageBlocks'].push(fullPath) + break; + } + }) + }) + break; + default: + if(libName.indexOf('.ejs') > -1){ + s.customAutoLoadTree.pages.push(thirdLevelName) + } + break; + } + }) + }) + break; + } + }) + }) + break; + case'languages': + var languagesFolder = s.checkCorrectPathEnding(customModulePath) + 'languages/' + fs.readdir(languagesFolder,function(err,files){ + if(err)return console.log(err); + files.forEach(function(filename){ + var fileData = require(languagesFolder + filename) + var rule = filename.replace('.json','') + if(config.language === rule){ + lang = Object.assign(lang,fileData) + } + if(s.loadedLanguages[rule]){ + s.loadedLanguages[rule] = Object.assign(s.loadedLanguages[rule],fileData) + }else{ + s.loadedLanguages[rule] = Object.assign(s.copySystemDefaultLanguage(),fileData) + } + }) + }) + break; + } + }) + }) + }catch(err){ + console.log('Failed to Load Module : ' + filename) + console.log(err) + } + } + } + }) + }else{ + fs.mkdirSync(folderPath) + } + }) +} diff --git a/libs/detector.js b/libs/detector.js index eac722f..0cc1135 100644 --- a/libs/detector.js +++ b/libs/detector.js @@ -1,6 +1,11 @@ -var P2P = require('pipe2pam'); +// Matrix In Region Libs > +var SAT = require('sat') +var V = SAT.Vector; +var P = SAT.Polygon; +// Matrix In Region Libs /> +var P2P = require('pipe2pam') // pamDiff is based on https://www.npmjs.com/package/pam-diff -var PamDiff = require('./detectorPamDiff.js'); +var PamDiff = require('pam-diff') module.exports = function(s,config){ s.createPamDiffEngine = function(e){ var width, @@ -46,61 +51,146 @@ module.exports = function(s,config){ [width,height], [width,0] ] - }; + } } e.triggerTimer = {} var regions = s.createPamDiffRegionArray(regionJson,globalColorThreshold,globalSensitivity,fullFrame) - - s.group[e.ke].mon[e.id].pamDiff = new PamDiff({ + var pamDiffOptions = { grayscale: 'luminosity', - regions : regions.forPam, - drawMatrix : e.details.detector_show_matrix - }); - s.group[e.ke].mon[e.id].p2p = new P2P(); - var sendTrigger = function(trigger){ - var detectorObject = { - f:'trigger', - id:e.id, - ke:e.ke, - name:trigger.name, - details:{ - plug:'built-in', - name:trigger.name, - reason:'motion', - confidence:trigger.percent - }, - plates:[], - imgHeight:e.details.detector_scale_y, - imgWidth:e.details.detector_scale_x - } - if(trigger.matrix)detectorObject.details.matrices = [trigger.matrix] - var region = Object.values(regionJson).find(x => x.name == detectorObject.name) - s.checkMaximumSensitivity(e, region, detectorObject, function() { - s.checkTriggerThreshold(e, region, detectorObject, function() { - detectorObject.doObjectDetection = (s.ocv && e.details.detector_use_detect_object === '1') - s.triggerEvent(detectorObject) - }) - }) + regions : regions.forPam } - if(e.details.detector_noise_filter==='1'){ - if(!s.group[e.ke].mon[e.id].noiseFilterArray)s.group[e.ke].mon[e.id].noiseFilterArray = {} - var noiseFilterArray = s.group[e.ke].mon[e.id].noiseFilterArray - Object.keys(regions.notForPam).forEach(function(name){ - if(!noiseFilterArray[name])noiseFilterArray[name]=[]; - }) - s.group[e.ke].mon[e.id].pamDiff.on('diff', (data) => { - data.trigger.forEach(function(trigger){ - s.filterTheNoise(e,noiseFilterArray,regions,trigger,function(){ - sendTrigger(trigger) + if(e.details.detector_show_matrix==='1'){ + pamDiffOptions.response = 'bounds' + } + s.group[e.ke].mon[e.id].pamDiff = new PamDiff(pamDiffOptions); + s.group[e.ke].mon[e.id].p2p = new P2P() + var regionArray = Object.values(regionJson) + if(config.detectorMergePamRegionTriggers === true){ + // merge pam triggers for performance boost + var buildTriggerEvent = function(trigger){ + var detectorObject = { + f:'trigger', + id:e.id, + ke:e.ke, + name:trigger.name, + details:{ + plug:'built-in', + name:trigger.name, + reason:'motion', + confidence:trigger.percent + }, + plates:[], + imgHeight:e.details.detector_scale_y, + imgWidth:e.details.detector_scale_x + } + if(trigger.merged){ + if(trigger.matrices)detectorObject.details.matrices = trigger.matrices + var filteredCount = 0 + var filteredCountSuccess = 0 + trigger.merged.forEach(function(triggerPiece){ + var region = regionArray.find(x => x.name == triggerPiece.name) + s.checkMaximumSensitivity(e, region, detectorObject, function(err1) { + s.checkTriggerThreshold(e, region, detectorObject, function(err2) { + ++filteredCount + if(!err1 && !err2)++filteredCountSuccess + if(filteredCount === trigger.merged.length && filteredCountSuccess > 0){ + detectorObject.doObjectDetection = (s.isAtleatOneDetectorPluginConnected && e.details.detector_use_detect_object === '1') + s.triggerEvent(detectorObject) + } + }) + }) + }) + }else{ + if(trigger.matrix)detectorObject.details.matrices = [trigger.matrix] + var region = regionArray.find(x => x.name == detectorObject.name) + s.checkMaximumSensitivity(e, region, detectorObject, function(err1) { + s.checkTriggerThreshold(e, region, detectorObject, function(err2) { + if(!err1 && !err2){ + detectorObject.doObjectDetection = (s.isAtleatOneDetectorPluginConnected && e.details.detector_use_detect_object === '1') + s.triggerEvent(detectorObject) + } + }) + }) + } + } + if(e.details.detector_noise_filter==='1'){ + if(!s.group[e.ke].mon[e.id].noiseFilterArray)s.group[e.ke].mon[e.id].noiseFilterArray = {} + var noiseFilterArray = s.group[e.ke].mon[e.id].noiseFilterArray + Object.keys(regions.notForPam).forEach(function(name){ + if(!noiseFilterArray[name])noiseFilterArray[name]=[]; + }) + s.group[e.ke].mon[e.id].pamDiff.on('diff', (data) => { + var filteredCount = 0 + var filteredCountSuccess = 0 + data.trigger.forEach(function(trigger){ + s.filterTheNoise(e,noiseFilterArray,regions,trigger,function(err){ + ++filteredCount + if(!err)++filteredCountSuccess + if(filteredCount === data.trigger.length && filteredCountSuccess > 0){ + buildTriggerEvent(s.mergePamTriggers(data)) + } + }) }) }) - }) + }else{ + s.group[e.ke].mon[e.id].pamDiff.on('diff', (data) => { + buildTriggerEvent(s.mergePamTriggers(data)) + }) + } }else{ - s.group[e.ke].mon[e.id].pamDiff.on('diff', (data) => { - data.trigger.forEach(sendTrigger) - }) + //config.detectorMergePamRegionTriggers NOT true + //original behaviour, all regions have their own event. + var buildTriggerEvent = function(trigger){ + var detectorObject = { + f:'trigger', + id:e.id, + ke:e.ke, + name:trigger.name, + details:{ + plug:'built-in', + name:trigger.name, + reason:'motion', + confidence:trigger.percent + }, + plates:[], + imgHeight:e.details.detector_scale_y, + imgWidth:e.details.detector_scale_x + } + if(trigger.matrix)detectorObject.details.matrices = [trigger.matrix] + var region = Object.values(regionJson).find(x => x.name == detectorObject.name) + s.checkMaximumSensitivity(e, region, detectorObject, function(err1) { + s.checkTriggerThreshold(e, region, detectorObject, function(err2) { + if(!err1 && ! err2){ + detectorObject.doObjectDetection = (s.isAtleatOneDetectorPluginConnected && e.details.detector_use_detect_object === '1') + s.triggerEvent(detectorObject) + } + }) + }) + } + if(e.details.detector_noise_filter==='1'){ + if(!s.group[e.ke].mon[e.id].noiseFilterArray)s.group[e.ke].mon[e.id].noiseFilterArray = {} + var noiseFilterArray = s.group[e.ke].mon[e.id].noiseFilterArray + Object.keys(regions.notForPam).forEach(function(name){ + if(!noiseFilterArray[name])noiseFilterArray[name]=[]; + }) + s.group[e.ke].mon[e.id].pamDiff.on('diff', (data) => { + data.trigger.forEach(function(trigger){ + s.filterTheNoise(e,noiseFilterArray,regions,trigger,function(){ + s.createMatrixFromPamTrigger(trigger) + buildTriggerEvent(trigger) + }) + }) + }) + }else{ + s.group[e.ke].mon[e.id].pamDiff.on('diff', (data) => { + data.trigger.forEach(function(trigger){ + s.createMatrixFromPamTrigger(trigger) + buildTriggerEvent(trigger) + }) + }) + } } } @@ -164,17 +254,20 @@ module.exports = function(s,config){ theNoise = theNoise / noiseFilterArray[trigger.name].length; var triggerPercentWithoutNoise = trigger.percent - theNoise; if(triggerPercentWithoutNoise > regions.notForPam[trigger.name].sensitivity){ - callback(trigger) + callback(null,trigger) + }else{ + callback(true) } } - s.checkMaximumSensitivity = function(monitor, region, detectorObject, success) { + s.checkMaximumSensitivity = function(monitor, region, detectorObject, callback) { var logName = detectorObject.id + ':' + detectorObject.name var globalMaxSensitivity = parseInt(monitor.details.detector_max_sensitivity) || undefined var maxSensitivity = parseInt(region.max_sensitivity) || globalMaxSensitivity if (maxSensitivity === undefined || detectorObject.details.confidence <= maxSensitivity) { - success() + callback(null) } else { + callback(true) if (monitor.triggerTimer[detectorObject.name] !== undefined) { clearTimeout(monitor.triggerTimer[detectorObject.name].timeout) monitor.triggerTimer[detectorObject.name] = undefined @@ -182,10 +275,10 @@ module.exports = function(s,config){ } } - s.checkTriggerThreshold = function(monitor, region, detectorObject, success){ + s.checkTriggerThreshold = function(monitor, region, detectorObject, callback){ var threshold = parseInt(region.threshold) || globalThreshold if (threshold <= 1) { - success() + callback(null) } else { if (monitor.triggerTimer[detectorObject.name] === undefined) { monitor.triggerTimer[detectorObject.name] = { @@ -194,10 +287,11 @@ module.exports = function(s,config){ } } if (--monitor.triggerTimer[detectorObject.name].count == 0) { - success() + callback(null) clearTimeout(monitor.triggerTimer[detectorObject.name].timeout) monitor.triggerTimer[detectorObject.name] = undefined } else { + callback(true) var fps = parseFloat(monitor.details.detector_fps) || 2 if (monitor.triggerTimer[detectorObject.name].timeout !== null) clearTimeout(monitor.triggerTimer[detectorObject.name].timeout) @@ -207,4 +301,92 @@ module.exports = function(s,config){ } } } + s.mergePamTriggers = function(data){ + if(data.trigger.length > 1){ + var n = 0 + var sum = 0 + var name = [] + var matrices = [] + data.trigger.forEach(function(trigger){ + name.push(trigger.name + ' ('+trigger.percent+'%)') + ++n + sum += trigger.percent + s.createMatrixFromPamTrigger(trigger) + if(trigger.matrix)matrices.push(trigger.matrix) + }) + var average = sum / n + name = name.join(', ') + if(matrices.length === 0)matrices = null + var trigger = { + name: name, + percent: parseInt(average), + matrices: matrices, + merged: data.trigger + } + }else{ + var trigger = data.trigger[0] + s.createMatrixFromPamTrigger(trigger) + trigger.matrices = [trigger.matrix] + } + return trigger + } + s.isAtleastOneMatrixInRegion = function(regions,matrices,callback){ + var regionPolys = [] + var matrixPoints = [] + regions.forEach(function(region,n){ + var polyPoints = [] + region.points.forEach(function(point){ + polyPoints.push(new V(parseInt(point[0]),parseInt(point[1]))) + }) + regionPolys[n] = new P(new V(0,0), polyPoints) + }) + var collisions = [] + var foundInRegion = false + matrices.forEach(function(matrix){ + var matrixPoints = [ + new V(matrix.x,matrix.y), + new V(matrix.width,matrix.y), + new V(matrix.width,matrix.height), + new V(matrix.x,matrix.height) + ] + var matrixPoly = new P(new V(0,0), matrixPoints) + regionPolys.forEach(function(region,n){ + var response = new SAT.Response() + var collided = SAT.testPolygonPolygon(matrixPoly, region, response) + if(collided === true){ + collisions.push({ + matrix: matrix, + region: regions[n] + }) + foundInRegion = true + } + }) + }) + if(callback)callback(foundInRegion,collisions) + return foundInRegion + } + s.createMatrixFromPamTrigger = function(trigger){ + if( + trigger.minX && + trigger.maxX && + trigger.minY && + trigger.maxY + ){ + var coordinates = [ + {"x" : trigger.minX, "y" : trigger.minY}, + {"x" : trigger.maxX, "y" : trigger.minY}, + {"x" : trigger.maxX, "y" : trigger.maxY} + ] + var width = Math.sqrt( Math.pow(coordinates[1].x - coordinates[0].x, 2) + Math.pow(coordinates[1].y - coordinates[0].y, 2)); + var height = Math.sqrt( Math.pow(coordinates[2].x - coordinates[1].x, 2) + Math.pow(coordinates[2].y - coordinates[1].y, 2)) + trigger.matrix = { + x: coordinates[0].x, + y: coordinates[0].y, + width: width, + height: height, + tag: trigger.name + } + } + return trigger + } } diff --git a/libs/dropInEvents.js b/libs/dropInEvents.js new file mode 100644 index 0000000..d5f1790 --- /dev/null +++ b/libs/dropInEvents.js @@ -0,0 +1,208 @@ +var fs = require('fs') +var execSync = require('child_process').execSync +module.exports = function(s,config,lang,app,io){ + if(config.dropInEventServer === true){ + if(config.dropInEventDeleteFileAfterTrigger === undefined)config.dropInEventDeleteFileAfterTrigger = true + var authenticateUser = function(username,password,callback){ + var splitUsername = username.split('@') + if(splitUsername[1] !== 'Shinobi' && splitUsername[1] !== 'shinobi'){ + s.sqlQuery('SELECT ke,uid FROM Users WHERE mail=? AND (pass=? OR pass=?)',[ + username, + password, + s.createHash(password) + ],function(err,r){ + var user + if(r && r[0]){ + user = r[0] + } + callback(err,user) + }) + }else{ + s.sqlQuery('SELECT ke,uid FROM API WHERE code=? AND ke=?',[ + splitUsername[0], //code + password //ke + ],function(err,r){ + var apiKey + if(r && r[0]){ + apiKey = r[0] + } + callback(err,apiKey) + }) + } + } + var beforeMonitorsLoadedOnStartup = function(){ + if(!config.dropInEventsDir){ + config.dropInEventsDir = s.dir.streams + 'dropInEvents/' + } + s.dir.dropInEvents = s.checkCorrectPathEnding(config.dropInEventsDir) + //dropInEvents dir + if(!fs.existsSync(s.dir.dropInEvents)){ + fs.mkdirSync(s.dir.dropInEvents) + } + } + var getDropInEventDir = function(monitorConfig){ + var ke = monitorConfig.ke + var mid = monitorConfig.mid + var groupEventDropDir = s.dir.dropInEvents + ke + var monitorEventDropDir = groupEventDropDir + '/' + mid + '/' + return monitorEventDropDir + } + var onMonitorStop = function(monitorConfig){ + var ke = monitorConfig.ke + var mid = monitorConfig.mid + if(s.group[monitorConfig.ke].mon[monitorConfig.mid].dropInEventWatcher){ + s.group[monitorConfig.ke].mon[monitorConfig.mid].dropInEventWatcher.close() + delete(s.group[monitorConfig.ke].mon[monitorConfig.mid].dropInEventWatcher) + } + var monitorEventDropDir = getDropInEventDir(monitorConfig) + if(fs.existsSync(monitorEventDropDir))execSync('rm -rf ' + monitorEventDropDir) + } + var onMonitorInit = function(monitorConfig){ + onMonitorStop(monitorConfig) + var ke = monitorConfig.ke + var mid = monitorConfig.mid + var monitorEventDropDir = getDropInEventDir(monitorConfig) + var groupEventDropDir = s.dir.dropInEvents + ke + if(!fs.existsSync(groupEventDropDir)){ + fs.mkdirSync(groupEventDropDir) + } + var monitorEventDropDir = groupEventDropDir + '/' + mid + '/' + if(!fs.existsSync(monitorEventDropDir)){ + fs.mkdirSync(monitorEventDropDir) + } + var fileQueue = {} + s.group[monitorConfig.ke].mon[monitorConfig.mid].dropInEventFileQueue = fileQueue + var eventTrigger = function(eventType,filename){ + var filePath = monitorEventDropDir + filename + if(filename.indexOf('.jpg') > -1 || filename.indexOf('.jpeg') > -1){ + var snapPath = s.dir.streams + ke + '/' + mid + '/s.jpg' + fs.unlink(snapPath,function(err){ + fs.createReadStream(filePath).pipe(fs.createWriteStream(snapPath)) + s.triggerEvent({ + id: mid, + ke: ke, + details: { + confidence: 100, + name: filename, + plug: "dropInEvent", + reason: "dropInEvent" + } + }) + }) + }else{ + s.triggerEvent({ + id: mid, + ke: ke, + details: { + confidence: 100, + name: filename, + plug: "dropInEvent", + reason: "ftpServer" + } + }) + } + if(config.dropInEventDeleteFileAfterTrigger){ + setTimeout(function(){ + fs.unlink(filePath,function(err){ + + }) + },1000 * 60 * 5) + } + } + var directoryWatch = fs.watch(monitorEventDropDir,function(eventType,filename){ + if(fs.existsSync(monitorEventDropDir + filename)){ + clearTimeout(fileQueue[filename]) + fileQueue[filename] = setTimeout(function(){ + eventTrigger(eventType,filename) + },1200) + } + }) + s.group[monitorConfig.ke].mon[monitorConfig.mid].dropInEventWatcher = directoryWatch + } + // FTP Server + if(config.ftpServer === true){ + if(!config.ftpServerPort)config.ftpServerPort = 21 + if(!config.ftpServerUrl)config.ftpServerUrl = `ftp://0.0.0.0:${config.ftpServerPort}` + config.ftpServerUrl = config.ftpServerUrl.replace('{{PORT}}',config.ftpServerPort) + const FtpSrv = require('ftp-srv') + const ftpServer = new FtpSrv({ + url: config.ftpServerUrl, + // log:{trace:function(){},error:function(){},child:function(){},info:function(){},warn:function(){} + }) + + ftpServer.on('login', (data, resolve, reject) => { + var username = data.username + var password = data.password + authenticateUser(username,password,function(err,user){ + if(user){ + resolve({root: s.dir.dropInEvents + user.ke}) + }else{ + // reject(new Error('Failed Authorization')) + } + }) + }) + + ftpServer.listen().then(() => { + s.systemLog(`FTP Server running on port ${config.ftpServerPort}...`) + }).catch(function(err){ + s.systemLog(err) + }) + } + //add extensions + s.beforeMonitorsLoadedOnStartup(beforeMonitorsLoadedOnStartup) + s.onMonitorInit(onMonitorInit) + s.onMonitorStop(onMonitorStop) + } + // SMTP Server + // allow starting SMTP server without dropInEventServer + if(config.smtpServer === true){ + var SMTPServer = require("smtp-server").SMTPServer; + if(!config.smtpServerPort && (config.smtpServerSsl && config.smtpServerSsl.enabled !== false || config.ssl)){config.smtpServerPort = 465}else if(!config.smtpServerPort){config.smtpServerPort = 25} + var smtpOptions = { + onAuth(auth, session, callback) { + var username = auth.username + var password = auth.password + authenticateUser(username,password,function(err,user){ + if(user){ + callback(null, {user: user.ke}) + }else{ + callback(new Error(lang.failedLoginText2)) + } + }) + }, + onRcptTo(address, session, callback) { + var split = address.address.split('@') + var monitorId = split[0] + var ke = session.user + if(s.group[ke].mon_conf[monitorId] && s.group[ke].mon[monitorId].isStarted === true){ + s.triggerEvent({ + id: monitorId, + ke: ke, + details: { + confidence: 100, + name: address.address, + plug: "dropInEvent", + reason: "smtpServer" + } + }) + }else{ + return callback(new Error(lang['No Monitor Exists with this ID.'])) + } + callback() + } + } + if(config.smtpServerSsl && config.smtpServerSsl.enabled !== false || config.ssl && config.ssl.cert && config.ssl.key){ + var key = config.ssl.key || fs.readFileSync(config.smtpServerSsl.key) + var cert = config.ssl.cert || fs.readFileSync(config.smtpServerSsl.cert) + smtpOptions = Object.assign(smtpOptions,{ + secure: true, + key: config.ssl.key, + cert: config.ssl.cert + }) + } + var server = new SMTPServer(smtpOptions) + server.listen(config.smtpServerPort,function(){ + s.systemLog(`SMTP Server running on port ${config.smtpServerPort}...`) + }) + } +} diff --git a/libs/events.js b/libs/events.js index 9682fa7..13d6047 100644 --- a/libs/events.js +++ b/libs/events.js @@ -4,6 +4,25 @@ var exec = require('child_process').exec; var spawn = require('child_process').spawn; var request = require('request'); module.exports = function(s,config,lang){ + var addEventDetailsToString = function(eventData,string,addOps){ + //d = event data + if(!addOps)addOps = {} + var newString = string + '' + var d = Object.assign(eventData,addOps) + var detailString = s.stringJSON(d.details) + newString = newString + .replace(/{{TIME}}/g,d.currentTimestamp) + .replace(/{{REGION_NAME}}/g,d.details.name) + .replace(/{{SNAP_PATH}}/g,s.dir.streams+'/'+d.ke+'/'+d.id+'/s.jpg') + .replace(/{{MONITOR_ID}}/g,d.id) + .replace(/{{GROUP_KEY}}/g,d.ke) + .replace(/{{DETAILS}}/g,detailString) + if(d.details.confidence){ + newString = newString + .replace(/{{CONFIDENCE}}/g,d.details.confidence) + } + return newString + } s.filterEvents = function(x,d){ switch(x){ case'archive': @@ -36,15 +55,13 @@ module.exports = function(s,config,lang){ s.onEventTriggerBeforeFilterExtensions.forEach(function(extender){ extender(d,filter) }) - if(s.group[d.ke].mon[d.id].open){ - d.details.videoTime = s.group[d.ke].mon[d.id].open; - } var detailString = JSON.stringify(d.details); if(!s.group[d.ke]||!s.group[d.ke].mon[d.id]){ return s.systemLog(lang['No Monitor Found, Ignoring Request']) } d.mon=s.group[d.ke].mon_conf[d.id]; var currentConfig = s.group[d.ke].mon[d.id].details + var hasMatrices = (d.details.matrices && d.details.matrices.length > 0) //read filters if( currentConfig.use_detector_filters === '1' && @@ -160,7 +177,7 @@ module.exports = function(s,config,lang){ }) if(d.details.matrices && d.details.matrices.length === 0 || filter.halt === true){ return - }else if(d.details.matrices && d.details.matrices.length > 0){ + }else if(hasMatrices){ var reviewedMatrix = [] d.details.matrices.forEach(function(matrix){ if(matrix)reviewedMatrix.push(matrix) @@ -193,6 +210,16 @@ module.exports = function(s,config,lang){ return } } + // check if object should be in region + if(hasMatrices && currentConfig.detector_obj_region === '1'){ + var regions = s.group[d.ke].mon[d.id].parsedObjects.cords + var isMatrixInRegions = s.isAtleastOneMatrixInRegion(regions,d.details.matrices) + if(isMatrixInRegions){ + s.debugLog('Matrix in region!') + }else{ + return + } + } // check modified indifference if(filter.indifference !== false && d.details.confidence < parseFloat(filter.indifference)){ // fails indifference check for modified indifference @@ -209,13 +236,29 @@ module.exports = function(s,config,lang){ frame : s.group[d.ke].mon[d.id].lastJpegDetectorFrame }) }else{ + if(currentConfig.detector_multi_trigger === '1'){ + s.getCamerasForMultiTrigger(d.mon).forEach(function(monitor){ + if(monitor.mid !== d.id){ + s.triggerEvent({ + id: monitor.mid, + ke: monitor.ke, + details: { + confidence: 100, + name: "multiTrigger", + plug: d.details.plug, + reason: d.details.reason + } + }) + } + }) + } //save this detection result in SQL, only coords. not image. - if(filter.save && currentConfig.detector_save==='1'){ - s.sqlQuery('INSERT INTO Events (ke,mid,details) VALUES (?,?,?)',[d.ke,d.id,detailString]) + if(filter.save && currentConfig.detector_save === '1'){ + s.sqlQuery('INSERT INTO Events (ke,mid,details,time) VALUES (?,?,?,?)',[d.ke,d.id,detailString,new Date()]) } if(currentConfig.detector_notrigger === '1'){ var detector_notrigger_timeout - if(!currentConfig.detector_notrigger_timeout||currentConfig.detector_notrigger_timeout===''){ + if(!currentConfig.detector_notrigger_timeout||currentConfig.detector_notrigger_timeout === ''){ detector_notrigger_timeout = 10 } detector_notrigger_timeout = parseFloat(currentConfig.detector_notrigger_timeout)*1000*60; @@ -270,17 +313,7 @@ module.exports = function(s,config,lang){ }) if(filter.webhook && currentConfig.detector_webhook === '1'){ - var detector_webhook_url = currentConfig.detector_webhook_url - .replace(/{{TIME}}/g,d.currentTimestamp) - .replace(/{{REGION_NAME}}/g,d.details.name) - .replace(/{{SNAP_PATH}}/g,s.dir.streams+'/'+d.ke+'/'+d.id+'/s.jpg') - .replace(/{{MONITOR_ID}}/g,d.id) - .replace(/{{GROUP_KEY}}/g,d.ke) - .replace(/{{DETAILS}}/g,detailString) - if(d.details.confidence){ - detector_webhook_url = detector_webhook_url - .replace(/{{CONFIDENCE}}/g,d.details.confidence) - } + var detector_webhook_url = addEventDetailsToString(d,currentConfig.detector_webhook_url) request({url:detector_webhook_url,method:'GET',encoding:null},function(err,data){ if(err){ s.userLog(d,{type:lang["Event Webhook Error"],msg:{error:err,data:data}}) @@ -289,28 +322,8 @@ module.exports = function(s,config,lang){ } if(filter.command && currentConfig.detector_command_enable === '1' && !s.group[d.ke].mon[d.id].detector_command){ - var detector_command_timeout - if(!currentConfig.detector_command_timeout||currentConfig.detector_command_timeout===''){ - detector_command_timeout = 1000*60*10; - }else{ - detector_command_timeout = parseFloat(currentConfig.detector_command_timeout)*1000*60; - } - s.group[d.ke].mon[d.id].detector_command=setTimeout(function(){ - clearTimeout(s.group[d.ke].mon[d.id].detector_command); - delete(s.group[d.ke].mon[d.id].detector_command); - - },detector_command_timeout); - var detector_command = currentConfig.detector_command - .replace(/{{TIME}}/g,d.currentTimestamp) - .replace(/{{REGION_NAME}}/g,d.details.name) - .replace(/{{SNAP_PATH}}/g,s.dir.streams+'/'+d.ke+'/'+d.id+'/s.jpg') - .replace(/{{MONITOR_ID}}/g,d.id) - .replace(/{{GROUP_KEY}}/g,d.ke) - .replace(/{{DETAILS}}/g,detailString) - if(d.details.confidence){ - detector_command = detector_command - .replace(/{{CONFIDENCE}}/g,d.details.confidence) - } + s.createTimeout(s.group[d.ke].mon[d.id].detector_command,currentConfig.detector_command_timeout,10) + var detector_command = addEventDetailsToString(d,currentConfig.detector_command) exec(detector_command,{detached: true}) } } @@ -319,14 +332,18 @@ module.exports = function(s,config,lang){ s.tx(d.cx,'DETECTOR_'+d.ke+d.id); } s.createEventBasedRecording = function(d){ + d.mon = s.group[d.ke].mon_conf[d.id] var currentConfig = s.group[d.ke].mon[d.id].details + if(currentConfig.detector !== '1'){ + return + } var detector_timeout if(!currentConfig.detector_timeout||currentConfig.detector_timeout===''){ detector_timeout = 10 }else{ detector_timeout = parseFloat(currentConfig.detector_timeout) } - if(currentConfig.watchdog_reset !== '1' || !s.group[d.ke].mon[d.id].eventBasedRecording.timeout){ + if(currentConfig.watchdog_reset === '1' || !s.group[d.ke].mon[d.id].eventBasedRecording.timeout){ clearTimeout(s.group[d.ke].mon[d.id].eventBasedRecording.timeout) s.group[d.ke].mon[d.id].eventBasedRecording.timeout = setTimeout(function(){ s.group[d.ke].mon[d.id].eventBasedRecording.allowEnd = true @@ -336,40 +353,28 @@ module.exports = function(s,config,lang){ },detector_timeout * 1000 * 60) } if(!s.group[d.ke].mon[d.id].eventBasedRecording.process){ - if(!d.auth){ - d.auth = s.gid(60) - } - if(!s.api[d.auth]){ - s.api[d.auth] = { - system: 1, - ip: '0.0.0.0', - details: {}, - lang: lang - } - } s.group[d.ke].mon[d.id].eventBasedRecording.allowEnd = false; var runRecord = function(){ var filename = s.formattedTime()+'.mp4' - s.userLog(d,{type:"Traditional Recording",msg:"Started"}) + s.userLog(d,{type:lang["Traditional Recording"],msg:lang["Started"]}) //-t 00:'+s.timeObject(new Date(detector_timeout * 1000 * 60)).format('mm:ss')+' - s.group[d.ke].mon[d.id].eventBasedRecording.process = spawn(config.ffmpegDir,s.splitForFFPMEG(('-loglevel warning -analyzeduration 1000000 -probesize 1000000 -re -i http://'+config.ip+':'+config.port+'/'+d.auth+'/hls/'+d.ke+'/'+d.id+'/detectorStream.m3u8 -c:v copy -strftime 1 "'+s.getVideoDirectory(d.mon) + filename + '"'))) + s.group[d.ke].mon[d.id].eventBasedRecording.process = spawn(config.ffmpegDir,s.splitForFFPMEG(('-loglevel warning -analyzeduration 1000000 -probesize 1000000 -re -i "'+s.dir.streams+'/'+d.ke+'/'+d.id+'/detectorStream.m3u8" -c:v copy -strftime 1 "'+s.getVideoDirectory(d.mon) + filename + '"'))) var ffmpegError=''; var error s.group[d.ke].mon[d.id].eventBasedRecording.process.stderr.on('data',function(data){ - s.userLog(d,{type:"Traditional Recording",msg:data.toString()}) + s.userLog(d,{type:lang["Traditional Recording"],msg:data.toString()}) }) s.group[d.ke].mon[d.id].eventBasedRecording.process.on('close',function(){ if(!s.group[d.ke].mon[d.id].eventBasedRecording.allowEnd){ - s.userLog(d,{type:"Traditional Recording",msg:"Detector Recording Process Exited Prematurely. Restarting."}) + s.userLog(d,{type:lang["Traditional Recording"],msg:lang["Detector Recording Process Exited Prematurely. Restarting."]}) runRecord() return } s.insertCompletedVideo(d.mon,{ file : filename }) - s.userLog(d,{type:"Traditional Recording",msg:"Detector Recording Complete"}) - delete(s.api[d.auth]) - s.userLog(d,{type:"Traditional Recording",msg:'Clear Recorder Process'}) + s.userLog(d,{type:lang["Traditional Recording"],msg:lang["Detector Recording Complete"]}) + s.userLog(d,{type:lang["Traditional Recording"],msg:lang["Clear Recorder Process"]}) delete(s.group[d.ke].mon[d.id].eventBasedRecording.process) clearTimeout(s.group[d.ke].mon[d.id].eventBasedRecording.timeout) delete(s.group[d.ke].mon[d.id].eventBasedRecording.timeout) @@ -385,5 +390,12 @@ module.exports = function(s,config,lang){ s.group[e.ke].mon[e.id].eventBasedRecording.allowEnd = true; s.group[e.ke].mon[e.id].eventBasedRecording.process.kill('SIGTERM'); } + // var stackedProcesses = s.group[e.ke].mon[e.id].eventBasedRecording.stackable + // Object.keys(stackedProcesses).forEach(function(key){ + // var item = stackedProcesses[key] + // clearTimeout(item.timeout) + // item.allowEnd = true; + // item.process.kill('SIGTERM'); + // }) } } diff --git a/libs/extenders.js b/libs/extenders.js index 6278fda..8059c79 100644 --- a/libs/extenders.js +++ b/libs/extenders.js @@ -1,5 +1,15 @@ module.exports = function(s,config){ ////// USER ////// + s.onSocketAuthenticationExtensions = [] + s.onSocketAuthentication = function(callback){ + s.onSocketAuthenticationExtensions.push(callback) + } + // + s.loadGroupExtensions = [] + s.loadGroupExtender = function(callback){ + s.loadGroupExtensions.push(callback) + } + // s.loadGroupAppExtensions = [] s.loadGroupAppExtender = function(callback){ s.loadGroupAppExtensions.push(callback) @@ -30,6 +40,11 @@ module.exports = function(s,config){ s.onTwoFactorAuthCodeNotificationExtensions.push(callback) } // + s.onStalePurgeLockExtensions = [] + s.onStalePurgeLock = function(callback){ + s.onStalePurgeLockExtensions.push(callback) + } + // s.cloudDiskUseStartupExtensions = {} ////// EVENTS ////// @@ -51,8 +66,81 @@ module.exports = function(s,config){ s.onMonitorInit = function(callback){ s.onMonitorInitExtensions.push(callback) } + // + s.onMonitorStartExtensions = [] + s.onMonitorStart = function(callback){ + s.onMonitorStartExtensions.push(callback) + } + // + s.onMonitorStopExtensions = [] + s.onMonitorStop = function(callback){ + s.onMonitorStopExtensions.push(callback) + } + // + s.onMonitorSaveExtensions = [] + s.onMonitorSave = function(callback){ + s.onMonitorSaveExtensions.push(callback) + } + // + s.onMonitorUnexpectedExitExtensions = [] + s.onMonitorUnexpectedExit = function(callback){ + s.onMonitorUnexpectedExitExtensions.push(callback) + } + // s.onDetectorNoTriggerTimeoutExtensions = [] s.onDetectorNoTriggerTimeout = function(callback){ s.onDetectorNoTriggerTimeoutExtensions.push(callback) } + // + s.onFfmpegCameraStringCreationExtensions = [] + s.onFfmpegCameraStringCreation = function(callback){ + s.onFfmpegCameraStringCreationExtensions.push(callback) + } + // + s.onMonitorPingFailedExtensions = [] + s.onMonitorPingFailed = function(callback){ + s.onMonitorPingFailedExtensions.push(callback) + } + // + s.onMonitorDiedExtensions = [] + s.onMonitorDied = function(callback){ + s.onMonitorDiedExtensions.push(callback) + } + + ///////// SYSTEM //////// + s.onProcessReadyExtensions = [] + s.onProcessReady = function(callback){ + s.onProcessReadyExtensions.push(callback) + } + // + s.onProcessExitExtensions = [] + s.onProcessExit = function(callback){ + s.onProcessExitExtensions.push(callback) + } + // + s.onBeforeDatabaseLoadExtensions = [] + s.onBeforeDatabaseLoad = function(callback){ + s.onBeforeDatabaseLoadExtensions.push(callback) + } + // + s.onFFmpegLoadedExtensions = [] + s.onFFmpegLoaded = function(callback){ + s.onFFmpegLoadedExtensions.push(callback) + } + // + s.beforeMonitorsLoadedOnStartupExtensions = [] + s.beforeMonitorsLoadedOnStartup = function(callback){ + s.beforeMonitorsLoadedOnStartupExtensions.push(callback) + } + // + s.onWebSocketConnectionExtensions = [] + s.onWebSocketConnection = function(callback){ + s.onWebSocketConnectionExtensions.push(callback) + } + // + s.onWebSocketDisconnectionExtensions = [] + s.onWebSocketDisconnection = function(callback){ + s.onWebSocketDisconnectionExtensions.push(callback) + } + // } diff --git a/libs/ffmpeg.js b/libs/ffmpeg.js index 409156e..e5b7bad 100644 --- a/libs/ffmpeg.js +++ b/libs/ffmpeg.js @@ -104,6 +104,9 @@ module.exports = function(s,config,onFinish){ ffmpeg.completeCheck = function(){ ffmpeg.checkVersion(function(){ ffmpeg.checkHwAccelMethods(function(){ + s.onFFmpegLoadedExtensions.forEach(function(extender){ + extender(ffmpeg) + }) onFinish(ffmpeg) }) }) @@ -132,7 +135,9 @@ module.exports = function(s,config,onFinish){ string += ' -map '+v.map }) }else{ - string += ' -map 0:0' + var primaryMap = '0:0' + if(e.details.primary_input && e.details.primary_input !== '')primaryMap = e.details.primary_input + string += ' -map ' + primaryMap } } return string; @@ -379,7 +384,16 @@ module.exports = function(s,config,onFinish){ //x = temporary values //check if CUDA is enabled e.isStreamer = (e.type === 'dashcam'|| e.type === 'socket') - if(e.details.accelerator === '1' && e.details.hwaccel === 'cuvid' && e.details.hwaccel_vcodec === ('h264_cuvid' || 'hevc_cuvid' || 'mjpeg_cuvid' || 'mpeg4_cuvid')){ + e.coProcessor = false + if( + e.details.use_coprocessor === '1' && + e.details.accelerator === '1' && + e.isStreamer === false && + (!e.details.input_maps || e.details.input_maps.length === 0) && + (e.details.snap === '1' || e.details.stream_type === 'mjpeg' || e.details.stream_type === 'b64' || e.details.detector === '1') + ){ + e.coProcessor = true + }else if(e.details.accelerator === '1' && e.details.hwaccel === 'cuvid' && e.details.hwaccel_vcodec === ('h264_cuvid' || 'hevc_cuvid' || 'mjpeg_cuvid' || 'mpeg4_cuvid')){ e.cudaEnabled = true } // @@ -560,9 +574,11 @@ module.exports = function(s,config,onFinish){ x.pipe+=x.preset_stream+x.stream_acodec+x.stream_vcodec+' -f hls'+x.cust_stream+' -hls_time '+x.hls_time+' -hls_list_size '+x.hls_list_size+' -start_number 0 -hls_allow_cache 0 -hls_flags +delete_segments+omit_endlist "'+e.sdir+'s.m3u8"'; break; case'mjpeg': + if(e.coProcessor === false){ if(e.details.stream_quality && e.details.stream_quality !== '')x.cust_stream+=' -q:v '+e.details.stream_quality; if(x.dimensions && x.cust_stream.indexOf('-s ')===-1){x.cust_stream+=' -s '+x.dimensions} x.pipe+=' -an -c:v mjpeg -f mpjpeg -boundary_tag shinobi'+x.cust_stream+x.stream_video_filters+' pipe:1'; + } break; case'h265': x.cust_stream+=' -movflags +frag_keyframe+empty_moov+default_base_moof -metadata title="Shinobi H.265 Stream" -reset_timestamps 1' @@ -575,9 +591,11 @@ module.exports = function(s,config,onFinish){ x.pipe+=' -f hevc'+x.stream_acodec+x.stream_vcodec+x.cust_stream+' pipe:1'; break; case'b64':case'':case undefined:case null://base64 - if(e.details.stream_quality && e.details.stream_quality !== '')x.cust_stream+=' -q:v '+e.details.stream_quality; - if(x.dimensions && x.cust_stream.indexOf('-s ')===-1){x.cust_stream+=' -s '+x.dimensions} - x.pipe+=' -an -c:v mjpeg -f image2pipe'+x.cust_stream+x.stream_video_filters+' pipe:1'; + if(e.coProcessor === false){ + if(e.details.stream_quality && e.details.stream_quality !== '')x.cust_stream+=' -q:v '+e.details.stream_quality; + if(x.dimensions && x.cust_stream.indexOf('-s ')===-1){x.cust_stream+=' -s '+x.dimensions} + x.pipe+=' -an -c:v mjpeg -f image2pipe'+x.cust_stream+x.stream_video_filters+' pipe:1'; + } break; default: x.pipe='' @@ -585,11 +603,12 @@ module.exports = function(s,config,onFinish){ } if(e.details.stream_channels){ e.details.stream_channels.forEach(function(v,n){ + // if(v.stream_type === 'mjpeg')e.coProcessor = true; x.pipe += s.createStreamChannel(e,n+config.pipeAddition,v) }) } //api - snapshot bin/ cgi.bin (JPEG Mode) - if(e.details.snap === '1'){ + if(e.details.snap === '1' && e.coProcessor === false){ if(e.details.input_map_choices&&e.details.input_map_choices.snap){ //add input feed map x.pipe += s.createFFmpegMap(e,e.details.input_map_choices.snap) @@ -628,7 +647,7 @@ module.exports = function(s,config,onFinish){ x.dimensions = e.details.stream_scale_x+'x'+e.details.stream_scale_y; } //record - segmenting - x.segment=' -f segment -segment_atclocktime 1 -reset_timestamps 1 -strftime 1 -segment_list pipe:2 -segment_time '+(60*e.cutoff)+' "'+e.dir+'%Y-%m-%dT%H-%M-%S.'+e.ext+'"'; + x.segment=' -f segment -segment_format_options movflags=faststart+frag_keyframe+empty_moov -segment_atclocktime 1 -reset_timestamps 1 -strftime 1 -segment_list pipe:2 -segment_time '+(60*e.cutoff)+' "'+e.dir+'%Y-%m-%dT%H-%M-%S.'+e.ext+'"'; //record - set defaults for extension, video quality switch(e.ext){ case'mp4': @@ -732,40 +751,67 @@ module.exports = function(s,config,onFinish){ x.record_string+=x.vcodec+x.record_fps+x.record_video_filters+x.record_dimensions+x.segment; } } + ffmpeg.buildAudioDetector = function(e,x){ + if(e.details.detector_audio === '1'){ + if(e.details.input_map_choices&&e.details.input_map_choices.detector_audio){ + //add input feed map + x.pipe += s.createFFmpegMap(e,e.details.input_map_choices.detector_audio) + }else{ + x.pipe += ' -map 0:a' + } + x.pipe += ' -acodec pcm_s16le -f s16le -ac 1 -ar 16000 pipe:6' + } + } ffmpeg.buildMainDetector = function(e,x){ //e = monitor object //x = temporary values x.cust_detect = ' ' //detector - plugins, motion - if(e.details.detector === '1' && e.details.detector_send_frames === '1'){ - if(e.details.input_map_choices&&e.details.input_map_choices.detector){ + var sendFramesGlobally = (e.details.detector_send_frames === '1') + var sendFramesToObjectDetector = (e.details.detector_send_frames_object !== '0' && e.details.detector_use_detect_object === '1') + if(e.details.detector === '1' && (sendFramesGlobally || sendFramesToObjectDetector) && e.coProcessor === false){ + if(sendFramesGlobally && e.details.input_map_choices && e.details.input_map_choices.detector){ //add input feed map x.pipe += s.createFFmpegMap(e,e.details.input_map_choices.detector) } - if(!e.details.detector_fps||e.details.detector_fps===''){e.details.detector_fps=2} - if(e.details.detector_scale_x&&e.details.detector_scale_x!==''&&e.details.detector_scale_y&&e.details.detector_scale_y!==''){x.dratio=' -s '+e.details.detector_scale_x+'x'+e.details.detector_scale_y}else{x.dratio=' -s 320x240'} + if(!e.details.detector_fps || e.details.detector_fps === ''){x.detector_fps = 2}else{x.detector_fps = parseInt(e.details.detector_fps)} + if(e.details.detector_scale_x && e.details.detector_scale_x !== '' && e.details.detector_scale_y && e.details.detector_scale_y !== ''){x.dratio=' -s '+e.details.detector_scale_x+'x'+e.details.detector_scale_y}else{x.dratio=' -s 320x240'} if(e.details.cust_detect&&e.details.cust_detect!==''){x.cust_detect+=e.details.cust_detect;} - x.detector_vf = ['fps='+e.details.detector_fps] + if(sendFramesGlobally)x.pipe += ' -r ' + x.detector_fps + x.dratio + x.cust_detect + x.detector_vf = [] if(e.cudaEnabled){ x.detector_vf.push('hwdownload,format=nv12') } - x.detector_vf = '-vf "'+x.detector_vf.join(',')+'"' - if(e.details.detector_pam==='1'){ - if(e.cudaEnabled){ + if(sendFramesGlobally && x.detector_vf.length > 0)x.pipe += ' -vf "'+x.detector_vf.join(',')+'"' + + var h264Output = ' -q:v 1 -an -c:v libx264 -f hls -tune zerolatency -g 1 -hls_time 2 -hls_list_size 3 -start_number 0 -live_start_index 3 -hls_allow_cache 0 -hls_flags +delete_segments+omit_endlist "'+e.sdir+'detectorStreamX.m3u8"' + if(e.details.detector_pam === '1'){ + if(sendFramesGlobally && e.cudaEnabled){ x.pipe += ' -vf "hwdownload,format=nv12"' } - x.pipe+=' -an -c:v pam -pix_fmt gray -f image2pipe -r '+e.details.detector_fps+x.cust_detect+x.dratio+' pipe:3' + if(sendFramesGlobally)x.pipe += ' -an -c:v pam -pix_fmt gray -f image2pipe pipe:3' if(e.details.detector_use_detect_object === '1'){ //for object detection x.pipe += s.createFFmpegMap(e,e.details.input_map_choices.detector) - x.pipe += ' -f singlejpeg '+x.detector_vf+x.cust_detect+x.dratio+' pipe:4'; + if(e.details.detector_scale_x_object&&e.details.detector_scale_x_object!==''&&e.details.detector_scale_y_object&&e.details.detector_scale_y_object!==''){x.dobjratio=' -s '+e.details.detector_scale_x_object+'x'+e.details.detector_scale_y_object}else{x.dobjratio=x.dratio} + x.pipe += ' -r ' + x.detector_fps + x.dobjratio + x.cust_detect + if(e.details.detector_h264 === '1'){ + x.pipe += h264Output + }else{ + x.pipe += ' -an -f singlejpeg pipe:4' + } + } + }else if(sendFramesGlobally){ + if(e.details.detector_h264 === '1'){ + x.pipe += h264Output + }else{ + x.pipe += ' -an -f singlejpeg pipe:3' } - }else{ - x.pipe+=' -f image2pipe '+x.detector_vf+x.cust_detect+x.dratio+' pipe:3'; } } //Traditional Recording Buffer if(e.details.detector=='1'&&e.details.detector_trigger=='1'&&e.details.detector_record_method==='sip'){ + if(e.details.cust_sip_record && e.details.cust_sip_record !== ''){x.pipe += ' ' + e.details.cust_sip_record} if(e.details.input_map_choices&&e.details.input_map_choices.detector_sip_buffer){ //add input feed map x.pipe += s.createFFmpegMap(e,e.details.input_map_choices.detector_sip_buffer) @@ -809,7 +855,6 @@ module.exports = function(s,config,onFinish){ if(!e.details.detector_buffer_hls_list_size||e.details.detector_buffer_hls_list_size===''){e.details.detector_buffer_hls_list_size='4'} if(!e.details.detector_buffer_start_number||e.details.detector_buffer_start_number===''){e.details.detector_buffer_start_number='0'} if(!e.details.detector_buffer_live_start_index||e.details.detector_buffer_live_start_index===''){e.details.detector_buffer_live_start_index='-3'} - if(e.details.detector_buffer_vcodec.indexOf('_vaapi')>-1){ if(x.hwaccel.indexOf('-vaapi_device')>-1){ x.detector_buffer_filters.push('format=nv12') @@ -830,7 +875,13 @@ module.exports = function(s,config,onFinish){ if(x.detector_buffer_filters.length>0){ x.pipe+=' -vf '+x.detector_buffer_filters.join(',') } - x.pipe+=x.detector_buffer_fps+x.detector_buffer_acodec+' -c:v '+e.details.detector_buffer_vcodec+' -f hls -tune '+e.details.detector_buffer_tune+' -g '+e.details.detector_buffer_g+' -hls_time '+e.details.detector_buffer_hls_time+' -hls_list_size '+e.details.detector_buffer_hls_list_size+' -start_number '+e.details.detector_buffer_start_number+' -live_start_index '+e.details.detector_buffer_live_start_index+' -hls_allow_cache 0 -hls_flags +delete_segments+omit_endlist "'+e.sdir+'detectorStream.m3u8"' + x.pipe += x.detector_buffer_fps+x.detector_buffer_acodec+' -c:v '+e.details.detector_buffer_vcodec+' -f hls -tune '+e.details.detector_buffer_tune+' -g '+e.details.detector_buffer_g+' -hls_time '+e.details.detector_buffer_hls_time+' -hls_list_size '+e.details.detector_buffer_hls_list_size+' -start_number '+e.details.detector_buffer_start_number+' -live_start_index '+e.details.detector_buffer_live_start_index+' -hls_allow_cache 0 -hls_flags +delete_segments+omit_endlist "'+e.sdir+'detectorStream.m3u8"' + } + } + ffmpeg.buildCoProcessorFeed = function(e,x){ + if(e.coProcessor === true){ + // the coProcessor ffmpeg consumes this HLS stream (no audio, frames only) + x.pipe += ' -q:v 1 -an -c:v copy -f hls -tune zerolatency -g 1 -hls_time 2 -hls_list_size 3 -start_number 0 -live_start_index 3 -hls_allow_cache 0 -hls_flags +delete_segments+omit_endlist "'+e.sdir+'coProcessor.m3u8"' } } ffmpeg.assembleMainPieces = function(e,x){ @@ -849,6 +900,10 @@ module.exports = function(s,config,onFinish){ case'mjpeg': x.ffmpegCommandString += ' -reconnect 1 -f mjpeg'+x.cust_input+x.hwaccel+' -i "'+e.url+'"'; break; + case'rtmp': + if(!e.details.rtmp_key)e.details.rtmp_key = '' + x.ffmpegCommandString += x.cust_input+x.hwaccel+` -i "rtmp://127.0.0.1:1935/${e.ke + '_' + e.mid + '_' + e.details.rtmp_key}"`; + break; case'h264':case'hls':case'mp4': x.ffmpegCommandString += x.cust_input+x.hwaccel+' -i "'+e.url+'"'; break; @@ -883,7 +938,12 @@ module.exports = function(s,config,onFinish){ ffmpeg.buildMainInput(e,x) ffmpeg.buildMainStream(e,x) ffmpeg.buildMainRecording(e,x) + ffmpeg.buildAudioDetector(e,x) ffmpeg.buildMainDetector(e,x) + ffmpeg.buildCoProcessorFeed(e,x) + s.onFfmpegCameraStringCreationExtensions.forEach(function(extender){ + extender(e,x) + }) ffmpeg.assembleMainPieces(e,x) ffmpeg.createPipeArray(e,x) //hold ffmpeg command for log stream @@ -895,9 +955,9 @@ module.exports = function(s,config,onFinish){ } if(!config.ffmpegDir){ ffmpeg.checkForWindows(function(){ - ffmpeg.checkForUnix(function(){ - ffmpeg.checkForFfbinary(function(){ - ffmpeg.checkForNpmStatic(function(){ + ffmpeg.checkForFfbinary(function(){ + ffmpeg.checkForNpmStatic(function(){ + ffmpeg.checkForUnix(function(){ console.log('No FFmpeg found.') }) }) diff --git a/libs/ffmpegCoProcessor.js b/libs/ffmpegCoProcessor.js new file mode 100644 index 0000000..6010cbe --- /dev/null +++ b/libs/ffmpegCoProcessor.js @@ -0,0 +1,210 @@ +var spawn = require('child_process').spawn; +module.exports = function(s,config,lang,ffmpeg){ + ffmpeg.buildCoProcessorInput = function(e,x){ + if(e.details.userLoglevel&&e.details.userLoglevel!==''){x.loglevel='-loglevel '+e.details.userLoglevel;}else{x.loglevel='-loglevel error'} + x.input = x.loglevel+' -re -i '+e.sdir+'coProcessor.m3u8' + } + ffmpeg.buildCoProcessorStream = function(e,x){ + x.stream_video_filters = [] + //stream - timestamp + if(e.details.stream_timestamp&&e.details.stream_timestamp=="1"&&e.details.vcodec!=='copy'){ + //font + if(e.details.stream_timestamp_font&&e.details.stream_timestamp_font!==''){x.stream_timestamp_font=e.details.stream_timestamp_font}else{x.stream_timestamp_font='/usr/share/fonts/truetype/freefont/FreeSans.ttf'} + //position x + if(e.details.stream_timestamp_x&&e.details.stream_timestamp_x!==''){x.stream_timestamp_x=e.details.stream_timestamp_x}else{x.stream_timestamp_x='(w-tw)/2'} + //position y + if(e.details.stream_timestamp_y&&e.details.stream_timestamp_y!==''){x.stream_timestamp_y=e.details.stream_timestamp_y}else{x.stream_timestamp_y='0'} + //text color + if(e.details.stream_timestamp_color&&e.details.stream_timestamp_color!==''){x.stream_timestamp_color=e.details.stream_timestamp_color}else{x.stream_timestamp_color='white'} + //box color + if(e.details.stream_timestamp_box_color&&e.details.stream_timestamp_box_color!==''){x.stream_timestamp_box_color=e.details.stream_timestamp_box_color}else{x.stream_timestamp_box_color='0x00000000@1'} + //text size + if(e.details.stream_timestamp_font_size&&e.details.stream_timestamp_font_size!==''){x.stream_timestamp_font_size=e.details.stream_timestamp_font_size}else{x.stream_timestamp_font_size='10'} + + x.stream_video_filters.push('drawtext=fontfile='+x.stream_timestamp_font+':text=\'%{localtime}\':x='+x.stream_timestamp_x+':y='+x.stream_timestamp_y+':fontcolor='+x.stream_timestamp_color+':box=1:boxcolor='+x.stream_timestamp_box_color+':fontsize='+x.stream_timestamp_font_size); + } + //stream - watermark for -vf + if(e.details.stream_watermark&&e.details.stream_watermark=="1"&&e.details.stream_watermark_location&&e.details.stream_watermark_location!==''){ + switch(e.details.stream_watermark_position){ + case'tl'://top left + x.stream_watermark_position='10:10' + break; + case'tr'://top right + x.stream_watermark_position='main_w-overlay_w-10:10' + break; + case'bl'://bottom left + x.stream_watermark_position='10:main_h-overlay_h-10' + break; + default://bottom right + x.stream_watermark_position='(main_w-overlay_w-10)/2:(main_h-overlay_h-10)/2' + break; + } + x.stream_video_filters.push('movie='+e.details.stream_watermark_location+'[watermark],[in][watermark]overlay='+x.stream_watermark_position+'[out]'); + } + //stream - rotation + if(e.details.rotate_stream&&e.details.rotate_stream!==""&&e.details.rotate_stream!=="no"&&e.details.stream_vcodec!=='copy'){ + x.stream_video_filters.push('transpose='+e.details.rotate_stream); + } + if(e.details.svf&&e.details.svf!==''){ + x.stream_video_filters.push(e.details.svf) + } + if(x.stream_video_filters.length>0){ + x.stream_video_filters=' -vf '+x.stream_video_filters.join(',') + }else{ + x.stream_video_filters='' + } + if(e.details.cust_stream&&e.details.cust_stream!==''){x.cust_stream=' '+e.details.cust_stream}else{x.cust_stream=''} + if(e.details.stream_fps&&e.details.stream_fps!==''){x.stream_fps=' -r '+e.details.stream_fps}else{x.stream_fps=''} + if(e.details.stream_vcodec !== 'copy' || e.details.stream_type === 'mjpeg' || e.details.stream_type === 'b64'){ + x.cust_stream += x.stream_fps + } + switch(e.details.stream_type){ + case'mjpeg': + if(e.details.stream_quality && e.details.stream_quality !== '')x.cust_stream+=' -q:v '+e.details.stream_quality; + if(x.dimensions && x.cust_stream.indexOf('-s ')===-1){x.cust_stream+=' -s '+x.dimensions} + x.pipe += ' -an -c:v mjpeg -f mpjpeg -boundary_tag shinobi'+x.cust_stream+x.stream_video_filters+' pipe:1'; + break; + case'b64':case'':case undefined:case null://base64 + if(e.details.stream_quality && e.details.stream_quality !== '')x.cust_stream+=' -q:v '+e.details.stream_quality; + if(x.dimensions && x.cust_stream.indexOf('-s ')===-1){x.cust_stream+=' -s '+x.dimensions} + x.pipe += ' -an -c:v mjpeg -f image2pipe'+x.cust_stream+x.stream_video_filters+' pipe:1'; + break; + } + } + ffmpeg.buildCoProcessorDetector = function(e,x){ + //detector frames + x.cust_detect=' ' + if(e.details.detector === '1'){ + if(e.details.detector_fps && e.details.detector_fps !== ''){ + x.detector_fps = e.details.detector_fps + }else{ + x.detector_fps = '2' + } + if(e.details.detector_scale_x && e.details.detector_scale_x !== '' && e.details.detector_scale_y && e.details.detector_scale_y !== ''){ + x.dratio=' -s '+e.details.detector_scale_x+'x'+e.details.detector_scale_y + }else{ + x.dratio=' -s 320x240' + } + + if(e.details.cust_detect&&e.details.cust_detect!==''){x.cust_detect+=e.details.cust_detect;} + if(e.details.detector_pam==='1'){ + x.pipe += ' -an -c:v pam -pix_fmt gray -f image2pipe -r '+x.detector_fps+x.cust_detect+x.dratio+' pipe:3' + if(e.details.detector_use_detect_object === '1'){ + if(e.details.detector_use_motion === '1'){ + if(e.details.detector_scale_x_object && e.details.detector_scale_x_object !== '' && e.details.detector_scale_y_object && e.details.detector_scale_y_object !== ''){ + x.dratio=' -s '+e.details.detector_scale_x_object+'x'+e.details.detector_scale_y_object + } + if(e.details.detector_fps_object && e.details.detector_fps_object !== ''){ + x.detector_fps = e.details.detector_fps_object + } + } + //for object detection + x.pipe += s.createFFmpegMap(e,e.details.input_map_choices.detector) + x.pipe += ' -f singlejpeg -vf fps='+x.detector_fps+x.cust_detect+x.dratio+' pipe:4'; + } + }else{ + x.pipe+=' -f singlejpeg -vf fps='+x.detector_fps+x.cust_detect+x.dratio+' pipe:3'; + } + } + } + ffmpeg.buildCoProcessorJpegApi = function(e,x){ + //snapshot frames + if(e.details.snap === '1'){ + if(!e.details.snap_fps || e.details.snap_fps === ''){e.details.snap_fps = 1} + if(e.details.snap_vf && e.details.snap_vf !== ''){x.snap_vf=' -vf '+e.details.snap_vf}else{x.snap_vf=''} + if(e.details.snap_scale_x && e.details.snap_scale_x !== '' && e.details.snap_scale_y && e.details.snap_scale_y !== ''){x.snap_ratio = ' -s '+e.details.snap_scale_x+'x'+e.details.snap_scale_y}else{x.snap_ratio=''} + if(e.details.cust_snap && e.details.cust_snap !== ''){x.cust_snap = ' '+e.details.cust_snap}else{x.cust_snap=''} + x.pipe += ' -update 1 -r '+e.details.snap_fps+x.cust_snap+x.snap_ratio+x.snap_vf+' "'+e.sdir+'s.jpg" -y'; + } + } + ffmpeg.buildCoProcessorPipeArray = function(e,x){ + x.stdioPipes = []; + var times = config.pipeAddition; + if(e.details.stream_channels){ + times+=e.details.stream_channels.length + } + for(var i=0; i < times; i++){ + x.stdioPipes.push('pipe') + } + } + s.ffmpegCoProcessor = function(e){ + if(e.coProcessor === false)return; + var x = {} + x.pipe = '' + ffmpeg.buildCoProcessorInput(e,x) + ffmpeg.buildCoProcessorStream(e,x) + ffmpeg.buildCoProcessorDetector(e,x) + ffmpeg.buildCoProcessorJpegApi(e,x) + ffmpeg.buildCoProcessorPipeArray(e,x) + var commandString = x.input + x.pipe + if(commandString === x.input){ + return false + } + s.group[e.ke].mon[e.mid].coProcessorCmd = commandString + return spawn(config.ffmpegDir,s.splitForFFPMEG((commandString).replace(/\s+/g,' ').trim()),{detached: true,stdio:x.stdioPipes}) + } + s.coSpawnLauncher = function(e){ + if(s.group[e.ke].mon[e.id].isStarted === true && e.coProcessor === true){ + s.coSpawnClose(e) + s.group[e.ke].mon[e.id].coSpawnProcessor = s.ffmpegCoProcessor(e) + if(s.group[e.ke].mon[e.id].coSpawnProcessor === false){ + return + } + s.userLog(e,{type:lang['coProcessor Started'],msg:{msg:lang.coProcessorTextStarted,cmd:s.group[e.ke].mon[e.id].coProcessorCmd}}); + s.group[e.ke].mon[e.id].coSpawnProcessorExit = function(){ + s.userLog(e,{type:lang['coProcess Unexpected Exit'],msg:{msg:lang['coProcess Crashed for Monitor']+' : '+e.id,cmd:s.group[e.ke].mon[e.id].coProcessorCmd}}); + setTimeout(function(){ + s.coSpawnLauncher(e) + },2000) + } + s.group[e.ke].mon[e.id].coSpawnProcessor.on('end',s.group[e.ke].mon[e.id].coSpawnProcessorExit) + s.group[e.ke].mon[e.id].coSpawnProcessor.on('exit',s.group[e.ke].mon[e.id].coSpawnProcessorExit) + var checkLog = function(d,x){return d.indexOf(x)>-1;} + s.group[e.ke].mon[e.id].coSpawnProcessor.stderr.on('data',function(d){ + d=d.toString(); + switch(true){ + case checkLog(d,'deprecated pixel format used'): + case checkLog(d,'[hls @'): + case checkLog(d,'Past duration'): + case checkLog(d,'Last message repeated'): + case checkLog(d,'pkt->duration = 0'): + case checkLog(d,'Non-monotonous DTS'): + case checkLog(d,'NULL @'): + return + break; + } + s.userLog(e,{type:lang.coProcessor,msg:d}); + }) + if(e.frame_to_stream){ + s.group[e.ke].mon[e.id].coSpawnProcessor.stdout.on('data',e.frame_to_stream) + } + if(e.details.detector === '1'){ + s.ocvTx({f:'init_monitor',id:e.id,ke:e.ke}) + //frames from motion detect + if(e.details.detector_pam === '1'){ + s.createPamDiffEngine(e) + s.group[e.ke].mon[e.id].coSpawnProcessor.stdio[3].pipe(s.group[e.ke].mon[e.id].p2p).pipe(s.group[e.ke].mon[e.id].pamDiff) + if(e.details.detector_use_detect_object === '1'){ + s.group[e.ke].mon[e.id].coSpawnProcessor.stdio[4].on('data',function(d){ + s.group[e.ke].mon[e.id].lastJpegDetectorFrame = d + }) + } + }else if(s.isAtleatOneDetectorPluginConnected){ + s.group[e.ke].mon[e.id].coSpawnProcessor.stdio[3].on('data',function(d){ + s.ocvTx({f:'frame',mon:s.group[e.ke].mon_conf[e.id].details,ke:e.ke,id:e.id,time:s.formattedTime(),frame:d}); + }) + } + } + } + } + s.coSpawnClose = function(e){ + if(s.group[e.ke].mon[e.id].coSpawnProcessor){ + s.group[e.ke].mon[e.id].coSpawnProcessor.removeListener('end',s.group[e.ke].mon[e.id].coSpawnProcessorExit); + s.group[e.ke].mon[e.id].coSpawnProcessor.removeListener('exit',s.group[e.ke].mon[e.id].coSpawnProcessorExit); + s.group[e.ke].mon[e.id].coSpawnProcessor.stdin.pause() + s.group[e.ke].mon[e.id].coSpawnProcessor.kill() + delete(s.group[e.ke].mon[e.id].coSpawnProcessor) + s.userLog(e,{type:lang['coProcessor Stopped'],msg:{msg:lang.coProcessorTextStopped+' : '+e.id}}); + } + } +} diff --git a/libs/language.js b/libs/language.js index 93fbe72..f58232d 100644 --- a/libs/language.js +++ b/libs/language.js @@ -18,42 +18,50 @@ module.exports = function(s,config){ var definitions = require(s.location.definitions+'/en_CA.json'); } //load languages dynamically + s.copySystemDefaultLanguage = function(){ + //en_CA + return Object.assign(lang,{}) + } s.loadedLanguages={} - s.loadedLanguages[config.language]=lang; + s.loadedLanguages[config.language] = s.copySystemDefaultLanguage() s.getLanguageFile = function(rule){ if(rule && rule !== ''){ var file = s.loadedLanguages[file] if(!file){ try{ s.loadedLanguages[rule] = require(s.location.languages+'/'+rule+'.json') - s.loadedLanguages[rule] = Object.assign(lang,s.loadedLanguages[rule]) + s.loadedLanguages[rule] = Object.assign(s.copySystemDefaultLanguage(),s.loadedLanguages[rule]) file = s.loadedLanguages[rule] }catch(err){ - file = lang + file = s.copySystemDefaultLanguage() } } }else{ - file = lang + file = s.copySystemDefaultLanguage() } return file } //load defintions dynamically + s.copySystemDefaultDefinitions = function(){ + //en_CA + return Object.assign(definitions,{}) + } s.loadedDefinitons={} - s.loadedDefinitons[config.language]=definitions; + s.loadedDefinitons[config.language] = s.copySystemDefaultDefinitions() s.getDefinitonFile = function(rule){ if(rule && rule !== ''){ var file = s.loadedDefinitons[file] if(!file){ try{ s.loadedDefinitons[rule] = require(s.location.definitions+'/'+rule+'.json') - s.loadedDefinitons[rule] = Object.assign(definitions,s.loadedDefinitons[rule]) + s.loadedDefinitons[rule] = Object.assign(s.copySystemDefaultDefinitions(),s.loadedDefinitons[rule]) file = s.loadedDefinitons[rule] }catch(err){ - file = definitions + file = s.copySystemDefaultDefinitions() } } }else{ - file = definitions + file = s.copySystemDefaultDefinitions() } return file } diff --git a/libs/monitor.js b/libs/monitor.js index 1c0a425..f1820b4 100644 --- a/libs/monitor.js +++ b/libs/monitor.js @@ -6,6 +6,7 @@ var Mp4Frag = require('mp4frag'); var onvif = require('node-onvif'); var request = require('request'); var connectionTester = require('connection-tester') +var SoundDetection = require('shinobi-sound-detection') var URL = require('url') module.exports = function(s,config,lang){ s.initiateMonitorObject = function(e){ @@ -21,6 +22,7 @@ module.exports = function(s,config,lang){ if(!s.group[e.ke].mon[e.mid].eventBasedRecording){s.group[e.ke].mon[e.mid].eventBasedRecording={}}; if(!s.group[e.ke].mon[e.mid].watch){s.group[e.ke].mon[e.mid].watch={}}; if(!s.group[e.ke].mon[e.mid].fixingVideos){s.group[e.ke].mon[e.mid].fixingVideos={}}; + if(!s.group[e.ke].mon[e.mid].parsedObjects){s.group[e.ke].mon[e.mid].parsedObjects={}}; if(!s.group[e.ke].mon[e.mid].isStarted){s.group[e.ke].mon[e.mid].isStarted = false}; if(s.group[e.ke].mon[e.mid].delete){clearTimeout(s.group[e.ke].mon[e.mid].delete)} if(!s.group[e.ke].mon_conf){s.group[e.ke].mon_conf={}} @@ -103,7 +105,7 @@ module.exports = function(s,config,lang){ var snapBuffer = [] var snapProcess = spawn(config.ffmpegDir,('-loglevel quiet -re -i '+url+options+' -frames:v 1 -f image2pipe pipe:1').split(' '),{detached: true}) snapProcess.stdout.on('data',function(data){ - snapBuffer.push(data) + if(snapBuffer)snapBuffer.push(data) }) snapProcess.stderr.on('data',function(data){ console.log(data.toString()) @@ -163,6 +165,9 @@ module.exports = function(s,config,lang){ var streamDirItems = fs.readdirSync(pathDir) var items = [] var copiedItems = [] + var videoLength = s.group[monitor.ke].mon_conf[monitor.id].details.detector_send_video_length + if(!videoLength || videoLength === '')videoLength = '10' + if(videoLength.length === 1)videoLength = '0' + videoLength var createMerged = function(copiedItems){ var allts = pathDir+items.join('_') fs.stat(allts,function(err,stats){ @@ -170,7 +175,7 @@ module.exports = function(s,config,lang){ //not exist var cat = 'cat '+copiedItems.join(' ')+' > '+allts exec(cat,function(){ - var merger = spawn(config.ffmpegDir,s.splitForFFPMEG(('-re -i '+allts+' -acodec copy -vcodec copy '+pathDir+mergedFile))) + var merger = spawn(config.ffmpegDir,s.splitForFFPMEG(('-re -i '+allts+' -acodec copy -vcodec copy -t 00:00:' + videoLength + ' '+pathDir+mergedFile))) merger.stderr.on('data',function(data){ s.userLog(monitor,{type:"Buffer Merge",msg:data.toString()}) }) @@ -198,7 +203,7 @@ module.exports = function(s,config,lang){ } }) items.sort() - items = items.slice(items.length - 5,items.length) + // items = items.slice(items.length - 5,items.length) items.forEach(function(filename){ try{ var tempFilename = filename.split('.') @@ -218,6 +223,64 @@ module.exports = function(s,config,lang){ }) return items } + s.mergeRecordedVideos = function(videoRows,groupKey,callback){ + var tempDir = s.dir.streams + groupKey + '/' + var pathDir = s.dir.fileBin + groupKey + '/' + var streamDirItems = fs.readdirSync(pathDir) + var items = [] + var mergedFile = [] + videoRows.forEach(function(video){ + var filepath = s.getVideoDirectory(video) + s.formattedTime(video.time) + '.' + video.ext + if( + filepath.indexOf('.mp4') > -1 + // || filename.indexOf('.webm') > -1 + ){ + mergedFile.push(s.formattedTime(video.time)) + items.push(filepath) + } + }) + mergedFile.sort() + mergedFile = mergedFile.join('_') + '.mp4' + var mergedFilepath = pathDir + mergedFile + var mergedRawFilepath = pathDir + 'raw_' + mergedFile + items.sort() + fs.stat(mergedFilepath,function(err,stats){ + if(err){ + //not exist + var tempScriptPath = tempDir + s.gid(5) + '.sh' + var cat = 'cat '+items.join(' ')+' > '+mergedRawFilepath + fs.writeFileSync(tempScriptPath,cat,'utf8') + exec('sh ' + tempScriptPath,function(){ + s.userLog({ + ke: groupKey, + mid: '$USER' + },{type:lang['Videos Merge'],msg:mergedFile}) + var merger = spawn(config.ffmpegDir,s.splitForFFPMEG(('-re -loglevel warning -i ' + mergedRawFilepath + ' -acodec copy -vcodec copy ' + mergedFilepath))) + merger.stderr.on('data',function(data){ + s.userLog({ + ke: groupKey, + mid: '$USER' + },{type:lang['Videos Merge'],msg:data.toString()}) + }) + merger.on('close',function(){ + s.file('delete',mergedRawFilepath) + s.file('delete',tempScriptPath) + setTimeout(function(){ + fs.stat(mergedFilepath,function(err,stats){ + if(!err)s.file('delete',mergedFilepath) + }) + },1000 * 60 * 60 * 24) + delete(merger) + callback(mergedFilepath,mergedFile) + }) + }) + }else{ + //file exist + callback(mergedFilepath,mergedFile) + } + }) + return items + } s.cameraDestroy = function(x,e,p){ if(s.group[e.ke]&&s.group[e.ke].mon[e.id]&&s.group[e.ke].mon[e.id].spawn !== undefined){ @@ -266,6 +329,7 @@ module.exports = function(s,config,lang){ if(s.group[e.ke].mon[e.id].childNode){ s.cx({f:'kill',d:s.cleanMonitorObject(e)},s.group[e.ke].mon[e.id].childNodeId) }else{ + s.coSpawnClose(e) if(!x||x===1){return}; p=x.pid; if(s.group[e.ke].mon_conf[e.id].type===('dashcam'||'socket'||'jpeg'||'pipe')){ @@ -282,12 +346,20 @@ module.exports = function(s,config,lang){ s.cameraCheckObjectsInDetails = function(e){ //parse Objects (['detector_cascades','cords','detector_filters','input_map_choices']).forEach(function(v){ - if(e.details&&e.details[v]&&(e.details[v] instanceof Object)===false){ + if(e.details && e.details[v]){ try{ - if(e.details[v] === '') e.details[v] = '{}' - e.details[v]=JSON.parse(e.details[v]); - if(!e.details[v])e.details[v]={}; - s.group[e.ke].mon[e.id].details = e.details; + if(!e.details[v] || e.details[v] === '')e.details[v] = '{}' + e.details[v] = s.parseJSON(e.details[v]) + if(!e.details[v])e.details[v] = {} + s.group[e.ke].mon[e.id].details = e.details + switch(v){ + case'cords': + s.group[e.ke].mon[e.id].parsedObjects[v] = Object.values(s.parseJSON(e.details[v])) + break; + default: + s.group[e.ke].mon[e.id].parsedObjects[v] = s.parseJSON(e.details[v]) + break; + } }catch(err){ } @@ -595,6 +667,14 @@ module.exports = function(s,config,lang){ // exec('chmod -R 777 '+e.sdir,function(err){ // // }) + var binDir = s.dir.fileBin + e.ke + '/' + if (!fs.existsSync(binDir)){ + fs.mkdirSync(binDir) + } + binDir = s.dir.fileBin + e.ke + '/' + e.id + '/' + if (!fs.existsSync(binDir)){ + fs.mkdirSync(binDir) + } return setStreamDir } s.stripAuthFromHost = function(e){ @@ -741,6 +821,9 @@ module.exports = function(s,config,lang){ } s.fatalCameraError(e,'Process Unexpected Exit'); s.orphanedVideoCheck(e,2,null,true) + s.onMonitorUnexpectedExitExtensions.forEach(function(extender){ + extender(Object.assign(s.group[e.ke].mon_conf[e.id],{}),e) + }) } } s.group[e.ke].mon[e.id].spawn.on('end',s.group[e.ke].mon[e.id].spawn_exit) @@ -773,7 +856,47 @@ module.exports = function(s,config,lang){ if(e.type==='jpeg'){ s.cameraPullJpegStream(e) } - if(e.details.detector === '1'){ + if(e.details.detector_audio === '1'){ + var triggerLevel + var triggerLevelMax + if(e.details.detector_audio_min_db && e.details.detector_audio_min_db !== ''){ + triggerLevel = parseInt(e.details.detector_audio_min_db) + }else{ + triggerLevel = 5 + } + if(e.details.detector_audio_max_db && e.details.detector_audio_max_db !== ''){ + triggerLevelMax = parseInt(e.details.detector_audio_max_db) + } + var audioDetector = new SoundDetection({ + format: { + bitDepth: 16, + numberOfChannels: 1, + signed: true + }, + triggerLevel: triggerLevel, + triggerLevelMax: triggerLevelMax + },function(dB) { + s.triggerEvent({ + f:'trigger', + id:e.id, + ke:e.ke, + name: 'db', + details:{ + plug:'audio', + name:'db', + reason:'soundChange', + confidence:dB + }, + plates:[], + imgHeight:e.details.detector_scale_y, + imgWidth:e.details.detector_scale_x + }) + }) + s.group[e.ke].mon[e.id].audioDetector = audioDetector + audioDetector.start() + s.group[e.ke].mon[e.id].spawn.stdio[6].pipe(audioDetector.streamDecoder) + } + if(e.details.detector === '1' && e.coProcessor === false){ s.ocvTx({f:'init_monitor',id:e.id,ke:e.ke}) //frames from motion detect if(e.details.detector_pam === '1'){ @@ -784,34 +907,10 @@ module.exports = function(s,config,lang){ s.group[e.ke].mon[e.id].lastJpegDetectorFrame = d }) } - }else if(s.ocv){ - if(s.ocv.connectionType !== 'ram'){ - s.group[e.ke].mon[e.id].spawn.stdio[3].on('data',function(d){ - s.ocvTx({f:'frame',mon:s.group[e.ke].mon_conf[e.id].details,ke:e.ke,id:e.id,time:s.formattedTime(),frame:d}); - }) - }else{ - s.group[e.ke].mon[e.id].spawn.stdio[3].on('data',function(d){ - if(!s.group[e.ke].mon[e.id].detectorFrameSaveBuffer){ - s.group[e.ke].mon[e.id].detectorFrameSaveBuffer=[d] - }else{ - s.group[e.ke].mon[e.id].detectorFrameSaveBuffer.push(d) - } - if(d[d.length-2] === 0xFF && d[d.length-1] === 0xD9){ - var buffer = Buffer.concat(s.group[e.ke].mon[e.id].detectorFrameSaveBuffer); - var frameLocation = s.dir.streams + e.ke + '/' + e.id + '/' + s.gid(5) + '.jpg' - if(s.ocv){ - fs.writeFile(frameLocation,buffer,function(err){ - if(err){ - s.debugLog(err) - }else{ - s.ocvTx({f:'frameFromRam',mon:s.group[e.ke].mon_conf[e.id].details,ke:e.ke,id:e.id,time:s.formattedTime(),frameLocation:frameLocation}) - } - }) - } - s.group[e.ke].mon[e.id].detectorFrameSaveBuffer = null; - } - }) - } + }else if(s.isAtleatOneDetectorPluginConnected){ + s.group[e.ke].mon[e.id].spawn.stdio[3].on('data',function(d){ + s.ocvTx({f:'frame',mon:s.group[e.ke].mon_conf[e.id].details,ke:e.ke,id:e.id,time:s.formattedTime(),frame:d}); + }) } } //frames to stream @@ -862,7 +961,11 @@ module.exports = function(s,config,lang){ break; } if(e.frameToStream){ - s.group[e.ke].mon[e.id].spawn.stdout.on('data',e.frameToStream) + if(e.coProcessor === true && e.details.stream_type === ('b64'||'mjpeg')){ + + }else{ + s.group[e.ke].mon[e.id].spawn.stdout.on('data',e.frameToStream) + } } if(e.details.stream_channels && e.details.stream_channels !== ''){ var createStreamEmitter = function(channel,number){ @@ -908,6 +1011,13 @@ module.exports = function(s,config,lang){ s.group[e.ke].mon[e.id].spawn.stderr.on('data',function(d){ d=d.toString(); switch(true){ + case checkLog(d,'No space left on device'): + s.checkUserPurgeLock(e.ke) + s.purgeDiskForGroup(e) + break; + case checkLog(d,'error while decoding'): + s.userLog(e,{type:lang['Error While Decoding'],msg:lang.ErrorWhileDecodingText}); + break; case checkLog(d,'[hls @'): case checkLog(d,'Past duration'): case checkLog(d,'Last message repeated'): @@ -935,10 +1045,11 @@ module.exports = function(s,config,lang){ case checkLog(d,'mjpeg_decode_dc'): case checkLog(d,'bad vlc'): case checkLog(d,'error dc'): + case checkLog(d,'No route to host'): s.launchMonitorProcesses(e) break; case /T[0-9][0-9]-[0-9][0-9]-[0-9][0-9]./.test(d): - var filename = d.split('.')[0]+'.'+e.ext + var filename = d.split('.')[0].split(' [')[0].trim()+'.'+e.ext s.insertCompletedVideo(e,{ file : filename },function(err){ @@ -996,7 +1107,7 @@ module.exports = function(s,config,lang){ e.detector_notrigger_timeout = parseFloat(e.details.detector_notrigger_timeout)*1000*60; s.group[e.ke].mon[e.id].detector_notrigger_timeout_function = function(){ s.onDetectorNoTriggerTimeoutExtensions.forEach(function(extender){ - extender(r,e) + extender(e) }) } clearInterval(s.group[e.ke].mon[e.id].detector_notrigger_timeout) @@ -1009,7 +1120,11 @@ module.exports = function(s,config,lang){ if(s.group[e.ke].mon[e.id].isStarted === true){ fs.stat(e.sdir+'s.jpg',function(err,snap){ var notStreaming = function(){ - s.launchMonitorProcesses(e) + if(e.coProcessor === true){ + s.coSpawnLauncher(e) + }else{ + s.launchMonitorProcesses(e) + } s.userLog(e,{type:lang['Camera is not streaming'],msg:{msg:lang['Restarting Process']}}) s.orphanedVideoCheck(e,2,null,true) } @@ -1034,13 +1149,6 @@ module.exports = function(s,config,lang){ //check if ffmpeg is recording s.group[e.ke].mon[e.id].fswatch = fs.watch(e.dir, {encoding : 'utf8'}, (event, filename) => { switch(event){ - case'rename': - try{ - s.group[e.ke].mon[e.id].open = filename.split('.')[0] - }catch(err){ - s.debugLog('Failed to split filename : ',filename) - } - break; case'change': s.resetRecordingCheck(e) break; @@ -1094,11 +1202,22 @@ module.exports = function(s,config,lang){ ){ s.cameraFilterFfmpegLog(e) } + if(e.coProcessor === true){ + setTimeout(function(){ + s.coSpawnLauncher(e) + },6000) + } + s.onMonitorStartExtensions.forEach(function(extender){ + extender(Object.assign(s.group[e.ke].mon_conf[e.id],{}),e) + }) }else{ + s.onMonitorPingFailedExtensions.forEach(function(extender){ + extender(Object.assign(s.group[e.ke].mon_conf[e.id],{}),e) + }) s.userLog(e,{type:lang["Ping Failed"],msg:lang.skipPingText1}); s.fatalCameraError(e,"Ping Failed");return; - } - } + } + } if( e.type !== 'socket' && e.type !== 'dashcam' && @@ -1136,6 +1255,9 @@ module.exports = function(s,config,lang){ if(o.success === true){ startVideoProcessor() }else{ + s.onMonitorPingFailedExtensions.forEach(function(extender){ + extender(Object.assign(s.group[e.ke].mon_conf[e.id],{}),e) + }) s.userLog(e,{type:lang["Ping Failed"],msg:lang.skipPingText1}); s.fatalCameraError(e,"Ping Failed");return; } @@ -1200,7 +1322,10 @@ module.exports = function(s,config,lang){ }else{ s.cameraDestroy(s.group[e.ke].mon[e.id].spawn,e) } - s.sendMonitorStatus({id:e.id,ke:e.ke,status:lang.Died}); + s.sendMonitorStatus({id:e.id,ke:e.ke,status:lang.Died}) + s.onMonitorDiedExtensions.forEach(function(extender){ + extender(Object.assign(s.group[e.ke].mon_conf[e.id],{}),e) + }) } s.isWatchCountable = function(d){ try{ @@ -1307,6 +1432,9 @@ module.exports = function(s,config,lang){ } s.tx(txData,'GRP_'+form.ke) callback(!endData.ok,endData) + s.onMonitorSaveExtensions.forEach(function(extender){ + extender(Object.assign(s.group[form.ke].mon_conf[form.mid],{}),form,endData) + }) }) } s.camera = function(x,e,cn){ @@ -1399,6 +1527,9 @@ module.exports = function(s,config,lang){ var wantedStatus = lang.Idle } s.sendMonitorStatus({id:e.id,ke:e.ke,status:wantedStatus}) + s.onMonitorStopExtensions.forEach(function(extender){ + extender(Object.assign(s.group[e.ke].mon_conf[e.id],{}),e) + }) break; case'start':case'record'://watch or record monitor url s.initiateMonitorObject({ke:e.ke,mid:e.id}) @@ -1420,8 +1551,8 @@ module.exports = function(s,config,lang){ s.group[e.ke].mon[e.mid].isRecording = false } //set up fatal error handler - if(e.details.fatal_max===''){ - e.details.fatal_max = 10 + if(e.details.fatal_max === ''){ + e.details.fatal_max = 0 }else{ e.details.fatal_max = parseFloat(e.details.fatal_max) } @@ -1439,4 +1570,78 @@ module.exports = function(s,config,lang){ } if(typeof cn === 'function'){setTimeout(function(){cn()},1000)} } + // + s.activateMonitorStates = function(groupKey,stateName,user,callback){ + var endData = { + ok: false + } + s.findPreset([groupKey,'monitorStates',stateName],function(notFound,preset){ + if(notFound === false){ + var sqlQuery = 'SELECT * FROM Monitors WHERE ke=? AND ' + var monitorQuery = [] + var sqlQueryValues = [groupKey] + var monitorPresets = {} + preset.details.monitors.forEach(function(monitor){ + monitorQuery.push('mid=?') + sqlQueryValues.push(monitor.mid) + monitorPresets[monitor.mid] = monitor + }) + sqlQuery += '('+monitorQuery.join(' OR ')+')' + s.sqlQuery(sqlQuery,sqlQueryValues,function(err,monitors){ + if(monitors && monitors[0]){ + monitors.forEach(function(monitor){ + s.checkDetails(monitor) + s.checkDetails(monitorPresets[monitor.mid]) + var monitorPreset = monitorPresets[monitor.mid] + monitorPreset.details = Object.assign(monitor.details,monitorPreset.details) + monitor = s.cleanMonitorObjectForDatabase(Object.assign(monitor,monitorPreset)) + monitor.details = JSON.stringify(monitor.details) + s.addOrEditMonitor(Object.assign(monitor,{}),function(err,endData){ + + },user) + }) + endData.ok = true + s.tx({f:'change_group_state',ke:groupKey,name:stateName},'GRP_'+groupKey) + callback(endData) + }else{ + endData.msg = user.lang['State Configuration has no monitors associated'] + callback(endData) + } + }) + }else{ + endData.msg = user.lang['State Configuration Not Found'] + callback(endData) + } + }) + } + s.getCamerasForMultiTrigger = function(monitor){ + var list={} + var cameras=[] + var group + try{ + group=JSON.parse(monitor.details.group_detector_multi) + if(!group){group=[]} + }catch(err){ + group=[] + } + group.forEach(function(b){ + Object.keys(s.group[monitor.ke].mon_conf).forEach(function(v){ + try{ + var groups = JSON.parse(s.group[monitor.ke].mon_conf[v].details.groups) + if(!groups){ + groups=[] + } + }catch(err){ + groups=[] + } + if(!list[v]&&groups.indexOf(b)>-1){ + list[v]={} + if(s.group[monitor.ke].mon_conf[v].mode !== 'stop'){ + cameras.push(Object.assign({},s.group[monitor.ke].mon_conf[v])) + } + } + }) + }) + return cameras + } } diff --git a/libs/notification.js b/libs/notification.js index 70118e9..9d24930 100644 --- a/libs/notification.js +++ b/libs/notification.js @@ -1,3 +1,4 @@ +var fs = require("fs") var Discord = require("discord.js") module.exports = function(s,config,lang){ //discord bot @@ -21,16 +22,27 @@ module.exports = function(s,config,lang){ text: "Shinobi Systems" } },data) - bot.channels.get(s.group[groupKey].init.discordbot_channel).send({ - embed: sendBody, - files: files - }).catch(err => { - if(err){ - s.userLog({ke:groupKey,mid:'$USER'},{type:lang.DiscordErrorText,msg:err}) - s.group[groupKey].discordBot = null - s.loadGroupApps({ke:groupKey}) - } - }) + var discordChannel = bot.channels.get(s.group[groupKey].init.discordbot_channel) + if(discordChannel && discordChannel.send){ + discordChannel.send({ + embed: sendBody, + files: files + }).catch(err => { + if(err){ + s.userLog({ke:groupKey,mid:'$USER'},{type:lang.DiscordErrorText,msg:err}) + s.group[groupKey].discordBot = null + s.loadGroupApps({ke:groupKey}) + } + }) + }else{ + s.userLog({ + ke: groupKey, + mid: '$USER' + },{ + type: lang.DiscordErrorText, + msg: 'Check the Channel ID' + }) + } } var onEventTriggerBeforeFilterForDiscord = function(d,filter){ filter.discord = true @@ -131,7 +143,13 @@ module.exports = function(s,config,lang){ ){ s.group[user.ke].discordBot = new Discord.Client() s.group[user.ke].discordBot.on('ready', () => { - console.log(`${user.mail} : Discord Bot Logged in as ${s.group[user.ke].discordBot.user.tag}!`) + s.userLog({ + ke: user.ke, + mid: '$USER' + },{ + type: lang.DiscordLoggedIn, + msg: s.group[user.ke].discordBot.user.tag + }) }) s.group[user.ke].discordBot.login(ar.discordbot_token) } diff --git a/libs/plugins.js b/libs/plugins.js index 24eaf51..e7f1edf 100644 --- a/libs/plugins.js +++ b/libs/plugins.js @@ -17,28 +17,76 @@ module.exports = function(s,config,lang){ break; } } - //multi plugin connections - s.connectedPlugins={} + s.connectedPlugins = {} + s.connectedDetectorPlugins = {} + s.detectorPluginArray = [] + s.isAtleatOneDetectorPluginConnected = false + s.addDetectorPlugin = function(name,d){ + s.connectedDetectorPlugins[d.plug] = { + started: s.timeObject(), + id: d.id, + plug: d.plug, + notice: d.notice, + connectionType: d.connectionType + } + s.resetDetectorPluginArray() + } + s.removeDetectorPlugin = function(name){ + delete(s.connectedDetectorPlugins[name]) + s.resetDetectorPluginArray(name) + } + s.resetDetectorPluginArray = function(){ + pluginArray = [] + Object.keys(s.connectedPlugins).forEach(function(name){ + var plugin = s.connectedPlugins[name] + if(plugin.plugged === true && plugin.type === 'detector'){ + pluginArray.push(name) + } + }) + if(pluginArray.length > 0)s.isAtleatOneDetectorPluginConnected = true + s.detectorPluginArray = pluginArray + } + s.sendToAllDetectors = function(data){ + s.detectorPluginArray.forEach(function(name){ + s.connectedPlugins[name].tx(data) + }) + } + s.sendDetectorInfoToClient = function(data,txFunction){ + s.detectorPluginArray.forEach(function(name){ + var detectorData = Object.assign(data,{ + notice: s.connectedDetectorPlugins[name].notice, + plug: name + }) + txFunction(detectorData) + }) + } + // s.sendToDetectorsInChain = function(){ + // + // } s.pluginInitiatorSuccess=function(mode,d,cn){ s.systemLog('pluginInitiatorSuccess',d) - if(mode==='client'){ - //is in client mode (camera.js is client) - cn.pluginEngine=d.plug - if(!s.connectedPlugins[d.plug]){ - s.connectedPlugins[d.plug]={plug:d.plug} + if(!s.connectedPlugins[d.plug]){ + s.connectedPlugins[d.plug]={ + plug: d.plug, + type: d.type } + } + s.connectedPlugins[d.plug].plugged = true + if(mode==='client'){ + s.connectedPlugins[d.plug].tx = function(x){return cn.emit('f',x)} + //is in client mode (camera.js is client) + cn.pluginEngine = d.plug s.systemLog('Connected to plugin : Detector - '+d.plug+' - '+d.type) switch(d.type){ default:case'detector': - s.ocv = { - started: s.timeObject(), + cn.detectorPlugin = d.plug + s.addDetectorPlugin(d.plug,{ id: cn.id, plug: d.plug, notice: d.notice, isClientPlugin: true, connectionType: d.connectionType - }; - cn.ocv = 1; + }) s.tx({f:'detector_plugged',plug:d.plug,notice:d.notice},'CPU') break; } @@ -46,21 +94,18 @@ module.exports = function(s,config,lang){ //is in host mode (camera.js is client) switch(d.type){ default:case'detector': - s.ocv = { - started:s.timeObject(), + s.addDetectorPlugin(d.plug,{ id:"host", plug:d.plug, notice:d.notice, isHostPlugin:true, connectionType: d.connectionType - }; + }) + s.tx({f:'detector_plugged',plug:d.plug,notice:d.notice},'CPU') break; } } - s.connectedPlugins[d.plug].plugged=true s.tx({f:'readPlugins',ke:d.ke},'CPU') - s.ocvTx({f:'api_key',key:d.plug}) - s.api[d.plug]={pluginEngine:d.plug,permissions:{},details:{},ip:'0.0.0.0'}; } s.pluginInitiatorFail=function(mode,d,cn){ if(s.connectedPlugins[d.plug])s.connectedPlugins[d.plug].plugged=false @@ -73,7 +118,10 @@ module.exports = function(s,config,lang){ } if(config.plugins&&config.plugins.length>0){ config.plugins.forEach(function(v){ - s.connectedPlugins[v.id]={plug:v.id} + s.connectedPlugins[v.id]={ + plug: v.id, + type: v.type + } if(v.enabled===false){return} if(v.mode==='host'){ //is in host mode (camera.js is client) @@ -102,7 +150,13 @@ module.exports = function(s,config,lang){ socket.on('ocv',s.pluginEventController); socket.on('disconnect', function(){ s.connectedPlugins[v.id].plugged=false - delete(s.api[v.id]) + if(v.type === 'detector'){ + s.tx({f:'detector_unplugged',plug:v.id},'CPU') + s.removeDetectorPlugin(v.id) + s.sendDetectorInfoToClient({f:'detector_plugged'},function(data){ + s.tx(data,'CPU') + }) + } s.systemLog('Plugin Disconnected : '+v.id) s.connectedPlugins[v.id].reconnector = setInterval(function(){ if(socket.connected===true){ diff --git a/libs/process.js b/libs/process.js index 122d2f1..2ae560b 100644 --- a/libs/process.js +++ b/libs/process.js @@ -7,6 +7,9 @@ module.exports = function(process,__dirname){ }); // [CTRL] + [C] = exit process.on('SIGINT', function() { + s.onProcessExitExtensions.forEach(function(extender){ + extender() + }) console.log('Shinobi is Exiting...') process.exit(); }); diff --git a/libs/rtmpserver.js b/libs/rtmpserver.js new file mode 100644 index 0000000..2253a86 --- /dev/null +++ b/libs/rtmpserver.js @@ -0,0 +1,23 @@ +module.exports = function(s,config,lang){ + if(config.rtmpServer){ + var defaultRtmpServerConfig = { + port: 1935, + chunk_size: 60000, + gop_cache: true, + ping: 60, + ping_timeout: 30 + } + var runningRtmpServerConfig + if(config.rtmpServer instanceof Object === 'false'){ + runningRtmpServerConfig = defaultRtmpServerConfig + }else{ + runningRtmpServerConfig = Object.assign(defaultRtmpServerConfig,config.rtmpServer) + } + s.systemLog(`RTMP Server Running on port ${runningRtmpServerConfig.port}...`) + var NodeRtmpServer = require('./rtmpserver/node_rtmp_server') + var nmcs = new NodeRtmpServer({ + rtmp: runningRtmpServerConfig + }) + nmcs.run() + } +} diff --git a/libs/rtmpserver/node_core_amf.js b/libs/rtmpserver/node_core_amf.js new file mode 100644 index 0000000..18bca14 --- /dev/null +++ b/libs/rtmpserver/node_core_amf.js @@ -0,0 +1,1184 @@ +/** + * Created by delian on 3/12/14. + * This module provides encoding and decoding of the AMF0 and AMF3 format + */ +const Logger = require('./node_core_logger'); + +const amf3dRules = { + 0x00: amf3decUndefined, + 0x01: amf3decNull, + 0x02: amf3decFalse, + 0x03: amf3decTrue, + 0x04: amf3decInteger, + 0x05: amf3decDouble, + 0x06: amf3decString, + 0x07: amf3decXmlDoc, + 0x08: amf3decDate, + 0x09: amf3decArray, + 0x0A: amf3decObject, + 0x0B: amf3decXml, + 0x0C: amf3decByteArray //, + // 0x0D: amf3decVecInt, + // 0x0E: amf3decVecUInt, + // 0x0F: amf3decVecDouble, + // 0x10: amf3decVecObject, + // 0x11: amf3decDict // No dictionary support for the moment! +}; + +const amf3eRules = { + 'string': amf3encString, + 'integer': amf3encInteger, + 'double': amf3encDouble, + 'xml': amf3encXmlDoc, + 'object': amf3encObject, + 'array': amf3encArray, + 'sarray': amf3encArray, + 'binary': amf3encByteArray, + 'true': amf3encTrue, + 'false': amf3encFalse, + 'undefined': amf3encUndefined, + 'null': amf3encNull +}; + +const amf0dRules = { + 0x00: amf0decNumber, + 0x01: amf0decBool, + 0x02: amf0decString, + 0x03: amf0decObject, + // 0x04: amf0decMovie, // Reserved + 0x05: amf0decNull, + 0x06: amf0decUndefined, + 0x07: amf0decRef, + 0x08: amf0decArray, + // 0x09: amf0decObjEnd, // Should never happen normally + 0x0A: amf0decSArray, + 0x0B: amf0decDate, + 0x0C: amf0decLongString, + // 0x0D: amf0decUnsupported, // Has been never originally implemented by Adobe! + // 0x0E: amf0decRecSet, // Has been never originally implemented by Adobe! + 0x0F: amf0decXmlDoc, + 0x10: amf0decTypedObj, + 0x11: amf0decSwitchAmf3 +}; + +const amf0eRules = { + 'string': amf0encString, + 'integer': amf0encNumber, + 'double': amf0encNumber, + 'xml': amf0encXmlDoc, + 'object': amf0encObject, + 'array': amf0encArray, + 'sarray': amf0encSArray, + 'binary': amf0encString, + 'true': amf0encBool, + 'false': amf0encBool, + 'undefined': amf0encUndefined, + 'null': amf0encNull +}; + +function amfType(o) { + let jsType = typeof o; + + if (o === null) return 'null'; + if (jsType == 'undefined') return 'undefined'; + if (jsType == 'number') { + if (parseInt(o) == o) return 'integer'; + return 'double'; + } + if (jsType == 'boolean') return o ? 'true' : 'false'; + if (jsType == 'string') return 'string'; + if (jsType == 'object') { + if (o instanceof Array) { + if (o.sarray) return 'sarray'; + return 'array'; + } + return 'object'; + } + throw new Error('Unsupported type!') +} + +// AMF3 implementation + +/** + * AMF3 Decode undefined value + * @returns {{len: number, value: undefined}} + */ +function amf3decUndefined() { + return { len: 1, value: undefined } +} + +/** + * AMF3 Encode undefined value + * @returns {Buffer} + */ +function amf3encUndefined() { + let buf = Buffer.alloc(1); + buf.writeUInt8(0x00); + return buf; +} + +/** + * AMF3 Decode null + * @returns {{len: number, value: null}} + */ +function amf3decNull() { + return { len: 1, value: null } +} + +/** + * AMF3 Encode null + * @returns {Buffer} + */ +function amf3encNull() { + let buf = Buffer.alloc(1); + buf.writeUInt8(0x01); + return buf; +} + +/** + * AMF3 Decode false + * @returns {{len: number, value: boolean}} + */ +function amf3decFalse() { + return { len: 1, value: false } +} + +/** + * AMF3 Encode false + * @returns {Buffer} + */ +function amf3encFalse() { + let buf = Buffer.alloc(1); + buf.writeUInt8(0x02); + return buf; +} + +/** + * AMF3 Decode true + * @returns {{len: number, value: boolean}} + */ +function amf3decTrue() { + return { len: 1, value: true } +} + +/** + * AMF3 Encode true + * @returns {Buffer} + */ +function amf3encTrue() { + let buf = Buffer.alloc(1); + buf.writeUInt8(0x03); + return buf; +} + +/** + * Generic decode of AMF3 UInt29 values + * @param buf + * @returns {{len: number, value: number}} + */ +function amf3decUI29(buf) { + let val = 0; + let len = 1; + let b; + + do { + b = buf.readUInt8(len++); + val = (val << 7) + (b & 0x7F); + } while (len < 5 || b > 0x7F); + + if (len == 5) val = val | b; // Preserve the major bit of the last byte + + return { len: len, value: val } +} + +/** + * Generic encode of AMF3 UInt29 value + * @param num + * @returns {Buffer} + */ +function amf3encUI29(num) { + let len = 0; + if (num < 0x80) len = 1; + if (num < 0x4000) len = 2; + if (num < 0x200000) len = 3; + if (num >= 0x200000) len = 4; + let buf = Buffer.alloc(len); + switch (len) { + case 1: + buf.writeUInt8(num, 0); + break; + case 2: + buf.writeUInt8(num & 0x7F, 0); + buf.writeUInt8((num >> 7) | 0x80, 1); + break; + case 3: + buf.writeUInt8(num & 0x7F, 0); + buf.writeUInt8((num >> 7) & 0x7F, 1); + buf.writeUInt8((num >> 14) | 0x80, 2); + break; + case 4: + buf.writeUInt8(num & 0xFF, 0); + buf.writeUInt8((num >> 8) & 0x7F, 1); + buf.writeUInt8((num >> 15) | 0x7F, 2); + buf.writeUInt8((num >> 22) | 0x7F, 3); + break; + } + return buf; +} + +/** + * AMF3 Decode an integer + * @param buf + * @returns {{len: number, value: number}} + */ +function amf3decInteger(buf) { // Invert the integer + let resp = amf3decUI29(buf); + if (resp.value > 0x0FFFFFFF) resp.value = (resp.value & 0x0FFFFFFF) - 0x10000000; + return resp; +} + +/** + * AMF3 Encode an integer + * @param num + * @returns {Buffer} + */ +function amf3encInteger(num) { + let buf = Buffer.alloc(1); + buf.writeUInt8(0x4, 0); + return Buffer.concat([buf, amf3encUI29(num & 0x3FFFFFFF)]); // This AND will auto convert the sign bit! +} + +/** + * AMF3 Decode String + * @param buf + * @returns {{len: *, value: (*|String)}} + */ +function amf3decString(buf) { + let sLen = amf3decUI29(buf); + let s = sLen & 1; + sLen = sLen >> 1; // The real length without the lowest bit + if (s) return { len: sLen.value + 5, value: buf.slice(5, sLen.value + 5).toString('utf8') }; + throw new Error("Error, we have a need to decode a String that is a Reference"); // TODO: Implement references! +} + +/** + * AMF3 Encode String + * @param str + * @returns {Buffer} + */ +function amf3encString(str) { + let sLen = amf3encUI29(str.length << 1); + let buf = Buffer.alloc(1); + buf.writeUInt8(0x6, 0); + return Buffer.concat([buf, sLen, Buffer.from(str, 'utf8')]); +} + +/** + * AMF3 Decode XMLDoc + * @param buf + * @returns {{len: *, value: (*|String)}} + */ +function amf3decXmlDoc(buf) { + let sLen = amf3decUI29(buf); + let s = sLen & 1; + sLen = sLen >> 1; // The real length without the lowest bit + if (s) return { len: sLen.value + 5, value: buf.slice(5, sLen.value + 5).toString('utf8') }; + throw new Error("Error, we have a need to decode a String that is a Reference"); // TODO: Implement references! +} + +/** + * AMF3 Encode XMLDoc + * @param str + * @returns {Buffer} + */ +function amf3encXmlDoc(str) { + let sLen = amf3encUI29(str.length << 1); + let buf = Buffer.alloc(1); + buf.writeUInt8(0x7, 0); + return Buffer.concat([buf, sLen, Buffer.from(str, 'utf8')]); +} + +/** + * AMF3 Decode Generic XML + * @param buf + * @returns {{len: *, value: (*|String)}} + */ +function amf3decXml(buf) { + let sLen = amf3decUI29(buf); + let s = sLen & 1; + sLen = sLen >> 1; // The real length without the lowest bit + if (s) return { len: sLen.value + 5, value: buf.slice(5, sLen.value + 5).toString('utf8') }; + throw new Error("Error, we have a need to decode a String that is a Reference"); // TODO: Implement references! +} + +/** + * AMF3 Encode Generic XML + * @param str + * @returns {Buffer} + */ +function amf3encXml(str) { + let sLen = amf3encUI29(str.length << 1); + let buf = Buffer.alloc(1); + buf.writeUInt8(0x0B, 0); + return Buffer.concat([buf, sLen, Buffer.from(str, 'utf8')]); +} + +/** + * AMF3 Decide Byte Array + * @param buf + * @returns {{len: *, value: (Array|string|*|Buffer|Blob)}} + */ +function amf3decByteArray(buf) { + let sLen = amf3decUI29(buf); + let s = sLen & 1; // TODO: Check if we follow the same rule! + sLen = sLen >> 1; // The real length without the lowest bit + if (s) return { len: sLen.value + 5, value: buf.slice(5, sLen.value + 5) }; + throw new Error("Error, we have a need to decode a String that is a Reference"); // TODO: Implement references! +} + +/** + * AMF3 Encode Byte Array + * @param str + * @returns {Buffer} + */ +function amf3encByteArray(str) { + let sLen = amf3encUI29(str.length << 1); + let buf = Buffer.alloc(1); + buf.writeUInt8(0x0C, 0); + return Buffer.concat([buf, sLen, (typeof str == 'string') ? Buffer.from(str, 'binary') : str]); +} + +/** + * AMF3 Decode Double + * @param buf + * @returns {{len: number, value: (*|Number)}} + */ +function amf3decDouble(buf) { + return { len: 9, value: buf.readDoubleBE(1) } +} + +/** + * AMF3 Encode Double + * @param num + * @returns {Buffer} + */ +function amf3encDouble(num) { + let buf = Buffer.alloc(9); + buf.writeUInt8(0x05, 0); + buf.writeDoubleBE(num, 1); + return buf; +} + +/** + * AMF3 Decode Date + * @param buf + * @returns {{len: *, value: (*|Number)}} + */ +function amf3decDate(buf) { // The UI29 should be 1 + let uTz = amf3decUI29(buf); + let ts = buf.readDoubleBE(uTz.len); + return { len: uTz.len + 8, value: ts } +} + +/** + * AMF3 Encode Date + * @param ts + * @returns {Buffer} + */ +function amf3encDate(ts) { + let buf = Buffer.alloc(1); + buf.writeUInt8(0x8, 0); + let tsBuf = Buffer.alloc(8); + tsBuf.writeDoubleBE(ts, 0); + return Buffer.concat([buf, amf3encUI29(1), tsBuf]); // We always do 1 +} + +/** + * AMF3 Decode Array + * @param buf + * @returns {{len: *, value: *}} + */ +function amf3decArray(buf) { + let count = amf3decUI29(buf.slice(1)); + let obj = amf3decObject(buf.slice(count.len)); + if (count.value % 2 == 1) throw new Error("This is a reference to another array, which currently we don't support!"); + return { len: count.len + obj.len, value: obj.value } +} + +/** + * AMF3 Encode Array + */ +function amf3encArray() { + throw new Error('Encoding arrays is not supported yet!'); // TODO: Implement encoding of arrays +} + +/** + * AMF3 Decode Object + * @param buf + */ +function amf3decObject(buf) { + let obj = {}; + let pos = 0; + return obj; +} + +/** + * AMF3 Encode Object + * @param o + */ +function amf3encObject(o) { + +} + +// AMF0 Implementation + +/** + * AMF0 Decode Number + * @param buf + * @returns {{len: number, value: (*|Number)}} + */ +function amf0decNumber(buf) { + return { len: 9, value: buf.readDoubleBE(1) } +} + +/** + * AMF0 Encode Number + * @param num + * @returns {Buffer} + */ +function amf0encNumber(num) { + let buf = Buffer.alloc(9); + buf.writeUInt8(0x00, 0); + buf.writeDoubleBE(num, 1); + return buf; +} + +/** + * AMF0 Decode Boolean + * @param buf + * @returns {{len: number, value: boolean}} + */ +function amf0decBool(buf) { + return { len: 2, value: (buf.readUInt8(1) != 0) } +} + +/** + * AMF0 Encode Boolean + * @param num + * @returns {Buffer} + */ +function amf0encBool(num) { + let buf = Buffer.alloc(2); + buf.writeUInt8(0x01, 0); + buf.writeUInt8((num ? 1 : 0), 1); + return buf; +} + +/** + * AMF0 Decode Null + * @returns {{len: number, value: null}} + */ +function amf0decNull() { + return { len: 1, value: null } +} + +/** + * AMF0 Encode Null + * @returns {Buffer} + */ +function amf0encNull() { + let buf = Buffer.alloc(1); + buf.writeUInt8(0x05, 0); + return buf; +} + +/** + * AMF0 Decode Undefined + * @returns {{len: number, value: undefined}} + */ +function amf0decUndefined() { + return { len: 1, value: undefined } +} + +/** + * AMF0 Encode Undefined + * @returns {Buffer} + */ +function amf0encUndefined() { + let buf = Buffer.alloc(1); + buf.writeUInt8(0x06, 0); + return buf; +} + +/** + * AMF0 Decode Date + * @param buf + * @returns {{len: number, value: (*|Number)}} + */ +function amf0decDate(buf) { + // let s16 = buf.readInt16BE(1); + let ts = buf.readDoubleBE(3); + return { len: 11, value: ts } +} + +/** + * AMF0 Encode Date + * @param ts + * @returns {Buffer} + */ +function amf0encDate(ts) { + let buf = Buffer.alloc(11); + buf.writeUInt8(0x0B, 0); + buf.writeInt16BE(0, 1); + buf.writeDoubleBE(ts, 3); + return buf; +} + +/** + * AMF0 Decode Object + * @param buf + * @returns {{len: number, value: {}}} + */ +function amf0decObject(buf) { // TODO: Implement references! + let obj = {}; + let iBuf = buf.slice(1); + let len = 1; + // Logger.debug('ODec',iBuf.readUInt8(0)); + while (iBuf.readUInt8(0) != 0x09) { + // Logger.debug('Field', iBuf.readUInt8(0), iBuf); + let prop = amf0decUString(iBuf); + // Logger.debug('Got field for property', prop); + len += prop.len; + if(iBuf.length < prop.len) { + break; + } + if (iBuf.slice(prop.len).readUInt8(0) == 0x09) { + len++; + // Logger.debug('Found the end property'); + break; + } // END Object as value, we shall leave + if (prop.value == '') break; + let val = amf0DecodeOne(iBuf.slice(prop.len)); + // Logger.debug('Got field for value', val); + obj[prop.value] = val.value; + len += val.len; + iBuf = iBuf.slice(prop.len + val.len); + } + return { len: len, value: obj } +} + +/** + * AMF0 Encode Object + */ +function amf0encObject(o) { + if (typeof o !== 'object') return; + + let data = Buffer.alloc(1); + data.writeUInt8(0x03, 0); // Type object + let k; + for (k in o) { + data = Buffer.concat([data, amf0encUString(k), amf0EncodeOne(o[k])]); + } + let termCode = Buffer.alloc(1); + termCode.writeUInt8(0x09, 0); + return Buffer.concat([data, amf0encUString(''), termCode]); +} + +/** + * AMF0 Decode Reference + * @param buf + * @returns {{len: number, value: string}} + */ +function amf0decRef(buf) { + let index = buf.readUInt16BE(1); + return { len: 3, value: 'ref' + index } +} + +/** + * AMF0 Encode Reference + * @param index + * @returns {Buffer} + */ +function amf0encRef(index) { + let buf = Buffer.alloc(3); + buf.writeUInt8(0x07, 0); + buf.writeUInt16BE(index, 1); + return buf; +} + +/** + * AMF0 Decode String + * @param buf + * @returns {{len: *, value: (*|string|String)}} + */ +function amf0decString(buf) { + let sLen = buf.readUInt16BE(1); + return { len: 3 + sLen, value: buf.toString('utf8', 3, 3 + sLen) } +} + +/** + * AMF0 Decode Untyped (without the type byte) String + * @param buf + * @returns {{len: *, value: (*|string|String)}} + */ +function amf0decUString(buf) { + let sLen = buf.readUInt16BE(0); + return { len: 2 + sLen, value: buf.toString('utf8', 2, 2 + sLen) } +} + +/** + * Do AMD0 Encode of Untyped String + * @param s + * @returns {Buffer} + */ +function amf0encUString(str) { + let data = Buffer.from(str, 'utf8'); + let sLen = Buffer.alloc(2); + sLen.writeUInt16BE(data.length, 0); + return Buffer.concat([sLen, data]); +} + +/** + * AMF0 Encode String + * @param str + * @returns {Buffer} + */ +function amf0encString(str) { + let buf = Buffer.alloc(3); + buf.writeUInt8(0x02, 0); + buf.writeUInt16BE(str.length, 1); + return Buffer.concat([buf, Buffer.from(str, 'utf8')]); +} + +/** + * AMF0 Decode Long String + * @param buf + * @returns {{len: *, value: (*|string|String)}} + */ +function amf0decLongString(buf) { + let sLen = buf.readUInt32BE(1); + return { len: 5 + sLen, value: buf.toString('utf8', 5, 5 + sLen) } +} + +/** + * AMF0 Encode Long String + * @param str + * @returns {Buffer} + */ +function amf0encLongString(str) { + let buf = Buffer.alloc(5); + buf.writeUInt8(0x0C, 0); + buf.writeUInt32BE(str.length, 1); + return Buffer.concat([buf, Buffer.from(str, 'utf8')]); +} + +/** + * AMF0 Decode Array + * @param buf + * @returns {{len: *, value: ({}|*)}} + */ +function amf0decArray(buf) { + // let count = buf.readUInt32BE(1); + let obj = amf0decObject(buf.slice(4)); + return { len: 5 + obj.len, value: obj.value } +} + +/** + * AMF0 Encode Array + */ +function amf0encArray(a) { + let l = 0; + if (a instanceof Array) l = a.length; else l = Object.keys(a).length; + Logger.debug('Array encode', l, a); + let buf = Buffer.alloc(5); + buf.writeUInt8(8, 0); + buf.writeUInt32BE(l, 1); + let data = amf0encObject(a); + return Buffer.concat([buf, data.slice(1)]); +} + +/** + * AMF0 Encode Binary Array into binary Object + * @param aData + * @returns {Buffer} + */ +function amf0cnletray2Object(aData) { + let buf = Buffer.alloc(1); + buf.writeUInt8(0x3, 0); // Object id + return Buffer.concat([buf, aData.slice(5)]); +} + +/** + * AMF0 Encode Binary Object into binary Array + * @param oData + * @returns {Buffer} + */ +function amf0cnvObject2Array(oData) { + let buf = Buffer.alloc(5); + let o = amf0decObject(oData); + let l = Object.keys(o).length; + buf.writeUInt32BE(l, 1); + return Buffer.concat([buf, oData.slice(1)]); +} + +/** + * AMF0 Decode XMLDoc + * @param buf + * @returns {{len: *, value: (*|string|String)}} + */ +function amf0decXmlDoc(buf) { + let sLen = buf.readUInt16BE(1); + return { len: 3 + sLen, value: buf.toString('utf8', 3, 3 + sLen) } +} + +/** + * AMF0 Encode XMLDoc + * @param str + * @returns {Buffer} + */ +function amf0encXmlDoc(str) { // Essentially it is the same as string + let buf = Buffer.alloc(3); + buf.writeUInt8(0x0F, 0); + buf.writeUInt16BE(str.length, 1); + return Buffer.concat([buf, Buffer.from(str, 'utf8')]); +} + +/** + * AMF0 Decode Strict Array + * @param buf + * @returns {{len: number, value: Array}} + */ +function amf0decSArray(buf) { + let a = []; + let len = 5; + let ret; + for (let count = buf.readUInt32BE(1); count; count--) { + ret = amf0DecodeOne(buf.slice(len)); + a.push(ret.value); + len += ret.len; + } + return { len: len, value: amf0markSArray(a) } +} + +/** + * AMF0 Encode Strict Array + * @param a Array + */ +function amf0encSArray(a) { + Logger.debug('Do strict array!'); + let buf = Buffer.alloc(5); + buf.writeUInt8(0x0A, 0); + buf.writeUInt32BE(a.length, 1); + let i; + for (i = 0; i < a.length; i++) { + buf = Buffer.concat([buf, amf0EncodeOne(a[i])]); + } + return buf; +} + +function amf0markSArray(a) { + Object.defineProperty(a, 'sarray', { value: true }); + return a; +} + +/** + * AMF0 Decode Typed Object + * @param buf + * @returns {{len: number, value: ({}|*)}} + */ +function amf0decTypedObj(buf) { + let className = amf0decString(buf); + let obj = amf0decObject(buf.slice(className.len - 1)); + obj.value.__className__ = className.value; + return { len: className.len + obj.len - 1, value: obj.value } +} + +/** + * AMF0 Decode Switch AMF3 Object + * @param buf + * @returns {{len: number, value: ({}|*)}} + */ +function amf0decSwitchAmf3(buf) { + let r = amf3DecodeOne(buf.slice(1)); + return r; +} + +/** + * AMF0 Encode Typed Object + */ +function amf0encTypedObj() { + throw new Error("Error: SArray encoding is not yet implemented!"); // TODO: Error +} + +/** + * Decode one value from the Buffer according to the applied rules + * @param rules + * @param buffer + * @returns {*} + */ +function amfXDecodeOne(rules, buffer) { + if (!rules[buffer.readUInt8(0)]) { + Logger.error('Unknown field', buffer.readUInt8(0)); + return null; + } + return rules[buffer.readUInt8(0)](buffer); +} + +/** + * Decode one AMF0 value + * @param buffer + * @returns {*} + */ +function amf0DecodeOne(buffer) { + return amfXDecodeOne(amf0dRules, buffer); +} + +/** + * Decode one AMF3 value + * @param buffer + * @returns {*} + */ +function amf3DecodeOne(buffer) { + return amfXDecodeOne(amf3dRules, buffer); +} + +/** + * Decode a whole buffer of AMF values according to rules and return in array + * @param rules + * @param buffer + * @returns {Array} + */ +function amfXDecode(rules, buffer) { + // We shall receive clean buffer and will respond with an array of values + let resp = []; + let res; + for (let i = 0; i < buffer.length;) { + res = amfXDecodeOne(rules, buffer.slice(i)); + i += res.len; + resp.push(res.value); // Add the response + } + return resp; +} + +/** + * Decode a buffer of AMF3 values + * @param buffer + * @returns {Array} + */ +function amf3Decode(buffer) { + return amfXDecode(amf3dRules, buffer); +} + +/** + * Decode a buffer of AMF0 values + * @param buffer + * @returns {Array} + */ +function amf0Decode(buffer) { + return amfXDecode(amf0dRules, buffer); +} + +/** + * Encode one AMF value according to rules + * @param rules + * @param o + * @returns {*} + */ +function amfXEncodeOne(rules, o) { + // Logger.debug('amfXEncodeOne type',o,amfType(o),rules[amfType(o)]); + let f = rules[amfType(o)]; + if (f) return f(o); + throw new Error('Unsupported type for encoding!'); +} + +/** + * Encode one AMF0 value + * @param o + * @returns {*} + */ +function amf0EncodeOne(o) { + return amfXEncodeOne(amf0eRules, o); +} + +/** + * Encode one AMF3 value + * @param o + * @returns {*} + */ +function amf3EncodeOne(o) { + return amfXEncodeOne(amf3eRules, o); +} + +/** + * Encode an array of values into a buffer + * @param a + * @returns {Buffer} + */ +function amf3Encode(a) { + let buf = Buffer.alloc(0); + a.forEach(function (o) { + buf = Buffer.concat([buf, amf3EncodeOne(o)]); + }); + return buf; +} + +/** + * Encode an array of values into a buffer + * @param a + * @returns {Buffer} + */ +function amf0Encode(a) { + let buf = Buffer.alloc(0); + a.forEach(function (o) { + buf = Buffer.concat([buf, amf0EncodeOne(o)]); + }); + return buf; +} + + +const rtmpCmdCode = { + "_result": ["transId", "cmdObj", "info"], + "_error": ["transId", "cmdObj", "info", "streamId"], // Info / Streamid are optional + "onStatus": ["transId", "cmdObj", "info"], + "releaseStream": ["transId", "cmdObj", "streamName"], + "getStreamLength": ["transId", "cmdObj", "streamId"], + "getMovLen": ["transId", "cmdObj", "streamId"], + "FCPublish": ["transId", "cmdObj", "streamName"], + "FCUnpublish": ["transId", "cmdObj", "streamName"], + "onFCPublish": ["transId", "cmdObj", "info"], + "connect": ["transId", "cmdObj", "args"], + "call": ["transId", "cmdObj", "args"], + "createStream": ["transId", "cmdObj"], + "close": ["transId", "cmdObj"], + "play": ["transId", "cmdObj", "streamName", "start", "duration", "reset"], + "play2": ["transId", "cmdObj", "params"], + "deleteStream": ["transId", "cmdObj", "streamId"], + "closeStream": ["transId", "cmdObj"], + "receiveAudio": ["transId", "cmdObj", "bool"], + "receiveVideo": ["transId", "cmdObj", "bool"], + "publish": ["transId", "cmdObj", "streamName", "type"], + "seek": ["transId", "cmdObj", "ms"], + "pause": ["transId", "cmdObj", "pause", "ms"] +}; + +const rtmpDataCode = { + "@setDataFrame": ["method", "dataObj"], + "onMetaData": ["dataObj"], + "|RtmpSampleAccess": ["bool1", "bool2"], +}; + + +/** + * Decode a data! + * @param dbuf + * @returns {{cmd: (*|string|String|*), value: *}} + */ +function decodeAmf0Data(dbuf) { + let buffer = dbuf; + let resp = {}; + + let cmd = amf0DecodeOne(buffer); + if(cmd) { + resp.cmd = cmd.value; + buffer = buffer.slice(cmd.len); + + if (rtmpDataCode[cmd.value]) { + rtmpDataCode[cmd.value].forEach(function (n) { + if (buffer.length > 0) { + let r = amf0DecodeOne(buffer); + if(r) { + buffer = buffer.slice(r.len); + resp[n] = r.value; + } + } + }); + } else { + Logger.error('Unknown command', resp); + } + } + + return resp +} + +/** + * Decode a command! + * @param dbuf + * @returns {{cmd: (*|string|String|*), value: *}} + */ +function decodeAMF0Cmd(dbuf) { + let buffer = dbuf; + let resp = {}; + + let cmd = amf0DecodeOne(buffer); + resp.cmd = cmd.value; + buffer = buffer.slice(cmd.len); + + if (rtmpCmdCode[cmd.value]) { + rtmpCmdCode[cmd.value].forEach(function (n) { + if (buffer.length > 0) { + let r = amf0DecodeOne(buffer); + buffer = buffer.slice(r.len); + resp[n] = r.value; + } + }); + } else { + Logger.error('Unknown command', resp); + } + return resp +} + +/** + * Encode AMF0 Command + * @param opt + * @returns {*} + */ +function encodeAMF0Cmd(opt) { + let data = amf0EncodeOne(opt.cmd); + + if (rtmpCmdCode[opt.cmd]) { + rtmpCmdCode[opt.cmd].forEach(function (n) { + if (opt.hasOwnProperty(n)) + data = Buffer.concat([data, amf0EncodeOne(opt[n])]); + }); + } else { + Logger.error('Unknown command', opt); + } + // Logger.debug('Encoded as',data.toString('hex')); + return data +} + +function encodeAMF0Data(opt) { + let data = amf0EncodeOne(opt.cmd); + + if (rtmpDataCode[opt.cmd]) { + rtmpDataCode[opt.cmd].forEach(function (n) { + if (opt.hasOwnProperty(n)) + data = Buffer.concat([data, amf0EncodeOne(opt[n])]); + }); + } else { + Logger.error('Unknown data', opt); + } + // Logger.debug('Encoded as',data.toString('hex')); + return data +} + +/** + * + * @param dbuf + * @returns {{}} + */ +function decodeAMF3Cmd(dbuf) { + let buffer = dbuf; + let resp = {}; + + let cmd = amf3DecodeOne(buffer); + resp.cmd = cmd.value; + buffer = buffer.slice(cmd.len); + + if (rtmpCmdCode[cmd.value]) { + rtmpCmdCode[cmd.value].forEach(function (n) { + if (buffer.length > 0) { + let r = amf3DecodeOne(buffer); + buffer = buffer.slice(r.len); + resp[n] = r.value; + } + }); + } else { + Logger.error('Unknown command', resp); + } + return resp +} + +/** + * Encode AMF3 Command + * @param opt + * @returns {*} + */ +function encodeAMF3Cmd(opt) { + let data = amf0EncodeOne(opt.cmd); + + if (rtmpCmdCode[opt.cmd]) { + rtmpCmdCode[opt.cmd].forEach(function (n) { + if (opt.hasOwnProperty(n)) + data = Buffer.concat([data, amf3EncodeOne(opt[n])]); + }); + } else { + Logger.error('Unknown command', opt); + } + return data +} + +module.exports = { + decodeAmf3Cmd: decodeAMF3Cmd, + encodeAmf3Cmd: encodeAMF3Cmd, + decodeAmf0Cmd: decodeAMF0Cmd, + encodeAmf0Cmd: encodeAMF0Cmd, + decodeAmf0Data: decodeAmf0Data, + encodeAmf0Data: encodeAMF0Data, + amfType: amfType, + amf0Encode: amf0Encode, + amf0EncodeOne: amf0EncodeOne, + amf0Decode: amf0Decode, + amf0DecodeOne: amf0DecodeOne, + amf3Encode: amf3Encode, + amf3EncodeOne: amf3EncodeOne, + amf3Decode: amf3Decode, + amf3DecodeOne: amf3DecodeOne, + amf0cnvA2O: amf0cnletray2Object, + amf0cnvO2A: amf0cnvObject2Array, + amf0markSArray: amf0markSArray, + amf0decArray: amf0decArray, + amf0decBool: amf0decBool, + amf0decDate: amf0decDate, + amf0decLongString: amf0decLongString, + amf0decNull: amf0decNull, + amf0decNumber: amf0decNumber, + amf0decObject: amf0decObject, + amf0decRef: amf0decRef, + amf0decSArray: amf0decSArray, + amf0decString: amf0decString, + amf0decTypedObj: amf0decTypedObj, + amf0decUndefined: amf0decUndefined, + amf0decXmlDoc: amf0decXmlDoc, + amf0encArray: amf0encArray, + amf0encBool: amf0encBool, + amf0encDate: amf0encDate, + amf0encLongString: amf0encLongString, + amf0encNull: amf0encNull, + amf0encNumber: amf0encNumber, + amf0encObject: amf0encObject, + amf0encRef: amf0encRef, + amf0encSArray: amf0encSArray, + amf0encString: amf0encString, + amf0encTypedObj: amf0encTypedObj, + amf0encUndefined: amf0encUndefined, + amf0encXmlDoc: amf0encXmlDoc, + amf3decArray: amf3decArray, + amf3decByteArray: amf3decByteArray, + amf3decDate: amf3decDate, + amf3decDouble: amf3decDouble, + amf3decFalse: amf3decFalse, + amf3decInteger: amf3decInteger, + amf3decNull: amf3decNull, + amf3decObject: amf3decObject, + amf3decString: amf3decString, + amf3decTrue: amf3decTrue, + amf3decUI29: amf3decUI29, + amf3decUndefined: amf3decUndefined, + amf3decXml: amf3decXml, + amf3decXmlDoc: amf3decXmlDoc, + amf3encArray: amf3encArray, + amf3encByteArray: amf3encByteArray, + amf3encDate: amf3encDate, + amf3encDouble: amf3encDouble, + amf3encFalse: amf3encFalse, + amf3encInteger: amf3encInteger, + amf3encNull: amf3encNull, + amf3encObject: amf3encObject, + amf3encString: amf3encString, + amf3encTrue: amf3encTrue, + amf3encUI29: amf3encUI29, + amf3encUndefined: amf3encUndefined, + amf3encXml: amf3encXml, + amf3encXmlDoc: amf3encXmlDoc +}; \ No newline at end of file diff --git a/libs/rtmpserver/node_core_av.js b/libs/rtmpserver/node_core_av.js new file mode 100644 index 0000000..70b8bd7 --- /dev/null +++ b/libs/rtmpserver/node_core_av.js @@ -0,0 +1,501 @@ +// +// Created by Mingliang Chen on 17/12/21. +// illuspas[a]gmail.com +// Copyright (c) 2018 Nodemedia. All rights reserved. +// + +const Bitop = require('./node_core_bitop'); +const AAC_SAMPLE_RATE = [ + 96000, 88200, 64000, 48000, + 44100, 32000, 24000, 22050, + 16000, 12000, 11025, 8000, + 7350, 0, 0, 0 +]; + +const AAC_CHANNELS = [ + 0, 1, 2, 3, 4, 5, 6, 8 +]; + +const AUDIO_CODEC_NAME = [ + '', + 'ADPCM', + 'MP3', + 'LinearLE', + 'Nellymoser16', + 'Nellymoser8', + 'Nellymoser', + 'G711A', + 'G711U', + '', + 'AAC', + 'Speex', + '', + '', + 'MP3-8K', + 'DeviceSpecific', + 'Uncompressed' +]; + +const AUDIO_SOUND_RATE = [ + 5512, 11025, 22050, 44100 +]; + +const VIDEO_CODEC_NAME = [ + '', + 'Jpeg', + 'Sorenson-H263', + 'ScreenVideo', + 'On2-VP6', + 'On2-VP6-Alpha', + 'ScreenVideo2', + 'H264', + '', + '', + '', + '', + 'H265' +]; + +function getObjectType(bitop) { + let audioObjectType = bitop.read(5); + if (audioObjectType === 31) { + audioObjectType = bitop.read(6) + 32; + } + return audioObjectType; +} + +function getSampleRate(bitop, info) { + info.sampling_index = bitop.read(4); + return info.sampling_index == 0x0f ? bitop.read(24) : AAC_SAMPLE_RATE[info.sampling_index]; +} + +function readAACSpecificConfig(aacSequenceHeader) { + let info = {}; + let bitop = new Bitop(aacSequenceHeader); + bitop.read(16); + info.object_type = getObjectType(bitop); + info.sample_rate = getSampleRate(bitop, info); + info.chan_config = bitop.read(4); + if (info.chan_config < AAC_CHANNELS.length) { + info.channels = AAC_CHANNELS[info.chan_config]; + } + info.sbr = -1; + info.ps = -1; + if (info.object_type == 5 || info.object_type == 29) { + if (info.object_type == 29) { + info.ps = 1; + } + info.ext_object_type = 5; + info.sbr = 1; + info.sample_rate = getSampleRate(bitop, info); + info.object_type = getObjectType(bitop); + } + + return info; +} + +function getAACProfileName(info) { + switch (info.object_type) { + case 1: + return 'Main'; + case 2: + if (info.ps > 0) { + return 'HEv2'; + } + if (info.sbr > 0) { + return 'HE'; + } + return 'LC'; + case 3: + return 'SSR'; + case 4: + return 'LTP'; + case 5: + return 'SBR'; + default: + return ''; + } +} + +function readH264SpecificConfig(avcSequenceHeader) { + let info = {}; + let profile_idc, width, height, crop_left, crop_right, + crop_top, crop_bottom, frame_mbs_only, n, cf_idc, + num_ref_frames; + let bitop = new Bitop(avcSequenceHeader); + bitop.read(48); + info.width = 0; + info.height = 0; + + do { + info.profile = bitop.read(8); + info.compat = bitop.read(8); + info.level = bitop.read(8); + info.nalu = (bitop.read(8) & 0x03) + 1; + info.nb_sps = bitop.read(8) & 0x1F; + if (info.nb_sps == 0) { + break; + } + /* nal size */ + bitop.read(16); + + /* nal type */ + if (bitop.read(8) != 0x67) { + break; + } + /* SPS */ + profile_idc = bitop.read(8); + + /* flags */ + bitop.read(8); + + /* level idc */ + bitop.read(8); + + /* SPS id */ + bitop.read_golomb(); + + if (profile_idc == 100 || profile_idc == 110 || + profile_idc == 122 || profile_idc == 244 || profile_idc == 44 || + profile_idc == 83 || profile_idc == 86 || profile_idc == 118) { + /* chroma format idc */ + cf_idc = bitop.read_golomb(); + + if (cf_idc == 3) { + + /* separate color plane */ + bitop.read(1); + } + + /* bit depth luma - 8 */ + bitop.read_golomb(); + + /* bit depth chroma - 8 */ + bitop.read_golomb(); + + /* qpprime y zero transform bypass */ + bitop.read(1); + + /* seq scaling matrix present */ + if (bitop.read(1)) { + + for (n = 0; n < (cf_idc != 3 ? 8 : 12); n++) { + + /* seq scaling list present */ + if (bitop.read(1)) { + + /* TODO: scaling_list() + if (n < 6) { + } else { + } + */ + } + } + } + } + + /* log2 max frame num */ + bitop.read_golomb(); + + /* pic order cnt type */ + switch (bitop.read_golomb()) { + case 0: + + /* max pic order cnt */ + bitop.read_golomb(); + break; + + case 1: + + /* delta pic order alwys zero */ + bitop.read(1); + + /* offset for non-ref pic */ + bitop.read_golomb(); + + /* offset for top to bottom field */ + bitop.read_golomb(); + + /* num ref frames in pic order */ + num_ref_frames = bitop.read_golomb(); + + for (n = 0; n < num_ref_frames; n++) { + + /* offset for ref frame */ + bitop.read_golomb(); + } + } + + /* num ref frames */ + info.avc_ref_frames = bitop.read_golomb(); + + /* gaps in frame num allowed */ + bitop.read(1); + + /* pic width in mbs - 1 */ + width = bitop.read_golomb(); + + /* pic height in map units - 1 */ + height = bitop.read_golomb(); + + /* frame mbs only flag */ + frame_mbs_only = bitop.read(1); + + if (!frame_mbs_only) { + + /* mbs adaprive frame field */ + bitop.read(1); + } + + /* direct 8x8 inference flag */ + bitop.read(1); + + /* frame cropping */ + if (bitop.read(1)) { + + crop_left = bitop.read_golomb(); + crop_right = bitop.read_golomb(); + crop_top = bitop.read_golomb(); + crop_bottom = bitop.read_golomb(); + + } else { + crop_left = 0; + crop_right = 0; + crop_top = 0; + crop_bottom = 0; + } + info.level = info.level / 10.0; + info.width = (width + 1) * 16 - (crop_left + crop_right) * 2; + info.height = (2 - frame_mbs_only) * (height + 1) * 16 - (crop_top + crop_bottom) * 2; + + } while (0); + + return info; +} + +function HEVCParsePtl(bitop, hevc, max_sub_layers_minus1) { + let general_ptl = {}; + + general_ptl.profile_space = bitop.read(2); + general_ptl.tier_flag = bitop.read(1); + general_ptl.profile_idc = bitop.read(5); + general_ptl.profile_compatibility_flags = bitop.read(32); + general_ptl.general_progressive_source_flag = bitop.read(1); + general_ptl.general_interlaced_source_flag = bitop.read(1); + general_ptl.general_non_packed_constraint_flag = bitop.read(1); + general_ptl.general_frame_only_constraint_flag = bitop.read(1); + bitop.read(32); + bitop.read(12); + general_ptl.level_idc = bitop.read(8); + + general_ptl.sub_layer_profile_present_flag = []; + general_ptl.sub_layer_level_present_flag = []; + + for (let i = 0; i < max_sub_layers_minus1; i++) { + general_ptl.sub_layer_profile_present_flag[i] = bitop.read(1); + general_ptl.sub_layer_level_present_flag[i] = bitop.read(1); + } + + if (max_sub_layers_minus1 > 0) { + for (let i = max_sub_layers_minus1; i < 8; i++) { + bitop.read(2) + } + } + + general_ptl.sub_layer_profile_space = []; + general_ptl.sub_layer_tier_flag = []; + general_ptl.sub_layer_profile_idc = []; + general_ptl.sub_layer_profile_compatibility_flag = []; + general_ptl.sub_layer_progressive_source_flag = []; + general_ptl.sub_layer_interlaced_source_flag = []; + general_ptl.sub_layer_non_packed_constraint_flag = []; + general_ptl.sub_layer_frame_only_constraint_flag = []; + general_ptl.sub_layer_level_idc = []; + + for (let i = 0; i < max_sub_layers_minus1; i++) { + if (general_ptl.sub_layer_profile_present_flag[i]) { + general_ptl.sub_layer_profile_space[i] = bitop.read(2); + general_ptl.sub_layer_tier_flag[i] = bitop.read(1); + general_ptl.sub_layer_profile_idc[i] = bitop.read(5); + general_ptl.sub_layer_profile_compatibility_flag[i] = bitop.read(32); + general_ptl.sub_layer_progressive_source_flag[i] = bitop.read(1); + general_ptl.sub_layer_interlaced_source_flag[i] = bitop.read(1); + general_ptl.sub_layer_non_packed_constraint_flag[i] = bitop.read(1); + general_ptl.sub_layer_frame_only_constraint_flag[i] = bitop.read(1); + bitop.read(32); + bitop.read(12); + } + if (general_ptl.sub_layer_level_present_flag[i]) { + general_ptl.sub_layer_level_idc[i] = bitop.read(8); + } + else { + general_ptl.sub_layer_level_idc[i] = 1; + } + } + return general_ptl; +} + +function HEVCParseSPS(SPS, hevc) { + let psps = {}; + let NumBytesInNALunit = SPS.length; + let NumBytesInRBSP = 0; + let rbsp_array = []; + let bitop = new Bitop(SPS); + + bitop.read(1);//forbidden_zero_bit + bitop.read(6);//nal_unit_type + bitop.read(6);//nuh_reserved_zero_6bits + bitop.read(3);//nuh_temporal_id_plus1 + + for (let i = 2; i < NumBytesInNALunit; i++) { + if (i + 2 < NumBytesInNALunit && bitop.look(24) == 0x000003) { + rbsp_array.push(bitop.read(8)); + rbsp_array.push(bitop.read(8)); + i += 2; + let emulation_prevention_three_byte = bitop.read(8); /* equal to 0x03 */ + } else { + rbsp_array.push(bitop.read(8)); + } + } + let rbsp = Buffer.from(rbsp_array); + let rbspBitop = new Bitop(rbsp); + psps.sps_video_parameter_set_id = rbspBitop.read(4); + psps.sps_max_sub_layers_minus1 = rbspBitop.read(3); + psps.sps_temporal_id_nesting_flag = rbspBitop.read(1); + psps.profile_tier_level = HEVCParsePtl(rbspBitop, hevc, psps.sps_max_sub_layers_minus1); + psps.sps_seq_parameter_set_id = rbspBitop.read_golomb(); + psps.chroma_format_idc = rbspBitop.read_golomb(); + if (psps.chroma_format_idc == 3) { + psps.separate_colour_plane_flag = rbspBitop.read(1); + } else { + psps.separate_colour_plane_flag = 0; + } + psps.pic_width_in_luma_samples = rbspBitop.read_golomb(); + psps.pic_height_in_luma_samples = rbspBitop.read_golomb(); + psps.conformance_window_flag = rbspBitop.read(1); + if (psps.conformance_window_flag) { + let vert_mult = 1 + (psps.chroma_format_idc < 2); + let horiz_mult = 1 + (psps.chroma_format_idc < 3); + psps.conf_win_left_offset = rbspBitop.read_golomb() * horiz_mult; + psps.conf_win_right_offset = rbspBitop.read_golomb() * horiz_mult; + psps.conf_win_top_offset = rbspBitop.read_golomb() * vert_mult; + psps.conf_win_bottom_offset = rbspBitop.read_golomb() * vert_mult; + } + // Logger.debug(psps); + return psps; +} + +function readHEVCSpecificConfig(hevcSequenceHeader) { + let info = {}; + info.width = 0; + info.height = 0; + info.profile = 0; + info.level = 0; + // let bitop = new Bitop(hevcSequenceHeader); + // bitop.read(48); + hevcSequenceHeader = hevcSequenceHeader.slice(5); + + do { + let hevc = {}; + if (hevcSequenceHeader.length < 23) { + break; + } + + hevc.configurationVersion = hevcSequenceHeader[0]; + if (hevc.configurationVersion != 1) { + break; + } + hevc.general_profile_space = (hevcSequenceHeader[1] >> 6) & 0x03; + hevc.general_tier_flag = (hevcSequenceHeader[1] >> 5) & 0x01; + hevc.general_profile_idc = hevcSequenceHeader[1] & 0x1F; + hevc.general_profile_compatibility_flags = (hevcSequenceHeader[2] << 24) | (hevcSequenceHeader[3] << 16) | (hevcSequenceHeader[4] << 8) | hevcSequenceHeader[5]; + hevc.general_constraint_indicator_flags = ((hevcSequenceHeader[6] << 24) | (hevcSequenceHeader[7] << 16) | (hevcSequenceHeader[8] << 8) | hevcSequenceHeader[9]); + hevc.general_constraint_indicator_flags = (hevc.general_constraint_indicator_flags << 16) | (hevcSequenceHeader[10] << 8) | hevcSequenceHeader[11]; + hevc.general_level_idc = hevcSequenceHeader[12]; + hevc.min_spatial_segmentation_idc = ((hevcSequenceHeader[13] & 0x0F) << 8) | hevcSequenceHeader[14]; + hevc.parallelismType = hevcSequenceHeader[15] & 0x03; + hevc.chromaFormat = hevcSequenceHeader[16] & 0x03; + hevc.bitDepthLumaMinus8 = hevcSequenceHeader[17] & 0x07; + hevc.bitDepthChromaMinus8 = hevcSequenceHeader[18] & 0x07; + hevc.avgFrameRate = (hevcSequenceHeader[19] << 8) | hevcSequenceHeader[20]; + hevc.constantFrameRate = (hevcSequenceHeader[21] >> 6) & 0x03; + hevc.numTemporalLayers = (hevcSequenceHeader[21] >> 3) & 0x07; + hevc.temporalIdNested = (hevcSequenceHeader[21] >> 2) & 0x01; + hevc.lengthSizeMinusOne = hevcSequenceHeader[21] & 0x03; + let numOfArrays = hevcSequenceHeader[22]; + let p = hevcSequenceHeader.slice(23); + for (let i = 0; i < numOfArrays; i++) { + if (p.length < 3) { + brak; + } + let nalutype = p[0]; + let n = (p[1]) << 8 | p[2]; + // Logger.debug(nalutype, n); + p = p.slice(3); + for (let j = 0; j < n; j++) { + if (p.length < 2) { + break; + } + k = (p[0] << 8) | p[1]; + // Logger.debug('k', k); + if (p.length < 2 + k) { + break; + } + p = p.slice(2); + if (nalutype == 33) { + //SPS + let sps = Buffer.alloc(k); + p.copy(sps, 0, 0, k); + // Logger.debug(sps, sps.length); + hevc.psps = HEVCParseSPS(sps, hevc); + info.profile = hevc.general_profile_idc; + info.level = hevc.general_level_idc / 30.0; + info.width = hevc.psps.pic_width_in_luma_samples - (hevc.psps.conf_win_left_offset + hevc.psps.conf_win_right_offset); + info.height = hevc.psps.pic_height_in_luma_samples - (hevc.psps.conf_win_top_offset + hevc.psps.conf_win_bottom_offset); + } + p = p.slice(k); + } + } + } while (0); + + return info; +} + +function readAVCSpecificConfig(avcSequenceHeader) { + let codec_id = avcSequenceHeader[0] & 0x0f; + if (codec_id == 7) { + return readH264SpecificConfig(avcSequenceHeader); + } else if (codec_id == 12) { + return readHEVCSpecificConfig(avcSequenceHeader); + } +} + + +function getAVCProfileName(info) { + switch (info.profile) { + case 1: + return 'Main'; + case 2: + return 'Main 10'; + case 3: + return 'Main Still Picture'; + case 66: + return 'Baseline'; + case 77: + return 'Main'; + case 100: + return 'High'; + default: + return ''; + } +} + +module.exports = { + AUDIO_SOUND_RATE, + AUDIO_CODEC_NAME, + VIDEO_CODEC_NAME, + readAACSpecificConfig, + getAACProfileName, + readAVCSpecificConfig, + getAVCProfileName, +}; diff --git a/libs/rtmpserver/node_core_bitop.js b/libs/rtmpserver/node_core_bitop.js new file mode 100644 index 0000000..3c4b0cb --- /dev/null +++ b/libs/rtmpserver/node_core_bitop.js @@ -0,0 +1,54 @@ + +class Bitop { + constructor(buffer) { + this.buffer = buffer; + this.buflen = buffer.length; + this.bufpos = 0; + this.bufoff = 0; + this.iserro = false; + } + + read(n) { + let v = 0; + let d = 0; + while (n) { + if (n < 0 || this.bufpos >= this.buflen) { + this.iserro = true; + return 0; + } + + this.iserro = false; + d = this.bufoff + n > 8 ? 8 - this.bufoff : n; + + v <<= d; + v += (this.buffer[this.bufpos] >> (8 - this.bufoff - d)) & (0xff >> (8 - d)) + + this.bufoff += d; + n -= d; + + if (this.bufoff == 8) { + this.bufpos++; + this.bufoff = 0; + } + } + return v; + } + + look(n) { + let p = this.bufpos; + let o = this.bufoff; + let v = this.read(n); + this.bufpos = p; + this.bufoff = o; + return v; + } + + read_golomb() { + let n; + for (n = 0; this.read(1) == 0 && !this.iserro; n++); + return (1 << n) + this.read(n) - 1; + } + } + + module.exports = Bitop; + \ No newline at end of file diff --git a/libs/rtmpserver/node_core_ctx.js b/libs/rtmpserver/node_core_ctx.js new file mode 100644 index 0000000..9ea36a8 --- /dev/null +++ b/libs/rtmpserver/node_core_ctx.js @@ -0,0 +1,17 @@ +// +// Created by Mingliang Chen on 18/3/2. +// illuspas[a]gmail.com +// Copyright (c) 2018 Nodemedia. All rights reserved. +// +const EventEmitter = require('events'); + +let sessions = new Map(); +let publishers = new Map(); +let idlePlayers = new Set(); +let nodeEvent = new EventEmitter(); +let stat = { + inbytes: 0, + outbytes: 0, + accepted: 0 +}; +module.exports = { sessions, publishers, idlePlayers, nodeEvent, stat }; \ No newline at end of file diff --git a/libs/rtmpserver/node_core_logger.js b/libs/rtmpserver/node_core_logger.js new file mode 100644 index 0000000..332fc33 --- /dev/null +++ b/libs/rtmpserver/node_core_logger.js @@ -0,0 +1,53 @@ +const chalk = require('chalk'); + +LOG_TYPES = { + NONE: 0, + ERROR: 1, + NORMAL: 2, + DEBUG: 3, + FFDEBUG: 4 +}; + +let logType = LOG_TYPES.NORMAL; + +const setLogType = (type) => { + if (typeof type !== 'number') return; + + logType = type; +}; + +const logTime = () => { + let nowDate = new Date(); + return nowDate.toLocaleDateString() + ' ' + nowDate.toLocaleTimeString([], { hour12: false }); +}; + +const log = (...args) => { + if (logType < LOG_TYPES.NORMAL) return; + + console.log(logTime(), process.pid, chalk.bold.green('[INFO]'), ...args); +}; + +const error = (...args) => { + if (logType < LOG_TYPES.ERROR) return; + + console.log(logTime(), process.pid, chalk.bold.red('[ERROR]'), ...args); +}; + +const debug = (...args) => { + if (logType < LOG_TYPES.DEBUG) return; + + console.log(logTime(), process.pid, chalk.bold.blue('[DEBUG]'), ...args); +}; + +const ffdebug = (...args) => { + if (logType < LOG_TYPES.FFDEBUG) return; + + console.log(logTime(), process.pid, chalk.bold.blue('[FFDEBUG]'), ...args); +}; + +module.exports = { + LOG_TYPES, + setLogType, + + log, error, debug, ffdebug +} \ No newline at end of file diff --git a/libs/rtmpserver/node_core_utils.js b/libs/rtmpserver/node_core_utils.js new file mode 100644 index 0000000..da0e9fb --- /dev/null +++ b/libs/rtmpserver/node_core_utils.js @@ -0,0 +1,95 @@ +// +// Created by Mingliang Chen on 17/8/23. +// illuspas[a]gmail.com +// Copyright (c) 2018 Nodemedia. All rights reserved. +// +const Crypto = require('crypto'); +const EventEmitter = require('events'); +const { spawn } = require('child_process'); +const readline = require('readline'); +const context = require('./node_core_ctx'); + +function generateNewSessionID() { + let sessionID = ''; + const possible = 'ABCDEFGHIJKLMNOPQRSTUVWKYZ0123456789'; + const numPossible = possible.length; + do { + for (let i = 0; i < 8; i++) { + sessionID += possible.charAt((Math.random() * numPossible) | 0); + } + } while (context.sessions.has(sessionID)) + return sessionID; +} + +function genRandomName() { + let name = ''; + const possible = 'abcdefghijklmnopqrstuvwxyz0123456789'; + const numPossible = possible.length; + for (let i = 0; i < 4; i++) { + name += possible.charAt((Math.random() * numPossible) | 0); + } + + return name; +} + +function verifyAuth(signStr, streamId, secretKey) { + if (signStr === undefined) { + return false; + } + let now = Date.now() / 1000 | 0; + let exp = parseInt(signStr.split('-')[0]); + let shv = signStr.split('-')[1]; + let str = streamId + '-' + exp + '-' + secretKey; + if (exp < now) { + return false; + } + let md5 = Crypto.createHash('md5'); + let ohv = md5.update(str).digest('hex'); + return shv === ohv; +} + +function getFFmpegVersion(ffpath) { + return new Promise((resolve, reject) => { + let ffmpeg_exec = spawn(ffpath, ['-version']); + let version = ''; + ffmpeg_exec.on('error', (e) => { + reject(e); + }); + ffmpeg_exec.stdout.on('data', (data) => { + try { + version = data.toString().split(/(?:\r\n|\r|\n)/g)[0].split('\ ')[2]; + } catch (e) { + } + }); + ffmpeg_exec.on('close', (code) => { + resolve(version); + }); + }); +} + +function getFFmpegUrl() { + let url = ''; + switch (process.platform) { + case 'darwin': + url = 'https://ffmpeg.zeranoe.com/builds/macos64/static/ffmpeg-latest-macos64-static.zip'; + break; + case 'win32': + url = 'https://ffmpeg.zeranoe.com/builds/win64/static/ffmpeg-latest-win64-static.zip | https://ffmpeg.zeranoe.com/builds/win32/static/ffmpeg-latest-win32-static.zip'; + break; + case 'linux': + url = 'https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-64bit-static.tar.xz | https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-32bit-static.tar.xz'; + break; + default: + url = 'http://ffmpeg.org/download.html'; + break; + } + return url; +} + +module.exports = { + generateNewSessionID, + verifyAuth, + genRandomName, + getFFmpegVersion, + getFFmpegUrl +} diff --git a/libs/rtmpserver/node_rtmp_handshake.js b/libs/rtmpserver/node_rtmp_handshake.js new file mode 100644 index 0000000..2add436 --- /dev/null +++ b/libs/rtmpserver/node_rtmp_handshake.js @@ -0,0 +1,113 @@ +// +// Created by Mingliang Chen on 17/8/1. +// illuspas[a]gmail.com +// Copyright (c) 2018 Nodemedia. All rights reserved. +// +// const Logger = require('./node_core_logger'); + +const Crypto = require('crypto'); + +const MESSAGE_FORMAT_0 = 0; +const MESSAGE_FORMAT_1 = 1; +const MESSAGE_FORMAT_2 = 2; + +const RTMP_SIG_SIZE = 1536; +const SHA256DL = 32; + +const RandomCrud = Buffer.from([ + 0xf0, 0xee, 0xc2, 0x4a, 0x80, 0x68, 0xbe, 0xe8, + 0x2e, 0x00, 0xd0, 0xd1, 0x02, 0x9e, 0x7e, 0x57, + 0x6e, 0xec, 0x5d, 0x2d, 0x29, 0x80, 0x6f, 0xab, + 0x93, 0xb8, 0xe6, 0x36, 0xcf, 0xeb, 0x31, 0xae +]) + +const GenuineFMSConst = 'Genuine Adobe Flash Media Server 001'; +const GenuineFMSConstCrud = Buffer.concat([Buffer.from(GenuineFMSConst, 'utf8'), RandomCrud]); + +const GenuineFPConst = 'Genuine Adobe Flash Player 001'; +const GenuineFPConstCrud = Buffer.concat([Buffer.from(GenuineFPConst, 'utf8'), RandomCrud]); + +function calcHmac(data, key) { + let hmac = Crypto.createHmac('sha256', key); + hmac.update(data); + return hmac.digest(); +} + +function GetClientGenuineConstDigestOffset(buf) { + let offset = buf[0] + buf[1] + buf[2] + buf[3]; + offset = (offset % 728) + 12; + return offset; +} + +function GetServerGenuineConstDigestOffset(buf) { + let offset = buf[0] + buf[1] + buf[2] + buf[3]; + offset = (offset % 728) + 776; + return offset; +} + +function detectClientMessageFormat(clientsig) { + let computedSignature, msg, providedSignature, sdl; + sdl = GetServerGenuineConstDigestOffset(clientsig.slice(772, 776)); + msg = Buffer.concat([clientsig.slice(0, sdl), clientsig.slice(sdl + SHA256DL)], 1504); + computedSignature = calcHmac(msg, GenuineFPConst); + providedSignature = clientsig.slice(sdl, sdl + SHA256DL); + if (computedSignature.equals(providedSignature)) { + return MESSAGE_FORMAT_2; + } + sdl = GetClientGenuineConstDigestOffset(clientsig.slice(8, 12)); + msg = Buffer.concat([clientsig.slice(0, sdl), clientsig.slice(sdl + SHA256DL)], 1504); + computedSignature = calcHmac(msg, GenuineFPConst); + providedSignature = clientsig.slice(sdl, sdl + SHA256DL); + if (computedSignature.equals(providedSignature)) { + return MESSAGE_FORMAT_1; + } + return MESSAGE_FORMAT_0; +} + +function generateS1(messageFormat) { + let randomBytes = Crypto.randomBytes(RTMP_SIG_SIZE - 8); + let handshakeBytes = Buffer.concat([Buffer.from([0, 0, 0, 0, 1, 2, 3, 4]), randomBytes], RTMP_SIG_SIZE); + + let serverDigestOffset + if (messageFormat === 1) { + serverDigestOffset = GetClientGenuineConstDigestOffset(handshakeBytes.slice(8, 12)); + } else { + serverDigestOffset = GetServerGenuineConstDigestOffset(handshakeBytes.slice(772, 776)); + } + + msg = Buffer.concat([handshakeBytes.slice(0, serverDigestOffset), handshakeBytes.slice(serverDigestOffset + SHA256DL)], RTMP_SIG_SIZE - SHA256DL); + hash = calcHmac(msg, GenuineFMSConst); + hash.copy(handshakeBytes, serverDigestOffset, 0, 32); + return handshakeBytes; +} + +function generateS2(messageFormat, clientsig, callback) { + let randomBytes = Crypto.randomBytes(RTMP_SIG_SIZE - 32); + let challengeKeyOffset; + if (messageFormat === 1) { + challengeKeyOffset = GetClientGenuineConstDigestOffset(clientsig.slice(8, 12)); + } else { + challengeKeyOffset = GetServerGenuineConstDigestOffset(clientsig.slice(772, 776)); + } + let challengeKey = clientsig.slice(challengeKeyOffset, challengeKeyOffset + 32); + let hash = calcHmac(challengeKey, GenuineFMSConstCrud); + let signature = calcHmac(randomBytes, hash); + let s2Bytes = Buffer.concat([randomBytes, signature], RTMP_SIG_SIZE); + return s2Bytes +} + +function generateS0S1S2(clientsig) { + let clientType = Buffer.alloc(1, 3); + let messageFormat = detectClientMessageFormat(clientsig); + let allBytes; + if (messageFormat === MESSAGE_FORMAT_0) { + // Logger.debug('[rtmp handshake] using simple handshake.'); + allBytes = Buffer.concat([clientType, clientsig, clientsig]); + } else { + // Logger.debug('[rtmp handshake] using complex handshake.'); + allBytes = Buffer.concat([clientType, generateS1(messageFormat), generateS2(messageFormat, clientsig)]); + } + return allBytes; +} + +module.exports = { generateS0S1S2 }; diff --git a/libs/rtmpserver/node_rtmp_server.js b/libs/rtmpserver/node_rtmp_server.js new file mode 100644 index 0000000..76c907a --- /dev/null +++ b/libs/rtmpserver/node_rtmp_server.js @@ -0,0 +1,50 @@ +// +// Created by Mingliang Chen on 17/8/1. +// illuspas[a]gmail.com +// Copyright (c) 2018 Nodemedia. All rights reserved. +// +// const Logger = require('./node_core_logger'); + +const Net = require('net'); +const NodeRtmpSession = require('./node_rtmp_session'); +const NodeCoreUtils = require('./node_core_utils'); + +const context = require('./node_core_ctx'); + +const RTMP_PORT = 1935; + +class NodeRtmpServer { + constructor(config) { + config.rtmp.port = this.port = config.rtmp.port ? config.rtmp.port : RTMP_PORT; + this.tcpServer = Net.createServer((socket) => { + let session = new NodeRtmpSession(config, socket); + session.run(); + }) + } + + run() { + this.tcpServer.listen(this.port, () => { + // Logger.log(`Node Media Rtmp Server started on port: ${this.port}`); + }); + + this.tcpServer.on('error', (e) => { + // Logger.error(`Node Media Rtmp Server ${e}`); + }); + + this.tcpServer.on('close', () => { + // Logger.log('Node Media Rtmp Server Close.'); + }); + } + + stop() { + this.tcpServer.close(); + context.sessions.forEach((session, id) => { + if (session instanceof NodeRtmpSession) { + session.socket.destroy(); + context.sessions.delete(id); + } + }); + } +} + +module.exports = NodeRtmpServer diff --git a/libs/rtmpserver/node_rtmp_session.js b/libs/rtmpserver/node_rtmp_session.js new file mode 100644 index 0000000..93105fe --- /dev/null +++ b/libs/rtmpserver/node_rtmp_session.js @@ -0,0 +1,1248 @@ +// +// Created by Mingliang Chen on 18/4/1. +// illuspas[a]gmail.com +// Copyright (c) 2018 Nodemedia. All rights reserved. +// +// const EventEmitter = require('events'); +const QueryString = require('querystring'); +const AV = require('./node_core_av'); +const { AUDIO_SOUND_RATE, AUDIO_CODEC_NAME, VIDEO_CODEC_NAME } = require('./node_core_av'); + +const AMF = require('./node_core_amf'); +const Handshake = require('./node_rtmp_handshake'); +const NodeCoreUtils = require('./node_core_utils'); +const context = require('./node_core_ctx'); +// const Logger = require('./node_core_logger'); + +const N_CHUNK_STREAM = 8; +const RTMP_VERSION = 3; +const RTMP_HANDSHAKE_SIZE = 1536; +const RTMP_HANDSHAKE_UNINIT = 0; +const RTMP_HANDSHAKE_0 = 1; +const RTMP_HANDSHAKE_1 = 2; +const RTMP_HANDSHAKE_2 = 3; + +const RTMP_PARSE_INIT = 0; +const RTMP_PARSE_BASIC_HEADER = 1; +const RTMP_PARSE_MESSAGE_HEADER = 2; +const RTMP_PARSE_EXTENDED_TIMESTAMP = 3; +const RTMP_PARSE_PAYLOAD = 4; + +const MAX_CHUNK_HEADER = 18; + +const RTMP_CHUNK_TYPE_0 = 0; // 11-bytes: timestamp(3) + length(3) + stream type(1) + stream id(4) +const RTMP_CHUNK_TYPE_1 = 1; // 7-bytes: delta(3) + length(3) + stream type(1) +const RTMP_CHUNK_TYPE_2 = 2; // 3-bytes: delta(3) +const RTMP_CHUNK_TYPE_3 = 3; // 0-byte + +const RTMP_CHANNEL_PROTOCOL = 2; +const RTMP_CHANNEL_INVOKE = 3; +const RTMP_CHANNEL_AUDIO = 4; +const RTMP_CHANNEL_VIDEO = 5; +const RTMP_CHANNEL_DATA = 6; + +const rtmpHeaderSize = [11, 7, 3, 0]; + +/* Protocol Control Messages */ +const RTMP_TYPE_SET_CHUNK_SIZE = 1; +const RTMP_TYPE_ABORT = 2; +const RTMP_TYPE_ACKNOWLEDGEMENT = 3; // bytes read report +const RTMP_TYPE_WINDOW_ACKNOWLEDGEMENT_SIZE = 5; // server bandwidth +const RTMP_TYPE_SET_PEER_BANDWIDTH = 6; // client bandwidth + +/* User Control Messages Event (4) */ +const RTMP_TYPE_EVENT = 4; + +const RTMP_TYPE_AUDIO = 8; +const RTMP_TYPE_VIDEO = 9; + +/* Data Message */ +const RTMP_TYPE_FLEX_STREAM = 15; // AMF3 +const RTMP_TYPE_DATA = 18; // AMF0 + +/* Shared Object Message */ +const RTMP_TYPE_FLEX_OBJECT = 16; // AMF3 +const RTMP_TYPE_SHARED_OBJECT = 19; // AMF0 + +/* Command Message */ +const RTMP_TYPE_FLEX_MESSAGE = 17; // AMF3 +const RTMP_TYPE_INVOKE = 20; // AMF0 + +/* Aggregate Message */ +const RTMP_TYPE_METADATA = 22; + +const RTMP_CHUNK_SIZE = 128; +const RTMP_PING_TIME = 60000; +const RTMP_PING_TIMEOUT = 30000; + +const STREAM_BEGIN = 0x00; +const STREAM_EOF = 0x01; +const STREAM_DRY = 0x02; +const STREAM_EMPTY = 0x1f; +const STREAM_READY = 0x20; + +const RtmpPacket = { + create: (fmt = 0, cid = 0) => { + return { + header: { + fmt: fmt, + cid: cid, + timestamp: 0, + length: 0, + type: 0, + stream_id: 0 + }, + clock: 0, + payload: null, + capacity: 0, + bytes: 0 + }; + } +}; +class NodeRtmpSession { + constructor(config, socket) { + + this.config = config; + this.socket = socket; + this.id = NodeCoreUtils.generateNewSessionID(); + this.ip = socket.remoteAddress; + this.TAG = 'rtmp'; + // this.eventEmitter = new EventEmitter(); + + this.handshakePayload = Buffer.alloc(RTMP_HANDSHAKE_SIZE); + this.handshakeState = RTMP_HANDSHAKE_UNINIT; + this.handshakeBytes = 0; + + this.parserBuffer = Buffer.alloc(MAX_CHUNK_HEADER); + this.parserState = RTMP_PARSE_INIT; + this.parserBytes = 0; + this.parserBasicBytes = 0; + this.parserPacket = null; + this.inPackets = new Map(); + + this.inChunkSize = RTMP_CHUNK_SIZE; + this.outChunkSize = config.rtmp.chunk_size ? config.rtmp.chunk_size : RTMP_CHUNK_SIZE; + this.pingTime = config.rtmp.ping ? config.rtmp.ping * 1000 : RTMP_PING_TIME; + this.pingTimeout = config.rtmp.ping_timeout ? config.rtmp.ping_timeout * 1000 : RTMP_PING_TIMEOUT; + this.pingInterval = null; + + this.isIPC = false; + this.isLocal = this.ip === '127.0.0.1' || this.ip === '::1' || this.ip == '::ffff:127.0.0.1'; + this.isStarting = false; + this.isPublishing = false; + this.isPlaying = false; + this.isIdling = false; + this.isPause = false; + this.isReceiveAudio = true; + this.isReceiveVideo = true; + this.metaData = null; + this.aacSequenceHeader = null; + this.avcSequenceHeader = null; + this.audioCodec = 0; + this.audioCodecName = ''; + this.audioProfileName = ''; + this.audioSamplerate = 0; + this.audioChannels = 1; + this.videoCodec = 0; + this.videoCodecName = ''; + this.videoProfileName = ''; + this.videoWidth = 0; + this.videoHeight = 0; + this.videoFps = 0; + this.videoLevel = 0; + + this.gopCacheEnable = config.rtmp.gop_cache; + this.rtmpGopCacheQueue = null; + + this.ackSize = 0; + this.inAckSize = 0; + this.inLastAck = 0; + + this.appname = ''; + this.streams = 0; + + this.playStreamId = 0; + this.playStreamPath = ''; + this.playArgs = {}; + + this.publishStreamId = 0; + this.publishStreamPath = ''; + this.publishArgs = {}; + + this.players = new Set(); + this.writeBufferQueue = []; + context.sessions.set(this.id, this); + } + + // getEventEmitter() { + // return this.eventEmitter + // } + + run() { + this.socket.on('data', this.onSocketData.bind(this)); + this.socket.on('close', this.onSocketClose.bind(this)); + this.socket.on('error', this.onSocketError.bind(this)); + this.socket.on('timeout', this.onSocketTimeout.bind(this)); + this.socket.setTimeout(this.pingTimeout); + this.isStarting = true; + } + + stop() { + if (this.isStarting) { + this.isStarting = false; + + if (this.playStreamId > 0) { + this.onDeleteStream({ streamId: this.playStreamId }); + } + + if (this.publishStreamId > 0) { + this.onDeleteStream({ streamId: this.publishStreamId }); + } + + if (this.pingInterval != null) { + clearInterval(this.pingInterval); + this.pingInterval = null; + } + + if (!this.isIPC) { + // Logger.log(`[rtmp disconnect] id=${this.id}`); + context.nodeEvent.emit('doneConnect', this.id, this.connectCmdObj); + } + + context.sessions.delete(this.id); + this.socket.destroy(); + } + } + + reject() { + // Logger.log(`[rtmp reject] id=${this.id}`); + this.stop(); + } + + writeBuffer(data) { + this.writeBufferQueue.push(data); + if (this.writeBufferQueue.length >= 10) { + this.socket.write(Buffer.concat(this.writeBufferQueue)); + this.writeBufferQueue.length = 0; + } + } + + onSocketClose() { + // Logger.log('onSocketClose'); + this.stop(); + } + + onSocketError(e) { + // Logger.log('onSocketError', e); + this.stop(); + } + + onSocketTimeout() { + // Logger.log('onSocketTimeout'); + this.stop(); + } + + onSocketData(data) { + let bytes = data.length; + let p = 0; + let n = 0; + while (bytes > 0) { + switch (this.handshakeState) { + case RTMP_HANDSHAKE_UNINIT: + // Logger.log('RTMP_HANDSHAKE_UNINIT'); + this.handshakeState = RTMP_HANDSHAKE_0; + this.handshakeBytes = 0; + bytes -= 1; + p += 1; + break; + case RTMP_HANDSHAKE_0: + // Logger.log('RTMP_HANDSHAKE_0'); + n = RTMP_HANDSHAKE_SIZE - this.handshakeBytes; + n = n <= bytes ? n : bytes; + data.copy(this.handshakePayload, this.handshakeBytes, p, p + n); + this.handshakeBytes += n; + bytes -= n; + p += n; + if (this.handshakeBytes === RTMP_HANDSHAKE_SIZE) { + this.handshakeState = RTMP_HANDSHAKE_1; + this.handshakeBytes = 0; + let s0s1s2 = Handshake.generateS0S1S2(this.handshakePayload); + this.socket.write(s0s1s2); + } + break; + case RTMP_HANDSHAKE_1: + // Logger.log('RTMP_HANDSHAKE_1'); + n = RTMP_HANDSHAKE_SIZE - this.handshakeBytes; + n = n <= bytes ? n : bytes; + data.copy(this.handshakePayload, this.handshakeBytes, p, n); + this.handshakeBytes += n; + bytes -= n; + p += n; + if (this.handshakeBytes === RTMP_HANDSHAKE_SIZE) { + this.handshakeState = RTMP_HANDSHAKE_2; + this.handshakeBytes = 0; + this.handshakePayload = null; + } + break; + case RTMP_HANDSHAKE_2: + default: + // Logger.log('RTMP_HANDSHAKE_2'); + return this.rtmpChunkRead(data, p, bytes); + } + } + } + + rtmpChunkBasicHeaderCreate(fmt, cid) { + let out; + if (cid >= 64 + 255) { + out = Buffer.alloc(3); + out[0] = (fmt << 6) | 1; + out[1] = (cid - 64) & 0xFF; + out[2] = ((cid - 64) >> 8) & 0xFF; + } else if (cid >= 64) { + out = Buffer.alloc(2); + out[0] = (fmt << 6) | 0; + out[1] = (cid - 64) & 0xFF; + } else { + out = Buffer.alloc(1); + out[0] = (fmt << 6) | cid; + } + return out; + } + + rtmpChunkMessageHeaderCreate(header) { + let out = Buffer.alloc(rtmpHeaderSize[header.fmt % 4]); + if (header.fmt <= RTMP_CHUNK_TYPE_2) { + out.writeUIntBE(header.timestamp >= 0xffffff ? 0xffffff : header.timestamp, 0, 3); + } + + if (header.fmt <= RTMP_CHUNK_TYPE_1) { + out.writeUIntBE(header.length, 3, 3); + out.writeUInt8(header.type, 6); + } + + if (header.fmt === RTMP_CHUNK_TYPE_0) { + out.writeUInt32LE(header.stream_id, 7); + } + return out; + } + + rtmpChunksCreate(packet) { + let header = packet.header; + let payload = packet.payload; + let payloadSize = header.length; + let chunkSize = this.outChunkSize; + let chunksOffset = 0; + let payloadOffset = 0; + let chunkBasicHeader = this.rtmpChunkBasicHeaderCreate(header.fmt, header.cid); + let chunkBasicHeader3 = this.rtmpChunkBasicHeaderCreate(RTMP_CHUNK_TYPE_3, header.cid); + let chunkMessageHeader = this.rtmpChunkMessageHeaderCreate(header); + let useExtendedTimestamp = header.timestamp >= 0xffffff; + let headerSize = chunkBasicHeader.length + chunkMessageHeader.length + (useExtendedTimestamp ? 4 : 0); + let n = headerSize + payloadSize + Math.floor(payloadSize / chunkSize); + + if (useExtendedTimestamp) { + n += Math.floor(payloadSize / chunkSize) * 4; + } + if (!(payloadSize % chunkSize)) { + n -= 1; + if (useExtendedTimestamp) { //TODO CHECK + n -= 4; + } + } + + let chunks = Buffer.alloc(n); + chunkBasicHeader.copy(chunks, chunksOffset); + chunksOffset += chunkBasicHeader.length; + chunkMessageHeader.copy(chunks, chunksOffset); + chunksOffset += chunkMessageHeader.length; + if (useExtendedTimestamp) { + chunks.writeUInt32BE(header.timestamp, chunksOffset); + chunksOffset += 4; + } + while (payloadSize > 0) { + if (payloadSize > chunkSize) { + payload.copy(chunks, chunksOffset, payloadOffset, payloadOffset + chunkSize); + payloadSize -= chunkSize; + chunksOffset += chunkSize; + payloadOffset += chunkSize; + chunkBasicHeader3.copy(chunks, chunksOffset); + chunksOffset += chunkBasicHeader3.length; + if (useExtendedTimestamp) { + chunks.writeUInt32BE(header.timestamp, chunksOffset); + chunksOffset += 4; + } + } else { + payload.copy(chunks, chunksOffset, payloadOffset, payloadOffset + payloadSize); + payloadSize -= payloadSize; + chunksOffset += payloadSize; + payloadOffset += payloadSize; + } + } + return chunks; + } + + rtmpChunkRead(data, p, bytes) { + // Logger.log('rtmpChunkRead', p, bytes); + + let size = 0; + let offset = 0; + let extended_timestamp = 0; + + while (offset < bytes) { + switch (this.parserState) { + case RTMP_PARSE_INIT: + this.parserBytes = 1; + this.parserBuffer[0] = data[p + offset++]; + if (0 === (this.parserBuffer[0] & 0x3F)) { + this.parserBasicBytes = 2; + } else if (1 === (this.parserBuffer[0] & 0x3F)) { + this.parserBasicBytes = 3; + } else { + this.parserBasicBytes = 1; + } + this.parserState = RTMP_PARSE_BASIC_HEADER; + break; + case RTMP_PARSE_BASIC_HEADER: + while (this.parserBytes < this.parserBasicBytes && offset < bytes) { + this.parserBuffer[this.parserBytes++] = data[p + offset++]; + } + if (this.parserBytes >= this.parserBasicBytes) { + this.parserState = RTMP_PARSE_MESSAGE_HEADER; + } + break; + case RTMP_PARSE_MESSAGE_HEADER: + size = rtmpHeaderSize[this.parserBuffer[0] >> 6] + this.parserBasicBytes; + while (this.parserBytes < size && offset < bytes) { + this.parserBuffer[this.parserBytes++] = data[p + offset++]; + } + if (this.parserBytes >= size) { + this.rtmpPacketParse(); + this.parserState = RTMP_PARSE_EXTENDED_TIMESTAMP; + } + break; + case RTMP_PARSE_EXTENDED_TIMESTAMP: + size = rtmpHeaderSize[this.parserPacket.header.fmt] + this.parserBasicBytes; + if (this.parserPacket.header.timestamp === 0xFFFFFF) size += 4; + while (this.parserBytes < size && offset < bytes) { + this.parserBuffer[this.parserBytes++] = data[p + offset++]; + } + if (this.parserBytes >= size) { + if (this.parserPacket.header.timestamp === 0xFFFFFF) { + extended_timestamp = this.parserBuffer.readUInt32BE(rtmpHeaderSize[this.parserPacket.header.fmt] + this.parserBasicBytes); + } else { + extended_timestamp = this.parserPacket.header.timestamp; + } + + if (this.parserPacket.bytes === 0) { + if (RTMP_CHUNK_TYPE_0 === this.parserPacket.header.fmt) { + this.parserPacket.clock = extended_timestamp; + } else { + this.parserPacket.clock += extended_timestamp; + } + this.rtmpPacketAlloc(); + } + this.parserState = RTMP_PARSE_PAYLOAD; + } + break; + case RTMP_PARSE_PAYLOAD: + size = Math.min(this.inChunkSize - (this.parserPacket.bytes % this.inChunkSize), this.parserPacket.header.length - this.parserPacket.bytes); + size = Math.min(size, bytes - offset); + if (size > 0) { + data.copy(this.parserPacket.payload, this.parserPacket.bytes, p + offset, p + offset + size); + } + this.parserPacket.bytes += size; + offset += size; + + if (this.parserPacket.bytes >= this.parserPacket.header.length) { + this.parserState = RTMP_PARSE_INIT; + this.parserPacket.bytes = 0; + if(this.parserPacket.clock > 0xffffffff){ + //TODO Shit code, rewrite chunkcreate + break; + } + this.rtmpHandler(); + } else if (0 === (this.parserPacket.bytes % this.inChunkSize)) { + this.parserState = RTMP_PARSE_INIT; + } + break; + } + } + + this.inAckSize += data.length; + if (this.inAckSize >= 0xf0000000) { + this.inAckSize = 0; + this.inLastAck = 0; + } + if (this.ackSize > 0 && this.inAckSize - this.inLastAck >= this.ackSize) { + this.inLastAck = this.inAckSize; + this.sendACK(this.inAckSize); + } + + } + + rtmpPacketParse() { + let fmt = this.parserBuffer[0] >> 6; + let cid = 0; + if (this.parserBasicBytes === 2) { + cid = 64 + this.parserBuffer[1]; + } else if (this.parserBasicBytes === 3) { + cid = 64 + this.parserBuffer[1] + this.parserBuffer[2] << 8; + } else { + cid = this.parserBuffer[0] & 0x3F; + } + let hasp = this.inPackets.has(cid); + if (!hasp) { + this.parserPacket = RtmpPacket.create(fmt, cid); + this.inPackets.set(cid, this.parserPacket); + } else { + this.parserPacket = this.inPackets.get(cid); + } + this.parserPacket.header.fmt = fmt; + this.parserPacket.header.cid = cid; + this.rtmpChunkMessageHeaderRead(); + + if (this.parserPacket.header.type > RTMP_TYPE_METADATA) { + Logger.error("rtmp packet parse error.", this.parserPacket); + this.stop(); + } + + } + + rtmpChunkMessageHeaderRead() { + let offset = this.parserBasicBytes; + + // timestamp / delta + if (this.parserPacket.header.fmt <= RTMP_CHUNK_TYPE_2) { + this.parserPacket.header.timestamp = this.parserBuffer.readUIntBE(offset, 3); + offset += 3; + } + + // message length + type + if (this.parserPacket.header.fmt <= RTMP_CHUNK_TYPE_1) { + this.parserPacket.header.length = this.parserBuffer.readUIntBE(offset, 3); + this.parserPacket.header.type = this.parserBuffer[offset + 3]; + offset += 4; + } + + if (this.parserPacket.header.fmt === RTMP_CHUNK_TYPE_0) { + this.parserPacket.header.stream_id = this.parserBuffer.readUInt32LE(offset); + offset += 4; + } + return offset; + } + + rtmpPacketAlloc() { + if (this.parserPacket.capacity < this.parserPacket.header.length) { + this.parserPacket.payload = Buffer.alloc(this.parserPacket.header.length + 1024); + this.parserPacket.capacity = this.parserPacket.header.length + 1024; + } + } + + rtmpHandler() { + switch (this.parserPacket.header.type) { + case RTMP_TYPE_SET_CHUNK_SIZE: + case RTMP_TYPE_ABORT: + case RTMP_TYPE_ACKNOWLEDGEMENT: + case RTMP_TYPE_WINDOW_ACKNOWLEDGEMENT_SIZE: + case RTMP_TYPE_SET_PEER_BANDWIDTH: + return 0 === this.rtmpControlHandler() ? -1 : 0; + case RTMP_TYPE_EVENT: + return 0 === this.rtmpEventHandler() ? -1 : 0; + case RTMP_TYPE_AUDIO: + return this.rtmpAudioHandler(); + case RTMP_TYPE_VIDEO: + return this.rtmpVideoHandler(); + case RTMP_TYPE_FLEX_MESSAGE: + case RTMP_TYPE_INVOKE: + return this.rtmpInvokeHandler(); + case RTMP_TYPE_FLEX_STREAM:// AMF3 + case RTMP_TYPE_DATA: // AMF0 + return this.rtmpDataHandler(); + } + } + + rtmpControlHandler() { + let payload = this.parserPacket.payload; + switch (this.parserPacket.header.type) { + case RTMP_TYPE_SET_CHUNK_SIZE: + this.inChunkSize = payload.readUInt32BE(); + // Logger.debug('set inChunkSize', this.inChunkSize); + break; + case RTMP_TYPE_ABORT: + break; + case RTMP_TYPE_ACKNOWLEDGEMENT: + break; + case RTMP_TYPE_WINDOW_ACKNOWLEDGEMENT_SIZE: + this.ackSize = payload.readUInt32BE(); + // Logger.debug('set ack Size', this.ackSize); + break; + case RTMP_TYPE_SET_PEER_BANDWIDTH: + break; + } + } + + rtmpEventHandler() { + + } + + rtmpAudioHandler() { + let payload = this.parserPacket.payload.slice(0, this.parserPacket.header.length); + let sound_format = (payload[0] >> 4) & 0x0f; + let sound_type = payload[0] & 0x01; + let sound_size = (payload[0] >> 1) & 0x01; + let sound_rate = (payload[0] >> 2) & 0x03; + + if (this.audioCodec == 0) { + this.audioCodec = sound_format; + this.audioCodecName = AUDIO_CODEC_NAME[sound_format]; + this.audioSamplerate = AUDIO_SOUND_RATE[sound_rate]; + this.audioChannels = ++sound_type; + + if (sound_format == 4) { + this.audioSamplerate = 16000; + } else if (sound_format == 5) { + this.audioSamplerate = 8000; + } else if (sound_format == 11) { + this.audioSamplerate = 16000; + } else if (sound_format == 14) { + this.audioSamplerate = 8000; + } + + if (sound_format != 10 && !this.isIPC) { + // Logger.log(`[rtmp publish] Handle audio. id=${this.id} streamPath=${this.publishStreamPath} sound_format=${sound_format} sound_type=${sound_type} sound_size=${sound_size} sound_rate=${sound_rate} codec_name=${this.audioCodecName} ${this.audioSamplerate} ${this.audioChannels}ch`); + } + } + + if (sound_format == 10 && payload[1] == 0) { + //cache aac sequence header + this.isFirstAudioReceived = true; + this.aacSequenceHeader = Buffer.alloc(payload.length); + payload.copy(this.aacSequenceHeader); + let info = AV.readAACSpecificConfig(this.aacSequenceHeader); + this.audioProfileName = AV.getAACProfileName(info); + this.audioSamplerate = info.sample_rate; + this.audioChannels = info.channels; + if (!this.isIPC) { + // Logger.log(`[rtmp publish] Handle audio. id=${this.id} streamPath=${this.publishStreamPath} sound_format=${sound_format} sound_type=${sound_type} sound_size=${sound_size} sound_rate=${sound_rate} codec_name=${this.audioCodecName} ${this.audioSamplerate} ${this.audioChannels}ch`); + } + } + + let packet = RtmpPacket.create(); + packet.header.fmt = RTMP_CHUNK_TYPE_0; + packet.header.cid = RTMP_CHANNEL_AUDIO; + packet.header.type = RTMP_TYPE_AUDIO; + packet.payload = payload; + packet.header.length = packet.payload.length; + packet.header.timestamp = this.parserPacket.clock; + let rtmpChunks = this.rtmpChunksCreate(packet); + + //cache gop + if (this.rtmpGopCacheQueue != null) { + if (this.aacSequenceHeader != null && payload[1] === 0) { + //skip aac sequence header + } else { + this.rtmpGopCacheQueue.add(rtmpChunks); + } + } + + for (let playerId of this.players) { + let playerSession = context.sessions.get(playerId); + if (playerSession instanceof NodeRtmpSession) { + if (playerSession.isStarting && playerSession.isPlaying && !playerSession.isPause && playerSession.isReceiveAudio) { + rtmpChunks.writeUInt32LE(playerSession.playStreamId, 8); + playerSession.writeBuffer(rtmpChunks); + } + } + } + } + + rtmpVideoHandler() { + let payload = this.parserPacket.payload.slice(0, this.parserPacket.header.length); + let frame_type = (payload[0] >> 4) & 0x0f; + let codec_id = payload[0] & 0x0f; + + if (codec_id == 7 || codec_id == 12) { + //cache avc sequence header + if (frame_type == 1 && payload[1] == 0) { + this.avcSequenceHeader = Buffer.alloc(payload.length); + payload.copy(this.avcSequenceHeader); + let info = AV.readAVCSpecificConfig(this.avcSequenceHeader); + this.videoWidth = info.width; + this.videoHeight = info.height; + this.videoProfileName = AV.getAVCProfileName(info); + this.videoLevel = info.level; + this.rtmpGopCacheQueue = this.gopCacheEnable ? new Set() : null; + //Logger.log(`[rtmp publish] avc sequence header`,this.avcSequenceHeader); + } + } + + if (this.videoCodec == 0) { + this.videoCodec = codec_id; + this.videoCodecName = VIDEO_CODEC_NAME[codec_id]; + if (!this.isIPC) { + // Logger.log(`[rtmp publish] Handle video. id=${this.id} streamPath=${this.publishStreamPath} frame_type=${frame_type} codec_id=${codec_id} codec_name=${this.videoCodecName} ${this.videoWidth}x${this.videoHeight}`); + } + } + + let packet = RtmpPacket.create(); + packet.header.fmt = RTMP_CHUNK_TYPE_0; + packet.header.cid = RTMP_CHANNEL_VIDEO; + packet.header.type = RTMP_TYPE_VIDEO; + packet.payload = payload; + packet.header.length = packet.payload.length; + packet.header.timestamp = this.parserPacket.clock; + let rtmpChunks = this.rtmpChunksCreate(packet); + + //cache gop + if ((codec_id == 7 || codec_id == 12) && this.rtmpGopCacheQueue != null) { + if (frame_type == 1 && payload[1] == 1) { + this.rtmpGopCacheQueue.clear(); + } + if (frame_type == 1 && payload[1] == 0) { + //skip avc sequence header + } else { + this.rtmpGopCacheQueue.add(rtmpChunks); + } + } + + // Logger.log(rtmpChunks); + for (let playerId of this.players) { + let playerSession = context.sessions.get(playerId); + if (playerSession instanceof NodeRtmpSession) { + if (playerSession.isStarting && playerSession.isPlaying && !playerSession.isPause && playerSession.isReceiveVideo) { + rtmpChunks.writeUInt32LE(playerSession.playStreamId, 8); + playerSession.writeBuffer(rtmpChunks); + } + } + } + } + + rtmpDataHandler() { + let offset = this.parserPacket.header.type === RTMP_TYPE_FLEX_STREAM ? 1 : 0; + let payload = this.parserPacket.payload.slice(offset, this.parserPacket.header.length); + let dataMessage = AMF.decodeAmf0Data(payload); + switch (dataMessage.cmd) { + case '@setDataFrame': + if (dataMessage.dataObj) { + this.audioSamplerate = dataMessage.dataObj.audiosamplerate; + this.audioChannels = dataMessage.dataObj.stereo ? 2 : 1; + this.videoWidth = dataMessage.dataObj.width; + this.videoHeight = dataMessage.dataObj.height; + this.videoFps = dataMessage.dataObj.framerate; + } + + let opt = { + cmd: 'onMetaData', + dataObj: dataMessage.dataObj + }; + this.metaData = AMF.encodeAmf0Data(opt); + + let packet = RtmpPacket.create(); + packet.header.fmt = RTMP_CHUNK_TYPE_0; + packet.header.cid = RTMP_CHANNEL_DATA; + packet.header.type = RTMP_TYPE_DATA; + packet.payload = this.metaData; + packet.header.length = packet.payload.length; + let rtmpChunks = this.rtmpChunksCreate(packet); + + for (let playerId of this.players) { + let playerSession = context.sessions.get(playerId); + if (playerSession instanceof NodeRtmpSession) { + if (playerSession.isStarting && playerSession.isPlaying && !playerSession.isPause) { + rtmpChunks.writeUInt32LE(playerSession.playStreamId, 8); + playerSession.socket.write(rtmpChunks); + } + } + } + break; + } + } + + rtmpInvokeHandler() { + let offset = this.parserPacket.header.type === RTMP_TYPE_FLEX_MESSAGE ? 1 : 0; + let payload = this.parserPacket.payload.slice(offset, this.parserPacket.header.length); + let invokeMessage = AMF.decodeAmf0Cmd(payload); + // Logger.log(invokeMessage); + switch (invokeMessage.cmd) { + case 'connect': + this.onConnect(invokeMessage); + break; + case 'releaseStream': + break; + case 'FCPublish': + break; + case 'createStream': + this.onCreateStream(invokeMessage); + break; + case 'publish': + this.onPublish(invokeMessage); + break; + case 'play': + this.onPlay(invokeMessage); + break; + case 'pause': + this.onPause(invokeMessage); + break; + case 'FCUnpublish': + break; + case 'deleteStream': + this.onDeleteStream(invokeMessage); + break; + case 'closeStream': + this.onCloseStream(); + break; + case 'receiveAudio': + this.onReceiveAudio(invokeMessage); + break; + case 'receiveVideo': + this.onReceiveVideo(invokeMessage); + break; + } + } + + sendACK(size) { + let rtmpBuffer = Buffer.from('02000000000004030000000000000000', 'hex'); + rtmpBuffer.writeUInt32BE(size, 12); + this.socket.write(rtmpBuffer); + } + + sendWindowACK(size) { + let rtmpBuffer = Buffer.from('02000000000004050000000000000000', 'hex'); + rtmpBuffer.writeUInt32BE(size, 12); + this.socket.write(rtmpBuffer); + }; + + setPeerBandwidth(size, type) { + let rtmpBuffer = Buffer.from('0200000000000506000000000000000000', 'hex'); + rtmpBuffer.writeUInt32BE(size, 12); + rtmpBuffer[16] = type; + this.socket.write(rtmpBuffer); + }; + + setChunkSize(size) { + let rtmpBuffer = Buffer.from('02000000000004010000000000000000', 'hex'); + rtmpBuffer.writeUInt32BE(size, 12); + this.socket.write(rtmpBuffer); + }; + + sendStreamStatus(st, id) { + let rtmpBuffer = Buffer.from('020000000000060400000000000000000000', 'hex'); + rtmpBuffer.writeUInt16BE(st, 12); + rtmpBuffer.writeUInt32BE(id, 14); + this.socket.write(rtmpBuffer); + } + + sendInvokeMessage(sid, opt) { + let packet = RtmpPacket.create(); + packet.header.fmt = RTMP_CHUNK_TYPE_0; + packet.header.cid = RTMP_CHANNEL_INVOKE; + packet.header.type = RTMP_TYPE_INVOKE; + packet.header.stream_id = sid; + packet.payload = AMF.encodeAmf0Cmd(opt); + packet.header.length = packet.payload.length; + let chunks = this.rtmpChunksCreate(packet); + this.socket.write(chunks); + } + + sendDataMessage(opt, sid) { + let packet = RtmpPacket.create(); + packet.header.fmt = RTMP_CHUNK_TYPE_0; + packet.header.cid = RTMP_CHANNEL_DATA; + packet.header.type = RTMP_TYPE_DATA; + packet.payload = AMF.encodeAmf0Data(opt); + packet.header.length = packet.payload.length; + packet.header.stream_id = sid; + let chunks = this.rtmpChunksCreate(packet); + this.socket.write(chunks); + } + + sendStatusMessage(sid, level, code, description) { + let opt = { + cmd: 'onStatus', + transId: 0, + cmdObj: null, + info: { + level: level, + code: code, + description: description + } + }; + this.sendInvokeMessage(sid, opt); + } + + sendRtmpSampleAccess(sid) { + let opt = { + cmd: '|RtmpSampleAccess', + bool1: false, + bool2: false + }; + this.sendDataMessage(opt, sid); + } + + sendPingRequest() { + let currentTimestamp = Date.now() - this.startTimestamp; + let packet = RtmpPacket.create(); + packet.header.fmt = RTMP_CHUNK_TYPE_0; + packet.header.cid = RTMP_CHANNEL_PROTOCOL; + packet.header.type = RTMP_TYPE_EVENT; + packet.header.timestamp = currentTimestamp; + packet.payload = Buffer.from([0, 6, (currentTimestamp >> 24) & 0xff, (currentTimestamp >> 16) & 0xff, (currentTimestamp >> 8) & 0xff, currentTimestamp & 0xff]); + packet.header.length = packet.payload.length; + let chunks = this.rtmpChunksCreate(packet); + this.socket.write(chunks); + } + + respondConnect(tid) { + let opt = { + cmd: '_result', + transId: tid, + cmdObj: { + fmsVer: 'FMS/3,0,1,123', + capabilities: 31 + }, + info: { + level: 'status', + code: 'NetConnection.Connect.Success', + description: 'Connection succeeded.', + objectEncoding: this.objectEncoding + } + }; + this.sendInvokeMessage(0, opt); + } + + respondCreateStream(tid) { + this.streams++; + let opt = { + cmd: "_result", + transId: tid, + cmdObj: null, + info: this.streams + }; + this.sendInvokeMessage(0, opt); + } + + respondPlay() { + this.sendStreamStatus(STREAM_BEGIN, this.playStreamId); + this.sendStatusMessage(this.playStreamId, 'status', 'NetStream.Play.Reset', 'Playing and resetting stream.'); + this.sendStatusMessage(this.playStreamId, 'status', 'NetStream.Play.Start', 'Started playing stream.'); + this.sendRtmpSampleAccess(); + } + + onConnect(invokeMessage) { + invokeMessage.cmdObj.app = invokeMessage.cmdObj.app.replace('/', ''); //fix jwplayer + if (!this.isIPC) { + context.nodeEvent.emit('preConnect', this.id, invokeMessage.cmdObj); + } + // this.eventEmitter.emit('authConnection', { + // appname: this.appname, + // _this: this + // }); + if (!this.isStarting) { + return; + } + this.connectCmdObj = invokeMessage.cmdObj; + this.appname = invokeMessage.cmdObj.app; + this.objectEncoding = invokeMessage.cmdObj.objectEncoding != null ? invokeMessage.cmdObj.objectEncoding : 0; + this.connectTime = new Date(); + this.startTimestamp = Date.now(); + this.pingInterval = setInterval(() => { + this.sendPingRequest(); + }, this.pingTime); + this.sendWindowACK(5000000); + this.setPeerBandwidth(5000000, 2); + this.setChunkSize(this.outChunkSize); + this.respondConnect(invokeMessage.transId); + if (!this.isIPC) { + // Logger.log(`[rtmp connect] id=${this.id} ip=${this.ip} app=${this.appname} args=${JSON.stringify(invokeMessage.cmdObj)}`); + context.nodeEvent.emit('postConnect', this.id, invokeMessage.cmdObj); + } + } + + onCreateStream(invokeMessage) { + this.respondCreateStream(invokeMessage.transId); + } + + onPublish(invokeMessage) { + if (typeof invokeMessage.streamName !== 'string') { + return; + } + this.publishStreamPath = '/' + this.appname + '/' + invokeMessage.streamName.split('?')[0]; + this.publishArgs = QueryString.parse(invokeMessage.streamName.split('?')[1]); + this.publishStreamId = this.parserPacket.header.stream_id; + if (!this.isIPC) { + context.nodeEvent.emit('prePublish', this.id, this.publishStreamPath, this.publishArgs); + } + if (!this.isStarting) { + return; + } + + if (this.config.auth && this.config.auth.publish && !this.isLocal && !this.isIPC) { + let results = NodeCoreUtils.verifyAuth(this.publishArgs.sign, this.publishStreamPath, this.config.auth.secret); + if (!results) { + // Logger.log(`[rtmp publish] Unauthorized. id=${this.id} streamPath=${this.publishStreamPath} streamId=${this.publishStreamId} sign=${this.publishArgs.sign} `); + this.sendStatusMessage(this.publishStreamId, 'error', 'NetStream.publish.Unauthorized', 'Authorization required.'); + return; + } + } + + if (context.publishers.has(this.publishStreamPath)) { + // Logger.log(`[rtmp publish] Already has a stream. id=${this.id} streamPath=${this.publishStreamPath} streamId=${this.publishStreamId}`); + this.sendStatusMessage(this.publishStreamId, 'error', 'NetStream.Publish.BadName', 'Stream already publishing'); + } else if (this.isPublishing) { + // Logger.log(`[rtmp publish] NetConnection is publishing. id=${this.id} streamPath=${this.publishStreamPath} streamId=${this.publishStreamId}`); + this.sendStatusMessage(this.publishStreamId, 'error', 'NetStream.Publish.BadConnection', 'Connection already publishing'); + } else { + if (!this.isIPC) { + // Logger.log(`[rtmp publish] New stream. id=${this.id} streamPath=${this.publishStreamPath} streamId=${this.publishStreamId}`); + } + context.publishers.set(this.publishStreamPath, this.id); + this.isPublishing = true; + + this.sendStatusMessage(this.publishStreamId, 'status', 'NetStream.Publish.Start', `${this.publishStreamPath} is now published.`); + for (let idlePlayerId of context.idlePlayers) { + let idlePlayer = context.sessions.get(idlePlayerId); + if (idlePlayer.playStreamPath === this.publishStreamPath) { + idlePlayer.onStartPlay(); + context.idlePlayers.delete(idlePlayerId); + } + } + setTimeout(() => { + this.publishArgs.ac = this.audioCodec; + this.publishArgs.vc = this.videoCodec; + if (!this.isIPC) { + context.nodeEvent.emit('postPublish', this.id, this.publishStreamPath, this.publishArgs); + } + }, 1000);//TODO 只提交事件,不传音视频参数,由转码器自行分析 + + } + } + + onPlay(invokeMessage) { + if (typeof invokeMessage.streamName !== 'string') { + return; + } + this.playStreamPath = '/' + this.appname + '/' + invokeMessage.streamName.split('?')[0]; + this.playArgs = QueryString.parse(invokeMessage.streamName.split('?')[1]); + this.playStreamId = this.parserPacket.header.stream_id; + if (!this.isIPC) { + context.nodeEvent.emit('prePlay', this.id, this.playStreamPath, this.playArgs); + } + if (!this.isStarting) { + return; + } + + if (this.config.auth && this.config.auth.play && !this.isLocal && !this.isIPC) { + let results = NodeCoreUtils.verifyAuth(this.playArgs.sign, this.playStreamPath, this.config.auth.secret); + if (!results) { + // Logger.log(`[rtmp play] Unauthorized. id=${this.id} streamPath=${this.playStreamPath} streamId=${this.playStreamId} sign=${this.playArgs.sign}`); + this.sendStatusMessage(this.playStreamId, 'error', 'NetStream.play.Unauthorized', 'Authorization required.'); + return; + } + } + + if (this.isPlaying) { + if (!this.isIPC) { + // Logger.log(`[rtmp play] NetConnection is playing. id=${this.id} streamPath=${this.playStreamPath} streamId=${this.playStreamId} `); + } + this.sendStatusMessage(this.playStreamId, 'error', 'NetStream.Play.BadConnection', 'Connection already playing'); + } else { + this.respondPlay(); + } + + if (context.publishers.has(this.playStreamPath)) { + this.onStartPlay(); + } else { + // Logger.log(`[rtmp play] Stream not found. id=${this.id} streamPath=${this.playStreamPath} streamId=${this.playStreamId}`); + this.isIdling = true; + context.idlePlayers.add(this.id); + } + + } + + onStartPlay() { + let publisherId = context.publishers.get(this.playStreamPath); + let publisher = context.sessions.get(publisherId); + let players = publisher.players; + players.add(this.id); + + if (publisher.metaData != null) { + let packet = RtmpPacket.create(); + packet.header.fmt = RTMP_CHUNK_TYPE_0; + packet.header.cid = RTMP_CHANNEL_DATA; + packet.header.type = RTMP_TYPE_DATA; + packet.payload = publisher.metaData; + packet.header.length = packet.payload.length; + packet.header.stream_id = this.playStreamId; + let chunks = this.rtmpChunksCreate(packet); + this.socket.write(chunks); + } + + if (publisher.audioCodec === 10) { + let packet = RtmpPacket.create(); + packet.header.fmt = RTMP_CHUNK_TYPE_0; + packet.header.cid = RTMP_CHANNEL_AUDIO; + packet.header.type = RTMP_TYPE_AUDIO; + packet.payload = publisher.aacSequenceHeader; + packet.header.length = packet.payload.length; + packet.header.stream_id = this.playStreamId; + let chunks = this.rtmpChunksCreate(packet); + this.socket.write(chunks); + } + + if (publisher.videoCodec === 7 || publisher.videoCodec === 12) { + let packet = RtmpPacket.create(); + packet.header.fmt = RTMP_CHUNK_TYPE_0; + packet.header.cid = RTMP_CHANNEL_VIDEO; + packet.header.type = RTMP_TYPE_VIDEO; + packet.payload = publisher.avcSequenceHeader; + packet.header.length = packet.payload.length; + packet.header.stream_id = this.playStreamId; + let chunks = this.rtmpChunksCreate(packet); + this.socket.write(chunks); + } + + if (publisher.rtmpGopCacheQueue != null) { + for (let chunks of publisher.rtmpGopCacheQueue) { + chunks.writeUInt32LE(this.playStreamId, 8); + this.socket.write(chunks); + } + } + + this.isIdling = false; + this.isPlaying = true; + if (!this.isIPC) { + context.nodeEvent.emit('postPlay', this.id, this.playStreamPath, this.playArgs); + // Logger.log(`[rtmp play] Join stream. id=${this.id} streamPath=${this.playStreamPath} streamId=${this.playStreamId} `); + } + } + + onPause(invokeMessage) { + this.isPause = invokeMessage.pause; + let c = this.isPause ? 'NetStream.Pause.Notify' : 'NetStream.Unpause.Notify'; + let d = this.isPause ? 'Paused live' : 'Unpaused live'; + // Logger.log(`[rtmp play] ${d} stream. id=${this.id} streamPath=${this.playStreamPath} streamId=${this.playStreamId} `); + if (!this.isPause) { + this.sendStreamStatus(STREAM_BEGIN, this.playStreamId); + if (context.publishers.has(this.playStreamPath)) { + //fix ckplayer + let publisherId = context.publishers.get(this.playStreamPath); + let publisher = context.sessions.get(publisherId); + let players = publisher.players; + if (publisher.audioCodec === 10) { + let packet = RtmpPacket.create(); + packet.header.fmt = RTMP_CHUNK_TYPE_0; + packet.header.cid = RTMP_CHANNEL_AUDIO; + packet.header.type = RTMP_TYPE_AUDIO; + packet.payload = publisher.aacSequenceHeader; + packet.header.length = packet.payload.length; + packet.header.stream_id = this.playStreamId; + packet.header.timestamp = publisher.parserPacket.clock; // ?? 0 or clock + let chunks = this.rtmpChunksCreate(packet); + this.socket.write(chunks); + } + if (publisher.videoCodec === 7 || publisher.videoCodec === 12) { + let packet = RtmpPacket.create(); + packet.header.fmt = RTMP_CHUNK_TYPE_0; + packet.header.cid = RTMP_CHANNEL_VIDEO; + packet.header.type = RTMP_TYPE_VIDEO; + packet.payload = publisher.avcSequenceHeader; + packet.header.length = packet.payload.length; + packet.header.stream_id = this.playStreamId; + packet.header.timestamp = publisher.parserPacket.clock;// ?? 0 or clock + let chunks = this.rtmpChunksCreate(packet); + this.socket.write(chunks); + } + } + + } else { + this.sendStreamStatus(STREAM_EOF, this.playStreamId); + } + this.sendStatusMessage(this.playStreamId, c, d); + } + + onReceiveAudio(invokeMessage) { + this.isReceiveAudio = invokeMessage.bool; + // Logger.log(`[rtmp play] receiveAudio=${this.isReceiveAudio} id=${this.id} `); + } + + onReceiveVideo(invokeMessage) { + this.isReceiveVideo = invokeMessage.bool; + // Logger.log(`[rtmp play] receiveVideo=${this.isReceiveVideo} id=${this.id} `); + } + + onCloseStream() { + //red5-publisher + let closeStream = { streamId: this.parserPacket.header.stream_id }; + this.onDeleteStream(closeStream); + } + + onDeleteStream(invokeMessage) { + if (invokeMessage.streamId == this.playStreamId) { + if (this.isIdling) { + context.idlePlayers.delete(this.id); + this.isIdling = false; + } else { + let publisherId = context.publishers.get(this.playStreamPath); + if (publisherId != null) { + context.sessions.get(publisherId).players.delete(this.id); + } + if (!this.isIPC) { + context.nodeEvent.emit('donePlay', this.id, this.playStreamPath, this.playArgs); + } + this.isPlaying = false; + } + if (!this.isIPC) { + // Logger.log(`[rtmp play] Close stream. id=${this.id} streamPath=${this.playStreamPath} streamId=${this.playStreamId}`); + } + if (this.isStarting) { + this.sendStatusMessage(this.playStreamId, 'status', 'NetStream.Play.Stop', 'Stopped playing stream.'); + } + this.playStreamId = 0; + this.playStreamPath = ''; + } + + if (invokeMessage.streamId == this.publishStreamId) { + if (this.isPublishing) { + if (!this.isIPC) { + // Logger.log(`[rtmp publish] Close stream. id=${this.id} streamPath=${this.publishStreamPath} streamId=${this.publishStreamId}`); + context.nodeEvent.emit('donePublish', this.id, this.publishStreamPath, this.publishArgs); + } + if (this.isStarting) { + this.sendStatusMessage(this.publishStreamId, 'status', 'NetStream.Unpublish.Success', `${this.publishStreamPath} is now unpublished.`); + } + + for (let playerId of this.players) { + let player = context.sessions.get(playerId); + if (player instanceof NodeRtmpSession) { + player.sendStatusMessage(player.playStreamId, 'status', 'NetStream.Play.UnpublishNotify', 'stream is now unpublished.'); + } else { + player.stop(); + } + } + + //let the players to idlePlayers + for (let playerId of this.players) { + let player = context.sessions.get(playerId); + context.idlePlayers.add(playerId); + player.isPlaying = false; + player.isIdling = true; + if (player instanceof NodeRtmpSession) { + player.sendStreamStatus(STREAM_EOF, player.playStreamId); + } + } + + context.publishers.delete(this.publishStreamPath); + if (this.rtmpGopCacheQueue) { + this.rtmpGopCacheQueue.clear(); + } + this.players.clear(); + this.isPublishing = false; + } + this.publishStreamId = 0; + this.publishStreamPath = ''; + } + } +} + +module.exports = NodeRtmpSession; diff --git a/libs/scheduler.js b/libs/scheduler.js new file mode 100644 index 0000000..4cf0812 --- /dev/null +++ b/libs/scheduler.js @@ -0,0 +1,263 @@ +module.exports = function(s,config,lang,app,io){ + s.schedules = {} + //Get all Schedules + s.getAllSchedules = function(callback){ + s.schedules = {} + s.sqlQuery('SELECT * FROM Schedules',function(err,rows){ + rows.forEach(function(schedule){ + s.updateSchedule(schedule) + }) + if(callback)callback() + }) + } + //update schedule + s.updateSchedule = function(row){ + var schedule = Object.assign(row,{}) + if(!s.schedules[schedule.ke])s.schedules[schedule.ke] = {} + s.checkDetails(schedule) + if(!s.schedules[schedule.ke][schedule.name]){ + s.schedules[schedule.ke][schedule.name] = schedule + }else{ + s.schedules[schedule.ke][schedule.name] = Object.assign(s.schedules[schedule.ke][schedule.name],schedule) + } + } + //check time in schedule + s.checkTimeAgainstSchedule = function(start,end,callback){ + try{ + if( + start + ){ + var checkStartTime = new Date() + var startSplit = start.split(':') + var startHour = parseInt(startSplit[0]) + var startMin = parseInt(startSplit[1]) + checkStartTime.setHours(startHour) + checkStartTime.setMinutes(startMin) + if(end){ + var checkEndTime = new Date() + var endSplit = end.split(':') + var endHour = parseInt(endSplit[0]) + var endMin = parseInt(endSplit[1]) + checkEndTime.setHours(endHour) + checkEndTime.setMinutes(endMin) + } + var currentDate = new Date() + if( + ( + currentDate >= checkStartTime && + currentDate <= checkEndTime + ) || + currentDate >= checkStartTime && !end + ){ + callback() + }else{ + callback({ + currentDate : currentDate, + startTime : checkStartTime, + endTime : checkEndTime + }) + } + }else{ + callback() + } + }catch(err){ + console.log(err) + callback() + } + } + //check all Schedules + s.checkSchedules = function(v,callback){ + var groupKeys = Object.keys(s.schedules) + groupKeys.forEach(function(key){ + var scheduleNames = Object.keys(s.schedules[key]) + scheduleNames.forEach(function(name){ + var schedule = s.schedules[key][name] + if(!schedule.active && schedule.enabled === 1 && schedule.start && schedule.details.monitorStates){ + s.checkTimeAgainstSchedule(schedule.start,schedule.end,function(err){ + if(!err){ + schedule.active = true + var monitorStates = schedule.details.monitorStates + monitorStates.forEach(function(stateName){ + s.activateMonitorStates(key,stateName,{ + ke: key, + uid: 'System', + details: {}, + permissions: {}, + lang: lang + },function(endData){ + // console.log(endData) + }) + }) + }else{ + schedule.active = false + } + }) + } + }) + }) + } + // + s.findSchedule = function(groupKey,name,callback){ + //presetQueryVals = [ke, type, name] + s.sqlQuery("SELECT * FROM Schedules WHERE ke=? AND name=? LIMIT 1",[groupKey,name],function(err,schedules){ + var schedule + var notFound = false + if(schedules && schedules[0]){ + schedule = schedules[0] + s.checkDetails(schedule) + }else{ + notFound = true + } + callback(notFound,schedule) + }) + } + // + var onProcessReady = function(){ + s.getAllSchedules(function(){ + s.checkSchedules() + }) + setInterval(function(){ + s.checkSchedules() + },1000 * 60 * 5) + } + /** + * WebServerPath : API : Get Schedule + */ + app.all([ + config.webPaths.apiPrefix+':auth/schedule/:ke', + config.webPaths.adminApiPrefix+':auth/schedule/:ke', + config.webPaths.apiPrefix+':auth/schedule/:ke/:name', + config.webPaths.adminApiPrefix+':auth/schedule/:ke/:name', + config.webPaths.apiPrefix+':auth/schedules/:ke', + config.webPaths.adminApiPrefix+':auth/schedules/:ke', + config.webPaths.apiPrefix+':auth/schedules/:ke/:name', + config.webPaths.adminApiPrefix+':auth/schedules/:ke/:name', + ],function (req,res){ + s.auth(req.params,function(user){ + var endData = { + ok : false + } + if(user.details.sub){ + endData.msg = user.lang['Not Permitted'] + s.closeJsonResponse(res,endData) + return + } + var theQuery = "SELECT * FROM Schedules WHERE ke=?" + var theQueryValues = [req.params.ke] + if(req.params.name){ + theQuery += ' AND name=?' + theQueryValues.push(req.params.name) + } + s.sqlQuery(theQuery,theQueryValues,function(err,schedules){ + if(schedules && schedules[0]){ + endData.ok = true + schedules.forEach(function(schedule){ + s.checkDetails(schedule) + }) + endData.schedules = schedules + }else{ + endData.msg = user.lang['Not Found'] + } + s.closeJsonResponse(res,endData) + }) + }) + }) + /** + * WebServerPath : API : Update Schedule + */ + app.all([ + config.webPaths.apiPrefix+':auth/schedule/:ke/:name/:action', + config.webPaths.adminApiPrefix+':auth/schedule/:ke/:name/:action', + config.webPaths.apiPrefix+':auth/schedules/:ke/:name/:action', + config.webPaths.adminApiPrefix+':auth/schedules/:ke/:name/:action' + ],function (req,res){ + s.auth(req.params,function(user){ + var endData = { + ok : false + } + if(user.details.sub){ + endData.msg = user.lang['Not Permitted'] + s.closeJsonResponse(res,endData) + return + } + switch(req.params.action){ + case'insert':case'edit': + var form = s.getPostData(req) + s.checkDetails(form) + if(!form || !form.details){ + endData.msg = user.lang['Form Data Not Found'] + s.closeJsonResponse(res,endData) + return + } + form.enabled = parseInt(form.enabled) || 1; + s.findSchedule(req.params.ke,req.params.name,function(notFound,preset){ + if(notFound === true){ + endData.msg = lang["Inserted Schedule Configuration"] + var insertData = { + ke: req.params.ke, + name: req.params.name, + details: s.stringJSON(form.details), + start: form.start, + end: form.end, + enabled: form.enabled + } + s.sqlQuery('INSERT INTO Schedules ('+Object.keys(insertData).join(',')+') VALUES (?,?,?,?,?,?)',Object.values(insertData)) + s.tx({ + f: 'add_schedule', + insertData: insertData, + ke: req.params.ke, + name: req.params.name + },'GRP_'+req.params.ke) + }else{ + endData.msg = lang["Edited Schedule Configuration"] + var insertData = { + details: s.stringJSON(form.details), + start: form.start, + end: form.end, + enabled: form.enabled, + ke: req.params.ke, + name: req.params.name + } + s.sqlQuery('UPDATE Schedules SET details=?,start=?,end=?,enabled=? WHERE ke=? AND name=?',Object.values(insertData)) + s.tx({ + f: 'edit_schedule', + insertData: insertData, + ke: req.params.ke, + name: req.params.name + },'GRP_'+req.params.ke) + } + s.updateSchedule({ + ke: req.params.ke, + name: req.params.name, + details: s.stringJSON(form.details), + start: form.start, + end: form.end, + enabled: form.enabled + }) + endData.ok = true + s.closeJsonResponse(res,endData) + }) + break; + case'delete': + s.findSchedule(req.params.ke,req.params.name,function(notFound,schedule){ + if(notFound === true){ + endData.msg = user.lang['Schedule Configuration Not Found'] + s.closeJsonResponse(res,endData) + }else{ + s.sqlQuery('DELETE FROM Schedules WHERE ke=? AND name=?',[req.params.ke,req.params.name],function(err){ + if(!err){ + endData.msg = lang["Deleted Schedule Configuration"] + endData.ok = true + if(s.schedules[schedule.ke])delete(s.schedules[schedule.ke][schedule.name]) + } + s.closeJsonResponse(res,endData) + }) + } + }) + break; + } + }) + }) + //bind events + s.onProcessReady(onProcessReady) +} diff --git a/libs/socketio.js b/libs/socketio.js index c690f0e..3e0b139 100644 --- a/libs/socketio.js +++ b/libs/socketio.js @@ -9,12 +9,8 @@ module.exports = function(s,config,lang,io){ s.clientSocketConnection = {} //send data to detector plugin s.ocvTx=function(data){ - if(!s.ocv){return} - if(s.ocv.isClientPlugin===true){ - s.tx(data,s.ocv.id) - }else{ - s.connectedPlugins[s.ocv.plug].tx(data) - } + // chaining coming in future update + s.sendToAllDetectors(data) } //send data to socket client function s.tx = function(z,y,x){if(x){return x.broadcast.to(y).emit('f',z)};io.to(y).emit('f',z);} @@ -446,8 +442,8 @@ module.exports = function(s,config,lang,io){ s.group[d.ke].mon={} if(!s.group[d.ke].mon){s.group[d.ke].mon={}} } - if(s.ocv){ - tx({f:'detector_plugged',plug:s.ocv.plug,notice:s.ocv.notice}) + if(s.isAtleatOneDetectorPluginConnected){ + s.sendDetectorInfoToClient({f:'detector_plugged'},tx) s.ocvTx({f:'readPlugins',ke:d.ke}) } tx({f:'users_online',users:s.group[d.ke].users}) @@ -477,6 +473,9 @@ module.exports = function(s,config,lang,io){ console.log(err) } }) + s.onSocketAuthenticationExtensions.forEach(function(extender){ + extender(r,cn) + }) } s.sqlQuery('SELECT ke,uid,auth,mail,details FROM Users WHERE ke=? AND auth=? AND uid=?',[d.ke,d.auth,d.uid],function(err,r) { if(r&&r[0]){ @@ -512,12 +511,23 @@ module.exports = function(s,config,lang,io){ s.ocvTx(d.data) break; case'monitorOrder': - if(d.monitorOrder&&d.monitorOrder instanceof Object){ + if(d.monitorOrder && d.monitorOrder instanceof Object){ s.sqlQuery('SELECT details FROM Users WHERE uid=? AND ke=?',[cn.uid,cn.ke],function(err,r){ - if(r&&r[0]){ - r=JSON.parse(r[0].details); - r.monitorOrder=d.monitorOrder; - s.sqlQuery('UPDATE Users SET details=? WHERE uid=? AND ke=?',[JSON.stringify(r),cn.uid,cn.ke]) + if(r && r[0]){ + details = JSON.parse(r[0].details) + details.monitorOrder = d.monitorOrder + s.sqlQuery('UPDATE Users SET details=? WHERE uid=? AND ke=?',[s.s(details),cn.uid,cn.ke]) + } + }) + } + break; + case'monitorListOrder': + if(d.monitorListOrder && d.monitorListOrder instanceof Object){ + s.sqlQuery('SELECT details FROM Users WHERE uid=? AND ke=?',[cn.uid,cn.ke],function(err,r){ + if(r && r[0]){ + details = JSON.parse(r[0].details) + details.monitorListOrder = d.monitorListOrder + s.sqlQuery('UPDATE Users SET details=? WHERE uid=? AND ke=?',[s.s(details),cn.uid,cn.ke]) } }) } @@ -1355,22 +1365,29 @@ module.exports = function(s,config,lang,io){ } } if(cn.pluginEngine){ - s.connectedPlugins[cn.pluginEngine].plugged=false + s.connectedPlugins[cn.pluginEngine].plugged = false s.tx({f:'plugin_engine_unplugged',plug:cn.pluginEngine},'CPU') - delete(s.api[cn.pluginEngine]) } if(cn.cron){ delete(s.cron); } - if(cn.ocv){ - s.tx({f:'detector_unplugged',plug:s.ocv.plug},'CPU') - delete(s.ocv); - delete(s.api[cn.id]) + if(cn.detectorPlugin){ + s.tx({f:'detector_unplugged',plug:cn.detectorPlugin},'CPU') + s.removeDetectorPlugin(cn.detectorPlugin) + s.sendDetectorInfoToClient({f:'detector_plugged'},function(data){ + s.tx(data,'CPU') + }) } if(cn.superSessionKey){ delete(s.superUsersApi[cn.superSessionKey]) } + s.onWebSocketDisconnectionExtensions.forEach(function(extender){ + extender(cn) + }) delete(s.clientSocketConnection[cn.id]) }) + s.onWebSocketConnectionExtensions.forEach(function(extender){ + extender(cn) + }) }); } diff --git a/libs/sql.js b/libs/sql.js index d9d3d7b..27b0639 100644 --- a/libs/sql.js +++ b/libs/sql.js @@ -1,12 +1,24 @@ +moment = require('moment') module.exports = function(s,config){ + s.onBeforeDatabaseLoadExtensions.forEach(function(extender){ + extender(config) + }) //sql/database connection with knex s.databaseOptions = { client: config.databaseType, connection: config.db, } + var isSqlite = false if(s.databaseOptions.client.indexOf('sqlite')>-1){ + isSqlite = true s.databaseOptions.client = 'sqlite3'; s.databaseOptions.useNullAsDefault = true; + try{ + require('sqlite3') + }catch(err){ + console.log('Installing SQlite3 Module...') + require('child_process').execSync('npm install sqlite3 --unsafe-perm') + } } if(s.databaseOptions.client === 'sqlite3' && s.databaseOptions.connection.filename === undefined){ s.databaseOptions.connection.filename = s.mainDirectory+"/shinobi.sqlite" @@ -38,7 +50,7 @@ module.exports = function(s,config){ return newQuery } s.stringToSqlTime = function(value){ - newValue = new Date(value.replace('T',' ')) + newValue = new Date(s.nameToTime(value)).valueOf() return newValue } s.sqlQuery = function(query,values,onMoveOn,hideLog){ @@ -48,6 +60,11 @@ module.exports = function(s,config){ var values = []; } if(!onMoveOn){onMoveOn=function(){}} + // if(s.databaseOptions.client === 'pg'){ + // query = query + // .replace(/ NOT LIKE /g," NOT ILIKE ") + // .replace(/ LIKE /g," ILIKE ") + // } var mergedQuery = s.mergeQueryValues(query,values) s.debugLog('s.sqlQuery QUERY',mergedQuery) if(!s.databaseEngine || !s.databaseEngine.raw){ @@ -73,25 +90,54 @@ module.exports = function(s,config){ } }) } + s.openDatabaseTable = function(tableName){ + return s.databaseEngine(tableName) + } s.connectDatabase = function(){ s.databaseEngine = require('knex')(s.databaseOptions) } s.preQueries = function(){ - //add Cloud Videos table, will remove in future - s.sqlQuery('CREATE TABLE IF NOT EXISTS `Cloud Videos` (`mid` varchar(50) NOT NULL,`ke` varchar(50) DEFAULT NULL,`href` text NOT NULL,`size` float DEFAULT NULL,`time` timestamp NULL DEFAULT NULL,`end` timestamp NULL DEFAULT NULL,`status` int(1) DEFAULT \'0\' COMMENT \'0:Complete,1:Read,2:Archive\',`details` text) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;',[],function(err){ - // if(err)console.log(err) + var knex = s.databaseEngine + var mySQLtail = '' + if(config.databaseType === 'mysql'){ + mySQLtail = ' ENGINE=InnoDB DEFAULT CHARSET=utf8' + } + //add Presets table and modernize + var createPresetsTableQuery = 'CREATE TABLE IF NOT EXISTS `Presets` ( `ke` varchar(50) DEFAULT NULL, `name` text, `details` text, `type` varchar(50) DEFAULT NULL)' + s.sqlQuery( createPresetsTableQuery + mySQLtail + ';',[],function(err){ + if(err)console.error(err) + if(config.databaseType === 'sqlite3'){ + var aQuery = "ALTER TABLE Presets RENAME TO _Presets_old;" + aQuery += createPresetsTableQuery + aQuery += "INSERT INTO Presets (`ke`, `name`, `details`, `type`) SELECT `ke`, `name`, `details`, `type` FROM _Presets_old;COMMIT;DROP TABLE _Presets_old;" + }else{ + s.sqlQuery('ALTER TABLE `Presets` CHANGE COLUMN `type` `type` VARCHAR(50) NULL DEFAULT NULL AFTER `details`;',[],function(err){ + if(err)console.error(err) + },true) + } },true) - //add monitorStates to Preset ENUM - s.sqlQuery('ALTER TABLE `Presets` CHANGE COLUMN `type` `type` VARCHAR(50) NULL DEFAULT NULL AFTER `details`;',[],function(err){ - // if(err)console.log(err) + //add Schedules table, will remove in future + s.sqlQuery("CREATE TABLE IF NOT EXISTS `Schedules` (`ke` varchar(50) DEFAULT NULL,`name` text,`details` text,`start` varchar(10) DEFAULT NULL,`end` varchar(10) DEFAULT NULL,`enabled` int(1) NOT NULL DEFAULT '1')" + mySQLtail + ';',[],function(err){ + if(err)console.error(err) + },true) + //add Cloud Videos table, will remove in future + s.sqlQuery('CREATE TABLE IF NOT EXISTS `Cloud Videos` (`mid` varchar(50) NOT NULL,`ke` varchar(50) DEFAULT NULL,`href` text NOT NULL,`size` float DEFAULT NULL,`time` timestamp NULL DEFAULT NULL,`end` timestamp NULL DEFAULT NULL,`status` int(1) DEFAULT \'0\',`details` text)' + mySQLtail + ';',[],function(err){ + if(err)console.error(err) },true) //create Files table - s.sqlQuery('CREATE TABLE IF NOT EXISTS `Files` (`ke` varchar(50) NOT NULL,`mid` varchar(50) NOT NULL,`name` tinytext NOT NULL,`size` float NOT NULL DEFAULT \'0\',`details` text NOT NULL,`status` int(1) NOT NULL DEFAULT \'0\') ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;',[],function(err){ - // if(err)console.log(err) + var createFilesTableQuery = "CREATE TABLE IF NOT EXISTS `Files` (`ke` varchar(50) NOT NULL,`mid` varchar(50) NOT NULL,`name` tinytext NOT NULL,`size` float NOT NULL DEFAULT '0',`details` text NOT NULL,`status` int(1) NOT NULL DEFAULT '0',`time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP)" + s.sqlQuery(createFilesTableQuery + mySQLtail + ';',[],function(err){ + if(err)console.error(err) //add time column to Files table - s.sqlQuery('ALTER TABLE `Files` ADD COLUMN `time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP AFTER `status`;',[],function(err){ - // if(err)console.log(err) - },true) + if(config.databaseType === 'sqlite3'){ + var aQuery = "ALTER TABLE Files RENAME TO _Files_old;" + aQuery += createPresetsTableQuery + aQuery += "INSERT INTO Files (`ke`, `mid`, `name`, `details`, `size`, `status`, `time`) SELECT `ke`, `mid`, `name`, `details`, `size`, `status`, `time` FROM _Files_old;COMMIT;DROP TABLE _Files_old;" + }else{ + s.sqlQuery('ALTER TABLE `Files` ADD COLUMN `time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP AFTER `status`;',[],function(err){ + if(err && err.sqlMessage.indexOf('Duplicate') === -1)console.error(err) + },true) + } },true) delete(s.preQueries) } diff --git a/libs/startup.js b/libs/startup.js index 3a7b937..5754931 100644 --- a/libs/startup.js +++ b/libs/startup.js @@ -9,10 +9,34 @@ module.exports = function(s,config,lang,io){ console.log('Node.js version : '+execSync("node -v")) s.processReady = function(){ s.systemLog(lang.startUpText5) + s.onProcessReadyExtensions.forEach(function(extender){ + extender(true) + }) process.send('ready') } + var checkForTerminalCommands = function(callback){ + var next = function(){ + if(callback)callback() + } + if(!s.isWin){ + var etcPath = '/etc/shinobisystems/cctv.txt' + fs.stat(etcPath,function(err,stat){ + if(err || !stat){ + exec('node '+ s.mainDirectory + '/INSTALL/terminalCommands.js',function(err){ + if(err)console.log(err) + }) + } + next() + }) + }else{ + next() + } + } var loadedAccounts = [] var loadMonitors = function(callback){ + s.beforeMonitorsLoadedOnStartupExtensions.forEach(function(extender){ + extender() + }) s.systemLog(lang.startUpText4) //preliminary monitor start s.sqlQuery('SELECT * FROM Monitors', function(err,monitors) { @@ -147,6 +171,9 @@ module.exports = function(s,config,lang,io){ }) }) },10000) + //hourly check to see if sizePurge has failed to unlock + //checks to see if request count is the number of monitors + 10 + s.checkForStalePurgeLocks() //run prerequsite queries, load users and monitors if(config.childNodes.mode !== 'child'){ //sql/database connection with knex @@ -154,11 +181,13 @@ module.exports = function(s,config,lang,io){ //run prerequsite queries s.preQueries() setTimeout(function(){ - //load administrators (groups) - loadAdminUsers(function(){ - //load monitors (for groups) - loadMonitors(function(){ - s.processReady() + checkForTerminalCommands(function(){ + //load administrators (groups) + loadAdminUsers(function(){ + //load monitors (for groups) + loadMonitors(function(){ + s.processReady() + }) }) }) },1500) diff --git a/libs/uploaders.js b/libs/uploaders.js new file mode 100644 index 0000000..7b67957 --- /dev/null +++ b/libs/uploaders.js @@ -0,0 +1,11 @@ +module.exports = function(s,config,lang){ + var loadLib = function(lib){ + return require('./uploaders/' + lib + '.js') + } + loadLib('loader')(s,config,lang) + loadLib('backblazeB2')(s,config,lang) + loadLib('amazonS3')(s,config,lang) + loadLib('webdav')(s,config,lang) + loadLib('wasabi')(s,config,lang) + loadLib('sftp')(s,config,lang) +} diff --git a/libs/uploaders/amazonS3.js b/libs/uploaders/amazonS3.js new file mode 100644 index 0000000..345f458 --- /dev/null +++ b/libs/uploaders/amazonS3.js @@ -0,0 +1,137 @@ +var fs = require('fs'); +module.exports = function(s,config,lang){ + //Amazon S3 + var beforeAccountSaveForAmazonS3 = function(d){ + //d = save event + d.form.details.aws_use_global=d.d.aws_use_global + d.form.details.use_aws_s3=d.d.use_aws_s3 + } + var cloudDiskUseStartupForAmazonS3 = function(group,userDetails){ + group.cloudDiskUse['s3'].name = 'Amazon S3' + group.cloudDiskUse['s3'].sizeLimitCheck = (userDetails.use_aws_s3_size_limit === '1') + if(!userDetails.aws_s3_size_limit || userDetails.aws_s3_size_limit === ''){ + group.cloudDiskUse['s3'].sizeLimit = 10000 + }else{ + group.cloudDiskUse['s3'].sizeLimit = parseFloat(userDetails.aws_s3_size_limit) + } + } + var loadAmazonS3ForUser = function(e){ + // e = user + var userDetails = JSON.parse(e.details) + if(userDetails.aws_use_global === '1' && config.cloudUploaders && config.cloudUploaders.AmazonS3){ + // { + // aws_accessKeyId: "", + // aws_secretAccessKey: "", + // aws_region: "", + // aws_s3_bucket: "", + // aws_s3_dir: "", + // } + userDetails = Object.assign(userDetails,config.cloudUploaders.AmazonS3) + } + //Amazon S3 + if(!s.group[e.ke].aws && + !s.group[e.ke].aws_s3 && + userDetails.aws_s3 !== '0' && + userDetails.aws_accessKeyId !== ''&& + userDetails.aws_secretAccessKey && + userDetails.aws_secretAccessKey !== ''&& + userDetails.aws_region && + userDetails.aws_region !== ''&& + userDetails.aws_s3_bucket !== '' + ){ + if(!userDetails.aws_s3_dir || userDetails.aws_s3_dir === '/'){ + userDetails.aws_s3_dir = '' + } + if(userDetails.aws_s3_dir !== ''){ + userDetails.aws_s3_dir = s.checkCorrectPathEnding(userDetails.aws_s3_dir) + } + s.group[e.ke].aws = new require("aws-sdk") + s.group[e.ke].aws.config = new s.group[e.ke].aws.Config({ + accessKeyId: userDetails.aws_accessKeyId, + secretAccessKey: userDetails.aws_secretAccessKey, + region: userDetails.aws_region + }) + s.group[e.ke].aws_s3 = new s.group[e.ke].aws.S3(); + } + } + var unloadAmazonS3ForUser = function(user){ + s.group[user.ke].aws = null + s.group[user.ke].aws_s3 = null + } + var deleteVideoFromAmazonS3 = function(e,video,callback){ + // e = user + try{ + var videoDetails = JSON.parse(video.details) + }catch(err){ + var videoDetails = video.details + } + if(!videoDetails.location){ + videoDetails.location = video.href.split('.amazonaws.com')[1] + } + s.group[e.ke].aws_s3.deleteObject({ + Bucket: s.group[e.ke].init.aws_s3_bucket, + Key: videoDetails.location, + }, function(err, data) { + if (err) console.log(err); + callback() + }); + } + var uploadVideoToAmazonS3 = function(e,k){ + //e = video object + //k = temporary values + if(!k)k={}; + //cloud saver - amazon s3 + if(s.group[e.ke].aws_s3 && s.group[e.ke].init.use_aws_s3 !== '0' && s.group[e.ke].init.aws_s3_save === '1'){ + var ext = k.filename.split('.') + ext = ext[ext.length - 1] + var fileStream = fs.createReadStream(k.dir+k.filename); + fileStream.on('error', function (err) { + console.error(err) + }) + var saveLocation = s.group[e.ke].init.aws_s3_dir+e.ke+'/'+e.mid+'/'+k.filename + s.group[e.ke].aws_s3.upload({ + Bucket: s.group[e.ke].init.aws_s3_bucket, + Key: saveLocation, + Body:fileStream, + ACL:'public-read', + ContentType:'video/'+ext + },function(err,data){ + if(err){ + s.userLog(e,{type:lang['Amazon S3 Upload Error'],msg:err}) + } + if(s.group[e.ke].init.aws_s3_log === '1' && data && data.Location){ + var save = [ + e.mid, + e.ke, + k.startTime, + 1, + s.s({ + type : 's3', + location : saveLocation + }), + k.filesize, + k.endTime, + data.Location + ] + s.sqlQuery('INSERT INTO `Cloud Videos` (mid,ke,time,status,details,size,end,href) VALUES (?,?,?,?,?,?,?,?)',save) + s.setCloudDiskUsedForGroup(e,{ + amount : k.filesizeMB, + storageType : 's3' + }) + s.purgeCloudDiskForGroup(e,'s3') + } + }) + } + } + //amazon s3 + s.addCloudUploader({ + name: 's3', + loadGroupAppExtender: loadAmazonS3ForUser, + unloadGroupAppExtender: unloadAmazonS3ForUser, + insertCompletedVideoExtender: uploadVideoToAmazonS3, + deleteVideoFromCloudExtensions: deleteVideoFromAmazonS3, + cloudDiskUseStartupExtensions: cloudDiskUseStartupForAmazonS3, + beforeAccountSave: beforeAccountSaveForAmazonS3, + onAccountSave: cloudDiskUseStartupForAmazonS3, + }) +} diff --git a/libs/uploaders/backblazeB2.js b/libs/uploaders/backblazeB2.js new file mode 100644 index 0000000..c8f6f1d --- /dev/null +++ b/libs/uploaders/backblazeB2.js @@ -0,0 +1,170 @@ +var fs = require('fs'); +module.exports = function(s,config,lang){ + //Backblaze B2 + var beforeAccountSaveForBackblazeB2 = function(d){ + //d = save event + d.form.details.b2_use_global=d.d.b2_use_global + d.form.details.use_bb_b2=d.d.use_bb_b2 + } + var cloudDiskUseStartupForBackblazeB2 = function(group,userDetails){ + group.cloudDiskUse['b2'].name = 'Backblaze B2' + group.cloudDiskUse['b2'].sizeLimitCheck = (userDetails.use_bb_b2_size_limit === '1') + if(!userDetails.bb_b2_size_limit || userDetails.bb_b2_size_limit === ''){ + group.cloudDiskUse['b2'].sizeLimit = 10000 + }else{ + group.cloudDiskUse['b2'].sizeLimit = parseFloat(userDetails.bb_b2_size_limit) + } + } + var loadBackblazeB2ForUser = function(e){ + var userDetails = JSON.parse(e.details); + try{ + if(userDetails.b2_use_global === '1' && config.cloudUploaders && config.cloudUploaders.BackblazeB2){ + // { + // bb_b2_accountId: "", + // bb_b2_applicationKey: "", + // bb_b2_bucket: "", + // bb_b2_dir: "", + // } + userDetails = Object.assign(userDetails,config.cloudUploaders.BackblazeB2) + } + if(!s.group[e.ke].bb_b2 && + userDetails.bb_b2_accountId && + userDetails.bb_b2_accountId !=='' && + userDetails.bb_b2_applicationKey && + userDetails.bb_b2_applicationKey !=='' && + userDetails.bb_b2_bucket && + userDetails.bb_b2_bucket !== '' + ){ + var B2 = require('backblaze-b2') + if(!userDetails.bb_b2_dir || userDetails.bb_b2_dir === '/'){ + userDetails.bb_b2_dir = '' + } + if(userDetails.bb_b2_dir !== ''){ + userDetails.bb_b2_dir = s.checkCorrectPathEnding(userDetails.bb_b2_dir) + } + var backblazeErr = function(err){ + // console.log(err) + s.userLog({mid:'$USER',ke:e.ke},{type:lang['Backblaze Error'],msg:err.data || err}) + } + var createB2Connection = function(){ + var b2 = new B2({ + accountId: userDetails.bb_b2_accountId, + applicationKey: userDetails.bb_b2_applicationKey + }) + b2.authorize().then(function(resp){ + s.group[e.ke].bb_b2_downloadUrl = resp.data.downloadUrl + b2.listBuckets().then(function(resp){ + var buckets = resp.data.buckets + var bucketN = -2 + buckets.forEach(function(item,n){ + if(item.bucketName === userDetails.bb_b2_bucket){ + bucketN = n + } + }) + if(bucketN > -1){ + s.group[e.ke].bb_b2_bucketId = buckets[bucketN].bucketId + }else{ + b2.createBucket( + userDetails.bb_b2_bucket, + 'allPublic' + ).then(function(resp){ + s.group[e.ke].bb_b2_bucketId = resp.data.bucketId + }).catch(backblazeErr) + } + }).catch(backblazeErr) + }).catch(backblazeErr) + s.group[e.ke].bb_b2 = b2 + } + createB2Connection() + s.group[e.ke].bb_b2_refreshTimer = setInterval(createB2Connection,1000 * 60 * 60) + } + }catch(err){ + s.debugLog(err) + } + } + var unloadBackblazeB2ForUser = function(user){ + s.group[user.ke].bb_b2 = null + clearInterval(s.group[user.ke].bb_b2_refreshTimer) + } + var deleteVideoFromBackblazeB2 = function(e,video,callback){ + // e = user + try{ + var videoDetails = JSON.parse(video.details) + }catch(err){ + var videoDetails = video.details + } + s.group[e.ke].bb_b2.deleteFileVersion({ + fileId: videoDetails.fileId, + fileName: videoDetails.fileName + }).then(function(resp){ + // console.log('deleteFileVersion',resp.data) + }).catch(function(err){ + console.log('deleteFileVersion',err) + }) + } + var uploadVideoToBackblazeB2 = function(e,k){ + //e = video object + //k = temporary values + if(!k)k={}; + //cloud saver - Backblaze B2 + if(s.group[e.ke].bb_b2 && s.group[e.ke].init.use_bb_b2 !== '0' && s.group[e.ke].init.bb_b2_save === '1'){ + var backblazeErr = function(err){ + // console.log(err) + s.userLog({mid:'$USER',ke:e.ke},{type:lang['Backblaze Error'],msg:err.data}) + } + fs.readFile(k.dir+k.filename,function(err,data){ + var backblazeSavePath = s.group[e.ke].init.bb_b2_dir+e.ke+'/'+e.mid+'/'+k.filename + var getUploadUrl = function(bucketId,callback){ + s.group[e.ke].bb_b2.getUploadUrl(bucketId).then(function(resp){ + callback(resp.data) + }).catch(backblazeErr) + } + getUploadUrl(s.group[e.ke].bb_b2_bucketId,function(req){ + s.group[e.ke].bb_b2.uploadFile({ + uploadUrl: req.uploadUrl, + uploadAuthToken: req.authorizationToken, + filename: backblazeSavePath, + data: data, + onUploadProgress: null + }).then(function(resp){ + if(s.group[e.ke].init.bb_b2_log === '1' && resp.data.fileId){ + var backblazeDownloadUrl = s.group[e.ke].bb_b2_downloadUrl + '/file/' + s.group[e.ke].init.bb_b2_bucket + '/' + backblazeSavePath + var save = [ + e.mid, + e.ke, + k.startTime, + 1, + s.s({ + type : 'b2', + bucketId : resp.data.bucketId, + fileId : resp.data.fileId, + fileName : resp.data.fileName + }), + k.filesize, + k.endTime, + backblazeDownloadUrl + ] + s.sqlQuery('INSERT INTO `Cloud Videos` (mid,ke,time,status,details,size,end,href) VALUES (?,?,?,?,?,?,?,?)',save) + s.setCloudDiskUsedForGroup(e,{ + amount : k.filesizeMB, + storageType : 'b2' + }) + s.purgeCloudDiskForGroup(e,'b2') + } + }).catch(backblazeErr) + }) + }) + } + } + //backblaze b2 + s.addCloudUploader({ + name: 'b2', + loadGroupAppExtender: loadBackblazeB2ForUser, + unloadGroupAppExtender: unloadBackblazeB2ForUser, + insertCompletedVideoExtender: uploadVideoToBackblazeB2, + deleteVideoFromCloudExtensions: deleteVideoFromBackblazeB2, + cloudDiskUseStartupExtensions: cloudDiskUseStartupForBackblazeB2, + beforeAccountSave: beforeAccountSaveForBackblazeB2, + onAccountSave: cloudDiskUseStartupForBackblazeB2, + }) +} diff --git a/libs/uploaders/loader.js b/libs/uploaders/loader.js new file mode 100644 index 0000000..8634701 --- /dev/null +++ b/libs/uploaders/loader.js @@ -0,0 +1,20 @@ +module.exports = function(s){ + s.addCloudUploader = function(opt){ + s.loadGroupAppExtender(opt.loadGroupAppExtender) + s.unloadGroupAppExtender(opt.unloadGroupAppExtender) + s.insertCompletedVideoExtender(opt.insertCompletedVideoExtender) + s.deleteVideoFromCloudExtensions[opt.name] = opt.deleteVideoFromCloudExtensions + s.cloudDiskUseStartupExtensions[opt.name] = opt.cloudDiskUseStartupExtensions + s.beforeAccountSave(opt.beforeAccountSave) + s.onAccountSave(opt.onAccountSave) + s.cloudDisksLoader(opt.name) + } + s.addSimpleUploader = function(opt){ + s.loadGroupAppExtender(opt.loadGroupAppExtender) + s.unloadGroupAppExtender(opt.unloadGroupAppExtender) + s.insertCompletedVideoExtender(opt.insertCompletedVideoExtender) + s.beforeAccountSave(opt.beforeAccountSave) + s.onAccountSave(opt.onAccountSave) + s.onMonitorSave(opt.onMonitorSave) + } +} diff --git a/libs/uploaders/sftp.js b/libs/uploaders/sftp.js new file mode 100644 index 0000000..46edbf4 --- /dev/null +++ b/libs/uploaders/sftp.js @@ -0,0 +1,90 @@ +var fs = require('fs'); +var ssh2SftpClient = require('node-ssh') +module.exports = function(s,config,lang){ + //SFTP + var sftpErr = function(err){ + // console.log(err) + s.userLog({mid:'$USER',ke:e.ke},{type:lang['SFTP Error'],msg:err.data || err}) + } + var beforeAccountSaveForSftp = function(d){ + //d = save event + d.form.details.use_sftp = d.d.use_sftp + } + var loadSftpForUser = function(e){ + // e = user + var userDetails = JSON.parse(e.details); + //SFTP + if(!s.group[e.ke].sftp && + !s.group[e.ke].sftp && + userDetails.sftp !== '0' && + userDetails.sftp_host && + userDetails.sftp_host !== ''&& + userDetails.sftp_port && + userDetails.sftp_port !== '' + ){ + if(!userDetails.sftp_dir || userDetails.sftp_dir === '/'){ + userDetails.sftp_dir = '' + } + if(userDetails.sftp_dir !== ''){ + userDetails.sftp_dir = s.checkCorrectPathEnding(userDetails.sftp_dir) + } + var sftp = new ssh2SftpClient() + var connectionDetails = { + host: userDetails.sftp_host, + port: userDetails.sftp_port + } + if(!userDetails.sftp_port)connectionDetails.port = 22 + if(userDetails.sftp_username && userDetails.sftp_username !== '')connectionDetails.username = userDetails.sftp_username + if(userDetails.sftp_password && userDetails.sftp_password !== '')connectionDetails.password = userDetails.sftp_password + if(userDetails.sftp_privateKey && userDetails.sftp_privateKey !== '')connectionDetails.privateKey = userDetails.sftp_privateKey + sftp.connect(connectionDetails).catch(sftpErr) + s.group[e.ke].sftp = sftp + } + } + var unloadSftpForUser = function(user){ + if(s.group[user.ke].sftp && s.group[user.ke].sftp.end)s.group[user.ke].sftp.end().then(function(){ + s.group[user.ke].sftp = null + }) + } + var uploadVideoToSftp = function(e,k){ + //e = video object + //k = temporary values + if(!k)k={}; + //cloud saver - SFTP + if(s.group[e.ke].sftp && s.group[e.ke].init.use_sftp !== '0' && s.group[e.ke].init.sftp_save === '1'){ + var localPath = k.dir + k.filename + var saveLocation = s.group[e.ke].init.sftp_dir + e.ke + '/' + e.mid + '/' + k.filename + s.group[e.ke].sftp.putFile(localPath, saveLocation).catch(sftpErr) + } + } + var createSftpDirectory = function(monitorConfig){ + var monitorSaveDirectory = s.group[monitorConfig.ke].init.sftp_dir + monitorConfig.ke + '/' + monitorConfig.mid + s.group[monitorConfig.ke].sftp.mkdir(monitorSaveDirectory, true).catch(function(err){ + if(err.code !== 'ERR_ASSERTION'){ + sftpErr(err) + } + }) + } + var onMonitorSaveForSftp = function(monitorConfig){ + if(s.group[monitorConfig.ke].sftp && s.group[monitorConfig.ke].init.use_sftp !== '0' && s.group[monitorConfig.ke].init.sftp_save === '1'){ + createSftpDirectory(monitorConfig) + } + } + var onAccountSaveForSftp = function(group,userDetails,user){ + if(s.group[user.ke] && s.group[user.ke].sftp && s.group[user.ke].init.use_sftp !== '0' && s.group[user.ke].init.sftp_save === '1'){ + Object.keys(s.group[user.ke].mon_conf).forEach(function(monitorId){ + createSftpDirectory(s.group[user.ke].mon_conf[monitorId]) + }) + } + } + //SFTP (Simple Uploader) + s.addSimpleUploader({ + name: 'sftp', + loadGroupAppExtender: loadSftpForUser, + unloadGroupAppExtender: unloadSftpForUser, + insertCompletedVideoExtender: uploadVideoToSftp, + beforeAccountSave: beforeAccountSaveForSftp, + onAccountSave: onAccountSaveForSftp, + onMonitorSave: onMonitorSaveForSftp, + }) +} diff --git a/libs/uploaders/wasabi.js b/libs/uploaders/wasabi.js new file mode 100644 index 0000000..56b416c --- /dev/null +++ b/libs/uploaders/wasabi.js @@ -0,0 +1,138 @@ +var fs = require('fs'); +module.exports = function(s,config,lang){ + //Wasabi Hot Cloud Storage + var beforeAccountSaveForWasabiHotCloudStorage = function(d){ + //d = save event + d.form.details.whcs_use_global=d.d.whcs_use_global + d.form.details.use_whcs=d.d.use_whcs + } + var cloudDiskUseStartupForWasabiHotCloudStorage = function(group,userDetails){ + group.cloudDiskUse['whcs'].name = 'Wasabi Hot Cloud Storage' + group.cloudDiskUse['whcs'].sizeLimitCheck = (userDetails.use_whcs_size_limit === '1') + if(!userDetails.whcs_size_limit || userDetails.whcs_size_limit === ''){ + group.cloudDiskUse['whcs'].sizeLimit = 10000 + }else{ + group.cloudDiskUse['whcs'].sizeLimit = parseFloat(userDetails.whcs_size_limit) + } + } + var loadWasabiHotCloudStorageForUser = function(e){ + // e = user + var userDetails = JSON.parse(e.details) + if(userDetails.whcs_use_global === '1' && config.cloudUploaders && config.cloudUploaders.WasabiHotCloudStorage){ + // { + // whcs_accessKeyId: "", + // whcs_secretAccessKey: "", + // whcs_region: "", + // whcs_bucket: "", + // whcs_dir: "", + // } + userDetails = Object.assign(userDetails,config.cloudUploaders.WasabiHotCloudStorage) + } + //Wasabi Hot Cloud Storage + if(!s.group[e.ke].whcs && + userDetails.whcs !== '0' && + userDetails.whcs_accessKeyId !== ''&& + userDetails.whcs_secretAccessKey && + userDetails.whcs_secretAccessKey !== ''&& + userDetails.whcs_region && + userDetails.whcs_region !== ''&& + userDetails.whcs_bucket !== '' + ){ + if(!userDetails.whcs_dir || userDetails.whcs_dir === '/'){ + userDetails.whcs_dir = '' + } + if(userDetails.whcs_dir !== ''){ + userDetails.whcs_dir = s.checkCorrectPathEnding(userDetails.whcs_dir) + } + var AWS = new require("aws-sdk") + s.group[e.ke].whcs = AWS + var wasabiEndpoint = new AWS.Endpoint('s3.wasabisys.com') + s.group[e.ke].whcs.config = new s.group[e.ke].whcs.Config({ + endpoint: wasabiEndpoint, + accessKeyId: userDetails.whcs_accessKeyId, + secretAccessKey: userDetails.whcs_secretAccessKey, + region: userDetails.whcs_region + }) + s.group[e.ke].whcs = new s.group[e.ke].whcs.S3(); + } + } + var unloadWasabiHotCloudStorageForUser = function(user){ + s.group[user.ke].whcs = null + } + var deleteVideoFromWasabiHotCloudStorage = function(e,video,callback){ + // e = user + try{ + var videoDetails = JSON.parse(video.details) + }catch(err){ + var videoDetails = video.details + } + if(!videoDetails.location){ + videoDetails.location = video.href.split('wasabisys.com')[1] + } + s.group[e.ke].whcs.deleteObject({ + Bucket: s.group[e.ke].init.whcs_bucket, + Key: videoDetails.location, + }, function(err, data) { + if (err) console.log(err); + callback() + }); + } + var uploadVideoToWasabiHotCloudStorage = function(e,k){ + //e = video object + //k = temporary values + if(!k)k={}; + //cloud saver - Wasabi Hot Cloud Storage + if(s.group[e.ke].whcs && s.group[e.ke].init.use_whcs !== '0' && s.group[e.ke].init.whcs_save === '1'){ + var ext = k.filename.split('.') + ext = ext[ext.length - 1] + var fileStream = fs.createReadStream(k.dir+k.filename); + fileStream.on('error', function (err) { + console.error(err) + }) + var saveLocation = s.group[e.ke].init.whcs_dir+e.ke+'/'+e.mid+'/'+k.filename + s.group[e.ke].whcs.upload({ + Bucket: s.group[e.ke].init.whcs_bucket, + Key: saveLocation, + Body:fileStream, + ACL:'public-read', + ContentType:'video/'+ext + },function(err,data){ + if(err){ + s.userLog(e,{type:lang['Wasabi Hot Cloud Storage Upload Error'],msg:err}) + } + if(s.group[e.ke].init.whcs_log === '1' && data && data.Location){ + var save = [ + e.mid, + e.ke, + k.startTime, + 1, + s.s({ + type : 'whcs', + location : saveLocation + }), + k.filesize, + k.endTime, + data.Location + ] + s.sqlQuery('INSERT INTO `Cloud Videos` (mid,ke,time,status,details,size,end,href) VALUES (?,?,?,?,?,?,?,?)',save) + s.setCloudDiskUsedForGroup(e,{ + amount : k.filesizeMB, + storageType : 'whcs' + }) + s.purgeCloudDiskForGroup(e,'whcs') + } + }) + } + } + //wasabi + s.addCloudUploader({ + name: 'whcs', + loadGroupAppExtender: loadWasabiHotCloudStorageForUser, + unloadGroupAppExtender: unloadWasabiHotCloudStorageForUser, + insertCompletedVideoExtender: uploadVideoToWasabiHotCloudStorage, + deleteVideoFromCloudExtensions: deleteVideoFromWasabiHotCloudStorage, + cloudDiskUseStartupExtensions: cloudDiskUseStartupForWasabiHotCloudStorage, + beforeAccountSave: beforeAccountSaveForWasabiHotCloudStorage, + onAccountSave: cloudDiskUseStartupForWasabiHotCloudStorage, + }) +} diff --git a/libs/uploaders/webdav.js b/libs/uploaders/webdav.js new file mode 100644 index 0000000..572924c --- /dev/null +++ b/libs/uploaders/webdav.js @@ -0,0 +1,169 @@ +var fs = require('fs'); +var webdav = require("webdav-fs"); +module.exports = function(s,config,lang){ + // WebDAV + var beforeAccountSaveForWebDav = function(d){ + //d = save event + d.form.details.webdav_use_global=d.d.webdav_use_global + d.form.details.use_webdav=d.d.use_webdav + } + var cloudDiskUseStartupForWebDav = function(group,userDetails){ + group.cloudDiskUse['webdav'].name = 'WebDAV' + group.cloudDiskUse['webdav'].sizeLimitCheck = (userDetails.use_webdav_size_limit === '1') + if(!userDetails.webdav_size_limit || userDetails.webdav_size_limit === ''){ + group.cloudDiskUse['webdav'].sizeLimit = 10000 + }else{ + group.cloudDiskUse['webdav'].sizeLimit = parseFloat(userDetails.webdav_size_limit) + } + } + var loadWebDavForUser = function(e){ + // e = user + var userDetails = JSON.parse(e.details); + if(userDetails.webdav_use_global === '1' && config.cloudUploaders && config.cloudUploaders.WebDAV){ + // { + // webdav_user: "", + // webdav_pass: "", + // webdav_url: "", + // webdav_dir: "", + // } + userDetails = Object.assign(userDetails,config.cloudUploaders.WebDAV) + } + //owncloud/webdav + if(!s.group[e.ke].webdav && + userDetails.webdav_user&& + userDetails.webdav_user!==''&& + userDetails.webdav_pass&& + userDetails.webdav_pass!==''&& + userDetails.webdav_url&& + userDetails.webdav_url!=='' + ){ + if(!userDetails.webdav_dir||userDetails.webdav_dir===''){ + userDetails.webdav_dir='/' + } + userDetails.webdav_dir = s.checkCorrectPathEnding(userDetails.webdav_dir) + s.group[e.ke].webdav = webdav( + userDetails.webdav_url, + userDetails.webdav_user, + userDetails.webdav_pass + ) + } + } + var unloadWebDavForUser = function(user){ + s.group[user.ke].webdav = null + } + var deleteVideoFromWebDav = function(e,video,callback){ + // e = user + try{ + var videoDetails = JSON.parse(video.details) + }catch(err){ + var videoDetails = video.details + } + if(!videoDetails.location){ + var prefix = s.addUserPassToUrl(s.checkCorrectPathEnding(s.group[e.ke].init.webdav_url),s.group[e.ke].init.webdav_user,s.group[e.ke].init.webdav_pass) + videoDetails.location = video.href.replace(prefix,'') + } + s.group[e.ke].webdav.unlink(videoDetails.location, function(err) { + if (err) console.log(videoDetails.location,err) + callback() + }) + } + var uploadVideoToWebDav = function(e,k){ + //e = video object + //k = temporary values + if(!k)k={}; + //cloud saver - webdav + var wfs = s.group[e.ke].webdav + if(wfs && s.group[e.ke].init.use_webdav !== '0' && s.group[e.ke].init.webdav_save === "1"){ + var webdavUploadDir = s.group[e.ke].init.webdav_dir+e.ke+'/'+e.mid+'/' + var startWebDavUpload = function(){ + s.group[e.ke].mon[e.id].webdavDirExist = true + var wfsWriteStream = + fs.createReadStream(k.dir + k.filename).pipe(wfs.createWriteStream(webdavUploadDir + k.filename)) + if(s.group[e.ke].init.webdav_log === '1'){ + var webdavRemoteUrl = s.addUserPassToUrl(s.checkCorrectPathEnding(s.group[e.ke].init.webdav_url),s.group[e.ke].init.webdav_user,s.group[e.ke].init.webdav_pass) + s.group[e.ke].init.webdav_dir + e.ke + '/'+e.mid+'/'+k.filename + var save = [ + e.mid, + e.ke, + k.startTime, + 1, + s.s({ + type : 'webdav', + location : webdavUploadDir + k.filename + }), + k.filesize, + k.endTime, + webdavRemoteUrl + ] + s.sqlQuery('INSERT INTO `Cloud Videos` (mid,ke,time,status,details,size,end,href) VALUES (?,?,?,?,?,?,?,?)',save) + s.setCloudDiskUsedForGroup(e,{ + amount : k.filesizeMB, + storageType : 'webdav' + }) + s.purgeCloudDiskForGroup(e,'webdav') + } + } + if(s.group[e.ke].mon[e.id].webdavDirExist !== true){ + //check if webdav dir exist + var parentPoint = 0 + var webDavParentz = webdavUploadDir.split('/') + var webDavParents = [] + webDavParentz.forEach(function(v){ + if(v && v !== '')webDavParents.push(v) + }) + var stitchPieces = './' + var lastParentCheck = function(){ + ++parentPoint + if(parentPoint === webDavParents.length){ + startWebDavUpload() + } + checkPathPiece(webDavParents[parentPoint]) + } + var checkPathPiece = function(pathPiece){ + if(pathPiece && pathPiece !== ''){ + stitchPieces += pathPiece + '/' + wfs.stat(stitchPieces, function(error, stats) { + if(error){ + reply = { + status : error.status, + msg : lang.WebdavErrorTextTryCreatingDir, + dir : stitchPieces, + } + s.userLog(e,{type:lang['Webdav Error'],msg:reply}) + wfs.mkdir(stitchPieces, function(error) { + if(error){ + reply = { + status : error.status, + msg : lang.WebdavErrorTextCreatingDir, + dir : stitchPieces, + } + s.userLog(e,{type:lang['Webdav Error'],msg:reply}) + }else{ + lastParentCheck() + } + }) + }else{ + lastParentCheck() + } + }) + }else{ + ++parentPoint + } + } + checkPathPiece(webDavParents[0]) + }else{ + startWebDavUpload() + } + } + } + //webdav + s.addCloudUploader({ + name: 'webdav', + loadGroupAppExtender: loadWebDavForUser, + unloadGroupAppExtender: unloadWebDavForUser, + insertCompletedVideoExtender: uploadVideoToWebDav, + deleteVideoFromCloudExtensions: deleteVideoFromWebDav, + cloudDiskUseStartupExtensions: cloudDiskUseStartupForWebDav, + beforeAccountSave: beforeAccountSaveForWebDav, + onAccountSave: cloudDiskUseStartupForWebDav, + }) +} diff --git a/libs/user.js b/libs/user.js index 6c595ac..5b62758 100644 --- a/libs/user.js +++ b/libs/user.js @@ -15,7 +15,7 @@ module.exports = function(s,config){ if(s.group[e.ke].sizePurgeQueue.length > 0){ checkQueue() }else{ - s.group[e.ke].sizePurging=false + s.group[e.ke].sizePurging = false s.sendDiskUsedAmountToClients(e) } } @@ -116,6 +116,9 @@ module.exports = function(s,config){ s.tx({f:'log',ke:e.ke,mid:e.mid,log:x,time:s.timeObject()},'GRPLOG_'+e.ke); } s.loadGroup = function(e){ + s.loadGroupExtensions.forEach(function(extender){ + extender(e) + }) if(!s.group[e.ke]){ s.group[e.ke]={} } @@ -145,7 +148,7 @@ module.exports = function(s,config){ ar=JSON.parse(r.details); //load extenders s.loadGroupAppExtensions.forEach(function(extender){ - extender(r) + extender(r,ar) }) //disk Used Emitter if(!s.group[e.ke].diskUsedEmitter){ @@ -257,11 +260,11 @@ module.exports = function(s,config){ d.form.details.use_admin=d.d.use_admin d.form.details.use_ldap=d.d.use_ldap //check - if(d.d.edit_days=="0"){ - d.form.details.days=d.d.days; + if(d.d.edit_days == "0"){ + d.form.details.days = d.d.days; } - if(d.d.edit_size=="0"){ - d.form.details.size=d.d.size; + if(d.d.edit_size == "0"){ + d.form.details.size = d.d.size; } if(d.d.sub){ d.form.details.sub=d.d.sub; @@ -292,7 +295,7 @@ module.exports = function(s,config){ var userDetails = JSON.parse(d.form.details) s.group[d.ke].sizeLimit = parseFloat(newSize) s.onAccountSaveExtensions.forEach(function(extender){ - extender(s.group[d.ke],userDetails) + extender(s.group[d.ke],userDetails,user) }) s.unloadGroupAppExtensions.forEach(function(extender){ extender(user) @@ -305,4 +308,45 @@ module.exports = function(s,config){ } }) } + s.findPreset = function(presetQueryVals,callback){ + //presetQueryVals = [ke, type, name] + s.sqlQuery("SELECT * FROM Presets WHERE ke=? AND type=? AND name=? LIMIT 1",presetQueryVals,function(err,presets){ + var preset + var notFound = false + if(presets && presets[0]){ + preset = presets[0] + s.checkDetails(preset) + }else{ + notFound = true + } + callback(notFound,preset) + }) + } + s.checkUserPurgeLock = function(groupKey){ + var userGroup = s.group[groupKey] + if(s.group[groupKey].usedSpace > s.group[groupKey].sizeLimit){ + s.group[groupKey].sizePurgeQueue = [] + s.group[groupKey].sizePurging = false + s.systemLog(lang.sizePurgeLockedText + ' : ' + groupKey) + s.onStalePurgeLockExtensions.forEach(function(extender){ + extender(groupKey,s.group[groupKey].usedSpace,s.group[groupKey].sizeLimit) + }) + } + } + if(config.cron.deleteOverMax === true){ + s.checkForStalePurgeLocks = function(){ + var doCheck = function(){ + Object.keys(s.group).forEach(function(groupKey){ + s.checkUserPurgeLock(groupKey) + }) + } + clearTimeout(s.checkForStalePurgeLocksInterval) + s.checkForStalePurgeLocksInterval = setInterval(function(){ + doCheck() + },1000 * 60 * 60) + doCheck() + } + }else{ + s.checkForStalePurgeLocks = function(){} + } } diff --git a/libs/videos.js b/libs/videos.js index 4b54c34..dfbb5c0 100644 --- a/libs/videos.js +++ b/libs/videos.js @@ -230,11 +230,6 @@ module.exports = function(s,config,lang){ }) }) }) - fs.chmod(videoSnap,0o777,function(err){ - if(!err){ - fs.unlink(videoSnap,function(err){}) - } - }) }else{ console.log(new Error()) console.log(lang['Database row does not exist'],queryValues) @@ -242,55 +237,60 @@ module.exports = function(s,config,lang){ }) } s.deleteListOfVideos = function(videos){ - var query = 'DELETE FROM Videos WHERE ' - var videoQuery = [] - var queryValues = [] - videos.forEach(function(video){ - s.checkDetails(video) - //e = video object - video.dir = s.getVideoDirectory(video) - if(!video.filename && video.time){ - video.filename = s.formattedTime(video.time) - } - var filename, - time - if(video.filename.indexOf('.')>-1){ - filename = video.filename - }else{ - filename = video.filename+'.'+video.ext - } - if(video.filename && !video.time){ - time = s.nameToTime(filename) - }else{ - time = video.time - } - time = new Date(time) - fs.chmod(video.dir+filename,0o777,function(err){ - s.tx({ - f: 'video_delete', - filename: filename, - mid: video.id, - ke: video.ke, - time: s.nameToTime(filename), - end: s.formattedTime(new Date,'YYYY-MM-DD HH:mm:ss') - },'GRP_'+video.ke); - s.setDiskUsedForGroup(video,-(video.size / 1000000)) - fs.unlink(video.dir+filename,function(err){ - fs.stat(video.dir+filename,function(err){ - if(!err){ - s.file('delete',video.dir+filename) - } + var deleteSetOfVideos = function(videos){ + var query = 'DELETE FROM Videos WHERE ' + var videoQuery = [] + var queryValues = [] + videos.forEach(function(video){ + s.checkDetails(video) + //e = video object + video.dir = s.getVideoDirectory(video) + if(!video.filename && video.time){ + video.filename = s.formattedTime(video.time) + } + var filename, + time + if(video.filename.indexOf('.')>-1){ + filename = video.filename + }else{ + filename = video.filename+'.'+video.ext + } + if(video.filename && !video.time){ + time = s.nameToTime(filename) + }else{ + time = video.time + } + time = new Date(time) + fs.chmod(video.dir+filename,0o777,function(err){ + s.tx({ + f: 'video_delete', + filename: filename, + mid: video.id, + ke: video.ke, + time: s.nameToTime(filename), + end: s.formattedTime(new Date,'YYYY-MM-DD HH:mm:ss') + },'GRP_'+video.ke); + s.setDiskUsedForGroup(video,-(video.size / 1000000)) + fs.unlink(video.dir+filename,function(err){ + fs.stat(video.dir+filename,function(err){ + if(!err){ + s.file('delete',video.dir+filename) + } + }) }) }) + videoQuery.push('(`mid`=? AND `ke`=? AND `time`=?)') + queryValues = queryValues.concat([video.id,video.ke,time]) }) - videoQuery.push('(`mid`=? AND `ke`=? AND `time`=?)') - queryValues = queryValues.concat([video.id,video.ke,time]) - }) - query += videoQuery.join(' OR ') - s.sqlQuery(query,queryValues,function(err){ - if(err){ - s.systemLog(lang['List of Videos Delete Error'],err) - } + query += videoQuery.join(' OR ') + s.sqlQuery(query,queryValues,function(err){ + if(err){ + s.systemLog(lang['List of Videos Delete Error'],err) + } + }) + } + videos.chunk(100).forEach(function(videosChunk){ + deleteSetOfVideos(videosChunk) }) } s.deleteVideoFromCloudExtensions = {} @@ -378,4 +378,40 @@ module.exports = function(s,config,lang){ finish() } } + s.streamMp4FileOverHttp = function(filePath,req,res){ + var ext = filePath.split('.') + ext = filePath[filePath.length - 1] + var total = fs.statSync(filePath).size; + if (req.headers['range']) { + try{ + var range = req.headers.range; + var parts = range.replace(/bytes=/, "").split("-"); + var partialstart = parts[0]; + var partialend = parts[1]; + var start = parseInt(partialstart, 10); + var end = partialend ? parseInt(partialend, 10) : total-1; + var chunksize = (end-start)+1; + var file = fs.createReadStream(filePath, {start: start, end: end}); + req.headerWrite={ 'Content-Range': 'bytes ' + start + '-' + end + '/' + total, 'Accept-Ranges': 'bytes', 'Content-Length': chunksize, 'Content-Type': 'video/'+req.ext } + req.writeCode=206 + }catch(err){ + req.headerWrite={ 'Content-Length': total, 'Content-Type': 'video/'+req.ext}; + var file = fs.createReadStream(filePath) + req.writeCode=200 + } + } else { + req.headerWrite={ 'Content-Length': total, 'Content-Type': 'video/'+req.ext}; + var file = fs.createReadStream(filePath) + req.writeCode=200 + } + if(req.query.downloadName){ + req.headerWrite['content-disposition']='attachment; filename="'+req.query.downloadName+'"'; + } + res.writeHead(req.writeCode,req.headerWrite); + file.on('close',function(){ + res.end() + }) + file.pipe(res) + return file + } } diff --git a/libs/webServer.js b/libs/webServer.js index 9cc5363..03dc198 100644 --- a/libs/webServer.js +++ b/libs/webServer.js @@ -50,6 +50,8 @@ module.exports = function(s,config,lang,io){ if(config.renderPaths.grid === undefined){config.renderPaths.grid='pages/grid'} //slick.js (cycle) page if(config.renderPaths.cycle === undefined){config.renderPaths.cycle='pages/cycle'} + // Use uws/cws + if(config.useUWebsocketJs === undefined){config.useUWebsocketJs=true} //SSL options if(config.ssl&&config.ssl.key&&config.ssl.cert){ config.ssl.key=fs.readFileSync(s.checkRelativePath(config.ssl.key),'utf8') @@ -111,5 +113,11 @@ module.exports = function(s,config,lang,io){ path:s.checkCorrectPathEnding(config.webPaths.super)+'socket.io', transports: ['websocket'] }) + if(config.useUWebsocketJs === true){ + io.engine.ws = new (require('cws').Server)({ + noServer: true, + perMessageDeflate: false + }) + } return app } diff --git a/libs/webServerAdminPaths.js b/libs/webServerAdminPaths.js index 7d4809b..b28cfba 100644 --- a/libs/webServerAdminPaths.js +++ b/libs/webServerAdminPaths.js @@ -21,10 +21,10 @@ module.exports = function(s,config,lang,app){ return } var form = s.getPostData(req) - var uid = s.getPostData(req,'uid',false) - var mail = s.getPostData(req,'mail',false) + var uid = form.uid || s.getPostData(req,'uid',false) + var mail = form.mail || s.getPostData(req,'mail',false) if(form){ - var keys = Object.keys(form) + var keys = ['details'] var condition = [] var value = [] keys.forEach(function(v){ @@ -68,8 +68,9 @@ module.exports = function(s,config,lang,app){ s.closeJsonResponse(res,endData) return } - var uid = s.getPostData(req,'uid',false) - var mail = s.getPostData(req,'mail',false) + var form = s.getPostData(req) + var uid = form.uid || s.getPostData(req,'uid',false) + var mail = form.mail || s.getPostData(req,'mail',false) s.sqlQuery('DELETE FROM Users WHERE uid=? AND ke=? AND mail=?',[uid,req.params.ke,mail]) s.sqlQuery("SELECT * FROM API WHERE ke=? AND uid=?",[req.params.ke,uid],function(err,rows){ if(rows && rows[0]){ @@ -132,6 +133,12 @@ module.exports = function(s,config,lang,app){ uid: newId, mail: form.mail },'ADM_'+req.params.ke) + endData.user = { + details: s.parseJSON(details), + ke: req.params.ke, + uid: newId, + mail: form.mail + } } res.end(s.prettyPrint(endData)) }) @@ -159,7 +166,6 @@ module.exports = function(s,config,lang,app){ ok: false } res.setHeader('Content-Type', 'application/json'); - res.header("Access-Control-Allow-Origin",req.headers.origin); s.auth(req.params,function(user){ var hasRestrictions = user.details.sub && user.details.allmonitors !== '1' if(req.params.f !== 'delete'){ @@ -238,7 +244,6 @@ module.exports = function(s,config,lang,app){ ],function (req,res){ var endData = {ok:false} res.setHeader('Content-Type', 'application/json'); - res.header("Access-Control-Allow-Origin",req.headers.origin); s.auth(req.params,function(user){ var endData = { ok : false @@ -266,6 +271,7 @@ module.exports = function(s,config,lang,app){ },'GRP_' + req.params.ke) endData.ok = true } + endData.api = insert s.closeJsonResponse(res,endData) }) }else{ @@ -283,7 +289,6 @@ module.exports = function(s,config,lang,app){ ],function (req,res){ var endData = {ok:false} res.setHeader('Content-Type', 'application/json'); - res.header("Access-Control-Allow-Origin",req.headers.origin); s.auth(req.params,function(user){ var endData = { ok : false @@ -336,7 +341,6 @@ module.exports = function(s,config,lang,app){ ],function (req,res){ var endData = {ok:false} res.setHeader('Content-Type', 'application/json'); - res.header("Access-Control-Allow-Origin",req.headers.origin); s.auth(req.params,function(user){ var endData = { ok : false @@ -366,7 +370,7 @@ module.exports = function(s,config,lang,app){ /** * API : Administrator : Get Monitor State Presets List */ - app.get([ + app.all([ config.webPaths.apiPrefix+':auth/monitorStates/:ke', config.webPaths.adminApiPrefix+':auth/monitorStates/:ke' ],function (req,res){ @@ -411,19 +415,7 @@ module.exports = function(s,config,lang,app){ s.closeJsonResponse(res,endData) return } - var findPreset = function(callback){ - s.sqlQuery("SELECT * FROM Presets WHERE ke=? AND type=? AND name=? LIMIT 1",[req.params.ke,'monitorStates',req.params.stateName],function(err,presets){ - var preset - var notFound = false - if(presets && presets[0]){ - preset = presets[0] - s.checkDetails(preset) - }else{ - notFound = true - } - callback(notFound,preset) - }) - } + var presetQueryVals = [req.params.ke,'monitorStates',req.params.stateName] switch(req.params.action){ case'insert':case'edit': var form = s.getPostData(req) @@ -433,7 +425,7 @@ module.exports = function(s,config,lang,app){ s.closeJsonResponse(res,endData) return } - findPreset(function(notFound,preset){ + s.findPreset(presetQueryVals,function(notFound,preset){ if(notFound === true){ endData.msg = lang["Inserted State Configuration"] var details = { @@ -470,7 +462,7 @@ module.exports = function(s,config,lang,app){ }) break; case'delete': - findPreset(function(notFound,preset){ + s.findPreset(presetQueryVals,function(notFound,preset){ if(notFound === true){ endData.msg = user.lang['State Configuration Not Found'] s.closeJsonResponse(res,endData) @@ -486,43 +478,8 @@ module.exports = function(s,config,lang,app){ }) break; default://change monitors according to state - findPreset(function(notFound,preset){ - if(notFound === false){ - var sqlQuery = 'SELECT * FROM Monitors WHERE ke=? AND ' - var monitorQuery = [] - var sqlQueryValues = [req.params.ke] - var monitorPresets = {} - preset.details.monitors.forEach(function(monitor){ - monitorQuery.push('mid=?') - sqlQueryValues.push(monitor.mid) - monitorPresets[monitor.mid] = monitor - }) - sqlQuery += '('+monitorQuery.join(' OR ')+')' - s.sqlQuery(sqlQuery,sqlQueryValues,function(err,monitors){ - if(monitors && monitors[0]){ - monitors.forEach(function(monitor){ - s.checkDetails(monitor) - s.checkDetails(monitorPresets[monitor.mid]) - var monitorPreset = monitorPresets[monitor.mid] - monitorPreset.details = Object.assign(monitor.details,monitorPreset.details) - monitor = s.cleanMonitorObjectForDatabase(Object.assign(monitor,monitorPreset)) - monitor.details = JSON.stringify(monitor.details) - s.addOrEditMonitor(Object.assign(monitor,{}),function(err,endData){ - - },user) - }) - endData.ok = true - s.tx({f:'change_group_state',ke:req.params.ke,name:req.params.stateName},'GRP_'+req.params.ke) - s.closeJsonResponse(res,endData) - }else{ - endData.msg = user.lang['State Configuration has no monitors associated'] - s.closeJsonResponse(res,endData) - } - }) - }else{ - endData.msg = user.lang['State Configuration Not Found'] - s.closeJsonResponse(res,endData) - } + s.activateMonitorStates(req.params.ke,req.params.stateName,user,function(endData){ + s.closeJsonResponse(res,endData) }) break; } diff --git a/libs/webServerPaths.js b/libs/webServerPaths.js index 77b0300..9609638 100644 --- a/libs/webServerPaths.js +++ b/libs/webServerPaths.js @@ -8,6 +8,7 @@ var execSync = require('child_process').execSync; var exec = require('child_process').exec; var spawn = require('child_process').spawn; var httpProxy = require('http-proxy'); +var onvif = require('node-onvif'); var proxy = httpProxy.createProxyServer({}) var ejs = require('ejs'); var CircularJSON = require('circular-json'); @@ -67,6 +68,10 @@ module.exports = function(s,config,lang,app,io){ app.use(s.checkCorrectPathEnding(config.webPaths.super)+'libs',express.static(s.mainDirectory + '/web/libs')) app.use(bodyParser.json()); app.use(bodyParser.urlencoded({extended: true})); + app.use(function (req,res,next){ + res.header("Access-Control-Allow-Origin",req.headers.origin); + next() + }) app.set('views', s.mainDirectory + '/web'); app.set('view engine','ejs'); //add template handler @@ -125,7 +130,6 @@ module.exports = function(s,config,lang,app,io){ app.get(config.webPaths.apiPrefix+':auth/userInfo/:ke',function (req,res){ req.ret={ok:false}; res.setHeader('Content-Type', 'application/json'); - res.header("Access-Control-Allow-Origin",req.headers.origin); s.auth(req.params,function(user){ req.ret.ok=true req.ret.user=user @@ -151,9 +155,6 @@ module.exports = function(s,config,lang,app,io){ s.checkCorrectPathEnding(config.webPaths.super)+':screen', ],function (req,res){ req.ip = s.getClientIp(req) - if(req.query.json === 'true'){ - res.header("Access-Control-Allow-Origin",req.headers.origin); - } var screenChooser = function(screen){ var search = function(screen){ if(req.url.indexOf(screen) > -1){ @@ -181,7 +182,7 @@ module.exports = function(s,config,lang,app,io){ s.renderPage(req,res,config.renderPaths.index,{ failedLogin: true, message: lang.failedLoginText1, - lang: lang, + lang: s.copySystemDefaultLanguage(), config: config, screen: screenChooser(req.params.screen) },function(err,html){ @@ -239,7 +240,7 @@ module.exports = function(s,config,lang,app,io){ s.renderPage(req,res,config.renderPaths.index,{ failedLogin: true, message: lang.failedLoginText2, - lang: lang, + lang: s.copySystemDefaultLanguage(), config: config, screen: screenChooser(req.params.screen) },function(err,html){ @@ -286,7 +287,8 @@ module.exports = function(s,config,lang,app,io){ // config: config, $user: req.resp, lang: r.lang, - define: s.getDefinitonFile(r.details.lang) + define: s.getDefinitonFile(r.details.lang), + customAutoLoad: s.customAutoLoadTree }) }) break; @@ -297,7 +299,8 @@ module.exports = function(s,config,lang,app,io){ // config: config, $user: req.resp, lang: r.lang, - define: s.getDefinitonFile(r.details.lang) + define: s.getDefinitonFile(r.details.lang), + customAutoLoad: s.customAutoLoadTree }) }) break; @@ -311,17 +314,36 @@ module.exports = function(s,config,lang,app,io){ $subs: rr, $mons: rrr, lang: r.lang, - define: s.getDefinitonFile(r.details.lang) + define: s.getDefinitonFile(r.details.lang), + customAutoLoad: s.customAutoLoadTree }) }) }) }else{ //not admin user - renderPage(config.renderPaths.home,{$user:req.resp,config:config,lang:r.lang,define:s.getDefinitonFile(r.details.lang),addStorage:s.dir.addStorage,fs:fs,__dirname:s.mainDirectory}); + renderPage(config.renderPaths.home,{ + $user:req.resp, + config:config, + lang:r.lang, + define:s.getDefinitonFile(r.details.lang), + addStorage:s.dir.addStorage, + fs:fs, + __dirname:s.mainDirectory, + customAutoLoad: s.customAutoLoadTree + }); } break; default: - renderPage(config.renderPaths.home,{$user:req.resp,config:config,lang:r.lang,define:s.getDefinitonFile(r.details.lang),addStorage:s.dir.addStorage,fs:fs,__dirname:s.mainDirectory}); + renderPage(config.renderPaths.home,{ + $user:req.resp, + config:config, + lang:r.lang, + define:s.getDefinitonFile(r.details.lang), + addStorage:s.dir.addStorage, + fs:fs, + __dirname:s.mainDirectory, + customAutoLoad: s.customAutoLoadTree + }); break; } s.userLog({ke:r.ke,mid:'$USER'},{type:r.lang['New Authentication Token'],msg:{for:req.body.function,mail:r.mail,id:r.uid,ip:req.ip}}) @@ -511,6 +533,7 @@ module.exports = function(s,config,lang,app,io){ r=[] } data.Logs = r + data.customAutoLoad = s.customAutoLoadTree fs.readFile(s.location.config,'utf8',function(err,file){ data.plainConfig = JSON.parse(file) renderPage(config.renderPaths.super,data) @@ -558,7 +581,6 @@ module.exports = function(s,config,lang,app,io){ * API : Brute Protection Lock Reset by API */ app.get([config.webPaths.apiPrefix+':auth/resetBruteProtection/:ke'], function (req,res){ - res.header("Access-Control-Allow-Origin",req.headers.origin); s.auth(req.params,function(user){ if(s.failedLoginAttempts[user.mail]){ clearTimeout(s.failedLoginAttempts[user.mail].timeout) @@ -576,7 +598,6 @@ module.exports = function(s,config,lang,app,io){ config.webPaths.apiPrefix+':auth/cycle/:ke', config.webPaths.apiPrefix+':auth/cycle/:ke/:group' ], function(req,res) { - res.header("Access-Control-Allow-Origin",req.headers.origin); s.auth(req.params,function(user){ if(user.permissions.get_monitors==="0"){ res.end(user.lang['Not Permitted']) @@ -705,7 +726,6 @@ module.exports = function(s,config,lang,app,io){ }else{ res.setHeader('Content-Type', 'application/json'); } - res.header("Access-Control-Allow-Origin",req.headers.origin); req.fn=function(user){ if(user.permissions.get_monitors==="0"){ res.end(s.prettyPrint([])) @@ -821,7 +841,6 @@ module.exports = function(s,config,lang,app,io){ app.get([config.webPaths.apiPrefix+':auth/monitor/:ke',config.webPaths.apiPrefix+':auth/monitor/:ke/:id'], function (req,res){ req.ret={ok:false}; res.setHeader('Content-Type', 'application/json'); - res.header("Access-Control-Allow-Origin",req.headers.origin); req.fn=function(user){ if(user.permissions.get_monitors==="0"){ res.end(s.prettyPrint([])) @@ -903,6 +922,54 @@ module.exports = function(s,config,lang,app,io){ s.auth(req.params,req.fn,res,req); }); /** + * API : Merge Recorded Videos into one file + */ + app.get(config.webPaths.apiPrefix+':auth/videosMerge/:ke', function (req,res){ + var failed = function(resp){ + res.setHeader('Content-Type', 'application/json'); + res.end(s.prettyPrint(resp)) + } + if(req.query.videos && req.query.videos !== ''){ + s.auth(req.params,function(user){ + var videosSelected = JSON.parse(req.query.videos) + var where = [] + var values = [] + videosSelected.forEach(function(video){ + where.push("(ke=? AND mid=? AND `time`=?)") + if(!video.ke)video.ke = req.params.ke + values.push(video.ke) + values.push(video.mid) + var time = s.nameToTime(video.filename) + if(req.query.isUTC === 'true'){ + time = s.utcToLocal(time) + } + time = new Date(time) + values.push(time) + }) + s.sqlQuery('SELECT * FROM Videos WHERE '+where.join(' OR '),values,function(err,r){ + var resp = {ok: false} + if(r && r[0]){ + s.mergeRecordedVideos(r,req.params.ke,function(fullPath,filename){ + res.setHeader('Content-Disposition', 'attachment; filename="'+filename+'"') + var file = fs.createReadStream(fullPath) + file.on('close',function(){ + setTimeout(function(){ + s.file('delete',fullPath) + },1000 * 60 * 3) + res.end() + }) + file.pipe(res) + }) + }else{ + failed({ok:false,msg:'No Videos Found'}) + } + }) + },res,req); + }else{ + failed({ok:false,msg:'"videos" query variable is missing from request.'}) + } + }) + /** * API : Get Videos */ app.get([ @@ -912,7 +979,6 @@ module.exports = function(s,config,lang,app,io){ config.webPaths.apiPrefix+':auth/cloudVideos/:ke/:id' ], function (req,res){ res.setHeader('Content-Type', 'application/json'); - res.header("Access-Control-Allow-Origin",req.headers.origin); s.auth(req.params,function(user){ var hasRestrictions = user.details.sub && user.details.allmonitors !== '1' if( @@ -1033,7 +1099,6 @@ module.exports = function(s,config,lang,app,io){ app.get([config.webPaths.apiPrefix+':auth/events/:ke',config.webPaths.apiPrefix+':auth/events/:ke/:id',config.webPaths.apiPrefix+':auth/events/:ke/:id/:limit',config.webPaths.apiPrefix+':auth/events/:ke/:id/:limit/:start',config.webPaths.apiPrefix+':auth/events/:ke/:id/:limit/:start/:end'], function (req,res){ req.ret={ok:false}; res.setHeader('Content-Type', 'application/json'); - res.header("Access-Control-Allow-Origin",req.headers.origin); s.auth(req.params,function(user){ if(user.permissions.watch_videos==="0"||user.details.sub&&user.details.allmonitors!=='1'&&user.details.video_view.indexOf(req.params.id)===-1){ res.end(s.prettyPrint([])) @@ -1091,7 +1156,6 @@ module.exports = function(s,config,lang,app,io){ app.get([config.webPaths.apiPrefix+':auth/logs/:ke',config.webPaths.apiPrefix+':auth/logs/:ke/:id'], function (req,res){ req.ret={ok:false}; res.setHeader('Content-Type', 'application/json'); - res.header("Access-Control-Allow-Origin",req.headers.origin); s.auth(req.params,function(user){ if(user.permissions.get_logs==="0" || user.details.sub && user.details.view_logs !== '1'){ res.end(s.prettyPrint([])) @@ -1156,7 +1220,6 @@ module.exports = function(s,config,lang,app,io){ app.get(config.webPaths.apiPrefix+':auth/smonitor/:ke', function (req,res){ req.ret={ok:false}; res.setHeader('Content-Type', 'application/json'); - res.header("Access-Control-Allow-Origin",req.headers.origin); req.fn=function(user){ if(user.permissions.get_monitors==="0"){ res.end(s.prettyPrint([])) @@ -1193,7 +1256,6 @@ module.exports = function(s,config,lang,app,io){ app.get([config.webPaths.apiPrefix+':auth/monitor/:ke/:id/:f',config.webPaths.apiPrefix+':auth/monitor/:ke/:id/:f/:ff',config.webPaths.apiPrefix+':auth/monitor/:ke/:id/:f/:ff/:fff'], function (req,res){ req.ret={ok:false}; res.setHeader('Content-Type', 'application/json'); - res.header("Access-Control-Allow-Origin",req.headers.origin); s.auth(req.params,function(user){ if(user.permissions.control_monitors==="0"||user.details.sub&&user.details.allmonitors!=='1'&&user.details.monitor_edit.indexOf(req.params.id)===-1){ res.end(user.lang['Not Permitted']) @@ -1288,7 +1350,6 @@ module.exports = function(s,config,lang,app,io){ */ app.get([config.webPaths.apiPrefix+':auth/fileBin/:ke',config.webPaths.apiPrefix+':auth/fileBin/:ke/:id'],function (req,res){ res.setHeader('Content-Type', 'application/json'); - res.header("Access-Control-Allow-Origin",req.headers.origin); req.fn=function(user){ req.sql='SELECT * FROM Files WHERE ke=?';req.ar=[req.params.ke]; if(user.details.sub&&user.details.monitors&&user.details.allmonitors!=='1'){ @@ -1321,7 +1382,6 @@ module.exports = function(s,config,lang,app,io){ * API : Get fileBin file */ app.get(config.webPaths.apiPrefix+':auth/fileBin/:ke/:id/:year/:month/:day/:file', function (req,res){ - res.header("Access-Control-Allow-Origin",req.headers.origin); req.fn=function(user){ req.failed=function(){ res.end(user.lang['File Not Found']) @@ -1352,7 +1412,6 @@ module.exports = function(s,config,lang,app,io){ * API : Zip Videos and Get Link from fileBin */ app.get(config.webPaths.apiPrefix+':auth/zipVideos/:ke', function (req,res){ - res.header("Access-Control-Allow-Origin",req.headers.origin); var failed = function(resp){ res.setHeader('Content-Type', 'application/json'); res.end(s.prettyPrint(resp)) @@ -1375,7 +1434,7 @@ module.exports = function(s,config,lang,app,io){ values.push(time) }) s.sqlQuery('SELECT * FROM Videos WHERE '+where.join(' OR '),values,function(err,r){ - var resp = {ok:false} + var resp = {ok: false} if(r && r[0]){ resp.ok = true var zipDownload = null @@ -1396,7 +1455,7 @@ module.exports = function(s,config,lang,app,io){ fs.mkdirSync(fileBinDir); } r.forEach(function(video){ - timeFormatted = s.formattedTime(video.time) + var timeFormatted = s.formattedTime(video.time) video.filename = timeFormatted+'.'+video.ext var dir = s.getVideoDirectory(video)+video.filename var tempVideoFile = timeFormatted+' - '+video.mid+'.'+video.ext @@ -1418,16 +1477,27 @@ module.exports = function(s,config,lang,app,io){ var zipDownload = fs.createReadStream(zippedFile) zipDownload.pipe(res) zipDownload.on('error', function (error) { - s.userLog({ke:req.params.ke,mid:'$USER'},{title:'Zip Download Error',msg:error.toString()}) + var errorString = error.toString() + s.userLog({ + ke: req.params.ke, + mid: '$USER' + },{ + title: 'Zip Download Error', + msg: errorString + }) if(zipDownload && zipDownload.destroy){ zipDownload.destroy() } - }); + res.end(s.prettyPrint({ + ok: false, + msg: errorString + })) + }) zipDownload.on('close', function () { res.end() - zipDownload.destroy(); - fs.unlinkSync(zippedFile); - }); + zipDownload.destroy() + fs.unlinkSync(zippedFile) + }) }) }else{ failed({ok:false,msg:'No Videos Found'}) @@ -1437,7 +1507,120 @@ module.exports = function(s,config,lang,app,io){ }else{ failed({ok:false,msg:'"videos" query variable is missing from request.'}) } - }); + }) + /** + * API : Zip Cloud Videos and Get Link from fileBin + */ + app.get(config.webPaths.apiPrefix+':auth/zipCloudVideos/:ke', function (req,res){ + var failed = function(resp){ + res.setHeader('Content-Type', 'application/json'); + res.end(s.prettyPrint(resp)) + } + if(req.query.videos && req.query.videos !== ''){ + s.auth(req.params,function(user){ + var videosSelected = JSON.parse(req.query.videos) + var where = [] + var values = [] + videosSelected.forEach(function(video){ + where.push("(ke=? AND mid=? AND `time`=?)") + if(!video.ke)video.ke = req.params.ke + values.push(video.ke) + values.push(video.mid) + var time = s.nameToTime(video.filename) + if(req.query.isUTC === 'true'){ + time = s.utcToLocal(time) + } + time = new Date(time) + values.push(time) + }) + s.sqlQuery('SELECT * FROM `Cloud Videos` WHERE '+where.join(' OR '),values,function(err,r){ + var resp = {ok: false} + if(r && r[0]){ + resp.ok = true + var zipDownload = null + var tempFiles = [] + var fileId = s.gid() + var fileBinDir = s.dir.fileBin+req.params.ke+'/' + var tempScript = s.dir.streams+req.params.ke+'/'+fileId+'.sh' + var zippedFilename = s.formattedTime()+'-'+fileId+'-Shinobi_Cloud_Backed_Recordings.zip' + var zippedFile = fileBinDir+zippedFilename + var script = 'cd '+fileBinDir+' && zip -9 -r '+zippedFile + res.on('close', () => { + if(zipDownload && zipDownload.destroy){ + zipDownload.destroy() + } + fs.unlink(zippedFile); + }) + if(!fs.existsSync(fileBinDir)){ + fs.mkdirSync(fileBinDir); + } + var cloudDownloadCount = 0 + var getFile = function(video,completed){ + if(!video)completed(); + s.checkDetails(video) + var filename = video.href.split('/') + filename = filename[filename.length - 1] + var timeFormatted = s.formattedTime(video.time) + var tempVideoFile = video.details.type + '-' + video.mid + '-' + filename + var tempFileWriteStream = fs.createWriteStream(fileBinDir+tempVideoFile) + tempFileWriteStream.on('finish', function() { + ++cloudDownloadCount + getFile(r[cloudDownloadCount],completed) + }) + var cloudVideoDownload = request(video.href) + cloudVideoDownload.on('response', function (res) { + res.pipe(tempFileWriteStream) + }) + tempFiles.push(fileBinDir+tempVideoFile) + script += ' "'+tempVideoFile+'"' + } + getFile(r[cloudDownloadCount],function(){ + fs.writeFileSync(tempScript,script,'utf8') + var zipCreate = spawn('sh',(tempScript).split(' '),{detached: true}) + zipCreate.stderr.on('data',function(data){ + s.userLog({ke:req.params.ke,mid:'$USER'},{title:'Zip Create Error',msg:data.toString()}) + }) + zipCreate.on('exit',function(data){ + fs.unlinkSync(tempScript) + tempFiles.forEach(function(file){ + fs.unlink(file,function(){}) + }) + res.setHeader('Content-Disposition', 'attachment; filename="' + zippedFilename + '"') + var zipDownload = fs.createReadStream(zippedFile) + zipDownload.pipe(res) + zipDownload.on('error', function (error) { + var errorString = error.toString() + s.userLog({ + ke: req.params.ke, + mid: '$USER' + },{ + title: 'Zip Download Error', + msg: errorString + }) + if(zipDownload && zipDownload.destroy){ + zipDownload.destroy() + } + res.end(s.prettyPrint({ + ok: false, + msg: errorString + })) + }) + zipDownload.on('close', function () { + res.end() + zipDownload.destroy() + fs.unlinkSync(zippedFile) + }) + }) + }) + }else{ + failed({ok:false,msg:'No Videos Found'}) + } + }) + },res,req); + }else{ + failed({ok:false,msg:'"videos" query variable is missing from request.'}) + } + }) /** * API : Get Cloud Video File (proxy) */ @@ -1480,38 +1663,7 @@ module.exports = function(s,config,lang,app,io){ if(r&&r[0]){ req.dir=s.getVideoDirectory(r[0])+req.params.file if (fs.existsSync(req.dir)){ - req.ext=req.params.file.split('.')[1]; - var total = fs.statSync(req.dir).size; - if (req.headers['range']) { - try{ - var range = req.headers.range; - var parts = range.replace(/bytes=/, "").split("-"); - var partialstart = parts[0]; - var partialend = parts[1]; - var start = parseInt(partialstart, 10); - var end = partialend ? parseInt(partialend, 10) : total-1; - var chunksize = (end-start)+1; - var file = fs.createReadStream(req.dir, {start: start, end: end}); - req.headerWrite={ 'Content-Range': 'bytes ' + start + '-' + end + '/' + total, 'Accept-Ranges': 'bytes', 'Content-Length': chunksize, 'Content-Type': 'video/'+req.ext } - req.writeCode=206 - }catch(err){ - req.headerWrite={ 'Content-Length': total, 'Content-Type': 'video/'+req.ext}; - var file = fs.createReadStream(req.dir) - req.writeCode=200 - } - } else { - req.headerWrite={ 'Content-Length': total, 'Content-Type': 'video/'+req.ext}; - var file=fs.createReadStream(req.dir) - req.writeCode=200 - } - if(req.query.downloadName){ - req.headerWrite['content-disposition']='attachment; filename="'+req.query.downloadName+'"'; - } - res.writeHead(req.writeCode,req.headerWrite); - file.on('close',function(){ - res.end(); - }) - file.pipe(res); + s.streamMp4FileOverHttp(req.dir,req,res) }else{ res.end(user.lang['File Not Found in Filesystem']) } @@ -1524,27 +1676,34 @@ module.exports = function(s,config,lang,app,io){ /** * API : Motion Trigger via GET request */ - app.get(config.webPaths.apiPrefix+':auth/motion/:ke/:id', function (req,res){ - s.auth(req.params,function(user){ - if(req.query.data){ - try{ - var d={id:req.params.id,ke:req.params.ke,details:JSON.parse(req.query.data)}; - }catch(err){ - res.end('Data Broken',err); - return; - } - }else{ - res.end('No Data'); - return; - } - if(!d.ke||!d.id||!s.group[d.ke]){ - res.end(user.lang['No Group with this key exists']); - return; - } - s.triggerEvent(d) - res.end(user.lang['Trigger Successful']) - },res,req); - }) + app.get(config.webPaths.apiPrefix+':auth/motion/:ke/:id', function (req,res){ + s.auth(req.params,function(user){ + var endData = { + + } + if(req.query.data){ + try{ + var d = { + id: req.params.id, + ke: req.params.ke, + details: JSON.parse(req.query.data) + } + }catch(err){ + res.end('Data Broken',err) + return + } + }else{ + res.end('No Data') + return + } + if(!d.ke||!d.id||!s.group[d.ke]){ + res.end(user.lang['No Group with this key exists']) + return + } + s.triggerEvent(d) + res.end(user.lang['Trigger Successful']) + },res,req) + }) /** * API : WebHook Tester */ @@ -1560,7 +1719,6 @@ module.exports = function(s,config,lang,app,io){ */ app.get(config.webPaths.apiPrefix+':auth/control/:ke/:id/:direction', function (req,res){ res.setHeader('Content-Type', 'application/json'); - res.header("Access-Control-Allow-Origin",req.headers.origin); s.auth(req.params,function(user){ s.cameraControl(req.params,function(resp){ res.end(s.prettyPrint(resp)) @@ -1578,7 +1736,6 @@ module.exports = function(s,config,lang,app,io){ ], function (req,res){ req.ret={ok:false}; res.setHeader('Content-Type', 'application/json'); - res.header("Access-Control-Allow-Origin",req.headers.origin); s.auth(req.params,function(user){ if(user.permissions.watch_videos==="0"||user.details.sub&&user.details.allmonitors!=='1'&&user.details.video_delete.indexOf(req.params.id)===-1){ res.end(user.lang['Not Permitted']) @@ -1673,7 +1830,6 @@ module.exports = function(s,config,lang,app,io){ app.get(config.webPaths.apiPrefix+':auth/probe/:ke',function (req,res){ req.ret={ok:false}; res.setHeader('Content-Type', 'application/json'); - res.header("Access-Control-Allow-Origin",req.headers.origin); s.auth(req.params,function(user){ switch(req.query.action){ // case'stop': @@ -1720,7 +1876,6 @@ module.exports = function(s,config,lang,app,io){ app.all([config.webPaths.apiPrefix+':auth/onvif/:ke/:id/:action',config.webPaths.apiPrefix+':auth/onvif/:ke/:id/:service/:action'],function (req,res){ var response = {ok:false}; res.setHeader('Content-Type', 'application/json'); - res.header("Access-Control-Allow-Origin",req.headers.origin); s.auth(req.params,function(user){ var errorMessage = function(msg,error){ response.ok = false @@ -1865,4 +2020,13 @@ module.exports = function(s,config,lang,app,io){ s.closeJsonResponse(res,endData) },res,req) }) + /** + * Robots.txt + */ + app.get('/robots.txt', function (req,res){ + res.on('finish',function(){ + res.end() + }) + fs.createReadStream(s.mainDirectory + '/web/pages/robots.txt').pipe(res) + }) } diff --git a/libs/webServerStreamPaths.js b/libs/webServerStreamPaths.js index ad5e490..fea6779 100644 --- a/libs/webServerStreamPaths.js +++ b/libs/webServerStreamPaths.js @@ -16,7 +16,6 @@ module.exports = function(s,config,lang,app){ * Page : Get Embed Stream */ app.get([config.webPaths.apiPrefix+':auth/embed/:ke/:id',config.webPaths.apiPrefix+':auth/embed/:ke/:id/:addon'], function (req,res){ - res.header("Access-Control-Allow-Origin",req.headers.origin); req.params.protocol=req.protocol; s.auth(req.params,function(user){ if(user.permissions.watch_stream==="0"||user.details.sub&&user.details.allmonitors!=='1'&&user.details.monitors.indexOf(req.params.id)===-1){ @@ -100,7 +99,6 @@ module.exports = function(s,config,lang,app){ * @param {string} full - if `true` page will load the MJPEG iframe page */ app.get([config.webPaths.apiPrefix+':auth/mjpeg/:ke/:id',config.webPaths.apiPrefix+':auth/mjpeg/:ke/:id/:channel'], function(req,res) { - res.header("Access-Control-Allow-Origin",req.headers.origin); if(req.query.full=='true'){ s.renderPage(req,res,config.renderPaths.mjpeg,{url:config.webPaths.apiPrefix + req.params.auth+'/mjpeg/'+req.params.ke+'/'+req.params.id,originalURL:s.getOriginalUrl(req)}); res.end() @@ -163,7 +161,6 @@ module.exports = function(s,config,lang,app){ * API : Get HLS Stream */ app.get([config.webPaths.apiPrefix+':auth/hls/:ke/:id/:file',config.webPaths.apiPrefix+':auth/hls/:ke/:id/:channel/:file'], function (req,res){ - res.header("Access-Control-Allow-Origin",req.headers.origin); req.fn=function(user){ s.checkChildProxy(req.params,function(){ req.dir=s.dir.streams+req.params.ke+'/'+req.params.id+'/' @@ -186,7 +183,6 @@ module.exports = function(s,config,lang,app){ * API : Get JPEG Snapshot */ app.get(config.webPaths.apiPrefix+':auth/jpeg/:ke/:id/s.jpg', function(req,res){ - res.header("Access-Control-Allow-Origin",req.headers.origin); s.auth(req.params,function(user){ s.checkChildProxy(req.params,function(){ if(user.details.sub&&user.details.allmonitors!=='1'&&user.details.monitors&&user.details.monitors.indexOf(req.params.id)===-1){ @@ -212,7 +208,6 @@ module.exports = function(s,config,lang,app){ * API : Get FLV Stream */ app.get([config.webPaths.apiPrefix+':auth/flv/:ke/:id/s.flv',config.webPaths.apiPrefix+':auth/flv/:ke/:id/:channel/s.flv'], function(req,res) { - res.header("Access-Control-Allow-Origin",req.headers.origin); s.auth(req.params,function(user){ s.checkChildProxy(req.params,function(){ var Emitter,chunkChannel @@ -263,7 +258,6 @@ module.exports = function(s,config,lang,app){ * API : Get H.265/h265 HEVC stream */ app.get([config.webPaths.apiPrefix+':auth/h265/:ke/:id/s.hevc',config.webPaths.apiPrefix+':auth/h265/:ke/:id/:channel/s.hevc'], function(req,res) { - res.header("Access-Control-Allow-Origin",req.headers.origin); s.auth(req.params,function(user){ s.checkChildProxy(req.params,function(){ var Emitter,chunkChannel @@ -313,7 +307,6 @@ module.exports = function(s,config,lang,app){ config.webPaths.apiPrefix+':auth/h264/:ke/:id/:feed', config.webPaths.apiPrefix+':auth/h264/:ke/:id' ], function (req, res) { - res.header("Access-Control-Allow-Origin",req.headers.origin); s.auth(req.params,function(user){ s.checkChildProxy(req.params,function(){ if(!req.query.feed){req.query.feed='1'} diff --git a/libs/webServerSuperPaths.js b/libs/webServerSuperPaths.js index 9c4543a..7a25a6b 100644 --- a/libs/webServerSuperPaths.js +++ b/libs/webServerSuperPaths.js @@ -288,6 +288,7 @@ module.exports = function(s,config,lang,app){ ] ) s.tx({f:'add_account',details:form.details,ke:form.ke,uid:form.uid,mail:form.mail},'$') + endData.user = Object.assign(form,{}) //init user s.loadGroup(form) } @@ -324,7 +325,7 @@ module.exports = function(s,config,lang,app){ r = r[0] var details = JSON.parse(r.details) if(form.pass && form.pass !== ''){ - if(form.pass === form.password_again){ + if(form.pass === form.password_again || form.pass_again){ form.pass = s.createHash(form.pass); }else{ endData.msg = lang["Passwords Don't Match"] @@ -335,11 +336,18 @@ module.exports = function(s,config,lang,app){ delete(form.pass); } delete(form.password_again); + delete(form.pass_again); var keys = Object.keys(form) var set = [] var values = [] keys.forEach(function(v,n){ - if(set==='ke'||set==='password_again'||!form[v]){return} + if( + set === 'ke' || + !form[v] + ){ + //skip + return + } set.push(v+'=?') if(v === 'details'){ form[v] = s.stringJSON(Object.assign(details,s.parseJSON(form[v]))) @@ -360,6 +368,9 @@ module.exports = function(s,config,lang,app){ } close() }) + }else{ + endData.msg = lang['User Not Found'] + close() } }) }else{ @@ -409,53 +420,218 @@ module.exports = function(s,config,lang,app){ },res,req) }) /** - * API : Superuser : Export Entire System + * API : Superuser : Get Entire System */ app.all(config.webPaths.superApiPrefix+':auth/export/system', function (req,res){ + s.superAuth(req.params,function(resp){ + s.systemLog('Copy of the Database Exported',{ + by: resp.$user.mail, + ip: resp.ip + }) + var endData = { + ok : true + } + // var database = s.getPostData(req,'database') + endData.database = {} + var tableNames = [ + 'Users', + 'Monitors', + 'API', + 'Videos', + 'Cloud Videos', + 'Logs', + 'Files', + 'Presets', + ] + var completedTables = 0 + var tableExportLoop = function(callback){ + var tableName = tableNames[completedTables] + if(tableName){ + var tableIsSelected = s.getPostData(req,tableName) == 1 + if(tableIsSelected){ + s.sqlQuery('SELECT * FROM `' + tableName +'`',[],function(err,dataRows){ + endData.database[tableName] = dataRows + ++completedTables + tableExportLoop(callback) + }) + }else{ + ++completedTables + tableExportLoop(callback) + } + }else{ + callback() + } + } + tableExportLoop(function(){ + s.closeJsonResponse(res,endData) + }) + },res,req) + }) + /** + * API : Superuser : Import Entire System + */ + app.all(config.webPaths.superApiPrefix+':auth/import/system', function (req,res){ + s.superAuth(req.params,function(resp){ + var endData = { + ok : false + } + console.log(req.files) + // insert data + var data = s.getPostData(req) + var database = s.getPostData(req,'database') + if(data && data.database)database = data.database + if(database){ + var rowsExistingAlready = {} + var countOfRowsInserted = {} + var countOfRowsExistingAlready = {} + var insertRow = function(tableName,row,callback){ + if(!rowsExistingAlready[tableName])rowsExistingAlready[tableName] = [] + if(!countOfRowsExistingAlready[tableName])countOfRowsExistingAlready[tableName] = 0 + if(!countOfRowsInserted[tableName])countOfRowsInserted[tableName] = 0 + var fieldsToCheck = ['ke'] + switch(tableName){ + case'API': + fieldsToCheck = fieldsToCheck.concat([ + 'code', + 'uid' + ]) + break; + case'Cloud Videos': + fieldsToCheck = fieldsToCheck.concat([ + 'href', + 'mid' + ]) + break; + case'Videos': + fieldsToCheck = fieldsToCheck.concat([ + 'time', + 'mid' + ]) + break; + case'Users': + fieldsToCheck = fieldsToCheck.concat([ + 'uid', + 'mail' + ]) + break; + case'Presets': + fieldsToCheck = fieldsToCheck.concat([ + 'name', + 'type' + ]) + break; + case'Logs': + fieldsToCheck = fieldsToCheck.concat([ + 'time', + 'info', + 'mid' + ]) + break; + case'Events': + fieldsToCheck = fieldsToCheck.concat([ + 'time', + 'details', + 'mid' + ]) + break; + case'Files': + fieldsToCheck = fieldsToCheck.concat([ + 'details', + 'name', + 'mid' + ]) + break; + case'Monitors': + fieldsToCheck = fieldsToCheck.concat([ + 'host', + 'protocol', + 'port', + 'path', + 'mid' + ]) + break; + } + var keysToCheck = [] + var valuesToCheck = [] + fieldsToCheck.forEach(function(key){ + keysToCheck.push(key + '= ?') + valuesToCheck.push(row[key]) + }) + s.sqlQuery('SELECT * FROM ' + tableName + ' WHERE ' + keysToCheck.join(' AND '),valuesToCheck,function(err,selected){ + if(selected && selected[0]){ + selected = selected[0] + rowsExistingAlready[tableName].push(selected) + callback() + }else{ + var rowKeys = Object.keys(row) + var insertEscapes = [] + var insertValues = [] + rowKeys.forEach(function(key){ + insertEscapes.push('?') + insertValues.push(row[key]) + }) + s.sqlQuery('INSERT INTO ' + tableName + ' (' + rowKeys.join(',') +') VALUES (' + insertEscapes.join(',') + ')',insertValues,function(){ + if(!err){ + ++countOfRowsInserted[tableName] + } + callback() + }) + } + }) + } + var actionCount = {} + var insertTableRows = function(tableName,rows,callback){ + if(!actionCount[tableName])actionCount[tableName] = 0 + var insertLoop = function(){ + var row = rows[actionCount[tableName]] + if(row){ + insertRow(tableName,row,function(){ + ++actionCount[tableName] + insertLoop() + }) + }else{ + callback() + } + } + insertLoop() + } + var databaseTableKeys = Object.keys(database) + var completedTables = 0 + var tableInsertLoop = function(callback){ + var tableName = databaseTableKeys[completedTables] + var rows = database[databaseTableKeys[completedTables]] + if(tableName){ + insertTableRows(tableName,rows,function(){ + ++completedTables + tableInsertLoop(callback) + }) + }else{ + callback() + } + } + tableInsertLoop(function(){ + endData.ok = true + endData.tablesInsertedTo = databaseTableKeys + endData.countOfRowsInserted = countOfRowsInserted + endData.rowsExistingAlready = rowsExistingAlready + s.closeJsonResponse(res,endData) + }) + }else{ + endData.msg = lang['Database Not Found'] + s.closeJsonResponse(res,endData) + } + },res,req) + }) + /** + * API : Superuser : Force Check for Stale Purge Locks + */ + app.all(config.webPaths.superApiPrefix+':auth/system/checkForStalePurgeLocks', function (req,res){ s.superAuth(req.params,function(resp){ var endData = { ok : true } - var close = function(){ - res.end(s.prettyPrint(endData)) - } - var account = s.getPostData(req,'account') - s.sqlQuery('SELECT FROM Users',[],function(err,users){ - s.sqlQuery('SELECT FROM Monitors',[],function(err,monitors){ - s.sqlQuery('SELECT FROM API',[],function(err,monitors){ - s.sqlQuery('SELECT FROM Videos',[],function(err,monitors){ - s.sqlQuery('SELECT FROM Logs',[],function(err,monitors){ - - }) - }) - }) - }) - }) - s.sqlQuery('DELETE FROM API WHERE uid=? AND ke=?',[account.uid,account.ke]) - if(s.getPostData(req,'deleteSubAccounts',false) === '1'){ - s.sqlQuery('DELETE FROM Users WHERE ke=?',[account.ke]) - } - if(s.getPostData(req,'deleteMonitors',false) == '1'){ - s.sqlQuery('SELECT * FROM Monitors WHERE ke=?',[account.ke],function(err,monitors){ - if(monitors && monitors[0]){ - monitors.forEach(function(monitor){ - s.camera('stop',monitor) - }) - s.sqlQuery('DELETE FROM Monitors WHERE ke=?',[account.ke]) - } - }) - } - if(s.getPostData(req,'deleteVideos',false) == '1'){ - s.sqlQuery('DELETE FROM Videos WHERE ke=?',[account.ke]) - fs.chmod(s.dir.videos+account.ke,0o777,function(err){ - fs.unlink(s.dir.videos+account.ke,function(err){}) - }) - } - if(s.getPostData(req,'deleteEvents',false) == '1'){ - s.sqlQuery('DELETE FROM Events WHERE ke=?',[account.ke]) - } - s.tx({f:'delete_account',ke:account.ke,uid:account.uid,mail:account.mail},'$') - close() + s.checkForStalePurgeLocks() + res.end(s.prettyPrint(endData)) },res,req) }) } diff --git a/plugins/python-contour/.gitignore b/plugins/python-contour/.gitignore new file mode 100644 index 0000000..543f830 --- /dev/null +++ b/plugins/python-contour/.gitignore @@ -0,0 +1,3 @@ +conf.json +faces +data \ No newline at end of file diff --git a/plugins/python-contour/INSTALL.sh b/plugins/python-contour/INSTALL.sh new file mode 100644 index 0000000..da271df --- /dev/null +++ b/plugins/python-contour/INSTALL.sh @@ -0,0 +1,59 @@ +#!/bin/bash +echo "-----------------------------------------------" +echo "-- Installing Python Dlib Plugin for Shinobi --" +echo "-----------------------------------------------" +echo "-----------------------------------" +if [ ! -e "./conf.json" ]; then + echo "Creating conf.json" + sudo cp conf.sample.json conf.json +else + echo "conf.json already exists..." +fi +echo "-----------------------------------" +sudo apt update -y +echo "Installing python3" +sudo apt install python3 python3-dev python3-pip -y +echo "-----------------------------------" +sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y +sudo apt update +sudo apt-get install gcc-6 g++-6 -y && sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-6 60 --slave /usr/bin/g++ g++ /usr/bin/g++-6 +echo "-----------------------------------" +if ! [ -x "$(command -v nvidia-smi)" ]; then + echo "You need to install NVIDIA Drivers to use this." + echo "inside the Shinobi directory run the following :" + echo "sh INSTALL/cuda9-part1.sh" + exit 1 +else + echo "NVIDIA Drivers found..." + echo "$(nvidia-smi |grep 'Driver Version')" +fi +echo "-----------------------------------" +if [ ! -d "/usr/local/cuda" ]; then + echo "You need to install CUDA Toolkit to use this." + echo "inside the Shinobi directory run the following :" + echo "sh INSTALL/cuda9-part2-after-reboot.sh" + exit 1 +else + echo "CUDA Toolkit found..." +fi +echo "-----------------------------------" +if ! [ -x "$(command -v opencv_version)" ]; then + echo "You need to install OpenCV with CUDA first." + echo "inside the Shinobi directory run the following :" + echo "sh INSTALL/opencv-cuda.sh" + exit 1 +else + echo "OpenCV found... : $(opencv_version)" +fi +echo "-----------------------------------" +echo "Getting new pip..." +pip3 install --upgrade pip +pip install --user --upgrade pip +export PATH=/usr/local/cuda/bin:$PATH +echo "Smoking pips..." +pip3 install flask_socketio +pip3 install flask +pip3 install numpy +pip3 install gevent gevent-websocket +echo "Start the plugin with pm2 like so :" +echo "pm2 start shinobi-python-dlib.js" diff --git a/plugins/python-contour/README.md b/plugins/python-contour/README.md new file mode 100644 index 0000000..26c20f5 --- /dev/null +++ b/plugins/python-contour/README.md @@ -0,0 +1,72 @@ +# Python Contour Detection with OpenCV + +> This plugin requires the use of port `7990` by default. You can specify a different port by adding `pythonPort` to your plugin's conf.json. + +**Ubuntu and Debian only** + +Go to the Shinobi directory. **/home/Shinobi** is the default directory. + +``` +cd /home/Shinobi/plugins/python-contour +``` + +Copy the config file. + +``` +sh INSTALL.sh +``` + +Start the plugin. + +``` +pm2 start shinobi-python-contour.js +``` + +Doing this will reveal options in the monitor configuration. Shinobi does not need to be restarted when a plugin is initiated or stopped. + +## Run the plugin as a Host +> The main app (Shinobi) will be the client and the plugin will be the host. The purpose of allowing this method is so that you can use one plugin for multiple Shinobi instances. Allowing you to easily manage connections without starting multiple processes. + +Edit your plugins configuration file. Set the `hostPort` **to be different** than the `listening port for camera.js`. + +``` +nano conf.json +``` + +Here is a sample of a Host configuration for the plugin. + - `plug` is the name of the plugin corresponding in the main configuration file. + - `https` choose if you want to use SSL or not. Default is `false`. + - `hostPort` can be any available port number. **Don't make this the same port number as Shinobi.** Default is `8082`. + - `type` tells the main application (Shinobi) what kind of plugin it is. In this case it is a detector. + +``` +{ + "plug":"PythonContour", + "hostPort":8082, + "key":"SomeOpenALPRkeySoPeopleDontMessWithYourShinobi", + "mode":"host", + "type":"detector" +} +``` + +Now modify the **main configuration file** located in the main directory of Shinobi. *Where you currently should be.* + +``` +nano conf.json +``` + +Add the `plugins` array if you don't already have it. Add the following *object inside the array*. + +``` + "plugins":[ + { + "id" : "PythonContour", + "https" : false, + "host" : "localhost", + "port" : 8082, + "key" : "SomeOpenALPRkeySoPeopleDontMessWithYourShinobi", + "mode" : "host", + "type" : "detector" + } + ], +``` diff --git a/plugins/python-contour/bootPy.sh b/plugins/python-contour/bootPy.sh new file mode 100644 index 0000000..68be579 --- /dev/null +++ b/plugins/python-contour/bootPy.sh @@ -0,0 +1 @@ +python3 -u $@ \ No newline at end of file diff --git a/plugins/python-contour/conf.sample.json b/plugins/python-contour/conf.sample.json new file mode 100644 index 0000000..2687164 --- /dev/null +++ b/plugins/python-contour/conf.sample.json @@ -0,0 +1,10 @@ +{ + "plug":"PythonContour", + "host":"localhost", + "port":8080, + "pythonPort":7990, + "hostPort":8082, + "key":"YOUR_CONTOUR_PLUGIN_KEY", + "mode":"client", + "type":"detector" +} diff --git a/plugins/python-contour/package.json b/plugins/python-contour/package.json new file mode 100644 index 0000000..c4c96d9 --- /dev/null +++ b/plugins/python-contour/package.json @@ -0,0 +1,18 @@ +{ + "name": "shinobi-python-contour", + "version": "1.0.0", + "description": "Contour plugin for Shinobi that uses Python functions for detection.", + "main": "shinobi-python-contour.js", + "dependencies": { + "socket.io-client": "^1.7.4", + "express": "^4.16.2", + "moment": "^2.19.2", + "socket.io": "^2.0.4" + }, + "devDependencies": {}, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "Moe Alam", + "license": "ISC" +} diff --git a/plugins/python-contour/pumpkin.py b/plugins/python-contour/pumpkin.py new file mode 100644 index 0000000..728c037 --- /dev/null +++ b/plugins/python-contour/pumpkin.py @@ -0,0 +1,116 @@ +from flask import Flask, request, jsonify, render_template +from flask_socketio import SocketIO, emit +import cv2 +import os +import json +import numpy as np +import sys + +dirname = sys.argv[1] +try: + with open("{}/conf.json".format(dirname)) as json_file: + config = json.load(json_file) + httpPort = config['pythonPort'] + try: + httpPort + except NameError: + httpPort = 7990 +except Exception as e: + print("conf.json not found.") + httpPort = 7990 + +# Load Flask +app = Flask("Contour Detection for Shinobi (Pumpkin Pie)") +socketio = SocketIO(app) +# Silence Flask +# import logging +# log = logging.getLogger('werkzeug') +# log.setLevel(logging.ERROR) + +#load car detector +oldFrames = {} + +fgbg = cv2.createBackgroundSubtractorMOG2() + +# detection function +def spark(filepath,trackerId): + try: + filepath + except NameError: + return "File path not found." + frame = cv2.imread(filepath) + returnData = [] + # resize the frame, convert it to grayscale, and blur it + # frame = imutils.resize(frame, width=500) + gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) + gray = cv2.GaussianBlur(gray, (21, 21), 0) + + # if the first frame is None, initialize it + global oldFrames + try: + oldFrames[trackerId] + except KeyError: + oldFrames[trackerId] = None + + if oldFrames[trackerId] is None: + oldFrames[trackerId] = gray + + # compute the absolute difference between the current frame and + # first frame + frameDelta = cv2.absdiff(oldFrames[trackerId], gray) + thresh = cv2.threshold(frameDelta, 55, 255, cv2.THRESH_BINARY)[1] + + # dilate the thresholded image to fill in holes, then find contours + # on thresholded image + thresh = cv2.dilate(thresh, None, iterations=2) + image = thresh.copy() + image,cnts,hierarchy = cv2.findContours(image, cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE) + + # loop over the contours + for c in cnts: + # if the contour is too small, ignore it + #if cv2.contourArea(c) > args["max_area"] or cv2.contourArea < args["min_area"]: + # continue + d = max(cnts, key = cv2.contourArea) + # compute the bounding box for the contour, draw it on the frame, + # and update the text + (x, y, w, h) = cv2.boundingRect(d) + matrix = {} + matrix["tag"] = "Contour" + matrix["x"] = int(x) + matrix["y"] = int(y) + matrix["w"] = int(w) + matrix["h"] = int(h) + returnData.append(matrix) + return returnData + +# bake the image data by a file path +# POST body contains the "img" variable. The value should be to a local image path. +# Example : /dev/shm/streams/[GROUP_KEY]/[MONITOR_ID]/s.jpg +@app.route('/', methods=['GET']) +def index(): + return "Pumpkin.py is running. This web interface should NEVER be accessible remotely. The Node.js plugin that runs this script should only be allowed accessible remotely." + +# bake the image data by a file path +# POST body contains the "img" variable. The value should be to a local image path. +# Example : /dev/shm/streams/[GROUP_KEY]/[MONITOR_ID]/s.jpg +@app.route('/post', methods=['POST']) +def post(): + filepath = request.form['img'] + return jsonify(spark(filepath)) + +# bake the image data by a file path +# GET string contains the "img" variable. The value should be to a local image path. +# Example : /dev/shm/streams/[GROUP_KEY]/[MONITOR_ID]/s.jpg +@app.route('/get', methods=['GET']) +def get(): + filepath = request.args.get('img') + return jsonify(spark(filepath)) + +@socketio.on('f') +def receiveMessage(message): + emit('f',{'id':message.get("id"),'data':spark(message.get("path"),message.get("trackerId"))}) + +# quick-and-dirty start +if __name__ == '__main__': + socketio.run(app, port=httpPort) diff --git a/plugins/python-contour/shinobi-python-contour.js b/plugins/python-contour/shinobi-python-contour.js new file mode 100644 index 0000000..711eb47 --- /dev/null +++ b/plugins/python-contour/shinobi-python-contour.js @@ -0,0 +1,298 @@ +// +// Shinobi - Python DLIB Plugin +// Copyright (C) 2016-2025 Moe Alam, moeiscool +// +// # Donate +// +// If you like what I am doing here and want me to continue please consider donating :) +// PayPal : paypal@m03.ca +// +process.on('uncaughtException', function (err) { + console.error('uncaughtException',err); +}); +//main vars +var fs=require('fs'); +var exec = require('child_process').exec; +var spawn = require('child_process').spawn; +var moment = require('moment'); +var http = require('http'); +var express = require('express'); +var socketIoClient = require('socket.io-client'); +var config = require('./conf.json'); +var http = require('http'), + app = express(), + server = http.createServer(app); + +exec("kill $(ps aux | grep '[p]ython3 pumpkin.py' | awk '{print $2}')") + +s={ + group:{}, + dir:{}, + isWin:(process.platform==='win32'), + s:function(json){return JSON.stringify(json,null,3)} +} +s.checkCorrectPathEnding=function(x){ + var length=x.length + if(x.charAt(length-1)!=='/'){ + x=x+'/' + } + return x.replace('__DIR__',__dirname) +} +s.debugLog = function(){ + if(config.debugLog === true){ + console.log(new Date(),arguments) + if(config.debugLogVerbose === true){ + console.log(new Error()) + } + } +} +if(!config.port){config.port=8080} +if(!config.pythonScript){config.pythonScript=__dirname+'/pumpkin.py'} +if(!config.pythonPort){config.pythonPort=7990} +if(!config.hostPort){config.hostPort=8082} +if(config.systemLog===undefined){config.systemLog=true} +//default stream folder check +if(!config.streamDir){ + if(s.isWin===false){ + config.streamDir='/dev/shm' + }else{ + config.streamDir=config.windowsTempDir + } + if(!fs.existsSync(config.streamDir)){ + config.streamDir=__dirname+'/streams/' + }else{ + config.streamDir+='/streams/' + } +} +s.dir.streams=config.streamDir; +//streams dir +if(!fs.existsSync(s.dir.streams)){ + fs.mkdirSync(s.dir.streams); +} +s.gid=function(x){ + if(!x){x=10};var t = "";var p = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + for( var i=0; i < x; i++ ) + t += p.charAt(Math.floor(Math.random() * p.length)); + return t; +}; +s.getRequest = function(url,callback){ + return http.get(url, function(res){ + var body = ''; + res.on('data', function(chunk){ + body += chunk; + }); + res.on('end',function(){ + try{body = JSON.parse(body)}catch(err){} + callback(body) + }); + }).on('error', function(e){ +// s.systemLog("Get Snapshot Error", e); + }); +} +s.multiplerHeight = 1 +s.multiplerWidth = 1 +s.detectObject=function(buffer,d,tx){ + d.tmpFile=s.gid(5)+'.jpg' + if(!fs.existsSync(s.dir.streams)){ + fs.mkdirSync(s.dir.streams); + } + d.dir=s.dir.streams+d.ke+'/' + if(!fs.existsSync(d.dir)){ + fs.mkdirSync(d.dir); + } + d.dir=s.dir.streams+d.ke+'/'+d.id+'/' + if(!fs.existsSync(d.dir)){ + fs.mkdirSync(d.dir); + } + fs.writeFile(d.dir+d.tmpFile,buffer,function(err){ + if(err) return s.systemLog(err); + if(s.isPythonRunning === false){ + return console.log('Python Script is not Running.') + } + var callbackId = s.gid(10) + s.group[d.ke][d.id].sendToPython({path:d.dir+d.tmpFile,id:callbackId,trackerId:d.ke+d.id},function(data){ + if(data.length > 0){ + var mats=[] + data.forEach(function(v){ + mats.push({ + x:v.x, + y:v.y, + width: v.w, + height: v.h, + confidence:v.confidence, + tag:v.tag + }) + }) + tx({ + f:'trigger', + id:d.id, + ke:d.ke, + details:{ + plug:config.plug, + name:'dlib', + reason:'object', + matrices:mats, + imgHeight:parseFloat(d.mon.detector_scale_y), + imgWidth:parseFloat(d.mon.detector_scale_x) + } + }) + } + delete(s.callbacks[callbackId]) + exec('rm -rf '+d.dir+d.tmpFile,{encoding:'utf8'}) + }) + }) +} +s.systemLog=function(q,w,e){ + if(w===undefined){return} + if(!w){w=''} + if(!e){e=''} + if(config.systemLog===true){ + return console.log(moment().format(),q,w,e) + } +} +s.MainEventController=function(d,cn,tx){ + switch(d.f){ + case'init_plugin_as_host': + if(!cn){ + console.log('No CN',d) + return + } + if(d.key!==config.key){ + console.log(new Date(),'Plugin Key Mismatch',cn.request.connection.remoteAddress,d) + cn.emit('init',{ok:false}) + cn.disconnect() + }else{ + console.log(new Date(),'Plugin Connected to Client',cn.request.connection.remoteAddress) + cn.emit('init',{ok:true,plug:config.plug,notice:config.notice,type:config.type}) + } + break; + case'init_monitor': + if(s.group[d.ke]&&s.group[d.ke][d.id]){ + delete(s.group[d.ke][d.id].buffer) + s.group[d.ke][d.id].refreshTracker(d.ke+d.id) + } + break; + case'frame': + try{ + if(!s.group[d.ke]){ + s.group[d.ke]={} + } + if(!s.group[d.ke][d.id]){ + var engine = s.createCameraBridgeToPython(d.ke+d.id) + s.group[d.ke][d.id]={ + sendToPython : engine.sendToPython, + refreshTracker : engine.refreshTracker + } + } + if(!s.group[d.ke][d.id].buffer){ + s.group[d.ke][d.id].buffer=[d.frame]; + }else{ + s.group[d.ke][d.id].buffer.push(d.frame) + } + if(d.frame[d.frame.length-2] === 0xFF && d.frame[d.frame.length-1] === 0xD9){ + s.detectObject(Buffer.concat(s.group[d.ke][d.id].buffer),d,tx) + s.group[d.ke][d.id].buffer=null; + } + }catch(err){ + if(err){ + s.systemLog(err) + delete(s.group[d.ke][d.id].buffer) + } + } + break; + } +} +server.listen(config.hostPort); +//web pages and plugin api +app.get('/', function (req, res) { + res.end(''+config.plug+' for Shinobi is running') +}); +//Conector to Shinobi +if(config.mode==='host'){ + //start plugin as host + var io = require('socket.io')(server); + io.attach(server); + s.connectedClients={}; + io.on('connection', function (cn) { + s.connectedClients[cn.id]={id:cn.id} + s.connectedClients[cn.id].tx = function(data){ + data.pluginKey=config.key;data.plug=config.plug; + return io.to(cn.id).emit('ocv',data); + } + cn.on('f',function(d){ + s.MainEventController(d,cn,s.connectedClients[cn.id].tx) + }); + cn.on('disconnect',function(d){ + delete(s.connectedClients[cn.id]) + }) + }); +}else{ + //start plugin as client + if(!config.host){config.host='localhost'} + var io = socketIoClient('ws://'+config.host+':'+config.port);//connect to master + s.cx=function(x){x.pluginKey=config.key;x.plug=config.plug;return io.emit('ocv',x)} + io.on('connect',function(d){ + s.cx({f:'init',plug:config.plug,notice:config.notice,type:config.type}); + }) + io.on('disconnect',function(d){ + io.connect(); + }) + io.on('f',function(d){ + s.MainEventController(d,null,s.cx) + }) +} + +//Start Python Controller +s.callbacks = {} +s.createCameraBridgeToPython = function(uniqueId){ + var pythonIo = socketIoClient('ws://localhost:'+config.pythonPort,{transports : ['websocket']}); + var sendToPython = function(data,callback){ + s.callbacks[data.id] = callback + pythonIo.emit('f',data) + } + var refreshTracker = function(data){ + pythonIo.emit('refreshTracker',{trackerId : data}) + } + pythonIo.on('connect',function(d){ + s.debugLog(uniqueId+' is Connected from Python') + }) + pythonIo.on('disconnect',function(d){ + s.debugLog(uniqueId+' is Disconnected from Python') + setTimeout(function(){ + pythonIo.connect(); + s.debugLog(uniqueId+' is Attempting to Reconect to Python') + },3000) + }) + pythonIo.on('f',function(d){ + if(s.callbacks[d.id]){ + s.callbacks[d.id](d.data) + delete(s.callbacks[d.id]) + } + }) + return {refreshTracker : refreshTracker, sendToPython : sendToPython} +} + + +//Start Python Daemon +process.env.PYTHONUNBUFFERED = 1; +s.createPythonProcess = function(){ + s.isPythonRunning = false + s.pythonScript = spawn('sh',[__dirname+'/bootPy.sh',config.pythonScript,__dirname]); + var onStdErr = function(data){ + s.debugLog(data.toString()) + } + var onStdOut = function(data){ + s.debugLog(data.toString()) + } + setTimeout(function(){ + s.isPythonRunning = true + },5000) + s.pythonScript.stderr.on('data',onStdErr); + + s.pythonScript.stdout.on('data',onStdOut); + + s.pythonScript.on('close', function () { + s.debugLog('Python CLOSED') + }); +} +s.createPythonProcess() diff --git a/sql/docker/01-framework.sql b/sql/docker/01-framework.sql deleted file mode 100644 index cec2dda..0000000 --- a/sql/docker/01-framework.sql +++ /dev/null @@ -1,113 +0,0 @@ --- -------------------------------------------------------- --- Host: 192.168.88.58 --- Server version: 5.7.17-0ubuntu0.16.04.1 - (Ubuntu) --- Server OS: Linux --- HeidiSQL Version: 9.3.0.4984 --- -------------------------------------------------------- - -/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; -/*!40101 SET NAMES utf8mb4 */; -/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; -/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; - --- Dumping structure for table ccio.API -CREATE TABLE IF NOT EXISTS `API` ( - `ke` varchar(50) DEFAULT NULL, - `uid` varchar(50) DEFAULT NULL, - `ip` tinytext, - `code` varchar(100) DEFAULT NULL, - `details` text, - `time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - --- Data exporting was unselected. - - --- Dumping structure for table ccio.Events -CREATE TABLE IF NOT EXISTS `Events` ( - `ke` varchar(50) DEFAULT NULL, - `mid` varchar(50) DEFAULT NULL, - `details` text, - `time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP -) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC; - --- Data exporting was unselected. - - --- Dumping structure for table ccio.Logs -CREATE TABLE IF NOT EXISTS `Logs` ( - `ke` varchar(50) DEFAULT NULL, - `mid` varchar(50) DEFAULT NULL, - `info` text, - `time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - --- Data exporting was unselected. - - --- Dumping structure for table ccio.Monitors -CREATE TABLE IF NOT EXISTS `Monitors` ( - `mid` varchar(50) DEFAULT NULL, - `ke` varchar(50) DEFAULT NULL, - `name` varchar(50) DEFAULT NULL, - `shto` text, - `shfr` text, - `details` longtext, - `type` varchar(50) DEFAULT 'jpeg', - `ext` varchar(50) DEFAULT 'webm', - `protocol` varchar(50) DEFAULT 'http', - `host` varchar(100) DEFAULT '0.0.0.0', - `path` varchar(100) DEFAULT '/', - `port` int(8) DEFAULT '80', - `fps` int(8) DEFAULT '1', - `mode` varchar(15) DEFAULT NULL, - `width` int(11) DEFAULT '640', - `height` int(11) DEFAULT '360' -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - --- Data exporting was unselected. - - --- Dumping structure for table ccio.Presets -CREATE TABLE IF NOT EXISTS `Presets` ( - `ke` varchar(50) DEFAULT NULL, - `name` text, - `details` text, - `type` enum('monitor','event','user') DEFAULT NULL -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - --- Data exporting was unselected. - - --- Dumping structure for table ccio.Users -CREATE TABLE IF NOT EXISTS `Users` ( - `ke` varchar(50) DEFAULT NULL, - `uid` varchar(50) DEFAULT NULL, - `auth` varchar(50) DEFAULT NULL, - `mail` varchar(100) DEFAULT NULL, - `pass` varchar(100) DEFAULT NULL, - `details` longtext, - UNIQUE KEY `mail` (`mail`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - --- Data exporting was unselected. - - --- Dumping structure for table ccio.Videos -CREATE TABLE IF NOT EXISTS `Videos` ( - `mid` varchar(50) DEFAULT NULL, - `ke` varchar(50) DEFAULT NULL, - `ext` enum('webm','mp4') DEFAULT NULL, - `time` timestamp NULL DEFAULT NULL, - `duration` float DEFAULT NULL, - `size` float DEFAULT NULL, - `frames` int(11) DEFAULT NULL, - `end` timestamp NULL DEFAULT NULL, - `status` int(1) DEFAULT '0' COMMENT '0:Building,1:Complete,2:Read,3:Archive', - `details` text -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - --- Data exporting was unselected. -/*!40101 SET SQL_MODE=IFNULL(@OLD_SQL_MODE, '') */; -/*!40014 SET FOREIGN_KEY_CHECKS=IF(@OLD_FOREIGN_KEY_CHECKS IS NULL, 1, @OLD_FOREIGN_KEY_CHECKS) */; -/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; diff --git a/sql/framework.sql b/sql/framework.sql index 4961e54..7ef15e1 100644 --- a/sql/framework.sql +++ b/sql/framework.sql @@ -1,6 +1,6 @@ -- -------------------------------------------------------- --- Host: 192.168.88.37 --- Server version: 10.1.25-MariaDB- - Ubuntu 17.04 +-- Host: 192.168.1.31 +-- Server version: 10.1.30-MariaDB-0ubuntu0.17.10.1 - Ubuntu 17.10 -- Server OS: debian-linux-gnu -- HeidiSQL Version: 9.4.0.5125 -- -------------------------------------------------------- @@ -26,6 +26,19 @@ CREATE TABLE IF NOT EXISTS `API` ( `time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP ) ENGINE=InnoDB DEFAULT CHARSET=utf8; +-- Data exporting was unselected. +-- Dumping structure for table ccio.Cloud Videos +CREATE TABLE IF NOT EXISTS `Cloud Videos` ( + `mid` varchar(50) NOT NULL, + `ke` varchar(50) DEFAULT NULL, + `href` text NOT NULL, + `size` float DEFAULT NULL, + `time` timestamp NULL DEFAULT NULL, + `end` timestamp NULL DEFAULT NULL, + `status` int(1) DEFAULT '0' COMMENT '0:Complete,1:Read,2:Archive', + `details` text +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + -- Data exporting was unselected. -- Dumping structure for table ccio.Events CREATE TABLE IF NOT EXISTS `Events` ( @@ -101,6 +114,29 @@ CREATE TABLE IF NOT EXISTS `Videos` ( `details` text ) ENGINE=InnoDB DEFAULT CHARSET=utf8; +-- Data exporting was unselected. +-- Dumping structure for table ccio.Files +CREATE TABLE IF NOT EXISTS `Files` ( + `ke` varchar(50) NOT NULL, + `mid` varchar(50) NOT NULL, + `name` tinytext NOT NULL, + `size` float NOT NULL DEFAULT '0', + `details` text NOT NULL, + `status` int(1) NOT NULL DEFAULT '0' +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; +ALTER TABLE `Files` ADD COLUMN `time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP AFTER `status`; + +-- Data exporting was unselected. +-- Dumping structure for table ccio.Schedules +CREATE TABLE IF NOT EXISTS `Schedules` ( + `ke` varchar(50) DEFAULT NULL, + `name` text, + `details` text, + `start` varchar(10) DEFAULT NULL, + `end` varchar(10) DEFAULT NULL, + `enabled` int(1) NOT NULL DEFAULT '1' +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + -- Data exporting was unselected. /*!40101 SET SQL_MODE=IFNULL(@OLD_SQL_MODE, '') */; /*!40014 SET FOREIGN_KEY_CHECKS=IF(@OLD_FOREIGN_KEY_CHECKS IS NULL, 1, @OLD_FOREIGN_KEY_CHECKS) */; diff --git a/test/run.js b/test/run.js index 0ca943f..2e18014 100644 --- a/test/run.js +++ b/test/run.js @@ -1,94 +1,151 @@ -module.exports = function(s,config,lang,app,io){ +var fs = require('fs') +var request = require('request') +var execSync = require('child_process').execSync +module.exports = function(s,config,lang,io){ + var temp = {} + var superUsers = require(s.location.super) + var requestURL = 'http://'+config.bindip + ':' + config.port +'/' + var requestSuperURL = 'http://localhost:' + config.port +'/super/' + superUsers[0].tokens[0] + '/' + var getBaseURL = function(){ + return 'http://localhost:' + config.port +'/' + } + var buildRegularApiRequestURL = function(auth,path,groupKey){ + return getBaseURL() + auth + '/' + path + '/' + groupKey + '/' + } + var buildAdminRequestURL = function(auth,path,groupKey){ + return getBaseURL() + 'admin/' + auth + '/' + path + '/' + groupKey + '/' + } var checkResult = function(functionName,expectedResult,testResult){ if(expectedResult !== testResult){ console.log(expectedResult,testResult) - throw new Error('x ' + functionName + ' : Failed!') + console.log('x ' + functionName + ' : Failed!') + return false }else{ - console.log('- ' + functionName + ' : Success') + console.log('✓ ' + functionName + ' : Success') + return true } } + var administratorAccountData = { + "mail":"test@test1.com", + "pass":"test1", + "pass_again":"test1", + "ke":"GroupKey123456", + "details":{ + "factorAuth": "0", + "size": "10000", + "days": "5", + "event_days": "10", + "log_days": "10", + "max_camera": "", + "permissions": "all", + "edit_size": "1", + "edit_days": "1", + "edit_event_days": "1", + "edit_log_days": "1", + "use_admin": "1", + "use_aws_s3": "1", + "use_webdav": "1", + "use_discordbot": "1", + "use_ldap": "1" + } + } + var getAdministratorAccountData = function(){ + return Object.assign(administratorAccountData,{}) + } var sampleMonitorObject = require('./testMonitor-WatchOnly.json') var test = { "basic.js" : { - checkRelativePath : function(){ + checkRelativePath : function(next){ var expectedResult = s.mainDirectory + '/' var testResult = s.checkRelativePath('') - checkResult('checkRelativePath',expectedResult,testResult) + checkResult('Internal Function : checkRelativePath',expectedResult,testResult) + next() }, - parseJSON : function(){ + parseJSON : function(next){ var expectedResult = {} var testResult = s.parseJSON('{}') - checkResult('parseJSON',JSON.stringify(expectedResult),JSON.stringify(testResult)) + checkResult('Internal Function : parseJSON',JSON.stringify(expectedResult),JSON.stringify(testResult)) + next() }, - stringJSON : function(){ + stringJSON : function(next){ var expectedResult = '{}' var testResult = s.stringJSON({}) - checkResult('stringJSON',expectedResult,testResult) + checkResult('Internal Function : stringJSON',expectedResult,testResult) + next() }, - addUserPassToUrl : function(){ + addUserPassToUrl : function(next){ var expectedResult = 'http://user:pass@url.com' var testResult = s.addUserPassToUrl('http://url.com','user','pass') - checkResult('addUserPassToUrl',expectedResult,testResult) + checkResult('Internal Function : addUserPassToUrl',expectedResult,testResult) + next() }, - checkCorrectPathEnding : function(){ + checkCorrectPathEnding : function(next){ var expectedResult = '/' var testResult = s.checkCorrectPathEnding('') - checkResult('checkCorrectPathEnding',expectedResult,testResult) + checkResult('Internal Function : checkCorrectPathEnding',expectedResult,testResult) + next() }, - md5 : function(){ + md5 : function(next){ var expectedResult = '5f4dcc3b5aa765d61d8327deb882cf99' var testResult = s.md5('password') - checkResult('md5',expectedResult,testResult) + checkResult('Internal Function : md5',expectedResult,testResult) + next() }, - sha256 : function(){ + sha256 : function(next){ var expectedResult = '9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08' var testResult = require('crypto').createHash('sha256').update('test').digest("hex") - checkResult('createHash/sha256',expectedResult,testResult) + checkResult('Internal Function : createHash/sha256',expectedResult,testResult) + next() }, - nameToTime : function(){ + nameToTime : function(next){ var expectedResult = '2018-10-22 23:00:00' var testResult = s.nameToTime('2018-10-22T23-00-00.mp4') - checkResult('nameToTime',expectedResult,testResult) + checkResult('Internal Function : nameToTime',expectedResult,testResult) + next() }, - ipRange : function(){ + ipRange : function(next){ var expectedResult = [ '192.168.1.1', '192.168.1.2', '192.168.1.3' ] var testResult = s.ipRange('192.168.1.1','192.168.1.3') - checkResult('ipRange',JSON.stringify(expectedResult),JSON.stringify(testResult)) + checkResult('Internal Function : ipRange',JSON.stringify(expectedResult),JSON.stringify(testResult)) + next() }, - portRange : function(){ + portRange : function(next){ var expectedResult = [ 8000, 8001, 8002, ] var testResult = s.portRange(8000,8002) - checkResult('portRange',JSON.stringify(expectedResult),JSON.stringify(testResult)) + checkResult('Internal Function : portRange',JSON.stringify(expectedResult),JSON.stringify(testResult)) + next() }, - getFunctionParamNames : function(){ + getFunctionParamNames : function(next){ var testing = function(arg1,arg2){} var expectedResult = [ 'arg1', 'arg2', ] var testResult = s.getFunctionParamNames(testing) - checkResult('getFunctionParamNames',JSON.stringify(expectedResult),JSON.stringify(testResult)) + checkResult('Internal Function : getFunctionParamNames',JSON.stringify(expectedResult),JSON.stringify(testResult)) + next() } }, "ffmpeg.js" : { - splitForFFPMEG : function(){ + splitForFFPMEG : function(next){ var expectedResult = [ 'flag1', 'flag2', 'fl ag3', ] var testResult = s.splitForFFPMEG('flag1 flag2 "fl ag3"') - checkResult('splitForFFPMEG',JSON.stringify(expectedResult),JSON.stringify(testResult)) + checkResult('Internal Function : splitForFFPMEG',JSON.stringify(expectedResult),JSON.stringify(testResult)) + next() }, - "ffmpeg" : function(){ + "ffmpeg" : function(next){ //command string builder var x = {tmp : ''} s.checkDetails(sampleMonitorObject) @@ -100,7 +157,7 @@ module.exports = function(s,config,lang,app,io){ s.ffmpegFunctions.buildMainDetector(sampleMonitorObject,x) s.ffmpegFunctions.assembleMainPieces(sampleMonitorObject,x) var testResult = x.ffmpegCommandString - checkResult('ffmpeg',expectedResult,testResult) + checkResult('Internal Function : ffmpeg',expectedResult,testResult) //check pipe builder var expectedResult = [] var times = config.pipeAddition @@ -112,19 +169,490 @@ module.exports = function(s,config,lang,app,io){ } s.ffmpegFunctions.createPipeArray(sampleMonitorObject,x) var testResult = x.stdioPipes - checkResult('ffmpeg.createPipeArray',JSON.stringify(expectedResult),JSON.stringify(testResult)) + checkResult('Internal Function : ffmpeg.createPipeArray',JSON.stringify(expectedResult),JSON.stringify(testResult)) + next() } + }, + "webServer" : { + "super/accounts/saveSettings" : function(next){ + console.log(requestSuperURL) + var userData = { + "mail": "admin@shinobi.video1", + "pass": "password", + "pass_again": "password" + } + var builtURL = requestSuperURL + 'accounts/saveSettings?data=' + encodeURIComponent(s.s(userData)) + request(builtURL,function(err, httpResponse, body){ + var response = s.parseJSON(body) + checkResult('API : /accounts/saveSettings',true,response.ok) + next() + }) + }, + "super/accounts/registerAdmin" : function(next){ + var userData = getAdministratorAccountData() + var builtURL = requestSuperURL + 'accounts/registerAdmin?data=' + encodeURIComponent(s.s(userData)) + request(builtURL,function(err, httpResponse, body){ + var response = s.parseJSON(body) + administratorAccountData.uid = response.user.uid + checkResult('API : /accounts/registerAdmin',true,response.ok) + next() + }) + }, + "super/accounts/deleteAdmin" : function(next){ + var userData = getAdministratorAccountData() + var builtURL = requestSuperURL + 'accounts/deleteAdmin?account=' + encodeURIComponent(s.s({ + "mail":"test@test1.com", + "ke":"GroupKey123456", + "uid":administratorAccountData.uid + + })) + request(builtURL,function(err, httpResponse, body){ + var response = s.parseJSON(body) + checkResult('API : /accounts/deleteAdmin',true,response.ok) + next() + }) + }, + "super/accounts/registerAdmin (Recreate)" : function(next){ + var userData = getAdministratorAccountData() + var builtURL = requestSuperURL + 'accounts/registerAdmin?data=' + encodeURIComponent(s.s(userData)) + request(builtURL,function(err, httpResponse, body){ + var response = s.parseJSON(body) + administratorAccountData.uid = response.user.uid + checkResult('API : /accounts/registerAdmin',true,response.ok) + next() + }) + }, + "super/accounts/list" : function(next){ + var builtURL = requestSuperURL + 'accounts/list' + request(builtURL,function(err, httpResponse, body){ + var response = s.parseJSON(body) + if(response.ok === true){ + // administratorAccountData = response.users[0] + } + checkResult('API : /accounts/list',1,response.users.length) + next() + }) + }, + "super/accounts/list/admin" : function(next){ + var builtURL = requestSuperURL + 'accounts/list/admin' + request(builtURL,function(err, httpResponse, body){ + var response = s.parseJSON(body) + checkResult('API : /accounts/list/admin',1,response.users.length) + next() + }) + }, + "super/accounts/list/sub" : function(next){ + var builtURL = requestSuperURL + 'accounts/list/sub' + request(builtURL,function(err, httpResponse, body){ + var response = s.parseJSON(body) + checkResult('API : /accounts/list/sub',0,response.users.length) + next() + }) + }, + "super/accounts/editAdmin" : function(next){ + var userData = getAdministratorAccountData() + delete(userData.uid) + var builtURL = requestSuperURL + 'accounts/editAdmin?data=' + encodeURIComponent(s.s(userData)) + "&account=" + encodeURIComponent(s.s({ + "mail":"test@test1.com", + "ke":"GroupKey123456" + })) + request(builtURL,function(err, httpResponse, body){ + var response = s.parseJSON(body) + if(response.ok !== true)console.log(response.msg) + checkResult('API : /accounts/editAdmin',true,response.ok) + next() + }) + }, + "/ (Login via API)" : function(next){ + var userData = getAdministratorAccountData() + var builtURL = getBaseURL() + '?json=true' + request.post(builtURL,{ + form : {machineID: "testMachineId", mail: "test@test1.com", pass: "test1", function: "dash"} + },function(err, httpResponse, body){ + var response = s.parseJSON(body) + if(response.ok !== true)console.log(response) + administratorAccountData.auth = response.$user.auth_token + checkResult('API : / (Login via API)',true,response.ok) + next() + }) + }, + "/api/add" : function(next){ + var userData = getAdministratorAccountData() + var builtURL = buildRegularApiRequestURL(administratorAccountData.auth,'api',administratorAccountData.ke) + 'add' + request.post(builtURL,{ + form : { + "data": { + "ip": "0.0.0.0", + "details": { + "auth_socket": "1", + "get_monitors": "1", + "control_monitors": "1", + "get_logs": "1", + "watch_stream": "1", + "watch_snapshot": "1", + "watch_videos": "1", + "delete_videos": "1" + } + } + } + },function(err, httpResponse, body){ + var response = s.parseJSON(body) + if(response.ok !== true)console.log(builtURL,response) + temp.newApiKey = response.api.code + checkResult('API : /api/add',true,response.ok) + next() + }) + }, + "Delete API Key" : function(next){ + var userData = getAdministratorAccountData() + var builtURL = buildRegularApiRequestURL(administratorAccountData.auth,'api',administratorAccountData.ke) + 'delete' + request.post(builtURL,{ + form : { + "data": { + "code": temp.newApiKey + } + } + },function(err, httpResponse, body){ + var response = s.parseJSON(body) + if(response.ok !== true)console.log(builtURL,response) + checkResult('API : /api/delete',true,response.ok) + next() + }) + }, + "/admin/accounts/register" : function(next){ + var userData = getAdministratorAccountData() + var builtURL = buildAdminRequestURL(administratorAccountData.auth,'accounts',administratorAccountData.ke) + 'register' + request.post(builtURL,{ + form : { + "data": { + "mail": "test@test2.com", + "pass": "test1", + "password_again": "test1" + } + } + },function(err, httpResponse, body){ + var response = s.parseJSON(body) + if(response.ok !== true)console.log(builtURL,response) + temp.subAccount = response.user + checkResult('API : /admin/accounts/register',true,response.ok) + next() + }) + }, + "/admin/accounts/edit" : function(next){ + var userData = getAdministratorAccountData() + var builtURL = buildAdminRequestURL(administratorAccountData.auth,'accounts',administratorAccountData.ke) + 'edit' + request.post(builtURL,{ + form : { + "data": { + "uid": temp.subAccount.uid, + "mail": temp.subAccount.mail, + "details": temp.subAccount.details + } + } + },function(err, httpResponse, body){ + var response = s.parseJSON(body) + if(response.ok !== true)console.log(builtURL,response) + checkResult('API : /admin/accounts/edit',true,response.ok) + next() + }) + }, + "/admin/accounts/delete" : function(next){ + var userData = getAdministratorAccountData() + var builtURL = buildAdminRequestURL(administratorAccountData.auth,'accounts',administratorAccountData.ke) + 'delete' + request.post(builtURL,{ + form : { + "data": { + "uid": temp.subAccount.uid, + "mail": temp.subAccount.mail, + } + } + },function(err, httpResponse, body){ + var response = s.parseJSON(body) + if(response.ok !== true)console.log(builtURL,response) + temp.subAccount = null + checkResult('API : /admin/accounts/delete',true,response.ok) + next() + }) + }, + "/configureMonitor (Add)" : function(next){ + temp.monitorId = "10998" + var userData = getAdministratorAccountData() + var builtURL = buildRegularApiRequestURL(administratorAccountData.auth,'configureMonitor',administratorAccountData.ke) + temp.monitorId + request.post(builtURL,{ + form : { + "data": {"mode":"start","mid":temp.monitorId,"name":"ReoLinkWireless","type":"mp4","protocol":"https","host":"cdn.shinobi.video","port":"443","path":"/videos/faces.mp4","ext":"mp4","fps":"3","width":"2048","height":"1536","details":"{\"notes\":\"\",\"dir\":\"\",\"auto_host_enable\":\"1\",\"auto_host\":\"rtsp://user:pass@192.168.1.40:554/\",\"rtsp_transport\":\"tcp\",\"muser\":\"user\",\"mpass\":\"pass\",\"port_force\":null,\"fatal_max\":\"0\",\"aduration\":\"1000000\",\"probesize\":\"1000000\",\"stream_loop\":\"1\",\"sfps\":\"\",\"accelerator\":\"0\",\"hwaccel\":\"cuvid\",\"hwaccel_vcodec\":\"h264_cuvid\",\"hwaccel_device\":\"\",\"stream_type\":\"mp4\",\"stream_flv_type\":\"http\",\"stream_flv_maxLatency\":\"\",\"stream_mjpeg_clients\":\"0\",\"stream_vcodec\":\"copy\",\"stream_acodec\":\"no\",\"hls_time\":\"2\",\"hls_list_size\":\"2\",\"preset_stream\":\"\",\"signal_check\":\"\",\"signal_check_log\":\"0\",\"stream_quality\":\"1\",\"stream_fps\":\"10\",\"stream_scale_x\":\"3072\",\"stream_scale_y\":\"1728\",\"rotate_stream\":null,\"svf\":\"\",\"tv_channel\":null,\"tv_channel_id\":\"\",\"tv_channel_group_title\":\"\",\"stream_timestamp\":null,\"stream_timestamp_font\":\"\",\"stream_timestamp_font_size\":\"\",\"stream_timestamp_color\":\"\",\"stream_timestamp_box_color\":\"\",\"stream_timestamp_x\":\"\",\"stream_timestamp_y\":\"\",\"stream_watermark\":\"0\",\"stream_watermark_location\":\"\",\"stream_watermark_position\":null,\"snap\":\"0\",\"snap_fps\":\"1\",\"snap_scale_x\":\"1920\",\"snap_scale_y\":\"1072\",\"snap_vf\":\"\",\"vcodec\":\"copy\",\"crf\":\"1\",\"preset_record\":\"\",\"acodec\":\"no\",\"dqf\":\"0\",\"cutoff\":\"\",\"rotate_record\":null,\"vf\":\"\",\"timestamp\":\"0\",\"timestamp_font\":\"\",\"timestamp_font_size\":\"\",\"timestamp_color\":\"\",\"timestamp_box_color\":\"\",\"timestamp_x\":\"\",\"timestamp_y\":\"\",\"watermark\":null,\"watermark_location\":\"\",\"watermark_position\":null,\"cust_input\":\"\",\"cust_snap\":\"\",\"cust_rtmp\":\"\",\"cust_rawh264\":\"\",\"cust_detect\":\"\",\"cust_stream\":\"\",\"cust_stream_server\":\"\",\"cust_record\":\"\",\"custom_output\":\"\",\"detector\":\"0\",\"detector_pam\":\"0\",\"detector_noise_filter\":null,\"detector_webhook\":\"0\",\"detector_webhook_url\":\"\",\"detector_command_enable\":\"0\",\"detector_command\":\"\",\"detector_command_timeout\":\"\",\"detector_lock_timeout\":\"\",\"detector_save\":\"0\",\"detector_frame_save\":\"0\",\"detector_mail\":\"0\",\"detector_mail_timeout\":\"\",\"detector_record_method\":\"sip\",\"detector_trigger\":\"1\",\"detector_trigger_record_fps\":\"\",\"detector_timeout\":\"10\",\"watchdog_reset\":\"0\",\"detector_delete_motionless_videos\":\"0\",\"detector_send_frames\":\"1\",\"detector_region_of_interest\":\"0\",\"detector_fps\":\"\",\"detector_scale_x\":\"640\",\"detector_scale_y\":\"480\",\"detector_use_motion\":\"1\",\"detector_use_detect_object\":\"0\",\"detector_frame\":\"0\",\"detector_sensitivity\":\"\",\"cords\":\"[]\",\"detector_buffer_vcodec\":\"auto\",\"detector_buffer_fps\":\"\",\"detector_buffer_hls_time\":\"\",\"detector_buffer_hls_list_size\":\"\",\"detector_buffer_start_number\":\"\",\"detector_buffer_live_start_index\":\"\",\"detector_lisence_plate\":\"0\",\"detector_lisence_plate_country\":\"us\",\"detector_notrigger\":\"0\",\"detector_notrigger_mail\":\"0\",\"detector_notrigger_timeout\":\"\",\"control\":\"0\",\"control_base_url\":\"\",\"control_url_method\":null,\"control_stop\":null,\"control_url_stop_timeout\":\"\",\"control_url_center\":\"\",\"control_url_left\":\"\",\"control_url_left_stop\":\"\",\"control_url_right\":\"\",\"control_url_right_stop\":\"\",\"control_url_up\":\"\",\"control_url_up_stop\":\"\",\"control_url_down\":\"\",\"control_url_down_stop\":\"\",\"control_url_enable_nv\":\"\",\"control_url_disable_nv\":\"\",\"control_url_zoom_out\":\"\",\"control_url_zoom_out_stop\":\"\",\"control_url_zoom_in\":\"\",\"control_url_zoom_in_stop\":\"\",\"groups\":\"\",\"loglevel\":\"quiet\",\"sqllog\":\"0\",\"detector_cascades\":\"\",\"stream_channels\":\"\",\"input_maps\":\"\",\"input_map_choices\":\"\"}","shto":"[]","shfr":"[]"} + } + },function(err, httpResponse, body){ + var response = s.parseJSON(body) + if(response.ok !== true)console.log(builtURL,response) + checkResult('API : /configureMonitor (Add)',true,response.ok) + next() + }) + }, + "/configureMonitor (Add Second)" : function(next){ + temp.monitorId2 = "10999" + var userData = getAdministratorAccountData() + var builtURL = buildRegularApiRequestURL(administratorAccountData.auth,'configureMonitor',administratorAccountData.ke) + temp.monitorId2 + request.post(builtURL,{ + form : { + "data": {"mode":"start","mid":temp.monitorId2,"name":"ReoLinkWireless","type":"mp4","protocol":"https","host":"cdn.shinobi.video","port":"443","path":"/videos/faces.mp4","ext":"mp4","fps":"3","width":"2048","height":"1536","details":"{\"notes\":\"\",\"dir\":\"\",\"auto_host_enable\":\"1\",\"auto_host\":\"rtsp://user:pass@192.168.1.40:554/\",\"rtsp_transport\":\"tcp\",\"muser\":\"user\",\"mpass\":\"pass\",\"port_force\":null,\"fatal_max\":\"0\",\"aduration\":\"1000000\",\"probesize\":\"1000000\",\"stream_loop\":\"1\",\"sfps\":\"\",\"accelerator\":\"0\",\"hwaccel\":\"cuvid\",\"hwaccel_vcodec\":\"h264_cuvid\",\"hwaccel_device\":\"\",\"stream_type\":\"hls\",\"stream_flv_type\":\"http\",\"stream_flv_maxLatency\":\"\",\"stream_mjpeg_clients\":\"0\",\"stream_vcodec\":\"copy\",\"stream_acodec\":\"no\",\"hls_time\":\"2\",\"hls_list_size\":\"2\",\"preset_stream\":\"\",\"signal_check\":\"\",\"signal_check_log\":\"0\",\"stream_quality\":\"1\",\"stream_fps\":\"10\",\"stream_scale_x\":\"3072\",\"stream_scale_y\":\"1728\",\"rotate_stream\":null,\"svf\":\"\",\"tv_channel\":null,\"tv_channel_id\":\"\",\"tv_channel_group_title\":\"\",\"stream_timestamp\":null,\"stream_timestamp_font\":\"\",\"stream_timestamp_font_size\":\"\",\"stream_timestamp_color\":\"\",\"stream_timestamp_box_color\":\"\",\"stream_timestamp_x\":\"\",\"stream_timestamp_y\":\"\",\"stream_watermark\":\"0\",\"stream_watermark_location\":\"\",\"stream_watermark_position\":null,\"snap\":\"0\",\"snap_fps\":\"1\",\"snap_scale_x\":\"1920\",\"snap_scale_y\":\"1072\",\"snap_vf\":\"\",\"vcodec\":\"copy\",\"crf\":\"1\",\"preset_record\":\"\",\"acodec\":\"no\",\"dqf\":\"0\",\"cutoff\":\"\",\"rotate_record\":null,\"vf\":\"\",\"timestamp\":\"0\",\"timestamp_font\":\"\",\"timestamp_font_size\":\"\",\"timestamp_color\":\"\",\"timestamp_box_color\":\"\",\"timestamp_x\":\"\",\"timestamp_y\":\"\",\"watermark\":null,\"watermark_location\":\"\",\"watermark_position\":null,\"cust_input\":\"\",\"cust_snap\":\"\",\"cust_rtmp\":\"\",\"cust_rawh264\":\"\",\"cust_detect\":\"\",\"cust_stream\":\"\",\"cust_stream_server\":\"\",\"cust_record\":\"\",\"custom_output\":\"\",\"detector\":\"0\",\"detector_pam\":\"0\",\"detector_noise_filter\":null,\"detector_webhook\":\"0\",\"detector_webhook_url\":\"\",\"detector_command_enable\":\"0\",\"detector_command\":\"\",\"detector_command_timeout\":\"\",\"detector_lock_timeout\":\"\",\"detector_save\":\"0\",\"detector_frame_save\":\"0\",\"detector_mail\":\"0\",\"detector_mail_timeout\":\"\",\"detector_record_method\":\"sip\",\"detector_trigger\":\"1\",\"detector_trigger_record_fps\":\"\",\"detector_timeout\":\"10\",\"watchdog_reset\":\"0\",\"detector_delete_motionless_videos\":\"0\",\"detector_send_frames\":\"1\",\"detector_region_of_interest\":\"0\",\"detector_fps\":\"\",\"detector_scale_x\":\"640\",\"detector_scale_y\":\"480\",\"detector_use_motion\":\"1\",\"detector_use_detect_object\":\"0\",\"detector_frame\":\"0\",\"detector_sensitivity\":\"\",\"cords\":\"[]\",\"detector_buffer_vcodec\":\"auto\",\"detector_buffer_fps\":\"\",\"detector_buffer_hls_time\":\"\",\"detector_buffer_hls_list_size\":\"\",\"detector_buffer_start_number\":\"\",\"detector_buffer_live_start_index\":\"\",\"detector_lisence_plate\":\"0\",\"detector_lisence_plate_country\":\"us\",\"detector_notrigger\":\"0\",\"detector_notrigger_mail\":\"0\",\"detector_notrigger_timeout\":\"\",\"control\":\"0\",\"control_base_url\":\"\",\"control_url_method\":null,\"control_stop\":null,\"control_url_stop_timeout\":\"\",\"control_url_center\":\"\",\"control_url_left\":\"\",\"control_url_left_stop\":\"\",\"control_url_right\":\"\",\"control_url_right_stop\":\"\",\"control_url_up\":\"\",\"control_url_up_stop\":\"\",\"control_url_down\":\"\",\"control_url_down_stop\":\"\",\"control_url_enable_nv\":\"\",\"control_url_disable_nv\":\"\",\"control_url_zoom_out\":\"\",\"control_url_zoom_out_stop\":\"\",\"control_url_zoom_in\":\"\",\"control_url_zoom_in_stop\":\"\",\"groups\":\"\",\"loglevel\":\"quiet\",\"sqllog\":\"0\",\"detector_cascades\":\"\",\"stream_channels\":\"\",\"input_maps\":\"\",\"input_map_choices\":\"\"}","shto":"[]","shfr":"[]"} + } + },function(err, httpResponse, body){ + var response = s.parseJSON(body) + if(response.ok !== true)console.log(builtURL,response) + checkResult('API : /configureMonitor (Add Second)',true,response.ok) + next() + }) + }, + "/configureMonitor (Edit)" : function(next){ + var userData = getAdministratorAccountData() + var builtURL = buildRegularApiRequestURL(administratorAccountData.auth,'configureMonitor',administratorAccountData.ke) + temp.monitorId + request.post(builtURL,{ + form : { + "data": {"mode":"start","mid":temp.monitorId,"name":"ReoLinkWireless","type":"mp4","protocol":"https","host":"cdn.shinobi.video","port":"443","path":"/videos/faces.mp4","ext":"mp4","fps":"3","width":"2048","height":"1536","details":"{\"notes\":\"\",\"dir\":\"\",\"auto_host_enable\":\"1\",\"auto_host\":\"rtsp://user:pass@192.168.1.40:554/\",\"rtsp_transport\":\"tcp\",\"muser\":\"user\",\"mpass\":\"pass\",\"port_force\":null,\"fatal_max\":\"0\",\"aduration\":\"1000000\",\"probesize\":\"1000000\",\"stream_loop\":\"1\",\"sfps\":\"\",\"accelerator\":\"0\",\"hwaccel\":\"cuvid\",\"hwaccel_vcodec\":\"h264_cuvid\",\"hwaccel_device\":\"\",\"stream_type\":\"mp4\",\"stream_flv_type\":\"http\",\"stream_flv_maxLatency\":\"\",\"stream_mjpeg_clients\":\"0\",\"stream_vcodec\":\"copy\",\"stream_acodec\":\"no\",\"hls_time\":\"2\",\"hls_list_size\":\"2\",\"preset_stream\":\"\",\"signal_check\":\"\",\"signal_check_log\":\"0\",\"stream_quality\":\"1\",\"stream_fps\":\"10\",\"stream_scale_x\":\"3072\",\"stream_scale_y\":\"1728\",\"rotate_stream\":null,\"svf\":\"\",\"tv_channel\":null,\"tv_channel_id\":\"\",\"tv_channel_group_title\":\"\",\"stream_timestamp\":null,\"stream_timestamp_font\":\"\",\"stream_timestamp_font_size\":\"\",\"stream_timestamp_color\":\"\",\"stream_timestamp_box_color\":\"\",\"stream_timestamp_x\":\"\",\"stream_timestamp_y\":\"\",\"stream_watermark\":\"0\",\"stream_watermark_location\":\"\",\"stream_watermark_position\":null,\"snap\":\"0\",\"snap_fps\":\"1\",\"snap_scale_x\":\"1920\",\"snap_scale_y\":\"1072\",\"snap_vf\":\"\",\"vcodec\":\"copy\",\"crf\":\"1\",\"preset_record\":\"\",\"acodec\":\"no\",\"dqf\":\"0\",\"cutoff\":\"\",\"rotate_record\":null,\"vf\":\"\",\"timestamp\":\"0\",\"timestamp_font\":\"\",\"timestamp_font_size\":\"\",\"timestamp_color\":\"\",\"timestamp_box_color\":\"\",\"timestamp_x\":\"\",\"timestamp_y\":\"\",\"watermark\":null,\"watermark_location\":\"\",\"watermark_position\":null,\"cust_input\":\"\",\"cust_snap\":\"\",\"cust_rtmp\":\"\",\"cust_rawh264\":\"\",\"cust_detect\":\"\",\"cust_stream\":\"\",\"cust_stream_server\":\"\",\"cust_record\":\"\",\"custom_output\":\"\",\"detector\":\"0\",\"detector_pam\":\"0\",\"detector_noise_filter\":null,\"detector_webhook\":\"0\",\"detector_webhook_url\":\"\",\"detector_command_enable\":\"0\",\"detector_command\":\"\",\"detector_command_timeout\":\"\",\"detector_lock_timeout\":\"\",\"detector_save\":\"0\",\"detector_frame_save\":\"0\",\"detector_mail\":\"0\",\"detector_mail_timeout\":\"\",\"detector_record_method\":\"sip\",\"detector_trigger\":\"1\",\"detector_trigger_record_fps\":\"\",\"detector_timeout\":\"10\",\"watchdog_reset\":\"0\",\"detector_delete_motionless_videos\":\"0\",\"detector_send_frames\":\"1\",\"detector_region_of_interest\":\"0\",\"detector_fps\":\"\",\"detector_scale_x\":\"640\",\"detector_scale_y\":\"480\",\"detector_use_motion\":\"1\",\"detector_use_detect_object\":\"0\",\"detector_frame\":\"0\",\"detector_sensitivity\":\"\",\"cords\":\"[]\",\"detector_buffer_vcodec\":\"auto\",\"detector_buffer_fps\":\"\",\"detector_buffer_hls_time\":\"\",\"detector_buffer_hls_list_size\":\"\",\"detector_buffer_start_number\":\"\",\"detector_buffer_live_start_index\":\"\",\"detector_lisence_plate\":\"0\",\"detector_lisence_plate_country\":\"us\",\"detector_notrigger\":\"0\",\"detector_notrigger_mail\":\"0\",\"detector_notrigger_timeout\":\"\",\"control\":\"0\",\"control_base_url\":\"\",\"control_url_method\":null,\"control_stop\":null,\"control_url_stop_timeout\":\"\",\"control_url_center\":\"\",\"control_url_left\":\"\",\"control_url_left_stop\":\"\",\"control_url_right\":\"\",\"control_url_right_stop\":\"\",\"control_url_up\":\"\",\"control_url_up_stop\":\"\",\"control_url_down\":\"\",\"control_url_down_stop\":\"\",\"control_url_enable_nv\":\"\",\"control_url_disable_nv\":\"\",\"control_url_zoom_out\":\"\",\"control_url_zoom_out_stop\":\"\",\"control_url_zoom_in\":\"\",\"control_url_zoom_in_stop\":\"\",\"groups\":\"\",\"loglevel\":\"quiet\",\"sqllog\":\"0\",\"detector_cascades\":\"\",\"stream_channels\":\"\",\"input_maps\":\"\",\"input_map_choices\":\"\"}","shto":"[]","shfr":"[]"} + } + },function(err, httpResponse, body){ + var response = s.parseJSON(body) + if(response.ok !== true)console.log(builtURL,response) + checkResult('API : /configureMonitor (Edit)',true,response.ok) + next() + }) + }, + "/monitor/[MONITOR_ID] (Get)" : function(next){ + var userData = getAdministratorAccountData() + var builtURL = buildRegularApiRequestURL(administratorAccountData.auth,'monitor',administratorAccountData.ke) + temp.monitorId + request.get(builtURL,function(err, httpResponse, body){ + var response = s.parseJSON(body) + checkResult('API : /monitor/[MONITOR_ID] (Get)',temp.monitorId,response.mid) + next() + }) + }, + "/monitor/[MONITOR_ID]/[MODE] (Mode Switch to Disabled)" : function(next){ + var userData = getAdministratorAccountData() + var builtURL = buildRegularApiRequestURL(administratorAccountData.auth,'monitor',administratorAccountData.ke) + temp.monitorId + '/stop' + request.get(builtURL,function(err, httpResponse, body){ + var response = s.parseJSON(body) + checkResult('API : /monitor/[MONITOR_ID] (Mode Switch to Disabled)',true,response.ok) + next() + }) + }, + "/monitor/[MONITOR_ID]/[MODE] (Mode Switch to Watch-Only)" : function(next){ + var userData = getAdministratorAccountData() + var builtURL = buildRegularApiRequestURL(administratorAccountData.auth,'monitor',administratorAccountData.ke) + temp.monitorId + '/start' + request.get(builtURL,function(err, httpResponse, body){ + var response = s.parseJSON(body) + checkResult('API : /monitor/[MONITOR_ID] (Mode Switch to Watch-Only)',true,response.ok) + next() + }) + }, + "/monitor/[MONITOR_ID]/[MODE] (Mode Switch to Record)" : function(next){ + var userData = getAdministratorAccountData() + var builtURL = buildRegularApiRequestURL(administratorAccountData.auth,'monitor',administratorAccountData.ke) + temp.monitorId + '/record' + request.get(builtURL,function(err, httpResponse, body){ + var response = s.parseJSON(body) + checkResult('API : /monitor/[MONITOR_ID] (Mode Switch to Record)',true,response.ok) + next() + }) + }, + "/monitor (Get All)" : function(next){ + var userData = getAdministratorAccountData() + var builtURL = buildRegularApiRequestURL(administratorAccountData.auth,'monitor',administratorAccountData.ke) + request.get(builtURL,function(err, httpResponse, body){ + var response = s.parseJSON(body) + if(!checkResult('API : /monitor (Get All)',2,response.length)){ + console.log(Object.keys(response)) + } + next() + }) + }, + "/configureMonitor (Delete)" : function(next){ + var userData = getAdministratorAccountData() + var builtURL = buildRegularApiRequestURL(administratorAccountData.auth,'configureMonitor',administratorAccountData.ke) + temp.monitorId2 + '/delete' + request.post(builtURL,function(err, httpResponse, body){ + var response = s.parseJSON(body) + if(response.ok !== true)console.log(builtURL,response) + checkResult('API : /configureMonitor (Delete)',true,response.ok) + next() + }) + }, + "/monitorStates Insert (Disable + Detector Off)" : function(next){ + var userData = getAdministratorAccountData() + var builtURL = buildRegularApiRequestURL(administratorAccountData.auth,'monitorStates',administratorAccountData.ke) + 'DisableWithDetectorOff/insert' + request.post(builtURL,{ + form: { + data: { + "monitors": [ + { + "mode":"stop", + "mid":temp.monitorId, + "details": { + "detector": "0" + } + } + ] + } + } + },function(err, httpResponse, body){ + var response = s.parseJSON(body) + if(response.ok !== true)console.log(builtURL,response) + checkResult('API : /monitorStates Insert (Disable + Detector Off)',true,response.ok) + next() + }) + }, + "/monitorStates Insert (Enable + Detector On)" : function(next){ + var userData = getAdministratorAccountData() + var builtURL = buildRegularApiRequestURL(administratorAccountData.auth,'monitorStates',administratorAccountData.ke) + 'EnableWithDetectorOn/insert' + request.post(builtURL,{ + form: { + data: { + "monitors": [ + { + "mode":"start", + "mid":temp.monitorId, + "details": { + "detector": "1" + } + } + ] + } + } + },function(err, httpResponse, body){ + var response = s.parseJSON(body) + if(response.ok !== true)console.log(builtURL,response) + checkResult('API : /monitorStates Insert (Enable + Detector On)',true,response.ok) + next() + }) + }, + "/monitorStates Insert (Continuous Recording)" : function(next){ + var userData = getAdministratorAccountData() + var builtURL = buildRegularApiRequestURL(administratorAccountData.auth,'monitorStates',administratorAccountData.ke) + 'RecordOnly/insert' + request.post(builtURL,{ + form: { + data: { + "monitors": [ + { + "mode":"record", + "mid":temp.monitorId, + "details": { + "detector": "0" + } + } + ] + } + } + },function(err, httpResponse, body){ + var response = s.parseJSON(body) + if(response.ok !== true)console.log(builtURL,response) + checkResult('API : /monitorStates Insert (Continuous Recording)',true,response.ok) + next() + }) + }, + "/monitorStates List" : function(next){ + var userData = getAdministratorAccountData() + var builtURL = buildRegularApiRequestURL(administratorAccountData.auth,'monitorStates',administratorAccountData.ke) + request.get(builtURL,function(err, httpResponse, body){ + var response = s.parseJSON(body) + if(response.ok !== true)console.log(builtURL,response) + checkResult('API : /monitorStates List',true,response.ok) + next() + }) + }, + "/monitorStates Run Action (Disable + Detector Off)" : function(next){ + var userData = getAdministratorAccountData() + var builtURL = buildRegularApiRequestURL(administratorAccountData.auth,'monitorStates',administratorAccountData.ke) + 'DisableWithDetectorOff' + request.get(builtURL,function(err, httpResponse, body){ + var response = s.parseJSON(body) + if(response.ok !== true)console.log(builtURL,response) + checkResult('API : /monitorStates Run Action (Disable + Detector Off)',true,response.ok) + next() + }) + }, + "/monitorStates Run Action (Enable + Detector On)" : function(next){ + var userData = getAdministratorAccountData() + var builtURL = buildRegularApiRequestURL(administratorAccountData.auth,'monitorStates',administratorAccountData.ke) + 'EnableWithDetectorOn' + request.get(builtURL,function(err, httpResponse, body){ + var response = s.parseJSON(body) + if(response.ok !== true)console.log(builtURL,response) + checkResult('API : /monitorStates Run Action (Enable + Detector On)',true,response.ok) + next() + }) + }, + "/monitorStates Run Action (Continuous Recording)" : function(next){ + var userData = getAdministratorAccountData() + var builtURL = buildRegularApiRequestURL(administratorAccountData.auth,'monitorStates',administratorAccountData.ke) + 'RecordOnly' + request.get(builtURL,function(err, httpResponse, body){ + var response = s.parseJSON(body) + if(response.ok !== true)console.log(builtURL,response) + checkResult('API : /monitorStates Run Action (Continuous Recording)',true,response.ok) + next() + }) + }, + "/monitorStates Delete (Disable + Detector Off)" : function(next){ + var userData = getAdministratorAccountData() + var builtURL = buildRegularApiRequestURL(administratorAccountData.auth,'monitorStates',administratorAccountData.ke) + 'DisableWithDetectorOff/delete' + request.get(builtURL,function(err, httpResponse, body){ + var response = s.parseJSON(body) + if(response.ok !== true)console.log(builtURL,response) + checkResult('API : /monitorStates Delete (Disable + Detector Off)',true,response.ok) + next() + }) + }, + "/monitorStates Delete (Enable + Detector On)" : function(next){ + var userData = getAdministratorAccountData() + var builtURL = buildRegularApiRequestURL(administratorAccountData.auth,'monitorStates',administratorAccountData.ke) + 'EnableWithDetectorOn/delete' + request.get(builtURL,function(err, httpResponse, body){ + var response = s.parseJSON(body) + if(response.ok !== true)console.log(builtURL,response) + checkResult('API : /monitorStates Delete (Enable + Detector On)',true,response.ok) + next() + }) + }, + "/monitorStates Delete (Continuous Recording)" : function(next){ + var userData = getAdministratorAccountData() + var builtURL = buildRegularApiRequestURL(administratorAccountData.auth,'monitorStates',administratorAccountData.ke) + 'RecordOnly/delete' + request.get(builtURL,function(err, httpResponse, body){ + var response = s.parseJSON(body) + if(response.ok !== true)console.log(builtURL,response) + checkResult('API : /monitorStates Delete (Continuous Recording)',true,response.ok) + next() + }) + }, } } console.log('----- Function Test Starting') - Object.keys(test).forEach(function(libkey){ - var library = test[libkey] - console.log('--- Testing ' + libkey + '...') - Object.keys(library).forEach(function(key){ - var functionTest = library[key] - functionTest() - }) - console.log('-- Completed ' + libkey + '...') + var completedGroups = 0 + var testGroupKeys = Object.keys(test) + var testGroupRunLoop = function(callback){ + var tableName = testGroupKeys[completedGroups] + var testers = test[testGroupKeys[completedGroups]] + if(tableName){ + console.log('--- Testing ' + tableName + '...') + // test functions > + var completedFunctions = 0 + var testFunctionsKeys = Object.keys(testers) + var testFunctionRunLoop = function(innerCallback){ + var functioName = testFunctionsKeys[completedFunctions] + var theFunction = testers[testFunctionsKeys[completedFunctions]] + if(functioName){ + theFunction(function(){ + ++completedFunctions + testFunctionRunLoop(innerCallback) + }) + }else{ + innerCallback() + } + } + testFunctionRunLoop(function(){ + console.log('-- Completed ' + tableName + '...') + ++completedGroups + testGroupRunLoop(callback) + }) + // test functions /> + }else{ + callback() + } + } + testGroupRunLoop(function(){ + console.log('---- Function Test Ended') }) - console.log('---- Function Test Ended') } diff --git a/test/testAdminUser.json b/test/testAdminUser.json deleted file mode 100644 index b23e9f5..0000000 --- a/test/testAdminUser.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "mail": "user@shinobi.video", - "ke": "", - "pass": "password", - "password_again": "password", - "details": "{\"factorAuth\":\"0\",\"size\":\"\",\"days\":\"\",\"event_days\":\"\",\"log_days\":\"\",\"max_camera\":\"\",\"permissions\":\"all\",\"edit_size\":\"1\",\"edit_days\":\"1\",\"edit_event_days\":\"1\",\"edit_log_days\":\"1\",\"use_admin\":\"1\",\"use_aws_s3\":\"1\",\"use_webdav\":\"1\",\"use_discordbot\":\"1\",\"use_ldap\":\"1\"}" -} diff --git a/test/testApiAdd.json b/test/testApiAdd.json deleted file mode 100644 index 4ca075a..0000000 --- a/test/testApiAdd.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "data": { - "ip": "[IP ADDRESS]", - "details": { - "auth_socket": "1", - "get_monitors": "1", - "control_monitors": "1", - "get_logs": "1", - "watch_stream": "1", - "watch_snapshot": "1", - "watch_videos": "1", - "delete_videos": "1" - } - } -} diff --git a/test/testApiDelete.json b/test/testApiDelete.json deleted file mode 100644 index 977a20b..0000000 --- a/test/testApiDelete.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "data": { - "code": "[API KEY]" - } -} diff --git a/web/libs/css/dash2.basic.css b/web/libs/css/dash2.basic.css new file mode 100644 index 0000000..0e96231 --- /dev/null +++ b/web/libs/css/dash2.basic.css @@ -0,0 +1,89 @@ +/*Cusotm Bootstrap*/ +.col-5ths, +.col-sm-5ths, +.col-md-5ths, +.col-lg-5ths { + position: relative; + min-height: 1px; + padding-right: 15px; + padding-left: 15px; +} + +.col-5ths { + -webkit-box-flex: 0; + -webkit-flex: 0 0 20%; + -ms-flex: 0 0 20%; + flex: 0 0 20%; + max-width: 20%; +} + +@media (min-width: 576px) { + .col-sm-5ths { + -webkit-box-flex: 0; + -webkit-flex: 0 0 20%; + -ms-flex: 0 0 20%; + flex: 0 0 20%; + max-width: 20%; + } +} + +@media (min-width: 768px) { + .col-md-5ths { + -webkit-box-flex: 0; + -webkit-flex: 0 0 20%; + -ms-flex: 0 0 20%; + flex: 0 0 20%; + max-width: 20%; + } +} +::-webkit-scrollbar-thumb:hover { + background-color:#bd9565; +} +::-webkit-scrollbar-thumb { + background-color:#bd9565; + border: 2px solid transparent; + border-radius: 10px; + background-clip: padding-box; +} +/**/ +.flex{display:flex} +.flex>div{flex:1} +.flex-block{display:inline-flex;width:100%;flex-flow: row wrap;} +.flex-unit-3{flex:3} +.flex-inline{display: inline-flex;position:relative} +@import (less) "../less/pie.less"; +ul{list-style:none} +*{transition:0.2s;box-sizing:border-box} +.affix-top{position:fixed} +.no-padding{padding:0!important} +.no-margin{margin:0!important} +.pre-inline{white-space: normal;word-break: normal} +.pre-inline>ul{margin:0;padding:0} +a{cursor:pointer} +nav h4{cursor:default;font-size:95%;padding:16px 40px;font-weight:100;text-transform:uppercase;letter-spacing:2px} +.m-r{margin-right:10px} +.m-b{margin-bottom:10px} +.m-t{margin-top:10px} +.m-l{margin-left:10px} +.overflow-hidden{overflow: hidden!important} +.list-inline{list-style:none} +.list-inline li{display:inline-block;vertical-align: top;margin:0;} +.truncate{width:100%;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;} +img{max-width:100%} +.display-table{display:table;width:100%} +.display-inline{display:inline-block} +.display-table-cell{display:table-cell} +.small{font-size:80%} +.super-center{position:absolute;left:0;top:0;right:0;bottom:0;margin:auto;width: 4em;height: 1em;} +.permission_monitor_edit{display:none} +.permission_video_delete{display:none} +.nodata .divider{margin:5px 0} +.loading .divider{margin:5px 0} +/* Video Grid */ +.video_grid{overflow: auto;height: 100%;display: block;} +.video_grid .col-md-2{padding-left:5px;padding-right:5px;padding-bottom:10px} +.video_grid .thumb{width:100%;height:150px;display:inline-block;background-size:cover;position:relative;overflow:hidden;border-radius:4px;border:1px solid #000;box-shadow:0 0 10px #151515} +.video_grid .thumb .title-strip, .video_grid .thumb .button-strip{width:100%;position:absolute;left:0;background:rgba(0,0,0,0.7);color:#fff;padding:4px} +.video_grid .thumb .title-strip{top:0;opacity:0.5} +.video_grid .thumb .button-strip{bottom:0;opacity:0} +.video_grid .thumb:hover .title-strip, .video_grid .thumb:hover .button-strip{opacity:1} diff --git a/web/libs/css/dash2.forms.css b/web/libs/css/dash2.forms.css new file mode 100644 index 0000000..a1d0ffe --- /dev/null +++ b/web/libs/css/dash2.forms.css @@ -0,0 +1,44 @@ +form.modal-body{margin:0} +.form-group label span{padding:5px;font-weight: 400;color: #2d2d2d;display:block;border-bottom: 1px dotted #ddd;font-size: 10pt;} +.form-group label{display:table} +.form-group label>div{display:table-cell} +.form-group label>div:nth-child(2n-1){width:30%} +.form-group label>div:nth-child(2){width:70%;padding:5px;border:1px solid #dedede;border-radius:5px} +.dark .form-group label>div,.dark .form-group label>div>span{border-color:#454545;color:#fff} +.important.form-group label>div:nth-child(2),.important.form-group label>div>span{border-color:red} +.form-group label span small{margin-left: 2px;display:block;font-weight: 600;} +.form-group-group .round-left{border-radius: 50px 0 0 50px;margin-left:10px} +.form-group-group blockquote:before,.form-group-group blockquote:after{display:none!important} +.form-group-group blockquote{letter-spacing:normal;font-style:normal} +.form-group-group blockquote p:empty{display:none} +.form-group-group blockquote p{font-size:inherit} +.form-group-group blockquote p:last-child{margin-bottom:0} +.form-group-group-group>div,.form-group-group-group .h_us_advanced>div{margin-bottom:15px;} +.form-group-group{padding:0 10px 10px 10px;overflow:hidden;margin-bottom:15px;border-radius:5px;border:1px solid #ddd;background:#fff} +.form-group-group table{width:100%} +.form-group-group table tr td{padding:10px 5px} +.form-group-group table tr:not(:last-child) td{border-bottom:1px dotted #eee} +.form-group-group .mdl-list__item{border-bottom:1px solid #eee;} +.form-group-group .mdl-list__item:hover{background:#e6e6e6;border-radius:4px;} +.dark .form-group-group .mdl-list__item{color:#fff;border-bottom:1px solid #444;} +.dark .form-group-group .mdl-list__item:hover{background:#555;} +.form-group-group:last-child,.form-group-group > .form-group:last-child{margin-bottom:0} +.form-group-group h4{margin:0 -10px 15px -10px;padding:15px;background:#ddd;} +.form-group-group h4 small{color:#fff;} +.form-group-group.red{border-color:#d9534f} +.form-group-group.red h4{background:#d9534f;color:#fff} +.form-group-group.purple{border-color:#3f51b5} +.form-group-group.purple h4{background:#3f51b5;color:#fff} +.form-group-group.blue{border-color:#337ab7} +.form-group-group.blue h4{background:#337ab7;color:#fff} +.form-group-group.navy{border-color:#31708f} +.form-group-group.navy h4{background:#31708f;color:#fff} +.form-group-group.green{border-color:#449d44} +.form-group-group.green h4{background:#449d44;color:#fff} +.form-group-group.forestgreen{border-color:#1e4046} +.form-group-group.forestgreen h4{background:#1e4046;color:#fff} +.form-group-group.orange{border-color:#c49a68} +.form-group-group.orange h4{background:#c49a68;color:#fff} +.form-group-group.grey{border-color:#777} +.form-group-group.grey h4{background:#777;color:#fff} +.dark .form-group-group{background:#222} diff --git a/web/libs/css/dash2.modal.css b/web/libs/css/dash2.modal.css new file mode 100644 index 0000000..b0a2cc2 --- /dev/null +++ b/web/libs/css/dash2.modal.css @@ -0,0 +1,6 @@ +.dark.modal .modal-header,.dark.modal .modal-footer{background:#333;border-color:#444;} +.dark.modal .modal-header{color:#fff;} +.dark.modal .modal-footer>*:not(.btn){color:#fff;} +.dark.modal .modal-body{background:#333;} +.dark.modal .close{color:#fff;} +.dark.modal{color:#fff;} diff --git a/web/libs/css/dash2.monitors.css b/web/libs/css/dash2.monitors.css new file mode 100644 index 0000000..c69ccb3 --- /dev/null +++ b/web/libs/css/dash2.monitors.css @@ -0,0 +1,86 @@ + +.jpegMode .cpu_load .progress-bar,.jpegMode .ram_load .progress-bar{background-color:#5cb85c} +.jpegMode [system="jpegToggle"],[system].text-success{color:#5cb85c!important} + +.monitor_item .stream-hud{opacity:0;position:absolute;top:0;left:0;width:100%;height:100%;z-index:10} +.monitor_item .stream-hud .camera_cpu_usage{position:absolute;top:0;left:0;width: 100%;} +.monitor_item .stream-hud .camera_cpu_usage .progress{width: 100%;} +.monitor_item .stream-hud .camera_cpu_usage:hover .progress{height:20px;transition:0.2s} +.monitor_item .stream-hud .controls{position:absolute;top:10px;left:10px;} +.monitor_item .stream-hud:hover{opacity:1} +.monitor_item .stream-hud .bottom-text{position:absolute;bottom:0;left:0;width:70%;padding:5px;text-shadow: 0 0 10px #333;} +.monitor_item .stream-hud:hover .bottom-text{top:0;} +.monitor_item .stream-hud .bottom-text .detector-fade{background: rgba(0,0,0,0.4);padding:10px 20px;border-radius:10px} +.monitor_item .stream-hud .lamp{position:absolute;top:5px;right:5px;z-index:1;text-shadow: 0 0 15px #333;} +.monitor_item[mode="Disabled"] .stream-hud .lamp{color:#5d5d5d} +.monitor_item[mode="Watch Only"] .stream-hud .lamp{color:#5da8e8} +.monitor_item[mode="Idle"] .stream-hud .lamp{color:#fff} +.monitor_item[mode="Record"] .stream-hud .lamp{color:#d9534f} +/*.data-menu{max-height:700px}*/ +.data-menu:not(:last-child){border-right:1px solid #fff;} +.data-menu.logs{list-style:none;} +.monitor_item .motionVision{display:none} + +.monitor_item .grid-stack-item-content{width:100%!important;left:0!important;right:0!important} +.monitor_item .ui-resizable-se {bottom: 10px!important;} +.monitor_item .stream-block{position: relative;text-align: center} +.monitor_item .mdl-data_window{overflow-x: auto;background:rgba(0,0,0,0.7);color:#fff;height:100%} +.monitor_item .mdl-data_window:not(.col-md-6){width:0;min-width:0;height:0px;min-height:0} + + +.monitor_item.fullscreen img.stream-element{height:100%;width:auto} +.monitor_item.fullscreen canvas.stream-element{height:auto;width:auto;background-color:black;} +.monitor_item .stream-element{border: 0;object-fit: fill;height: 100%;width:100%} +.monitor_item{position:relative;padding:0;transition:none;background:#000} +.monitor_item .mdl-card{min-height:auto;border:1px solid #272727;border-radius:0px;overflow:hidden} +.monitor_item .mdl-card__media{position:relative;padding:0!important;display:block!important;background:#000;} +.monitor_item.selected .stream-element{height:600px} +.monitor_item.selected .fa-expand:before{content:"\f066"} +.monitor_item .mdl-card__supporting-text{background:#222;color:#fff!important;display:block;min-height:auto!important} +.monitor_item.detector_triggered .detector-fade{opacity:1} +.monitor_item .detector-fade{opacity:0} +.monitor_item .indifference{position:absolute;width:100%;left:0;top:0;transition:0.2s;} +.monitor_item .progress{width:100%;background:#333;box-shadow:0;} +.monitor_item .indifference:hover .progress{height:20px;transition:0.2s} +.hide_indifference .indifference{display:none!important} +.hide_indifference [class_toggle="hide_indifference"]{color:#d9534f!important} +.monitor_item .mdl-card:not(.mdl-cell--4-col-desktop) .mdl-card__supporting-text .monitor_details{display:none;font-size:90%;margin-bottom:10px} +.monitor_item[mode="Record"] [mode="record"]{display:none} +.monitor_item[mode="Watch Only"] [mode="start"]{display:none} +.monitor_item .stream-hud .controls .btn{opacity:0.7} +.monitor_item.doObjectDetection .progress-bar{background-color: #57d94f} + +.data-menu{text-align:left} +.data-menu ul,.side-menu ul{list-style:none;margin:0;padding:0;} +.data-menu li,.side-menu li:not(.mdl-menu__item){ + border-bottom:1px solid #54502d;padding:10px; +} +.data-menu .progress-circle{margin:0 10px 0 0;position:relative;height:40px;width:40px;float:left} +.data-menu .progress-circle span:after{content:''} +img.circle-img,div.circle-img{border-radius:50%;height:50px;width:50px} +.circle-img.sm{height:25px;width:25px} + +@media screen and (max-width:1500px){ + .monitor_item .mdl-card__supporting-text .btn{ + padding: 5px 10px; + font-size: 11px; + line-height: 1.5; + } +} + +#monitors_live .monitor_item [class_toggle="show_logs"]{display:none} +#monitors_live .monitor_item .indifference{top:-5px} +#monitors_live .monitor_item .mdl-cell--8-col{width:100%;border:0;border-radius:0;margin:0;position:relative} +#monitors_live .monitor_item .mdl-cell--4-col-desktop,.monitor_item .mdl-card__supporting-text{display:none} +#monitors_live .monitor_item .mdl-card__supporting-text .monitor_details,#monitors_live .monitor_item .mdl-card__supporting-text .btn-group{display:none;text-align:center} +#monitors_live .monitor_item .mdl-card__supporting-text:not(.meta){display:block;position:absolute;bottom:0;left:0;height:0;padding:0;overflow:visible} +#monitors_live .monitor_item.show_data .mdl-card__supporting-text:not(.meta){width:50%} +#monitors_live .monitor_item.detector_triggered .mdl-card__supporting-text:not(.meta) .indifference{opacity:0.5;} +#monitors_live .monitor_item:hover .mdl-card__supporting-text:not(.meta){padding:15px;z-index:15;height:auto;} +#monitors_live .monitor_item:hover .mdl-card__supporting-text .monitor_details{display:block} +#monitors_live .monitor_item:hover .mdl-card__supporting-text .btn-group{display:inline-block} + +.signal.green{background:#5cb85c} +[status="1"] .btn[video="launch"],[data-status="1"] .btn[video="launch"]{background:#337ab7;border-color:#337ab7} +[status="2"] .btn[launch="video"],[status="2"] .btn[video="launch"],[data-status="2"] .btn[video="launch"]{background:#a59100;border-color:#a59100} +.signal.red{background:#c9302c} diff --git a/web/libs/css/dash2.powervideo.css b/web/libs/css/dash2.powervideo.css new file mode 100644 index 0000000..624a3be --- /dev/null +++ b/web/libs/css/dash2.powervideo.css @@ -0,0 +1,8 @@ +#pvideo_viewer iframe{border:0;width:100%;height:350px;margin-bottom:10px;overflow:hidden} +#pvideo_viewer video{max-height:300px;max-width:100%;} +#pvideo_viewer .holder{height:300px;} +#pvideo_viewer h3{margin-top:0} +#pvideo_viewer .progressBar{position:relative;} +#pvideo_viewer .bufferBar{position:absolute;left:0;top:0;opacity:0.4} +#pvideo_viewer .timeBar{position:relative;z-index: 222;background:transparent} +#pvideo_viewer h3{font-family:monospace} diff --git a/web/libs/css/dash2.ptzcontrols.css b/web/libs/css/dash2.ptzcontrols.css new file mode 100644 index 0000000..0ecee29 --- /dev/null +++ b/web/libs/css/dash2.ptzcontrols.css @@ -0,0 +1,89 @@ +/*Control Pad*/ +.PTZ_controls { + z-index: 111; + position: absolute; + left: 20px; + top: 20px; + margin:0; + display: inline-block; + width: 120px; +} +.PTZ_controls .btn-group{margin-top:10px} +.PTZ_controls .pad { + position: relative; + height: 120px; + width: 120px; + background: #b7b7b7; + border-radius: 50%; + box-shadow: inset 0 0 1px rgba(120, 120, 120, 0.6), inset 0 2px 2px rgba(0, 0, 0, 0.1), 0 2px 2px rgba(240, 240, 240, 0.4); +} +.PTZ_controls .control { + position: absolute; +} +.PTZ_controls .pad .control { + height: 30px; + width: 30px; + background: #636363; + box-shadow: 0 0 0 2px rgba(0, 0, 0, 0.6), 0 0 0 3px rgba(60, 60, 60, 0.2), 0 0 0 4px rgba(60, 60, 60, 0.2); + border-radius: 2px; +} +.PTZ_controls .zoom_in{ + top: 0; + right: 0; +} +.PTZ_controls .zoom_out{ + bottom: 0; + right: 0; +} +.PTZ_controls .nv_enabled{ + top: 0; + right: 0; +} +.PTZ_controls .nv_disable{ + bottom: 0; + right: 0; +} +.PTZ_controls .pad .top { + top: 15px; + left: 50%; + margin: 0 0 0 -15px; +} +.PTZ_controls .pad .left { + top: 45px; + left: 15px; +} +.PTZ_controls .pad .right { + top: 45px; + right: 15px; +} +.PTZ_controls .pad .control.right:before { + transform: rotate(90deg) translate(-3px, -5px); +} +.PTZ_controls .pad .bottom { + bottom: 15px; + left: 50%; + margin: 0 0 0 -15px; +} +/* Overlap the other controls to hide box-shadow */ +.PTZ_controls .pad .middle { + height: 34px; + width: 34px; + z-index: 5; + top: 43px; + left: 50%; + margin: 0 0 0 -17px; + box-shadow: none; + border-radius: 3px; +} +.PTZ_controls .pad .middle:after { + position: absolute; + top: 50%; + left: 50%; + margin: -35% 0 0 -35%; + content: ''; + background: #636363; + height: 70%; + width: 70%; + border-radius: 100%; + box-shadow: inset 0 0 2px rgba(120, 120, 120, 0.6), inset 0 2px 8px rgba(0, 0, 0, 0.1), 0 2px 2px rgba(240, 240, 240, 0.2); +} diff --git a/web/libs/css/dash2.regioneditor.css b/web/libs/css/dash2.regioneditor.css new file mode 100644 index 0000000..09d3ee6 --- /dev/null +++ b/web/libs/css/dash2.regioneditor.css @@ -0,0 +1,5 @@ +#region_editor .modal-body{text-align:center;overflow:auto;max-height:800px} +#region_editor .canvas_holder{position:relative;display:inline-block;overflow:auto;min-height:450px} +#region_editor .cord_element{position:absolute;background:rgba(221, 221, 221, 0.8);z-index:11;padding:5px;} +#region_editor .cord_element.selected{z-index:12;} +#region_editor .cord_element .controls{margin-bottom:5px;} diff --git a/web/libs/css/dash2.righttoleft.css b/web/libs/css/dash2.righttoleft.css new file mode 100644 index 0000000..39d59a4 --- /dev/null +++ b/web/libs/css/dash2.righttoleft.css @@ -0,0 +1,11 @@ +.right-to-left {text-align:right} +.right-to-left select{direction: rtl;} +.right-to-left input,.right-to-left textarea{direction: rtl;text-align:right} +.right-to-left .form-group label span{padding-right:10px} +.right-to-left .modal-footer{text-align:left} +.right-to-left .mdl-menu__item>div>*{flex:1} +.right-to-left .mdl-menu__item>div>i{margin-right:0;margin-left:5px} +.right-to-left .mdl-menu__item{text-align:right} +.right-to-left .mdl-menu__item i{float:right} +.right-to-left .pull-right,.right-to-left .close{float:left!important} +.right-to-left .pull-left,.right-to-left .mdl-menu__item span{float:right!important} diff --git a/web/libs/css/dash2.timelapse.css b/web/libs/css/dash2.timelapse.css new file mode 100644 index 0000000..924bc2f --- /dev/null +++ b/web/libs/css/dash2.timelapse.css @@ -0,0 +1,13 @@ +#timelapse_video_line{overflow-y:scroll;overflow-x:hidden;max-height:400px;margin:0;text-align:left} +#timelapse_video_display .videoBefore,#timelapse_video_display .videoAfter{display:none} +.timelapse_video:not(:last-child){border-bottom:1px solid #444;} +.timelapse_video .frame{width:50px;height:50px;background-size:cover;background-position:center;border-radius:5px} +.timelapse_video>div>div:not(:last-child){padding-right:10px} +.timelapse_video .flex-block:not(:last-child){padding-bottom:10px} +.timelapse_video.list-group-item{padding:10px} +.timelapse_hud{position: relative;background:#000} +.timelapse_hud .timelapse_playRate{position: absolute;font-family: monospace;top:10px;right:0;left:0;margin:auto;font-size:23px} +#timelapse .progress-bar{transition:0.5s!important} +.timelapse_hud .controlBar{position: absolute;background:rgba(22,22,22,0.8);width:100%;left:0;bottom:0;} +.timelapse_hud .hover-hide{opacity:0} +.timelapse_hud:hover .hover-hide{opacity:1;z-index:5} diff --git a/web/libs/css/main.dash2.css b/web/libs/css/main.dash2.css index a62515c..b04b37b 100644 --- a/web/libs/css/main.dash2.css +++ b/web/libs/css/main.dash2.css @@ -1,87 +1,3 @@ -/*Cusotm Bootstrap*/ -.col-5ths, -.col-sm-5ths, -.col-md-5ths, -.col-lg-5ths { - position: relative; - min-height: 1px; - padding-right: 15px; - padding-left: 15px; -} - -.col-5ths { - -webkit-box-flex: 0; - -webkit-flex: 0 0 20%; - -ms-flex: 0 0 20%; - flex: 0 0 20%; - max-width: 20%; -} - -@media (min-width: 576px) { - .col-sm-5ths { - -webkit-box-flex: 0; - -webkit-flex: 0 0 20%; - -ms-flex: 0 0 20%; - flex: 0 0 20%; - max-width: 20%; - } -} - -@media (min-width: 768px) { - .col-md-5ths { - -webkit-box-flex: 0; - -webkit-flex: 0 0 20%; - -ms-flex: 0 0 20%; - flex: 0 0 20%; - max-width: 20%; - } -} -::-webkit-scrollbar-thumb:hover { - background-color:#bd9565; -} -::-webkit-scrollbar-thumb { - background-color:#bd9565; - border: 2px solid transparent; - border-radius: 10px; - background-clip: padding-box; -} -/**/ -.flex{display:flex} -.flex>div{flex:1} -.flex-block{display:inline-flex;width:100%;flex-flow: row wrap;} -.flex-unit-3{flex:3} -.flex-inline{display: inline-flex;position:relative} -@import (less) "../less/pie.less"; -ul{list-style:none} -*{transition:0.2s;box-sizing:border-box} -.affix-top{position:fixed} -.no-padding{padding:0!important} -.no-margin{margin:0!important} -.pre-inline{white-space: normal;word-break: normal} -.pre-inline>ul{margin:0;padding:0} -a{cursor:pointer} -nav h4{cursor:default;font-size:95%;padding:16px 40px;font-weight:100;text-transform:uppercase;letter-spacing:2px} -.m-r{margin-right:10px} -.m-b{margin-bottom:10px} -.m-t{margin-top:10px} -.m-l{margin-left:10px} -.overflow-hidden{overflow: hidden!important} -.list-inline{list-style:none} -.list-inline li{display:inline-block;vertical-align: top;margin:0;} -.truncate{width:100%;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;} -img{max-width:100%} -.display-table{display:table;width:100%} -.display-inline{display:inline-block} -.display-table-cell{display:table-cell} -.small{font-size:80%} -.super-center{position:absolute;left:0;top:0;right:0;bottom:0;margin:auto;width: 4em;height: 1em;} -.jpegMode .cpu_load .progress-bar,.jpegMode .ram_load .progress-bar{background-color:#5cb85c} -.jpegMode [system="jpegToggle"],[system].text-success{color:#5cb85c!important} -.permission_monitor_edit{display:none} -.permission_video_delete{display:none} -.nodata .divider{margin:5px 0} -.loading .divider{margin:5px 0} - #accbtn{ text-overflow: ellipsis; white-space: nowrap; @@ -89,75 +5,6 @@ img{max-width:100%} padding: 0; } -.monitor_item .stream-hud{opacity:0;position:absolute;top:0;left:0;width:100%;height:100%;z-index:2} -.monitor_item .stream-hud .camera_cpu_usage{position:absolute;top:0;left:0;width: 100%;} -.monitor_item .stream-hud .camera_cpu_usage .progress{width: 100%;} -.monitor_item .stream-hud .camera_cpu_usage:hover .progress{height:20px;transition:0.2s} -.monitor_item .stream-hud .controls{position:absolute;top:10px;left:10px;} -.monitor_item .stream-hud:hover{opacity:1} -.monitor_item .stream-hud .bottom-text{position:absolute;bottom:0;left:0;width:100%;padding:5px;text-shadow: 0 0 10px #333;} -.monitor_item .stream-hud .bottom-text .detector-fade{background: rgba(0,0,0,0.4);padding:10px 20px;border-radius:10px} -.monitor_item .stream-hud .lamp{position:absolute;top:5px;right:5px;z-index:1;text-shadow: 0 0 15px #333;} -.monitor_item[mode="Disabled"] .stream-hud .lamp{color:#5d5d5d} -.monitor_item[mode="Watch Only"] .stream-hud .lamp{color:#5da8e8} -.monitor_item[mode="Idle"] .stream-hud .lamp{color:#fff} -.monitor_item[mode="Record"] .stream-hud .lamp{color:#d9534f} -/*.data-menu{max-height:700px}*/ -.data-menu:not(:last-child){border-right:1px solid #fff;} -.data-menu.logs{list-style:none;} -.monitor_item .motionVision{display:none} - -.monitor_item .grid-stack-item-content{width:100%!important;left:0!important;right:0!important} -.monitor_item .ui-resizable-se {bottom: 10px!important;} -.monitor_item .stream-block{position: relative;text-align: center} -.monitor_item .mdl-data_window{overflow-x: auto;background:rgba(0,0,0,0.7);color:#fff;height:100%} -.monitor_item .mdl-data_window:not(.col-md-6){width:0;min-width:0;height:0px;min-height:0} - - -.monitor_item.fullscreen img.stream-element{height:100%;width:auto} -.monitor_item.fullscreen canvas.stream-element{height:auto;width:auto;background-color:black;} -.monitor_item .stream-element{border: 0;object-fit: fill;height: 100%;width:100%} -.monitor_item{position:relative;padding:0;transition:none;background:#000} -.monitor_item .mdl-card{min-height:auto;border:1px solid #272727;border-radius:0px;overflow:hidden} -.monitor_item .mdl-card__media{position:relative;padding:0!important;display:block!important;background:#000;} -.monitor_item.selected .stream-element{height:600px} -.monitor_item.selected .fa-expand:before{content:"\f066"} -.monitor_item .mdl-card__supporting-text{background:#222;color:#fff!important;display:block;min-height:auto!important} -.monitor_item.detector_triggered .detector-fade{opacity:1} -.monitor_item .detector-fade{opacity:0} -.monitor_item .indifference{position:absolute;width:100%;left:0;top:0;transition:0.2s;} -.monitor_item .progress{width:100%;background:#333;box-shadow:0;} -.monitor_item .indifference:hover .progress{height:20px;transition:0.2s} -.hide_indifference .indifference{display:none!important} -.hide_indifference [class_toggle="hide_indifference"]{color:#d9534f!important} -.monitor_item .mdl-card:not(.mdl-cell--4-col-desktop) .mdl-card__supporting-text .monitor_details{display:none;font-size:90%;margin-bottom:10px} -.monitor_item[mode="Record"] [mode="record"]{display:none} -.monitor_item[mode="Watch Only"] [mode="start"]{display:none} -.monitor_item .stream-hud .controls .btn{opacity:0.7} -.monitor_item.doObjectDetection .progress-bar{background-color: #57d94f} - -@media screen and (max-width:1500px){ - .monitor_item .mdl-card__supporting-text .btn{ - padding: 5px 10px; - font-size: 11px; - line-height: 1.5; - } -} - -#monitors_live .monitor_item [class_toggle="show_logs"]{display:none} -#monitors_live .monitor_item .indifference{top:-5px} -#monitors_live .monitor_item .mdl-cell--8-col{width:100%;border:0;border-radius:0;margin:0;position:relative} -#monitors_live .monitor_item .mdl-cell--4-col-desktop,.monitor_item .mdl-card__supporting-text{display:none} -#monitors_live .monitor_item .mdl-card__supporting-text .monitor_details,#monitors_live .monitor_item .mdl-card__supporting-text .btn-group{display:none;text-align:center} -#monitors_live .monitor_item .mdl-card__supporting-text:not(.meta){display:block;position:absolute;bottom:0;left:0;height:0;padding:0;} -#monitors_live .monitor_item.show_data .mdl-card__supporting-text:not(.meta){width:50%} -#monitors_live .monitor_item.detector_triggered .mdl-card__supporting-text:not(.meta) .indifference{opacity:0.5;} -#monitors_live .monitor_item:hover .mdl-card__supporting-text:not(.meta){padding:15px;z-index:15;height:auto;} -#monitors_live .monitor_item:hover .mdl-card__supporting-text .monitor_details{display:block} -#monitors_live .monitor_item:hover .mdl-card__supporting-text .btn-group{display:inline-block} - - - #vis_pwrvideo{height:250px} #monSectionStreamChannels,#monSectionInputMaps{margin-bottom: 15px;} #monSectionStreamChannels:empty,#monSectionInputMaps:empty{display:none} @@ -169,19 +16,12 @@ img{max-width:100%} .demo-blog .demo-blog__posts.montage{max-width:100%} - +.mdl-layout__drawer{overflow-y: visible!important} +.hide-side .mdl-layout__drawer{overflow-y: hidden} .mdl-layout__header-row{padding-left:10!important} .mdl-layout__header-row .nav>li>a{border-radius:50%;} .mdl-layout__drawer-button i{position:absolute;top:0;right:0;bottom:0;left:0;margin:auto;height:1em;color:#fff} -.data-menu{text-align:left} -.data-menu ul,.side-menu ul{list-style:none;margin:0;padding:0;} -.data-menu li,.side-menu li{ - border-bottom:1px solid #54502d;padding:10px; -} -.data-menu .progress-circle{margin:0 10px 0 0;position:relative;height:40px;width:40px;float:left} -.data-menu .progress-circle span:after{content:''} -img.circle-img,div.circle-img{border-radius:50%;height:50px;width:50px} -.circle-img.sm{height:25px;width:25px} + .video_video{margin:auto;max-width:100%;max-height:600px;} #confirm_window .video_video{margin-top:15px} @@ -200,60 +40,9 @@ img.circle-img,div.circle-img{border-radius:50%;height:50px;width:50px} .flex-container-modal-body .flex-block>div{flex:1;float:none} .modal{overflow:auto!important} -form.modal-body{margin:0} -#region_editor .modal-body{text-align:center;overflow:auto;max-height:800px} -#region_editor .canvas_holder{position:relative;display:inline-block;overflow:auto;min-height:450px} -#region_editor .cord_element{position:absolute;background:rgba(221, 221, 221, 0.8);z-index:11;padding:5px;} -#region_editor .cord_element.selected{z-index:12;} -#region_editor .cord_element .controls{margin-bottom:5px;} -.form-group label span{padding:5px;font-weight: 400;color: #2d2d2d;display:block;border-bottom: 1px dotted #ddd;font-size: 10pt;} -.form-group label{display:table} -.form-group label>div{display:table-cell} -.form-group label>div:nth-child(2n-1){width:30%} -.form-group label>div:nth-child(2){width:70%;padding:5px;border:1px solid #dedede;border-radius:5px} -.dark .form-group label>div,.dark .form-group label>div>span{border-color:#454545;color:#fff} -.important.form-group label>div:nth-child(2),.important.form-group label>div>span{border-color:red} -.form-group label span small{margin-left: 2px;display:block;font-weight: 600;} -.form-group-group .round-left{border-radius: 50px 0 0 50px;margin-left:10px} -.form-group-group blockquote:before,.form-group-group blockquote:after{display:none!important} -.form-group-group blockquote{letter-spacing:normal;font-style:normal} -.form-group-group blockquote p:empty{display:none} -.form-group-group blockquote p{font-size:inherit} -.form-group-group blockquote p:last-child{margin-bottom:0} -.form-group-group-group>div,.form-group-group-group .h_us_advanced>div{margin-bottom:15px;} -.form-group-group{padding:0 10px 10px 10px;overflow:hidden;margin-bottom:15px;border-radius:5px;border:1px solid #ddd;background:#fff} -.form-group-group table{width:100%} -.form-group-group table tr td{padding:10px 5px} -.form-group-group table tr:not(:last-child) td{border-bottom:1px dotted #eee} -.form-group-group .mdl-list__item{border-bottom:1px solid #eee;} -.form-group-group .mdl-list__item:hover{background:#e6e6e6;border-radius:4px;} -.dark .form-group-group .mdl-list__item{color:#fff;border-bottom:1px solid #444;} -.dark .form-group-group .mdl-list__item:hover{background:#555;} -.form-group-group:last-child,.form-group-group > .form-group:last-child{margin-bottom:0} -.form-group-group h4{margin:0 -10px 15px -10px;padding:15px;background:#ddd;} -.form-group-group h4 small{color:#fff;} -.form-group-group.red{border-color:#d9534f} -.form-group-group.red h4{background:#d9534f;color:#fff} -.form-group-group.purple{border-color:#3f51b5} -.form-group-group.purple h4{background:#3f51b5;color:#fff} -.form-group-group.blue{border-color:#337ab7} -.form-group-group.blue h4{background:#337ab7;color:#fff} -.form-group-group.navy{border-color:#31708f} -.form-group-group.navy h4{background:#31708f;color:#fff} -.form-group-group.green{border-color:#449d44} -.form-group-group.green h4{background:#449d44;color:#fff} -.form-group-group.forestgreen{border-color:#1e4046} -.form-group-group.forestgreen h4{background:#1e4046;color:#fff} -.form-group-group.orange{border-color:#c49a68} -.form-group-group.orange h4{background:#c49a68;color:#fff} -.form-group-group.grey{border-color:#777} -.form-group-group.grey h4{background:#777;color:#fff} -.dark .form-group-group{background:#222} + .videos_list .title{font-size:12pt;padding:0 10px} -[status="1"] .btn[video="launch"],[data-status="1"] .btn[video="launch"]{background:#337ab7;border-color:#337ab7} -[status="2"] .btn[launch="video"],[status="2"] .btn[video="launch"],[data-status="2"] .btn[video="launch"]{background:#a59100;border-color:#a59100} -.signal.red{background:#c9302c} -.signal.green{background:#5cb85c} + .demo-drawer{background:#2b2a2a;color:#fff;} .demo-drawer.mdl-layout__drawer .mdl-navigation{padding-top:0;} .demo-drawer::-webkit-scrollbar{display:none;} @@ -285,12 +74,14 @@ form.modal-body{margin:0} .nav-xs.side-menu.list-blocks .monitor_block img{width:40px;height:40px;} .side-menu.list-blocks .monitor_block .box{width:calc(100% - 70px);display:inline-block} .nav-xs.side-menu.list-blocks .monitor_block .list-data{display:none} +.side-menu .mdl-menu{z-index: 12} + #monitors_list .monitor_block{transition:none} .dropdown-menu.scrollable{max-height:300px} .upload_file input{display:none} #video_preview .stream-objects{right:0;margin:auto;display:inline-block;position:relative;width:auto} .stream-block,.stream-objects{overflow: hidden!important} -.stream-objects{position:absolute;top:0;left:0;width:100%;height:100%;z-index:1} +.stream-objects{position:absolute;top:0;left:0;width:100%;height:100%;z-index:10} .stream-objects .tag{position:absolute;bottom:100%;left:0;background:red;color:#fff;font-family:monospace;font-size:80%;border-radius:5px 5px 0 0 ;padding:3px 5px;} .stream-objects .stream-detected-object{position:absolute;top:0;left:0;border:3px solid red;background:transparent;border-radius:5px} .stream-objects .stream-detected-point{position:absolute;top:0;left:0;border:3px solid yellow;background:transparent;border-radius:5px} @@ -306,39 +97,11 @@ form.modal-body{margin:0} .form-group label{width:100%} -#pvideo_viewer iframe{border:0;width:100%;height:350px;margin-bottom:10px;overflow:hidden} -#pvideo_viewer video{max-height:300px;max-width:100%;} -#pvideo_viewer .holder{height:300px;} -#pvideo_viewer h3{margin-top:0} -#pvideo_viewer .progressBar{position:relative;} -#pvideo_viewer .bufferBar{position:absolute;left:0;top:0;opacity:0.4} -#pvideo_viewer .timeBar{position:relative;z-index: 222;background:transparent} -#pvideo_viewer h3{font-family:monospace} + #vis_monitors{overflow:auto;max-height:400px} #vis_monitors .btn-group-vertical{width:100%} -/*timeline*/ -#timelapse_video_line{overflow-y:scroll;overflow-x:hidden;max-height:400px;margin:0;text-align:left} -#timelapse_video_display .videoBefore,#timelapse_video_display .videoAfter{display:none} -.timelapse_video:not(:last-child){border-bottom:1px solid #444;} -.timelapse_video .frame{width:50px;height:50px;background-size:cover;background-position:center;border-radius:5px} -.timelapse_video>div>div:not(:last-child){padding-right:10px} -.timelapse_video .flex-block:not(:last-child){padding-bottom:10px} -.timelapse_video.list-group-item{padding:10px} -.timelapse_hud{position: relative;background:#000} -.timelapse_hud .timelapse_playRate{position: absolute;font-family: monospace;top:10px;right:0;left:0;margin:auto;font-size:23px} -#timelapse .progress-bar{transition:0.5s!important} -.timelapse_hud .controlBar{position: absolute;background:rgba(22,22,22,0.8);width:100%;left:0;bottom:0;} -.timelapse_hud .hover-hide{opacity:0} -.timelapse_hud:hover .hover-hide{opacity:1;z-index:5} -.video_grid{overflow: auto;height: 100%;display: block;} -.video_grid .col-md-2{padding-left:5px;padding-right:5px;padding-bottom:10px} -.video_grid .thumb{width:100%;height:150px;display:inline-block;background-size:cover;position:relative;overflow:hidden;border-radius:4px;border:1px solid #000;box-shadow:0 0 10px #151515} -.video_grid .thumb .title-strip, .video_grid .thumb .button-strip{width:100%;position:absolute;left:0;background:rgba(0,0,0,0.7);color:#fff;padding:4px} -.video_grid .thumb .title-strip{top:0;opacity:0.5} -.video_grid .thumb .button-strip{bottom:0;opacity:0} -.video_grid .thumb:hover .title-strip, .video_grid .thumb:hover .button-strip{opacity:1} .table-striped>tbody>tr>td{vertical-align:middle} .table-striped .thumbnail{width:100px;height:80px;border-radius:5px;margin:0;display:inline-block;} @@ -352,13 +115,6 @@ form.modal-body{margin:0} background-color: #c49a68; border-color: #c49a68; } - -.dark.modal .modal-header,.dark.modal .modal-footer{background:#333;border-color:#444;} -.dark.modal .modal-header{color:#fff;} -.dark.modal .modal-footer>*:not(.btn){color:#fff;} -.dark.modal .modal-body{background:#333;} -.dark.modal .close{color:#fff;} -.dark.modal{color:#fff;} .dark .table-striped>tbody>tr:nth-of-type(even){background:#616161} .dark .table-striped>tbody>tr>td{border-color:#222;color:#fff} .dark .table-striped>thead>tr>th{border-color:#222;color:#fff;background:#616161;vertical-align:middle;} @@ -481,95 +237,10 @@ ul.msg_list li .message { .mdl-js-layout.hide-side:not(.is-small-screen)>.mdl-layout__header{ margin-left: 0px;width:100%;transition:0.2s } -/*Control Pad*/ -.PTZ_controls { - z-index: 111; - position: absolute; - left: 20px; - top: 20px; - margin:0; - display: inline-block; - width: 120px; -} -.PTZ_controls .btn-group{margin-top:10px} -.PTZ_controls .pad { - position: relative; - height: 120px; - width: 120px; - background: #b7b7b7; - border-radius: 50%; - box-shadow: inset 0 0 1px rgba(120, 120, 120, 0.6), inset 0 2px 2px rgba(0, 0, 0, 0.1), 0 2px 2px rgba(240, 240, 240, 0.4); -} -.PTZ_controls .control { - position: absolute; -} -.PTZ_controls .pad .control { - height: 30px; - width: 30px; - background: #636363; - box-shadow: 0 0 0 2px rgba(0, 0, 0, 0.6), 0 0 0 3px rgba(60, 60, 60, 0.2), 0 0 0 4px rgba(60, 60, 60, 0.2); - border-radius: 2px; -} -.PTZ_controls .zoom_in{ - top: 0; - right: 0; -} -.PTZ_controls .zoom_out{ - bottom: 0; - right: 0; -} -.PTZ_controls .nv_enabled{ - top: 0; - right: 0; -} -.PTZ_controls .nv_disable{ - bottom: 0; - right: 0; -} -.PTZ_controls .pad .top { - top: 15px; - left: 50%; - margin: 0 0 0 -15px; -} -.PTZ_controls .pad .left { - top: 45px; - left: 15px; -} -.PTZ_controls .pad .right { - top: 45px; - right: 15px; -} -.PTZ_controls .pad .control.right:before { - transform: rotate(90deg) translate(-3px, -5px); -} -.PTZ_controls .pad .bottom { - bottom: 15px; - left: 50%; - margin: 0 0 0 -15px; -} -/* Overlap the other controls to hide box-shadow */ -.PTZ_controls .pad .middle { - height: 34px; - width: 34px; - z-index: 5; - top: 43px; - left: 50%; - margin: 0 0 0 -17px; - box-shadow: none; - border-radius: 3px; -} -.PTZ_controls .pad .middle:after { - position: absolute; - top: 50%; - left: 50%; - margin: -35% 0 0 -35%; - content: ''; - background: #636363; - height: 70%; - width: 70%; - border-radius: 100%; - box-shadow: inset 0 0 2px rgba(120, 120, 120, 0.6), inset 0 2px 8px rgba(0, 0, 0, 0.1), 0 2px 2px rgba(240, 240, 240, 0.2); -} +.mdl-menu__item>div{display:flex;align-items: center;width:100%} +.mdl-menu__item>div>i{margin-right:5px} + + /*Digital Zoom*/ .stream-block{ position: relative; @@ -663,20 +334,7 @@ ul.msg_list li .message { -moz-animation: blink 1s linear infinite; animation: blink 1s linear infinite; } -.mdl-menu__item>div{display:flex;align-items: center;width:100%} -.mdl-menu__item>div>i{margin-right:5px} -/*For languages that are right to left*/ -.right-to-left {text-align:right} -.right-to-left select{direction: rtl;} -.right-to-left input,.right-to-left textarea{direction: rtl;text-align:right} -.right-to-left .form-group label span{padding-right:10px} -.right-to-left .modal-footer{text-align:left} -.right-to-left .mdl-menu__item>div>*{flex:1} -.right-to-left .mdl-menu__item>div>i{margin-right:0;margin-left:5px} -.right-to-left .mdl-menu__item{text-align:right} -.right-to-left .mdl-menu__item i{float:right} -.right-to-left .pull-right,.right-to-left .close{float:left!important} -.right-to-left .pull-left,.right-to-left .mdl-menu__item span{float:right!important} + /* All-CSS Toggle Switch (Checkbox Hack) by Marcus Burnette - https://codepen.io/mburnette/pen/LxNxNg */ .marc-toggle { width: 50px; diff --git a/web/libs/css/main.dash2.old.css b/web/libs/css/main.dash2.old.css new file mode 100644 index 0000000..63e9d69 --- /dev/null +++ b/web/libs/css/main.dash2.old.css @@ -0,0 +1,742 @@ +/*Cusotm Bootstrap*/ +.col-5ths, +.col-sm-5ths, +.col-md-5ths, +.col-lg-5ths { + position: relative; + min-height: 1px; + padding-right: 15px; + padding-left: 15px; +} + +.col-5ths { + -webkit-box-flex: 0; + -webkit-flex: 0 0 20%; + -ms-flex: 0 0 20%; + flex: 0 0 20%; + max-width: 20%; +} + +@media (min-width: 576px) { + .col-sm-5ths { + -webkit-box-flex: 0; + -webkit-flex: 0 0 20%; + -ms-flex: 0 0 20%; + flex: 0 0 20%; + max-width: 20%; + } +} + +@media (min-width: 768px) { + .col-md-5ths { + -webkit-box-flex: 0; + -webkit-flex: 0 0 20%; + -ms-flex: 0 0 20%; + flex: 0 0 20%; + max-width: 20%; + } +} +::-webkit-scrollbar-thumb:hover { + background-color:#bd9565; +} +::-webkit-scrollbar-thumb { + background-color:#bd9565; + border: 2px solid transparent; + border-radius: 10px; + background-clip: padding-box; +} +/**/ +.flex{display:flex} +.flex>div{flex:1} +.flex-block{display:inline-flex;width:100%;flex-flow: row wrap;} +.flex-unit-3{flex:3} +.flex-inline{display: inline-flex;position:relative} +@import (less) "../less/pie.less"; +ul{list-style:none} +*{transition:0.2s;box-sizing:border-box} +.affix-top{position:fixed} +.no-padding{padding:0!important} +.no-margin{margin:0!important} +.pre-inline{white-space: normal;word-break: normal} +.pre-inline>ul{margin:0;padding:0} +a{cursor:pointer} +nav h4{cursor:default;font-size:95%;padding:16px 40px;font-weight:100;text-transform:uppercase;letter-spacing:2px} +.m-r{margin-right:10px} +.m-b{margin-bottom:10px} +.m-t{margin-top:10px} +.m-l{margin-left:10px} +.overflow-hidden{overflow: hidden!important} +.list-inline{list-style:none} +.list-inline li{display:inline-block;vertical-align: top;margin:0;} +.truncate{width:100%;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;} +img{max-width:100%} +.display-table{display:table;width:100%} +.display-inline{display:inline-block} +.display-table-cell{display:table-cell} +.small{font-size:80%} +.super-center{position:absolute;left:0;top:0;right:0;bottom:0;margin:auto;width: 4em;height: 1em;} +.jpegMode .cpu_load .progress-bar,.jpegMode .ram_load .progress-bar{background-color:#5cb85c} +.jpegMode [system="jpegToggle"],[system].text-success{color:#5cb85c!important} +.permission_monitor_edit{display:none} +.permission_video_delete{display:none} +.nodata .divider{margin:5px 0} +.loading .divider{margin:5px 0} + +#accbtn{ + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; + padding: 0; +} + +.monitor_item .stream-hud{opacity:0;position:absolute;top:0;left:0;width:100%;height:100%;z-index:10} +.monitor_item .stream-hud .camera_cpu_usage{position:absolute;top:0;left:0;width: 100%;} +.monitor_item .stream-hud .camera_cpu_usage .progress{width: 100%;} +.monitor_item .stream-hud .camera_cpu_usage:hover .progress{height:20px;transition:0.2s} +.monitor_item .stream-hud .controls{position:absolute;top:10px;left:10px;} +.monitor_item .stream-hud:hover{opacity:1} +.monitor_item .stream-hud .bottom-text{position:absolute;bottom:0;left:0;width:100%;padding:5px;text-shadow: 0 0 10px #333;} +.monitor_item .stream-hud .bottom-text .detector-fade{background: rgba(0,0,0,0.4);padding:10px 20px;border-radius:10px} +.monitor_item .stream-hud .lamp{position:absolute;top:5px;right:5px;z-index:1;text-shadow: 0 0 15px #333;} +.monitor_item[mode="Disabled"] .stream-hud .lamp{color:#5d5d5d} +.monitor_item[mode="Watch Only"] .stream-hud .lamp{color:#5da8e8} +.monitor_item[mode="Idle"] .stream-hud .lamp{color:#fff} +.monitor_item[mode="Record"] .stream-hud .lamp{color:#d9534f} +/*.data-menu{max-height:700px}*/ +.data-menu:not(:last-child){border-right:1px solid #fff;} +.data-menu.logs{list-style:none;} +.monitor_item .motionVision{display:none} + +.monitor_item .grid-stack-item-content{width:100%!important;left:0!important;right:0!important} +.monitor_item .ui-resizable-se {bottom: 10px!important;} +.monitor_item .stream-block{position: relative;text-align: center} +.monitor_item .mdl-data_window{overflow-x: auto;background:rgba(0,0,0,0.7);color:#fff;height:100%} +.monitor_item .mdl-data_window:not(.col-md-6){width:0;min-width:0;height:0px;min-height:0} + + +.monitor_item.fullscreen img.stream-element{height:100%;width:auto} +.monitor_item.fullscreen canvas.stream-element{height:auto;width:auto;background-color:black;} +.monitor_item .stream-element{border: 0;object-fit: fill;height: 100%;width:100%} +.monitor_item{position:relative;padding:0;transition:none;background:#000} +.monitor_item .mdl-card{min-height:auto;border:1px solid #272727;border-radius:0px;overflow:hidden} +.monitor_item .mdl-card__media{position:relative;padding:0!important;display:block!important;background:#000;height:100%} +.monitor_item.selected .stream-element{height:600px} +.monitor_item.selected .fa-expand:before{content:"\f066"} +.monitor_item .mdl-card__supporting-text{background:#222;color:#fff!important;display:block;min-height:auto!important} +.monitor_item.detector_triggered .detector-fade{opacity:1} +.monitor_item .detector-fade{opacity:0} +.monitor_item .indifference{position:absolute;width:100%;left:0;top:0;transition:0.2s;} +.monitor_item .progress{width:100%;background:#333;box-shadow:0;} +.monitor_item .indifference:hover .progress{height:20px;transition:0.2s} +.hide_indifference .indifference{display:none!important} +.hide_indifference [class_toggle="hide_indifference"]{color:#d9534f!important} +.monitor_item .mdl-card:not(.mdl-cell--4-col-desktop) .mdl-card__supporting-text .monitor_details{display:none;font-size:90%;margin-bottom:10px} +.monitor_item[mode="Record"] [mode="record"]{display:none} +.monitor_item[mode="Watch Only"] [mode="start"]{display:none} +.monitor_item .stream-hud .controls .btn{opacity:0.7} +.monitor_item.doObjectDetection .progress-bar{background-color: #57d94f} + +@media screen and (max-width:1500px){ + .monitor_item .mdl-card__supporting-text .btn{ + padding: 5px 10px; + font-size: 11px; + line-height: 1.5; + } +} + +#monitors_live .monitor_item [class_toggle="show_logs"]{display:none} +#monitors_live .monitor_item .indifference{top:-5px} +#monitors_live .monitor_item .mdl-cell--8-col{width:100%;border:0;border-radius:0;margin:0;position:relative} +#monitors_live .monitor_item .mdl-cell--4-col-desktop,.monitor_item .mdl-card__supporting-text{display:none} +#monitors_live .monitor_item .mdl-card__supporting-text .monitor_details,#monitors_live .monitor_item .mdl-card__supporting-text .btn-group{display:none;text-align:center} +#monitors_live .monitor_item .mdl-card__supporting-text:not(.meta){display:block;position:absolute;bottom:0;left:0;height:0;padding:0;overflow:visible;} +#monitors_live .monitor_item.show_data .mdl-card__supporting-text:not(.meta){width:50%} +#monitors_live .monitor_item.detector_triggered .mdl-card__supporting-text:not(.meta) .indifference{opacity:0.5;} +#monitors_live .monitor_item:hover .mdl-card__supporting-text:not(.meta){padding:15px;z-index:15;height:auto;} +#monitors_live .monitor_item:hover .mdl-card__supporting-text .monitor_details{display:block} +#monitors_live .monitor_item:hover .mdl-card__supporting-text .btn-group{display:inline-block} + + + +#vis_pwrvideo{height:250px} +#monSectionStreamChannels,#monSectionInputMaps{margin-bottom: 15px;} +#monSectionStreamChannels:empty,#monSectionInputMaps:empty{display:none} +#region_editor_live iframe,.canvas_holder canvas{border:0;position:absolute;left:0;top:0} +.canvas_holder canvas{z-index:11} + +.demo-blog .mdl-card__media ~ .mdl-card__supporting-text{position:relative;overflow:initial;cursor:move} +.demo-blog .mdl-card__media ~ .mdl-card__supporting-text .btn-group{cursor: default} + +.demo-blog .demo-blog__posts.montage{max-width:100%} + + +.mdl-layout__header-row{padding-left:10!important} +.mdl-layout__header-row .nav>li>a{border-radius:50%;} +.mdl-layout__drawer-button i{position:absolute;top:0;right:0;bottom:0;left:0;margin:auto;height:1em;color:#fff} +.data-menu{text-align:left} +.data-menu ul,.side-menu ul{list-style:none;margin:0;padding:0;} +.data-menu li,.side-menu li{ + border-bottom:1px solid #54502d;padding:10px; +} +.data-menu .progress-circle{margin:0 10px 0 0;position:relative;height:40px;width:40px;float:left} +.data-menu .progress-circle span:after{content:''} +img.circle-img,div.circle-img{border-radius:50%;height:50px;width:50px} +.circle-img.sm{height:25px;width:25px} + +.video_video{margin:auto;max-width:100%;max-height:600px;} +#confirm_window .video_video{margin-top:15px} +#confirm_window .info-table{margin-top:15px} +@media (max-width: 768px){ + .full.modal .modal-body,.medium.modal .modal-body{max-height:400px;overflow:auto} +} +@media (min-width: 768px){ + .modal.full,.modal.medium{padding-left:0!important;} + .modal.full .modal-dialog{width:calc(100% - 10px)!important;margin: 30px auto;} + .modal.medium .modal-dialog{width:calc(70% - 10px)!important;margin: 30px auto;} + .full.modal .modal-body,.medium.modal .modal-body{height:calc(100% - 200px);overflow:auto} +} + +.flex-container-modal-body{overflow: auto} +.flex-container-modal-body .flex-block>div{flex:1;float:none} + +.modal{overflow:auto!important} +form.modal-body{margin:0} +#region_editor .modal-body{text-align:center;overflow:auto;max-height:800px} +#region_editor .canvas_holder{position:relative;display:inline-block;overflow:auto;min-height:450px} +#region_editor .cord_element{position:absolute;background:rgba(221, 221, 221, 0.8);z-index:11;padding:5px;} +#region_editor .cord_element.selected{z-index:12;} +#region_editor .cord_element .controls{margin-bottom:5px;} +.form-group label span{padding:5px;font-weight: 400;color: #2d2d2d;display:block;border-bottom: 1px dotted #ddd;font-size: 10pt;} +.form-group label{display:table} +.form-group label>div{display:table-cell} +.form-group label>div:nth-child(2n-1){width:30%} +.form-group label>div:nth-child(2){width:70%;padding:5px;border:1px solid #dedede;border-radius:5px} +.dark .form-group label>div,.dark .form-group label>div>span{border-color:#454545;color:#fff} +.important.form-group label>div:nth-child(2),.important.form-group label>div>span{border-color:red} +.form-group label span small{margin-left: 2px;display:block;font-weight: 600;} +.form-group-group .round-left{border-radius: 50px 0 0 50px;margin-left:10px} +.form-group-group blockquote:before,.form-group-group blockquote:after{display:none!important} +.form-group-group blockquote{letter-spacing:normal;font-style:normal} +.form-group-group blockquote p:empty{display:none} +.form-group-group blockquote p{font-size:inherit} +.form-group-group blockquote p:last-child{margin-bottom:0} +.form-group-group-group>div,.form-group-group-group .h_us_advanced>div{margin-bottom:15px;} +.form-group-group{padding:0 10px 10px 10px;overflow:hidden;margin-bottom:15px;border-radius:5px;border:1px solid #ddd;background:#fff} +.form-group-group table{width:100%} +.form-group-group table tr td{padding:10px 5px} +.form-group-group table tr:not(:last-child) td{border-bottom:1px dotted #eee} +.form-group-group .mdl-list__item{border-bottom:1px solid #eee;} +.form-group-group .mdl-list__item:hover{background:#e6e6e6;border-radius:4px;} +.dark .form-group-group .mdl-list__item{color:#fff;border-bottom:1px solid #444;} +.dark .form-group-group .mdl-list__item:hover{background:#555;} +.form-group-group:last-child,.form-group-group > .form-group:last-child{margin-bottom:0} +.form-group-group h4{margin:0 -10px 15px -10px;padding:15px;background:#ddd;} +.form-group-group h4 small{color:#fff;} +.form-group-group.red{border-color:#d9534f} +.form-group-group.red h4{background:#d9534f;color:#fff} +.form-group-group.purple{border-color:#3f51b5} +.form-group-group.purple h4{background:#3f51b5;color:#fff} +.form-group-group.blue{border-color:#337ab7} +.form-group-group.blue h4{background:#337ab7;color:#fff} +.form-group-group.navy{border-color:#31708f} +.form-group-group.navy h4{background:#31708f;color:#fff} +.form-group-group.green{border-color:#449d44} +.form-group-group.green h4{background:#449d44;color:#fff} +.form-group-group.forestgreen{border-color:#1e4046} +.form-group-group.forestgreen h4{background:#1e4046;color:#fff} +.form-group-group.orange{border-color:#c49a68} +.form-group-group.orange h4{background:#c49a68;color:#fff} +.form-group-group.grey{border-color:#777} +.form-group-group.grey h4{background:#777;color:#fff} +.dark .form-group-group{background:#222} +.videos_list .title{font-size:12pt;padding:0 10px} +[status="1"] .btn[video="launch"],[data-status="1"] .btn[video="launch"]{background:#337ab7;border-color:#337ab7} +[status="2"] .btn[launch="video"],[status="2"] .btn[video="launch"],[data-status="2"] .btn[video="launch"]{background:#a59100;border-color:#a59100} +.signal.red{background:#c9302c} +.signal.green{background:#5cb85c} +.demo-drawer{background:#2b2a2a;color:#fff;} +.demo-drawer.mdl-layout__drawer .mdl-navigation{padding-top:0;} +.demo-drawer::-webkit-scrollbar{display:none;} +.small-square-img{height:40px;width:40px;border-radius:5px} + +.side-menu .monitor_block{padding:0;position:relative} +.side-menu .monitor_block img{width:100%;height:75px;cursor:pointer;border: 0.5px inset #263238;} +@media screen and (max-width:1025px){ +.side-menu .monitor_block img{height:175px;} +} +.side-menu .monitor_block:hover .icons{opacity:1} +.side-menu .monitor_block:hover .title{opacity:1} +.side-menu .monitor_block .icons,.side-menu .monitor_block .title{opacity:0;width:100%;bottom:0;left:0;background:rgba(0,0,0,0.6);position:absolute;padding:2.5px;z-index:11;cursor:move} +.side-menu .monitor_block .title{bottom:auto;top:0;color:#fff} +.nav-xs.side-menu .monitor_block{width:100%} +.side-menu .monitor_block .list-data{display:none} +.output_data:empty{display:none} +.output_data{max-height:500px;font-family:monospace;padding:10px;border-radius:5px;background:#f3f3f3;overflow:auto} +.dark .output_data{background:#222;} +#probe .output_data div>div{margin-left:10px} +.side-menu.list-blocks .monitor_block .icons,.side-menu.list-blocks .monitor_block .title{position:inherit;opacity:1;background:none} +.side-menu.list-blocks .monitor_block .title{padding:5px;border-radius:5px;background:#222;} +.side-menu.list-blocks .monitor_block:not(:last-child){border-bottom: 1px solid #54502d;} +.side-menu.list-blocks .monitor_block:first-child{border-top: 1px solid #54502d;} +.side-menu.list-blocks .monitor_block{float:none;width:100%;padding: 10px} +.side-menu.list-blocks .monitor_block.ui-sortable-helper{background:rgba(0,0,0,0.6);border-radius:5px;padding:5px;border:0} +.side-menu.list-blocks .monitor_block .list-data{display:block} +.side-menu.list-blocks .monitor_block img{width:60px;height:60px;cursor:pointer;display:inline-block;margin-right:10px;border-radius:50%;vertical-align:top;border:0} +.nav-xs.side-menu.list-blocks .monitor_block img{width:40px;height:40px;} +.side-menu.list-blocks .monitor_block .box{width:calc(100% - 70px);display:inline-block} +.nav-xs.side-menu.list-blocks .monitor_block .list-data{display:none} +#monitors_list .monitor_block{transition:none} +.dropdown-menu.scrollable{max-height:300px} +.upload_file input{display:none} +#video_preview .stream-objects{right:0;margin:auto;display:inline-block;position:relative;width:auto} +.stream-block,.stream-objects{overflow: hidden!important} +.stream-objects{position:absolute;top:0;left:0;width:100%;height:100%;z-index:10} +.stream-objects .tag{position:absolute;bottom:100%;left:0;background:red;color:#fff;font-family:monospace;font-size:80%;border-radius:5px 5px 0 0 ;padding:3px 5px;} +.stream-objects .stream-detected-object{position:absolute;top:0;left:0;border:3px solid red;background:transparent;border-radius:5px} +.stream-objects .stream-detected-point{position:absolute;top:0;left:0;border:3px solid yellow;background:transparent;border-radius:5px} +.stream-objects .point{position:absolute;top:0;left:0;border:3px solid red;border-radius:50%} + + +#side_menu_right.nav-xs{width:0!important;overflow:hidden} +.side-menu table{color:#fff;} +#main_canvas{background:#333;color:#fff;padding-top:0} +#main_header{background:#222;color:#fff;} +#logs_modal table tr td:first-child{width:10%} +[class_toggle]{cursor:pointer} + +.form-group label{width:100%} + +#pvideo_viewer iframe{border:0;width:100%;height:350px;margin-bottom:10px;overflow:hidden} +#pvideo_viewer video{max-height:300px;max-width:100%;} +#pvideo_viewer .holder{height:300px;} +#pvideo_viewer h3{margin-top:0} +#pvideo_viewer .progressBar{position:relative;} +#pvideo_viewer .bufferBar{position:absolute;left:0;top:0;opacity:0.4} +#pvideo_viewer .timeBar{position:relative;z-index: 222;background:transparent} +#pvideo_viewer h3{font-family:monospace} + +#vis_monitors{overflow:auto;max-height:400px} +#vis_monitors .btn-group-vertical{width:100%} + +/*timeline*/ +#timelapse_video_line{overflow-y:scroll;overflow-x:hidden;max-height:400px;margin:0;text-align:left} +#timelapse_video_display .videoBefore,#timelapse_video_display .videoAfter{display:none} +.timelapse_video:not(:last-child){border-bottom:1px solid #444;} +.timelapse_video .frame{width:50px;height:50px;background-size:cover;background-position:center;border-radius:5px} +.timelapse_video>div>div:not(:last-child){padding-right:10px} +.timelapse_video .flex-block:not(:last-child){padding-bottom:10px} +.timelapse_video.list-group-item{padding:10px} +.timelapse_hud{position: relative;background:#000} +.timelapse_hud .timelapse_playRate{position: absolute;font-family: monospace;top:10px;right:0;left:0;margin:auto;font-size:23px} +#timelapse .progress-bar{transition:0.5s!important} +.timelapse_hud .controlBar{position: absolute;background:rgba(22,22,22,0.8);width:100%;left:0;bottom:0;} +.timelapse_hud .hover-hide{opacity:0} +.timelapse_hud:hover .hover-hide{opacity:1;z-index:5} +.video_grid{overflow: auto;height: 100%;display: block;} +.video_grid .col-md-2{padding-left:5px;padding-right:5px;padding-bottom:10px} +.video_grid .thumb{width:100%;height:150px;display:inline-block;background-size:cover;position:relative;overflow:hidden;border-radius:4px;border:1px solid #000;box-shadow:0 0 10px #151515} +.video_grid .thumb .title-strip, .video_grid .thumb .button-strip{width:100%;position:absolute;left:0;background:rgba(0,0,0,0.7);color:#fff;padding:4px} +.video_grid .thumb .title-strip{top:0;opacity:0.5} +.video_grid .thumb .button-strip{bottom:0;opacity:0} +.video_grid .thumb:hover .title-strip, .video_grid .thumb:hover .button-strip{opacity:1} + +.table-striped>tbody>tr>td{vertical-align:middle} +.table-striped .thumbnail{width:100px;height:80px;border-radius:5px;margin:0;display:inline-block;} +#motion_list{height:155px;overflow:auto;border-radius:5px;border:1px solid #444;position:relative;background: #222;margin:0} +.dark .list-group-item{border-color: #444;background:#222} +.dark .list-group-item.active{background:#c49a68;border-color:#a7865f} +.novideos{text-transform: uppercase;text-align: center;border-bottom:0!important;padding-top: 55%!important;letter-spacing:2px} + +.btn-warning { + color: #fff; + background-color: #c49a68; + border-color: #c49a68; +} + +.dark.modal .modal-header,.dark.modal .modal-footer{background:#333;border-color:#444;} +.dark.modal .modal-header{color:#fff;} +.dark.modal .modal-footer>*:not(.btn){color:#fff;} +.dark.modal .modal-body{background:#333;} +.dark.modal .close{color:#fff;} +.dark.modal{color:#fff;} +.dark .table-striped>tbody>tr:nth-of-type(even){background:#616161} +.dark .table-striped>tbody>tr>td{border-color:#222;color:#fff} +.dark .table-striped>thead>tr>th{border-color:#222;color:#fff;background:#616161;vertical-align:middle;} +.dark .table-striped>tbody>tr:nth-of-type(odd){background-color: #4c4747;} +.dark .table>tbody>tr.active>td{background:inherit;border:0} +.dark code{color: #c49a68;background-color: #36333d;} +.dark a:not(.btn){color: #c49a68;} +.follow-list ul{padding:0;margin:0;font-family:"Roboto","Helvetica","Arial",sans-serif;} +.follow-list ul a:not(.btn){color:#fff} +.os_bars{width:600px;display:inline-block;padding:5px 0 0 10px} +@media screen and (max-width: 600px){ + .os_bars{width:200px;} + .os_bars label{padding:2.5px 0;margin:0;font-size:8pt} +} +.os_bars .display-table .display-table-cell{padding:5px;vertical-align:center;width:33%} +.progress{height:5px;margin:0;} +.os_bars label,.os_bars .percent{padding:2.5px 0;margin:0;font-size:7.5pt} +.ui-pnotify-hide .ui-pnotify{display:none!important} +/*cool dropdown thing*/ +ul.msg_list li { + background: #f7f7f7;color:#333; + padding: 5px; + display: list-item; + margin: 6px 6px 0; + width: 96% !important +} + +ul.msg_list li div{display:block} + +ul.msg_list li:last-child { + margin-bottom: 6px; + padding: 10px +} + +ul.msg_list li a { + padding: 3px 5px !important +} +ul.msg_list li .progress { + height:5px;margin:10px 0 0 0; +} + +ul.msg_list li .image img { + border-radius: 2px 2px 2px 2px; + -webkit-border-radius: 2px 2px 2px 2px; + float: left; + margin-right: 10px; + width: 11% +} + +ul.msg_list li .time { + font-size: 11px; + font-style: italic; + font-weight: bold; + position: absolute; +} + +ul.msg_list li .message { + display: block !important; + font-size: 11px +} + +.dropdown-menu.msg_list span { + white-space: normal +} + +.dropdown-menu { + border: medium none; + box-shadow: none; + display: none; + float: left; + font-size: 12px; + left: 0; + list-style: none outside none; + padding: 0; + position: absolute; + text-shadow: none; + top: 100%; + z-index: 9998; + border: 1px solid #D9DEE4; + border-top-left-radius: 0; + border-top-right-radius: 0 +} + +.dropdown-menu>li>a { + color: #5A738E +} + +.navbar-nav .open .dropdown-menu { + position: absolute; + background: #fff; + margin-top: 0; + border: 1px solid #D9DEE4; + -webkit-box-shadow: none; + right: 0; + left: auto; + width: 220px +} +.is-small-screen .nav>li{display:inline-block} +.navbar-nav .open .dropdown-menu li a{padding:7px 15px} +.navbar-nav .open .dropdown-menu.msg_list { + width: 300px +} +.nav>li>a{color:#fff} +.nav>li>a:focus, .nav>li>a:hover,.nav .open>a, .nav .open>a:focus, .nav .open>a:hover{background:#867560} + +.mdl-js-layout.hide-side:not(.is-small-screen){ + +} +@media screen and (min-width: 1025px){ + .mdl-js-layout.hide-side:not(.is-small-screen)>.mdl-layout__drawer { + width: 0px;transition:0.2s + } +} +.mdl-js-layout.hide-side:not(.is-small-screen) .mdl-layout__header .mdl-layout__drawer-button{ + display:none; +} +.mdl-js-layout.hide-side:not(.is-small-screen)>.mdl-layout__content{ + margin-left: 0px;transition:0.2s +} +.mdl-js-layout.hide-side:not(.is-small-screen)>.mdl-layout__header{ + margin-left: 0px;width:100%;transition:0.2s +} +/*Control Pad*/ +.PTZ_controls { + z-index: 111; + position: absolute; + left: 20px; + top: 20px; + margin:0; + display: inline-block; + width: 120px; +} +.PTZ_controls .btn-group{margin-top:10px} +.PTZ_controls .pad { + position: relative; + height: 120px; + width: 120px; + background: #b7b7b7; + border-radius: 50%; + box-shadow: inset 0 0 1px rgba(120, 120, 120, 0.6), inset 0 2px 2px rgba(0, 0, 0, 0.1), 0 2px 2px rgba(240, 240, 240, 0.4); +} +.PTZ_controls .control { + position: absolute; +} +.PTZ_controls .pad .control { + height: 30px; + width: 30px; + background: #636363; + box-shadow: 0 0 0 2px rgba(0, 0, 0, 0.6), 0 0 0 3px rgba(60, 60, 60, 0.2), 0 0 0 4px rgba(60, 60, 60, 0.2); + border-radius: 2px; +} +.PTZ_controls .zoom_in{ + top: 0; + right: 0; +} +.PTZ_controls .zoom_out{ + bottom: 0; + right: 0; +} +.PTZ_controls .nv_enabled{ + top: 0; + right: 0; +} +.PTZ_controls .nv_disable{ + bottom: 0; + right: 0; +} +.PTZ_controls .pad .top { + top: 15px; + left: 50%; + margin: 0 0 0 -15px; +} +.PTZ_controls .pad .left { + top: 45px; + left: 15px; +} +.PTZ_controls .pad .right { + top: 45px; + right: 15px; +} +.PTZ_controls .pad .control.right:before { + transform: rotate(90deg) translate(-3px, -5px); +} +.PTZ_controls .pad .bottom { + bottom: 15px; + left: 50%; + margin: 0 0 0 -15px; +} +/* Overlap the other controls to hide box-shadow */ +.PTZ_controls .pad .middle { + height: 34px; + width: 34px; + z-index: 5; + top: 43px; + left: 50%; + margin: 0 0 0 -17px; + box-shadow: none; + border-radius: 3px; +} +.PTZ_controls .pad .middle:after { + position: absolute; + top: 50%; + left: 50%; + margin: -35% 0 0 -35%; + content: ''; + background: #636363; + height: 70%; + width: 70%; + border-radius: 100%; + box-shadow: inset 0 0 2px rgba(120, 120, 120, 0.6), inset 0 2px 8px rgba(0, 0, 0, 0.1), 0 2px 2px rgba(240, 240, 240, 0.2); +} +/*Digital Zoom*/ +.stream-block{ + position: relative; + overflow: auto; +} +.zoomGlass { + overflow: hidden; + transition: none; + width: 175px; height: 175px; + position: absolute; + border-radius: 15px; + border: 3px solid #ddd; + z-index:9999; +} +.zoomGlass iframe,.zoomGlass canvas{position:absolute;transition: none;} +.zoomGlass .hoverShade{position:absolute;width:100%;height:100%} + +.dark.form-control,.dark .form-control { + display: block; + width: 100%; + height: 35px; + padding: 6px 12px; + font-size: 14px; + line-height: 1.5; + color: #eee; + background-color: #36333d; + background-image: none; + border: 1px solid #444; + border-radius: 4px; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; +} + +.dark.form-control:focus,.dark .form-control:focus { + color: #ddd; + background-color: #333; + box-shadow: none; +} + + +/*** custom checkboxes ***/ + +.checkbox input[type=checkbox] { display:none; } /* to hide the checkbox itself */ +.checkbox input[type=checkbox] + label:before { + font-family: FontAwesome; + display: inline-block; +} + +.checkbox input[type=checkbox] + label:before { content: "\f096"; } /* unchecked icon */ +.checkbox input[type=checkbox] + label:before { letter-spacing: 10px; } /* space between checkbox and label */ + +.checkbox input[type=checkbox]:checked + label:before { content: "\f046"; } /* checked icon */ +.checkbox input[type=checkbox]:checked + label:before { letter-spacing: 5px; } /* allow space for check mark */ + +/*Clock*/ +#time-date {font-size:12px; text-align:center;} +@media screen and (min-width:1025px){ + #clock {padding-right:35px} +} +#clock ul { width:150px; margin:0 auto; padding:0px; list-style:none; text-align:center; } +#clock ul li { display:inline; font-size:1.6em; text-align:center;font-family:monospace;} + +#clock .point { position:relative; -moz-animation:mymove 1s ease infinite; -webkit-animation:mymove 1s ease infinite; } + +/*custom vis.js css*/ +.vis-timeline{background:#212121;color:#fff;border-color:#444} +.vis-time-axis .vis-text{color: #dedede} +.vis-item.vis-range .vis-item-content{background:#333;color:#fff} +.vis-time-axis .vis-grid.vis-minor{border-color:#444} + + +@-moz-document url-prefix() { + .full.modal .modal-body, .medium.modal .modal-body { + height:70% + } +} + +/*animations*/ +@keyframes blink { + 0% { opacity:1 } + 50% { opacity:0 } + 100% { opacity:1 } +} +@-webkit-keyframes blink { + 0% { opacity:1 } + 50% { opacity:0 } + 100% { opacity:1 } +} +.blink,[mode="Record"] .lamp { + -webkit-animation: blink 1s linear infinite; + -moz-animation: blink 1s linear infinite; + animation: blink 1s linear infinite; +} +.mdl-menu__item>div{display:flex;align-items: center;width:100%} +.mdl-menu__item>div>i{margin-right:5px} +/*For languages that are right to left*/ +.right-to-left {text-align:right} +.right-to-left select{direction: rtl;} +.right-to-left input,.right-to-left textarea{direction: rtl;text-align:right} +.right-to-left .form-group label span{padding-right:10px} +.right-to-left .modal-footer{text-align:left} +.right-to-left .mdl-menu__item>div>*{flex:1} +.right-to-left .mdl-menu__item>div>i{margin-right:0;margin-left:5px} +.right-to-left .mdl-menu__item{text-align:right} +.right-to-left .mdl-menu__item i{float:right} +.right-to-left .pull-right,.right-to-left .close{float:left!important} +.right-to-left .pull-left,.right-to-left .mdl-menu__item span{float:right!important} +/* All-CSS Toggle Switch (Checkbox Hack) by Marcus Burnette - https://codepen.io/mburnette/pen/LxNxNg */ +.marc-toggle { + width: 50px; + height: 25px; +} +.marc-toggle.abs-bot-left { + position: absolute; + bottom: 10px; + left: 10px; +} +.marc-toggle.abs-bot-right { + position: absolute; + bottom: 10px; + right: 10px; +} +.marc-toggle input[type=checkbox]{ + height: 0; + width: 0; + visibility: hidden; +} + +.marc-toggle label { + cursor: pointer; + text-indent: -9999px; + width: 100px; + height: 20px; + background: grey; + display: block; + border-radius: 100px; + margin-bottom: 0; + position: relative; +} + +.marc-toggle label:after { + content: ''; + position: absolute; + top: 5px; + left: 5px; + width: 10px; + height: 10px; + background: #fff; + border-radius: 90px; + transition: 0.3s; +} + +.marc-toggle input:checked + label { + background: #00118c; +} + +.marc-toggle input:checked + label:after { + left: calc(100% - 5px); + transform: translateX(-100%); +} + +.marc-toggle label:active:after { + width: 10px; +} + +/*hexagon pattern*/ +.bg-hexagon { + background-color: #054e9f; + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='28' height='49' viewBox='0 0 28 49'%3E%3Cg fill-rule='evenodd'%3E%3Cg id='hexagons' fill='%23fdfdfd' fill-opacity='0.4' fill-rule='nonzero'%3E%3Cpath d='M13.99 9.25l13 7.5v15l-13 7.5L1 31.75v-15l12.99-7.5zM3 17.9v12.7l10.99 6.34 11-6.35V17.9l-11-6.34L3 17.9zM0 15l12.98-7.5V0h-2v6.35L0 12.69v2.3zm0 18.5L12.98 41v8h-2v-6.85L0 35.81v-2.3zM15 0v7.5L27.99 15H28v-2.31h-.01L17 6.35V0h-2zm0 49v-8l12.99-7.5H28v2.31h-.01L17 42.15V49h-2z'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E"); +} diff --git a/web/libs/css/material-design-iconic-font.min.css b/web/libs/css/material-design-iconic-font.min.css new file mode 100644 index 0000000..e1a58fe --- /dev/null +++ b/web/libs/css/material-design-iconic-font.min.css @@ -0,0 +1 @@ +@font-face{font-family:Material-Design-Iconic-Font;src:url(../fonts/Material-Design-Iconic-Font.woff2?v=2.2.0) format('woff2'),url(../fonts/Material-Design-Iconic-Font.woff?v=2.2.0) format('woff'),url(../fonts/Material-Design-Iconic-Font.ttf?v=2.2.0) format('truetype')}.zmdi{display:inline-block;font:normal normal normal 14px/1 'Material-Design-Iconic-Font';font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.zmdi-hc-lg{font-size:1.33333333em;line-height:.75em;vertical-align:-15%}.zmdi-hc-2x{font-size:2em}.zmdi-hc-3x{font-size:3em}.zmdi-hc-4x{font-size:4em}.zmdi-hc-5x{font-size:5em}.zmdi-hc-fw{width:1.28571429em;text-align:center}.zmdi-hc-ul{padding-left:0;margin-left:2.14285714em;list-style-type:none}.zmdi-hc-ul>li{position:relative}.zmdi-hc-li{position:absolute;left:-2.14285714em;width:2.14285714em;top:.14285714em;text-align:center}.zmdi-hc-li.zmdi-hc-lg{left:-1.85714286em}.zmdi-hc-border{padding:.1em .25em;border:solid .1em #9e9e9e;border-radius:2px}.zmdi-hc-border-circle{padding:.1em .25em;border:solid .1em #9e9e9e;border-radius:50%}.zmdi.pull-left{float:left;margin-right:.15em}.zmdi.pull-right{float:right;margin-left:.15em}.zmdi-hc-spin{-webkit-animation:zmdi-spin 1.5s infinite linear;animation:zmdi-spin 1.5s infinite linear}.zmdi-hc-spin-reverse{-webkit-animation:zmdi-spin-reverse 1.5s infinite linear;animation:zmdi-spin-reverse 1.5s infinite linear}@-webkit-keyframes zmdi-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes zmdi-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@-webkit-keyframes zmdi-spin-reverse{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(-359deg);transform:rotate(-359deg)}}@keyframes zmdi-spin-reverse{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(-359deg);transform:rotate(-359deg)}}.zmdi-hc-rotate-90{-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.zmdi-hc-rotate-180{-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.zmdi-hc-rotate-270{-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.zmdi-hc-flip-horizontal{-webkit-transform:scale(-1,1);-ms-transform:scale(-1,1);transform:scale(-1,1)}.zmdi-hc-flip-vertical{-webkit-transform:scale(1,-1);-ms-transform:scale(1,-1);transform:scale(1,-1)}.zmdi-hc-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.zmdi-hc-stack-1x,.zmdi-hc-stack-2x{position:absolute;left:0;width:100%;text-align:center}.zmdi-hc-stack-1x{line-height:inherit}.zmdi-hc-stack-2x{font-size:2em}.zmdi-hc-inverse{color:#fff}.zmdi-3d-rotation:before{content:'\f101'}.zmdi-airplane-off:before{content:'\f102'}.zmdi-airplane:before{content:'\f103'}.zmdi-album:before{content:'\f104'}.zmdi-archive:before{content:'\f105'}.zmdi-assignment-account:before{content:'\f106'}.zmdi-assignment-alert:before{content:'\f107'}.zmdi-assignment-check:before{content:'\f108'}.zmdi-assignment-o:before{content:'\f109'}.zmdi-assignment-return:before{content:'\f10a'}.zmdi-assignment-returned:before{content:'\f10b'}.zmdi-assignment:before{content:'\f10c'}.zmdi-attachment-alt:before{content:'\f10d'}.zmdi-attachment:before{content:'\f10e'}.zmdi-audio:before{content:'\f10f'}.zmdi-badge-check:before{content:'\f110'}.zmdi-balance-wallet:before{content:'\f111'}.zmdi-balance:before{content:'\f112'}.zmdi-battery-alert:before{content:'\f113'}.zmdi-battery-flash:before{content:'\f114'}.zmdi-battery-unknown:before{content:'\f115'}.zmdi-battery:before{content:'\f116'}.zmdi-bike:before{content:'\f117'}.zmdi-block-alt:before{content:'\f118'}.zmdi-block:before{content:'\f119'}.zmdi-boat:before{content:'\f11a'}.zmdi-book-image:before{content:'\f11b'}.zmdi-book:before{content:'\f11c'}.zmdi-bookmark-outline:before{content:'\f11d'}.zmdi-bookmark:before{content:'\f11e'}.zmdi-brush:before{content:'\f11f'}.zmdi-bug:before{content:'\f120'}.zmdi-bus:before{content:'\f121'}.zmdi-cake:before{content:'\f122'}.zmdi-car-taxi:before{content:'\f123'}.zmdi-car-wash:before{content:'\f124'}.zmdi-car:before{content:'\f125'}.zmdi-card-giftcard:before{content:'\f126'}.zmdi-card-membership:before{content:'\f127'}.zmdi-card-travel:before{content:'\f128'}.zmdi-card:before{content:'\f129'}.zmdi-case-check:before{content:'\f12a'}.zmdi-case-download:before{content:'\f12b'}.zmdi-case-play:before{content:'\f12c'}.zmdi-case:before{content:'\f12d'}.zmdi-cast-connected:before{content:'\f12e'}.zmdi-cast:before{content:'\f12f'}.zmdi-chart-donut:before{content:'\f130'}.zmdi-chart:before{content:'\f131'}.zmdi-city-alt:before{content:'\f132'}.zmdi-city:before{content:'\f133'}.zmdi-close-circle-o:before{content:'\f134'}.zmdi-close-circle:before{content:'\f135'}.zmdi-close:before{content:'\f136'}.zmdi-cocktail:before{content:'\f137'}.zmdi-code-setting:before{content:'\f138'}.zmdi-code-smartphone:before{content:'\f139'}.zmdi-code:before{content:'\f13a'}.zmdi-coffee:before{content:'\f13b'}.zmdi-collection-bookmark:before{content:'\f13c'}.zmdi-collection-case-play:before{content:'\f13d'}.zmdi-collection-folder-image:before{content:'\f13e'}.zmdi-collection-image-o:before{content:'\f13f'}.zmdi-collection-image:before{content:'\f140'}.zmdi-collection-item-1:before{content:'\f141'}.zmdi-collection-item-2:before{content:'\f142'}.zmdi-collection-item-3:before{content:'\f143'}.zmdi-collection-item-4:before{content:'\f144'}.zmdi-collection-item-5:before{content:'\f145'}.zmdi-collection-item-6:before{content:'\f146'}.zmdi-collection-item-7:before{content:'\f147'}.zmdi-collection-item-8:before{content:'\f148'}.zmdi-collection-item-9-plus:before{content:'\f149'}.zmdi-collection-item-9:before{content:'\f14a'}.zmdi-collection-item:before{content:'\f14b'}.zmdi-collection-music:before{content:'\f14c'}.zmdi-collection-pdf:before{content:'\f14d'}.zmdi-collection-plus:before{content:'\f14e'}.zmdi-collection-speaker:before{content:'\f14f'}.zmdi-collection-text:before{content:'\f150'}.zmdi-collection-video:before{content:'\f151'}.zmdi-compass:before{content:'\f152'}.zmdi-cutlery:before{content:'\f153'}.zmdi-delete:before{content:'\f154'}.zmdi-dialpad:before{content:'\f155'}.zmdi-dns:before{content:'\f156'}.zmdi-drink:before{content:'\f157'}.zmdi-edit:before{content:'\f158'}.zmdi-email-open:before{content:'\f159'}.zmdi-email:before{content:'\f15a'}.zmdi-eye-off:before{content:'\f15b'}.zmdi-eye:before{content:'\f15c'}.zmdi-eyedropper:before{content:'\f15d'}.zmdi-favorite-outline:before{content:'\f15e'}.zmdi-favorite:before{content:'\f15f'}.zmdi-filter-list:before{content:'\f160'}.zmdi-fire:before{content:'\f161'}.zmdi-flag:before{content:'\f162'}.zmdi-flare:before{content:'\f163'}.zmdi-flash-auto:before{content:'\f164'}.zmdi-flash-off:before{content:'\f165'}.zmdi-flash:before{content:'\f166'}.zmdi-flip:before{content:'\f167'}.zmdi-flower-alt:before{content:'\f168'}.zmdi-flower:before{content:'\f169'}.zmdi-font:before{content:'\f16a'}.zmdi-fullscreen-alt:before{content:'\f16b'}.zmdi-fullscreen-exit:before{content:'\f16c'}.zmdi-fullscreen:before{content:'\f16d'}.zmdi-functions:before{content:'\f16e'}.zmdi-gas-station:before{content:'\f16f'}.zmdi-gesture:before{content:'\f170'}.zmdi-globe-alt:before{content:'\f171'}.zmdi-globe-lock:before{content:'\f172'}.zmdi-globe:before{content:'\f173'}.zmdi-graduation-cap:before{content:'\f174'}.zmdi-home:before{content:'\f175'}.zmdi-hospital-alt:before{content:'\f176'}.zmdi-hospital:before{content:'\f177'}.zmdi-hotel:before{content:'\f178'}.zmdi-hourglass-alt:before{content:'\f179'}.zmdi-hourglass-outline:before{content:'\f17a'}.zmdi-hourglass:before{content:'\f17b'}.zmdi-http:before{content:'\f17c'}.zmdi-image-alt:before{content:'\f17d'}.zmdi-image-o:before{content:'\f17e'}.zmdi-image:before{content:'\f17f'}.zmdi-inbox:before{content:'\f180'}.zmdi-invert-colors-off:before{content:'\f181'}.zmdi-invert-colors:before{content:'\f182'}.zmdi-key:before{content:'\f183'}.zmdi-label-alt-outline:before{content:'\f184'}.zmdi-label-alt:before{content:'\f185'}.zmdi-label-heart:before{content:'\f186'}.zmdi-label:before{content:'\f187'}.zmdi-labels:before{content:'\f188'}.zmdi-lamp:before{content:'\f189'}.zmdi-landscape:before{content:'\f18a'}.zmdi-layers-off:before{content:'\f18b'}.zmdi-layers:before{content:'\f18c'}.zmdi-library:before{content:'\f18d'}.zmdi-link:before{content:'\f18e'}.zmdi-lock-open:before{content:'\f18f'}.zmdi-lock-outline:before{content:'\f190'}.zmdi-lock:before{content:'\f191'}.zmdi-mail-reply-all:before{content:'\f192'}.zmdi-mail-reply:before{content:'\f193'}.zmdi-mail-send:before{content:'\f194'}.zmdi-mall:before{content:'\f195'}.zmdi-map:before{content:'\f196'}.zmdi-menu:before{content:'\f197'}.zmdi-money-box:before{content:'\f198'}.zmdi-money-off:before{content:'\f199'}.zmdi-money:before{content:'\f19a'}.zmdi-more-vert:before{content:'\f19b'}.zmdi-more:before{content:'\f19c'}.zmdi-movie-alt:before{content:'\f19d'}.zmdi-movie:before{content:'\f19e'}.zmdi-nature-people:before{content:'\f19f'}.zmdi-nature:before{content:'\f1a0'}.zmdi-navigation:before{content:'\f1a1'}.zmdi-open-in-browser:before{content:'\f1a2'}.zmdi-open-in-new:before{content:'\f1a3'}.zmdi-palette:before{content:'\f1a4'}.zmdi-parking:before{content:'\f1a5'}.zmdi-pin-account:before{content:'\f1a6'}.zmdi-pin-assistant:before{content:'\f1a7'}.zmdi-pin-drop:before{content:'\f1a8'}.zmdi-pin-help:before{content:'\f1a9'}.zmdi-pin-off:before{content:'\f1aa'}.zmdi-pin:before{content:'\f1ab'}.zmdi-pizza:before{content:'\f1ac'}.zmdi-plaster:before{content:'\f1ad'}.zmdi-power-setting:before{content:'\f1ae'}.zmdi-power:before{content:'\f1af'}.zmdi-print:before{content:'\f1b0'}.zmdi-puzzle-piece:before{content:'\f1b1'}.zmdi-quote:before{content:'\f1b2'}.zmdi-railway:before{content:'\f1b3'}.zmdi-receipt:before{content:'\f1b4'}.zmdi-refresh-alt:before{content:'\f1b5'}.zmdi-refresh-sync-alert:before{content:'\f1b6'}.zmdi-refresh-sync-off:before{content:'\f1b7'}.zmdi-refresh-sync:before{content:'\f1b8'}.zmdi-refresh:before{content:'\f1b9'}.zmdi-roller:before{content:'\f1ba'}.zmdi-ruler:before{content:'\f1bb'}.zmdi-scissors:before{content:'\f1bc'}.zmdi-screen-rotation-lock:before{content:'\f1bd'}.zmdi-screen-rotation:before{content:'\f1be'}.zmdi-search-for:before{content:'\f1bf'}.zmdi-search-in-file:before{content:'\f1c0'}.zmdi-search-in-page:before{content:'\f1c1'}.zmdi-search-replace:before{content:'\f1c2'}.zmdi-search:before{content:'\f1c3'}.zmdi-seat:before{content:'\f1c4'}.zmdi-settings-square:before{content:'\f1c5'}.zmdi-settings:before{content:'\f1c6'}.zmdi-shield-check:before{content:'\f1c7'}.zmdi-shield-security:before{content:'\f1c8'}.zmdi-shopping-basket:before{content:'\f1c9'}.zmdi-shopping-cart-plus:before{content:'\f1ca'}.zmdi-shopping-cart:before{content:'\f1cb'}.zmdi-sign-in:before{content:'\f1cc'}.zmdi-sort-amount-asc:before{content:'\f1cd'}.zmdi-sort-amount-desc:before{content:'\f1ce'}.zmdi-sort-asc:before{content:'\f1cf'}.zmdi-sort-desc:before{content:'\f1d0'}.zmdi-spellcheck:before{content:'\f1d1'}.zmdi-storage:before{content:'\f1d2'}.zmdi-store-24:before{content:'\f1d3'}.zmdi-store:before{content:'\f1d4'}.zmdi-subway:before{content:'\f1d5'}.zmdi-sun:before{content:'\f1d6'}.zmdi-tab-unselected:before{content:'\f1d7'}.zmdi-tab:before{content:'\f1d8'}.zmdi-tag-close:before{content:'\f1d9'}.zmdi-tag-more:before{content:'\f1da'}.zmdi-tag:before{content:'\f1db'}.zmdi-thumb-down:before{content:'\f1dc'}.zmdi-thumb-up-down:before{content:'\f1dd'}.zmdi-thumb-up:before{content:'\f1de'}.zmdi-ticket-star:before{content:'\f1df'}.zmdi-toll:before{content:'\f1e0'}.zmdi-toys:before{content:'\f1e1'}.zmdi-traffic:before{content:'\f1e2'}.zmdi-translate:before{content:'\f1e3'}.zmdi-triangle-down:before{content:'\f1e4'}.zmdi-triangle-up:before{content:'\f1e5'}.zmdi-truck:before{content:'\f1e6'}.zmdi-turning-sign:before{content:'\f1e7'}.zmdi-wallpaper:before{content:'\f1e8'}.zmdi-washing-machine:before{content:'\f1e9'}.zmdi-window-maximize:before{content:'\f1ea'}.zmdi-window-minimize:before{content:'\f1eb'}.zmdi-window-restore:before{content:'\f1ec'}.zmdi-wrench:before{content:'\f1ed'}.zmdi-zoom-in:before{content:'\f1ee'}.zmdi-zoom-out:before{content:'\f1ef'}.zmdi-alert-circle-o:before{content:'\f1f0'}.zmdi-alert-circle:before{content:'\f1f1'}.zmdi-alert-octagon:before{content:'\f1f2'}.zmdi-alert-polygon:before{content:'\f1f3'}.zmdi-alert-triangle:before{content:'\f1f4'}.zmdi-help-outline:before{content:'\f1f5'}.zmdi-help:before{content:'\f1f6'}.zmdi-info-outline:before{content:'\f1f7'}.zmdi-info:before{content:'\f1f8'}.zmdi-notifications-active:before{content:'\f1f9'}.zmdi-notifications-add:before{content:'\f1fa'}.zmdi-notifications-none:before{content:'\f1fb'}.zmdi-notifications-off:before{content:'\f1fc'}.zmdi-notifications-paused:before{content:'\f1fd'}.zmdi-notifications:before{content:'\f1fe'}.zmdi-account-add:before{content:'\f1ff'}.zmdi-account-box-mail:before{content:'\f200'}.zmdi-account-box-o:before{content:'\f201'}.zmdi-account-box-phone:before{content:'\f202'}.zmdi-account-box:before{content:'\f203'}.zmdi-account-calendar:before{content:'\f204'}.zmdi-account-circle:before{content:'\f205'}.zmdi-account-o:before{content:'\f206'}.zmdi-account:before{content:'\f207'}.zmdi-accounts-add:before{content:'\f208'}.zmdi-accounts-alt:before{content:'\f209'}.zmdi-accounts-list-alt:before{content:'\f20a'}.zmdi-accounts-list:before{content:'\f20b'}.zmdi-accounts-outline:before{content:'\f20c'}.zmdi-accounts:before{content:'\f20d'}.zmdi-face:before{content:'\f20e'}.zmdi-female:before{content:'\f20f'}.zmdi-male-alt:before{content:'\f210'}.zmdi-male-female:before{content:'\f211'}.zmdi-male:before{content:'\f212'}.zmdi-mood-bad:before{content:'\f213'}.zmdi-mood:before{content:'\f214'}.zmdi-run:before{content:'\f215'}.zmdi-walk:before{content:'\f216'}.zmdi-cloud-box:before{content:'\f217'}.zmdi-cloud-circle:before{content:'\f218'}.zmdi-cloud-done:before{content:'\f219'}.zmdi-cloud-download:before{content:'\f21a'}.zmdi-cloud-off:before{content:'\f21b'}.zmdi-cloud-outline-alt:before{content:'\f21c'}.zmdi-cloud-outline:before{content:'\f21d'}.zmdi-cloud-upload:before{content:'\f21e'}.zmdi-cloud:before{content:'\f21f'}.zmdi-download:before{content:'\f220'}.zmdi-file-plus:before{content:'\f221'}.zmdi-file-text:before{content:'\f222'}.zmdi-file:before{content:'\f223'}.zmdi-folder-outline:before{content:'\f224'}.zmdi-folder-person:before{content:'\f225'}.zmdi-folder-star-alt:before{content:'\f226'}.zmdi-folder-star:before{content:'\f227'}.zmdi-folder:before{content:'\f228'}.zmdi-gif:before{content:'\f229'}.zmdi-upload:before{content:'\f22a'}.zmdi-border-all:before{content:'\f22b'}.zmdi-border-bottom:before{content:'\f22c'}.zmdi-border-clear:before{content:'\f22d'}.zmdi-border-color:before{content:'\f22e'}.zmdi-border-horizontal:before{content:'\f22f'}.zmdi-border-inner:before{content:'\f230'}.zmdi-border-left:before{content:'\f231'}.zmdi-border-outer:before{content:'\f232'}.zmdi-border-right:before{content:'\f233'}.zmdi-border-style:before{content:'\f234'}.zmdi-border-top:before{content:'\f235'}.zmdi-border-vertical:before{content:'\f236'}.zmdi-copy:before{content:'\f237'}.zmdi-crop:before{content:'\f238'}.zmdi-format-align-center:before{content:'\f239'}.zmdi-format-align-justify:before{content:'\f23a'}.zmdi-format-align-left:before{content:'\f23b'}.zmdi-format-align-right:before{content:'\f23c'}.zmdi-format-bold:before{content:'\f23d'}.zmdi-format-clear-all:before{content:'\f23e'}.zmdi-format-clear:before{content:'\f23f'}.zmdi-format-color-fill:before{content:'\f240'}.zmdi-format-color-reset:before{content:'\f241'}.zmdi-format-color-text:before{content:'\f242'}.zmdi-format-indent-decrease:before{content:'\f243'}.zmdi-format-indent-increase:before{content:'\f244'}.zmdi-format-italic:before{content:'\f245'}.zmdi-format-line-spacing:before{content:'\f246'}.zmdi-format-list-bulleted:before{content:'\f247'}.zmdi-format-list-numbered:before{content:'\f248'}.zmdi-format-ltr:before{content:'\f249'}.zmdi-format-rtl:before{content:'\f24a'}.zmdi-format-size:before{content:'\f24b'}.zmdi-format-strikethrough-s:before{content:'\f24c'}.zmdi-format-strikethrough:before{content:'\f24d'}.zmdi-format-subject:before{content:'\f24e'}.zmdi-format-underlined:before{content:'\f24f'}.zmdi-format-valign-bottom:before{content:'\f250'}.zmdi-format-valign-center:before{content:'\f251'}.zmdi-format-valign-top:before{content:'\f252'}.zmdi-redo:before{content:'\f253'}.zmdi-select-all:before{content:'\f254'}.zmdi-space-bar:before{content:'\f255'}.zmdi-text-format:before{content:'\f256'}.zmdi-transform:before{content:'\f257'}.zmdi-undo:before{content:'\f258'}.zmdi-wrap-text:before{content:'\f259'}.zmdi-comment-alert:before{content:'\f25a'}.zmdi-comment-alt-text:before{content:'\f25b'}.zmdi-comment-alt:before{content:'\f25c'}.zmdi-comment-edit:before{content:'\f25d'}.zmdi-comment-image:before{content:'\f25e'}.zmdi-comment-list:before{content:'\f25f'}.zmdi-comment-more:before{content:'\f260'}.zmdi-comment-outline:before{content:'\f261'}.zmdi-comment-text-alt:before{content:'\f262'}.zmdi-comment-text:before{content:'\f263'}.zmdi-comment-video:before{content:'\f264'}.zmdi-comment:before{content:'\f265'}.zmdi-comments:before{content:'\f266'}.zmdi-check-all:before{content:'\f267'}.zmdi-check-circle-u:before{content:'\f268'}.zmdi-check-circle:before{content:'\f269'}.zmdi-check-square:before{content:'\f26a'}.zmdi-check:before{content:'\f26b'}.zmdi-circle-o:before{content:'\f26c'}.zmdi-circle:before{content:'\f26d'}.zmdi-dot-circle-alt:before{content:'\f26e'}.zmdi-dot-circle:before{content:'\f26f'}.zmdi-minus-circle-outline:before{content:'\f270'}.zmdi-minus-circle:before{content:'\f271'}.zmdi-minus-square:before{content:'\f272'}.zmdi-minus:before{content:'\f273'}.zmdi-plus-circle-o-duplicate:before{content:'\f274'}.zmdi-plus-circle-o:before{content:'\f275'}.zmdi-plus-circle:before{content:'\f276'}.zmdi-plus-square:before{content:'\f277'}.zmdi-plus:before{content:'\f278'}.zmdi-square-o:before{content:'\f279'}.zmdi-star-circle:before{content:'\f27a'}.zmdi-star-half:before{content:'\f27b'}.zmdi-star-outline:before{content:'\f27c'}.zmdi-star:before{content:'\f27d'}.zmdi-bluetooth-connected:before{content:'\f27e'}.zmdi-bluetooth-off:before{content:'\f27f'}.zmdi-bluetooth-search:before{content:'\f280'}.zmdi-bluetooth-setting:before{content:'\f281'}.zmdi-bluetooth:before{content:'\f282'}.zmdi-camera-add:before{content:'\f283'}.zmdi-camera-alt:before{content:'\f284'}.zmdi-camera-bw:before{content:'\f285'}.zmdi-camera-front:before{content:'\f286'}.zmdi-camera-mic:before{content:'\f287'}.zmdi-camera-party-mode:before{content:'\f288'}.zmdi-camera-rear:before{content:'\f289'}.zmdi-camera-roll:before{content:'\f28a'}.zmdi-camera-switch:before{content:'\f28b'}.zmdi-camera:before{content:'\f28c'}.zmdi-card-alert:before{content:'\f28d'}.zmdi-card-off:before{content:'\f28e'}.zmdi-card-sd:before{content:'\f28f'}.zmdi-card-sim:before{content:'\f290'}.zmdi-desktop-mac:before{content:'\f291'}.zmdi-desktop-windows:before{content:'\f292'}.zmdi-device-hub:before{content:'\f293'}.zmdi-devices-off:before{content:'\f294'}.zmdi-devices:before{content:'\f295'}.zmdi-dock:before{content:'\f296'}.zmdi-floppy:before{content:'\f297'}.zmdi-gamepad:before{content:'\f298'}.zmdi-gps-dot:before{content:'\f299'}.zmdi-gps-off:before{content:'\f29a'}.zmdi-gps:before{content:'\f29b'}.zmdi-headset-mic:before{content:'\f29c'}.zmdi-headset:before{content:'\f29d'}.zmdi-input-antenna:before{content:'\f29e'}.zmdi-input-composite:before{content:'\f29f'}.zmdi-input-hdmi:before{content:'\f2a0'}.zmdi-input-power:before{content:'\f2a1'}.zmdi-input-svideo:before{content:'\f2a2'}.zmdi-keyboard-hide:before{content:'\f2a3'}.zmdi-keyboard:before{content:'\f2a4'}.zmdi-laptop-chromebook:before{content:'\f2a5'}.zmdi-laptop-mac:before{content:'\f2a6'}.zmdi-laptop:before{content:'\f2a7'}.zmdi-mic-off:before{content:'\f2a8'}.zmdi-mic-outline:before{content:'\f2a9'}.zmdi-mic-setting:before{content:'\f2aa'}.zmdi-mic:before{content:'\f2ab'}.zmdi-mouse:before{content:'\f2ac'}.zmdi-network-alert:before{content:'\f2ad'}.zmdi-network-locked:before{content:'\f2ae'}.zmdi-network-off:before{content:'\f2af'}.zmdi-network-outline:before{content:'\f2b0'}.zmdi-network-setting:before{content:'\f2b1'}.zmdi-network:before{content:'\f2b2'}.zmdi-phone-bluetooth:before{content:'\f2b3'}.zmdi-phone-end:before{content:'\f2b4'}.zmdi-phone-forwarded:before{content:'\f2b5'}.zmdi-phone-in-talk:before{content:'\f2b6'}.zmdi-phone-locked:before{content:'\f2b7'}.zmdi-phone-missed:before{content:'\f2b8'}.zmdi-phone-msg:before{content:'\f2b9'}.zmdi-phone-paused:before{content:'\f2ba'}.zmdi-phone-ring:before{content:'\f2bb'}.zmdi-phone-setting:before{content:'\f2bc'}.zmdi-phone-sip:before{content:'\f2bd'}.zmdi-phone:before{content:'\f2be'}.zmdi-portable-wifi-changes:before{content:'\f2bf'}.zmdi-portable-wifi-off:before{content:'\f2c0'}.zmdi-portable-wifi:before{content:'\f2c1'}.zmdi-radio:before{content:'\f2c2'}.zmdi-reader:before{content:'\f2c3'}.zmdi-remote-control-alt:before{content:'\f2c4'}.zmdi-remote-control:before{content:'\f2c5'}.zmdi-router:before{content:'\f2c6'}.zmdi-scanner:before{content:'\f2c7'}.zmdi-smartphone-android:before{content:'\f2c8'}.zmdi-smartphone-download:before{content:'\f2c9'}.zmdi-smartphone-erase:before{content:'\f2ca'}.zmdi-smartphone-info:before{content:'\f2cb'}.zmdi-smartphone-iphone:before{content:'\f2cc'}.zmdi-smartphone-landscape-lock:before{content:'\f2cd'}.zmdi-smartphone-landscape:before{content:'\f2ce'}.zmdi-smartphone-lock:before{content:'\f2cf'}.zmdi-smartphone-portrait-lock:before{content:'\f2d0'}.zmdi-smartphone-ring:before{content:'\f2d1'}.zmdi-smartphone-setting:before{content:'\f2d2'}.zmdi-smartphone-setup:before{content:'\f2d3'}.zmdi-smartphone:before{content:'\f2d4'}.zmdi-speaker:before{content:'\f2d5'}.zmdi-tablet-android:before{content:'\f2d6'}.zmdi-tablet-mac:before{content:'\f2d7'}.zmdi-tablet:before{content:'\f2d8'}.zmdi-tv-alt-play:before{content:'\f2d9'}.zmdi-tv-list:before{content:'\f2da'}.zmdi-tv-play:before{content:'\f2db'}.zmdi-tv:before{content:'\f2dc'}.zmdi-usb:before{content:'\f2dd'}.zmdi-videocam-off:before{content:'\f2de'}.zmdi-videocam-switch:before{content:'\f2df'}.zmdi-videocam:before{content:'\f2e0'}.zmdi-watch:before{content:'\f2e1'}.zmdi-wifi-alt-2:before{content:'\f2e2'}.zmdi-wifi-alt:before{content:'\f2e3'}.zmdi-wifi-info:before{content:'\f2e4'}.zmdi-wifi-lock:before{content:'\f2e5'}.zmdi-wifi-off:before{content:'\f2e6'}.zmdi-wifi-outline:before{content:'\f2e7'}.zmdi-wifi:before{content:'\f2e8'}.zmdi-arrow-left-bottom:before{content:'\f2e9'}.zmdi-arrow-left:before{content:'\f2ea'}.zmdi-arrow-merge:before{content:'\f2eb'}.zmdi-arrow-missed:before{content:'\f2ec'}.zmdi-arrow-right-top:before{content:'\f2ed'}.zmdi-arrow-right:before{content:'\f2ee'}.zmdi-arrow-split:before{content:'\f2ef'}.zmdi-arrows:before{content:'\f2f0'}.zmdi-caret-down-circle:before{content:'\f2f1'}.zmdi-caret-down:before{content:'\f2f2'}.zmdi-caret-left-circle:before{content:'\f2f3'}.zmdi-caret-left:before{content:'\f2f4'}.zmdi-caret-right-circle:before{content:'\f2f5'}.zmdi-caret-right:before{content:'\f2f6'}.zmdi-caret-up-circle:before{content:'\f2f7'}.zmdi-caret-up:before{content:'\f2f8'}.zmdi-chevron-down:before{content:'\f2f9'}.zmdi-chevron-left:before{content:'\f2fa'}.zmdi-chevron-right:before{content:'\f2fb'}.zmdi-chevron-up:before{content:'\f2fc'}.zmdi-forward:before{content:'\f2fd'}.zmdi-long-arrow-down:before{content:'\f2fe'}.zmdi-long-arrow-left:before{content:'\f2ff'}.zmdi-long-arrow-return:before{content:'\f300'}.zmdi-long-arrow-right:before{content:'\f301'}.zmdi-long-arrow-tab:before{content:'\f302'}.zmdi-long-arrow-up:before{content:'\f303'}.zmdi-rotate-ccw:before{content:'\f304'}.zmdi-rotate-cw:before{content:'\f305'}.zmdi-rotate-left:before{content:'\f306'}.zmdi-rotate-right:before{content:'\f307'}.zmdi-square-down:before{content:'\f308'}.zmdi-square-right:before{content:'\f309'}.zmdi-swap-alt:before{content:'\f30a'}.zmdi-swap-vertical-circle:before{content:'\f30b'}.zmdi-swap-vertical:before{content:'\f30c'}.zmdi-swap:before{content:'\f30d'}.zmdi-trending-down:before{content:'\f30e'}.zmdi-trending-flat:before{content:'\f30f'}.zmdi-trending-up:before{content:'\f310'}.zmdi-unfold-less:before{content:'\f311'}.zmdi-unfold-more:before{content:'\f312'}.zmdi-apps:before{content:'\f313'}.zmdi-grid-off:before{content:'\f314'}.zmdi-grid:before{content:'\f315'}.zmdi-view-agenda:before{content:'\f316'}.zmdi-view-array:before{content:'\f317'}.zmdi-view-carousel:before{content:'\f318'}.zmdi-view-column:before{content:'\f319'}.zmdi-view-comfy:before{content:'\f31a'}.zmdi-view-compact:before{content:'\f31b'}.zmdi-view-dashboard:before{content:'\f31c'}.zmdi-view-day:before{content:'\f31d'}.zmdi-view-headline:before{content:'\f31e'}.zmdi-view-list-alt:before{content:'\f31f'}.zmdi-view-list:before{content:'\f320'}.zmdi-view-module:before{content:'\f321'}.zmdi-view-quilt:before{content:'\f322'}.zmdi-view-stream:before{content:'\f323'}.zmdi-view-subtitles:before{content:'\f324'}.zmdi-view-toc:before{content:'\f325'}.zmdi-view-web:before{content:'\f326'}.zmdi-view-week:before{content:'\f327'}.zmdi-widgets:before{content:'\f328'}.zmdi-alarm-check:before{content:'\f329'}.zmdi-alarm-off:before{content:'\f32a'}.zmdi-alarm-plus:before{content:'\f32b'}.zmdi-alarm-snooze:before{content:'\f32c'}.zmdi-alarm:before{content:'\f32d'}.zmdi-calendar-alt:before{content:'\f32e'}.zmdi-calendar-check:before{content:'\f32f'}.zmdi-calendar-close:before{content:'\f330'}.zmdi-calendar-note:before{content:'\f331'}.zmdi-calendar:before{content:'\f332'}.zmdi-time-countdown:before{content:'\f333'}.zmdi-time-interval:before{content:'\f334'}.zmdi-time-restore-setting:before{content:'\f335'}.zmdi-time-restore:before{content:'\f336'}.zmdi-time:before{content:'\f337'}.zmdi-timer-off:before{content:'\f338'}.zmdi-timer:before{content:'\f339'}.zmdi-android-alt:before{content:'\f33a'}.zmdi-android:before{content:'\f33b'}.zmdi-apple:before{content:'\f33c'}.zmdi-behance:before{content:'\f33d'}.zmdi-codepen:before{content:'\f33e'}.zmdi-dribbble:before{content:'\f33f'}.zmdi-dropbox:before{content:'\f340'}.zmdi-evernote:before{content:'\f341'}.zmdi-facebook-box:before{content:'\f342'}.zmdi-facebook:before{content:'\f343'}.zmdi-github-box:before{content:'\f344'}.zmdi-github:before{content:'\f345'}.zmdi-google-drive:before{content:'\f346'}.zmdi-google-earth:before{content:'\f347'}.zmdi-google-glass:before{content:'\f348'}.zmdi-google-maps:before{content:'\f349'}.zmdi-google-pages:before{content:'\f34a'}.zmdi-google-play:before{content:'\f34b'}.zmdi-google-plus-box:before{content:'\f34c'}.zmdi-google-plus:before{content:'\f34d'}.zmdi-google:before{content:'\f34e'}.zmdi-instagram:before{content:'\f34f'}.zmdi-language-css3:before{content:'\f350'}.zmdi-language-html5:before{content:'\f351'}.zmdi-language-javascript:before{content:'\f352'}.zmdi-language-python-alt:before{content:'\f353'}.zmdi-language-python:before{content:'\f354'}.zmdi-lastfm:before{content:'\f355'}.zmdi-linkedin-box:before{content:'\f356'}.zmdi-paypal:before{content:'\f357'}.zmdi-pinterest-box:before{content:'\f358'}.zmdi-pocket:before{content:'\f359'}.zmdi-polymer:before{content:'\f35a'}.zmdi-share:before{content:'\f35b'}.zmdi-stackoverflow:before{content:'\f35c'}.zmdi-steam-square:before{content:'\f35d'}.zmdi-steam:before{content:'\f35e'}.zmdi-twitter-box:before{content:'\f35f'}.zmdi-twitter:before{content:'\f360'}.zmdi-vk:before{content:'\f361'}.zmdi-wikipedia:before{content:'\f362'}.zmdi-windows:before{content:'\f363'}.zmdi-aspect-ratio-alt:before{content:'\f364'}.zmdi-aspect-ratio:before{content:'\f365'}.zmdi-blur-circular:before{content:'\f366'}.zmdi-blur-linear:before{content:'\f367'}.zmdi-blur-off:before{content:'\f368'}.zmdi-blur:before{content:'\f369'}.zmdi-brightness-2:before{content:'\f36a'}.zmdi-brightness-3:before{content:'\f36b'}.zmdi-brightness-4:before{content:'\f36c'}.zmdi-brightness-5:before{content:'\f36d'}.zmdi-brightness-6:before{content:'\f36e'}.zmdi-brightness-7:before{content:'\f36f'}.zmdi-brightness-auto:before{content:'\f370'}.zmdi-brightness-setting:before{content:'\f371'}.zmdi-broken-image:before{content:'\f372'}.zmdi-center-focus-strong:before{content:'\f373'}.zmdi-center-focus-weak:before{content:'\f374'}.zmdi-compare:before{content:'\f375'}.zmdi-crop-16-9:before{content:'\f376'}.zmdi-crop-3-2:before{content:'\f377'}.zmdi-crop-5-4:before{content:'\f378'}.zmdi-crop-7-5:before{content:'\f379'}.zmdi-crop-din:before{content:'\f37a'}.zmdi-crop-free:before{content:'\f37b'}.zmdi-crop-landscape:before{content:'\f37c'}.zmdi-crop-portrait:before{content:'\f37d'}.zmdi-crop-square:before{content:'\f37e'}.zmdi-exposure-alt:before{content:'\f37f'}.zmdi-exposure:before{content:'\f380'}.zmdi-filter-b-and-w:before{content:'\f381'}.zmdi-filter-center-focus:before{content:'\f382'}.zmdi-filter-frames:before{content:'\f383'}.zmdi-filter-tilt-shift:before{content:'\f384'}.zmdi-gradient:before{content:'\f385'}.zmdi-grain:before{content:'\f386'}.zmdi-graphic-eq:before{content:'\f387'}.zmdi-hdr-off:before{content:'\f388'}.zmdi-hdr-strong:before{content:'\f389'}.zmdi-hdr-weak:before{content:'\f38a'}.zmdi-hdr:before{content:'\f38b'}.zmdi-iridescent:before{content:'\f38c'}.zmdi-leak-off:before{content:'\f38d'}.zmdi-leak:before{content:'\f38e'}.zmdi-looks:before{content:'\f38f'}.zmdi-loupe:before{content:'\f390'}.zmdi-panorama-horizontal:before{content:'\f391'}.zmdi-panorama-vertical:before{content:'\f392'}.zmdi-panorama-wide-angle:before{content:'\f393'}.zmdi-photo-size-select-large:before{content:'\f394'}.zmdi-photo-size-select-small:before{content:'\f395'}.zmdi-picture-in-picture:before{content:'\f396'}.zmdi-slideshow:before{content:'\f397'}.zmdi-texture:before{content:'\f398'}.zmdi-tonality:before{content:'\f399'}.zmdi-vignette:before{content:'\f39a'}.zmdi-wb-auto:before{content:'\f39b'}.zmdi-eject-alt:before{content:'\f39c'}.zmdi-eject:before{content:'\f39d'}.zmdi-equalizer:before{content:'\f39e'}.zmdi-fast-forward:before{content:'\f39f'}.zmdi-fast-rewind:before{content:'\f3a0'}.zmdi-forward-10:before{content:'\f3a1'}.zmdi-forward-30:before{content:'\f3a2'}.zmdi-forward-5:before{content:'\f3a3'}.zmdi-hearing:before{content:'\f3a4'}.zmdi-pause-circle-outline:before{content:'\f3a5'}.zmdi-pause-circle:before{content:'\f3a6'}.zmdi-pause:before{content:'\f3a7'}.zmdi-play-circle-outline:before{content:'\f3a8'}.zmdi-play-circle:before{content:'\f3a9'}.zmdi-play:before{content:'\f3aa'}.zmdi-playlist-audio:before{content:'\f3ab'}.zmdi-playlist-plus:before{content:'\f3ac'}.zmdi-repeat-one:before{content:'\f3ad'}.zmdi-repeat:before{content:'\f3ae'}.zmdi-replay-10:before{content:'\f3af'}.zmdi-replay-30:before{content:'\f3b0'}.zmdi-replay-5:before{content:'\f3b1'}.zmdi-replay:before{content:'\f3b2'}.zmdi-shuffle:before{content:'\f3b3'}.zmdi-skip-next:before{content:'\f3b4'}.zmdi-skip-previous:before{content:'\f3b5'}.zmdi-stop:before{content:'\f3b6'}.zmdi-surround-sound:before{content:'\f3b7'}.zmdi-tune:before{content:'\f3b8'}.zmdi-volume-down:before{content:'\f3b9'}.zmdi-volume-mute:before{content:'\f3ba'}.zmdi-volume-off:before{content:'\f3bb'}.zmdi-volume-up:before{content:'\f3bc'}.zmdi-n-1-square:before{content:'\f3bd'}.zmdi-n-2-square:before{content:'\f3be'}.zmdi-n-3-square:before{content:'\f3bf'}.zmdi-n-4-square:before{content:'\f3c0'}.zmdi-n-5-square:before{content:'\f3c1'}.zmdi-n-6-square:before{content:'\f3c2'}.zmdi-neg-1:before{content:'\f3c3'}.zmdi-neg-2:before{content:'\f3c4'}.zmdi-plus-1:before{content:'\f3c5'}.zmdi-plus-2:before{content:'\f3c6'}.zmdi-sec-10:before{content:'\f3c7'}.zmdi-sec-3:before{content:'\f3c8'}.zmdi-zero:before{content:'\f3c9'}.zmdi-airline-seat-flat-angled:before{content:'\f3ca'}.zmdi-airline-seat-flat:before{content:'\f3cb'}.zmdi-airline-seat-individual-suite:before{content:'\f3cc'}.zmdi-airline-seat-legroom-extra:before{content:'\f3cd'}.zmdi-airline-seat-legroom-normal:before{content:'\f3ce'}.zmdi-airline-seat-legroom-reduced:before{content:'\f3cf'}.zmdi-airline-seat-recline-extra:before{content:'\f3d0'}.zmdi-airline-seat-recline-normal:before{content:'\f3d1'}.zmdi-airplay:before{content:'\f3d2'}.zmdi-closed-caption:before{content:'\f3d3'}.zmdi-confirmation-number:before{content:'\f3d4'}.zmdi-developer-board:before{content:'\f3d5'}.zmdi-disc-full:before{content:'\f3d6'}.zmdi-explicit:before{content:'\f3d7'}.zmdi-flight-land:before{content:'\f3d8'}.zmdi-flight-takeoff:before{content:'\f3d9'}.zmdi-flip-to-back:before{content:'\f3da'}.zmdi-flip-to-front:before{content:'\f3db'}.zmdi-group-work:before{content:'\f3dc'}.zmdi-hd:before{content:'\f3dd'}.zmdi-hq:before{content:'\f3de'}.zmdi-markunread-mailbox:before{content:'\f3df'}.zmdi-memory:before{content:'\f3e0'}.zmdi-nfc:before{content:'\f3e1'}.zmdi-play-for-work:before{content:'\f3e2'}.zmdi-power-input:before{content:'\f3e3'}.zmdi-present-to-all:before{content:'\f3e4'}.zmdi-satellite:before{content:'\f3e5'}.zmdi-tap-and-play:before{content:'\f3e6'}.zmdi-vibration:before{content:'\f3e7'}.zmdi-voicemail:before{content:'\f3e8'}.zmdi-group:before{content:'\f3e9'}.zmdi-rss:before{content:'\f3ea'}.zmdi-shape:before{content:'\f3eb'}.zmdi-spinner:before{content:'\f3ec'}.zmdi-ungroup:before{content:'\f3ed'}.zmdi-500px:before{content:'\f3ee'}.zmdi-8tracks:before{content:'\f3ef'}.zmdi-amazon:before{content:'\f3f0'}.zmdi-blogger:before{content:'\f3f1'}.zmdi-delicious:before{content:'\f3f2'}.zmdi-disqus:before{content:'\f3f3'}.zmdi-flattr:before{content:'\f3f4'}.zmdi-flickr:before{content:'\f3f5'}.zmdi-github-alt:before{content:'\f3f6'}.zmdi-google-old:before{content:'\f3f7'}.zmdi-linkedin:before{content:'\f3f8'}.zmdi-odnoklassniki:before{content:'\f3f9'}.zmdi-outlook:before{content:'\f3fa'}.zmdi-paypal-alt:before{content:'\f3fb'}.zmdi-pinterest:before{content:'\f3fc'}.zmdi-playstation:before{content:'\f3fd'}.zmdi-reddit:before{content:'\f3fe'}.zmdi-skype:before{content:'\f3ff'}.zmdi-slideshare:before{content:'\f400'}.zmdi-soundcloud:before{content:'\f401'}.zmdi-tumblr:before{content:'\f402'}.zmdi-twitch:before{content:'\f403'}.zmdi-vimeo:before{content:'\f404'}.zmdi-whatsapp:before{content:'\f405'}.zmdi-xbox:before{content:'\f406'}.zmdi-yahoo:before{content:'\f407'}.zmdi-youtube-play:before{content:'\f408'}.zmdi-youtube:before{content:'\f409'}.zmdi-3d-rotation:before{content:'\f101'}.zmdi-airplane-off:before{content:'\f102'}.zmdi-airplane:before{content:'\f103'}.zmdi-album:before{content:'\f104'}.zmdi-archive:before{content:'\f105'}.zmdi-assignment-account:before{content:'\f106'}.zmdi-assignment-alert:before{content:'\f107'}.zmdi-assignment-check:before{content:'\f108'}.zmdi-assignment-o:before{content:'\f109'}.zmdi-assignment-return:before{content:'\f10a'}.zmdi-assignment-returned:before{content:'\f10b'}.zmdi-assignment:before{content:'\f10c'}.zmdi-attachment-alt:before{content:'\f10d'}.zmdi-attachment:before{content:'\f10e'}.zmdi-audio:before{content:'\f10f'}.zmdi-badge-check:before{content:'\f110'}.zmdi-balance-wallet:before{content:'\f111'}.zmdi-balance:before{content:'\f112'}.zmdi-battery-alert:before{content:'\f113'}.zmdi-battery-flash:before{content:'\f114'}.zmdi-battery-unknown:before{content:'\f115'}.zmdi-battery:before{content:'\f116'}.zmdi-bike:before{content:'\f117'}.zmdi-block-alt:before{content:'\f118'}.zmdi-block:before{content:'\f119'}.zmdi-boat:before{content:'\f11a'}.zmdi-book-image:before{content:'\f11b'}.zmdi-book:before{content:'\f11c'}.zmdi-bookmark-outline:before{content:'\f11d'}.zmdi-bookmark:before{content:'\f11e'}.zmdi-brush:before{content:'\f11f'}.zmdi-bug:before{content:'\f120'}.zmdi-bus:before{content:'\f121'}.zmdi-cake:before{content:'\f122'}.zmdi-car-taxi:before{content:'\f123'}.zmdi-car-wash:before{content:'\f124'}.zmdi-car:before{content:'\f125'}.zmdi-card-giftcard:before{content:'\f126'}.zmdi-card-membership:before{content:'\f127'}.zmdi-card-travel:before{content:'\f128'}.zmdi-card:before{content:'\f129'}.zmdi-case-check:before{content:'\f12a'}.zmdi-case-download:before{content:'\f12b'}.zmdi-case-play:before{content:'\f12c'}.zmdi-case:before{content:'\f12d'}.zmdi-cast-connected:before{content:'\f12e'}.zmdi-cast:before{content:'\f12f'}.zmdi-chart-donut:before{content:'\f130'}.zmdi-chart:before{content:'\f131'}.zmdi-city-alt:before{content:'\f132'}.zmdi-city:before{content:'\f133'}.zmdi-close-circle-o:before{content:'\f134'}.zmdi-close-circle:before{content:'\f135'}.zmdi-close:before{content:'\f136'}.zmdi-cocktail:before{content:'\f137'}.zmdi-code-setting:before{content:'\f138'}.zmdi-code-smartphone:before{content:'\f139'}.zmdi-code:before{content:'\f13a'}.zmdi-coffee:before{content:'\f13b'}.zmdi-collection-bookmark:before{content:'\f13c'}.zmdi-collection-case-play:before{content:'\f13d'}.zmdi-collection-folder-image:before{content:'\f13e'}.zmdi-collection-image-o:before{content:'\f13f'}.zmdi-collection-image:before{content:'\f140'}.zmdi-collection-item-1:before{content:'\f141'}.zmdi-collection-item-2:before{content:'\f142'}.zmdi-collection-item-3:before{content:'\f143'}.zmdi-collection-item-4:before{content:'\f144'}.zmdi-collection-item-5:before{content:'\f145'}.zmdi-collection-item-6:before{content:'\f146'}.zmdi-collection-item-7:before{content:'\f147'}.zmdi-collection-item-8:before{content:'\f148'}.zmdi-collection-item-9-plus:before{content:'\f149'}.zmdi-collection-item-9:before{content:'\f14a'}.zmdi-collection-item:before{content:'\f14b'}.zmdi-collection-music:before{content:'\f14c'}.zmdi-collection-pdf:before{content:'\f14d'}.zmdi-collection-plus:before{content:'\f14e'}.zmdi-collection-speaker:before{content:'\f14f'}.zmdi-collection-text:before{content:'\f150'}.zmdi-collection-video:before{content:'\f151'}.zmdi-compass:before{content:'\f152'}.zmdi-cutlery:before{content:'\f153'}.zmdi-delete:before{content:'\f154'}.zmdi-dialpad:before{content:'\f155'}.zmdi-dns:before{content:'\f156'}.zmdi-drink:before{content:'\f157'}.zmdi-edit:before{content:'\f158'}.zmdi-email-open:before{content:'\f159'}.zmdi-email:before{content:'\f15a'}.zmdi-eye-off:before{content:'\f15b'}.zmdi-eye:before{content:'\f15c'}.zmdi-eyedropper:before{content:'\f15d'}.zmdi-favorite-outline:before{content:'\f15e'}.zmdi-favorite:before{content:'\f15f'}.zmdi-filter-list:before{content:'\f160'}.zmdi-fire:before{content:'\f161'}.zmdi-flag:before{content:'\f162'}.zmdi-flare:before{content:'\f163'}.zmdi-flash-auto:before{content:'\f164'}.zmdi-flash-off:before{content:'\f165'}.zmdi-flash:before{content:'\f166'}.zmdi-flip:before{content:'\f167'}.zmdi-flower-alt:before{content:'\f168'}.zmdi-flower:before{content:'\f169'}.zmdi-font:before{content:'\f16a'}.zmdi-fullscreen-alt:before{content:'\f16b'}.zmdi-fullscreen-exit:before{content:'\f16c'}.zmdi-fullscreen:before{content:'\f16d'}.zmdi-functions:before{content:'\f16e'}.zmdi-gas-station:before{content:'\f16f'}.zmdi-gesture:before{content:'\f170'}.zmdi-globe-alt:before{content:'\f171'}.zmdi-globe-lock:before{content:'\f172'}.zmdi-globe:before{content:'\f173'}.zmdi-graduation-cap:before{content:'\f174'}.zmdi-home:before{content:'\f175'}.zmdi-hospital-alt:before{content:'\f176'}.zmdi-hospital:before{content:'\f177'}.zmdi-hotel:before{content:'\f178'}.zmdi-hourglass-alt:before{content:'\f179'}.zmdi-hourglass-outline:before{content:'\f17a'}.zmdi-hourglass:before{content:'\f17b'}.zmdi-http:before{content:'\f17c'}.zmdi-image-alt:before{content:'\f17d'}.zmdi-image-o:before{content:'\f17e'}.zmdi-image:before{content:'\f17f'}.zmdi-inbox:before{content:'\f180'}.zmdi-invert-colors-off:before{content:'\f181'}.zmdi-invert-colors:before{content:'\f182'}.zmdi-key:before{content:'\f183'}.zmdi-label-alt-outline:before{content:'\f184'}.zmdi-label-alt:before{content:'\f185'}.zmdi-label-heart:before{content:'\f186'}.zmdi-label:before{content:'\f187'}.zmdi-labels:before{content:'\f188'}.zmdi-lamp:before{content:'\f189'}.zmdi-landscape:before{content:'\f18a'}.zmdi-layers-off:before{content:'\f18b'}.zmdi-layers:before{content:'\f18c'}.zmdi-library:before{content:'\f18d'}.zmdi-link:before{content:'\f18e'}.zmdi-lock-open:before{content:'\f18f'}.zmdi-lock-outline:before{content:'\f190'}.zmdi-lock:before{content:'\f191'}.zmdi-mail-reply-all:before{content:'\f192'}.zmdi-mail-reply:before{content:'\f193'}.zmdi-mail-send:before{content:'\f194'}.zmdi-mall:before{content:'\f195'}.zmdi-map:before{content:'\f196'}.zmdi-menu:before{content:'\f197'}.zmdi-money-box:before{content:'\f198'}.zmdi-money-off:before{content:'\f199'}.zmdi-money:before{content:'\f19a'}.zmdi-more-vert:before{content:'\f19b'}.zmdi-more:before{content:'\f19c'}.zmdi-movie-alt:before{content:'\f19d'}.zmdi-movie:before{content:'\f19e'}.zmdi-nature-people:before{content:'\f19f'}.zmdi-nature:before{content:'\f1a0'}.zmdi-navigation:before{content:'\f1a1'}.zmdi-open-in-browser:before{content:'\f1a2'}.zmdi-open-in-new:before{content:'\f1a3'}.zmdi-palette:before{content:'\f1a4'}.zmdi-parking:before{content:'\f1a5'}.zmdi-pin-account:before{content:'\f1a6'}.zmdi-pin-assistant:before{content:'\f1a7'}.zmdi-pin-drop:before{content:'\f1a8'}.zmdi-pin-help:before{content:'\f1a9'}.zmdi-pin-off:before{content:'\f1aa'}.zmdi-pin:before{content:'\f1ab'}.zmdi-pizza:before{content:'\f1ac'}.zmdi-plaster:before{content:'\f1ad'}.zmdi-power-setting:before{content:'\f1ae'}.zmdi-power:before{content:'\f1af'}.zmdi-print:before{content:'\f1b0'}.zmdi-puzzle-piece:before{content:'\f1b1'}.zmdi-quote:before{content:'\f1b2'}.zmdi-railway:before{content:'\f1b3'}.zmdi-receipt:before{content:'\f1b4'}.zmdi-refresh-alt:before{content:'\f1b5'}.zmdi-refresh-sync-alert:before{content:'\f1b6'}.zmdi-refresh-sync-off:before{content:'\f1b7'}.zmdi-refresh-sync:before{content:'\f1b8'}.zmdi-refresh:before{content:'\f1b9'}.zmdi-roller:before{content:'\f1ba'}.zmdi-ruler:before{content:'\f1bb'}.zmdi-scissors:before{content:'\f1bc'}.zmdi-screen-rotation-lock:before{content:'\f1bd'}.zmdi-screen-rotation:before{content:'\f1be'}.zmdi-search-for:before{content:'\f1bf'}.zmdi-search-in-file:before{content:'\f1c0'}.zmdi-search-in-page:before{content:'\f1c1'}.zmdi-search-replace:before{content:'\f1c2'}.zmdi-search:before{content:'\f1c3'}.zmdi-seat:before{content:'\f1c4'}.zmdi-settings-square:before{content:'\f1c5'}.zmdi-settings:before{content:'\f1c6'}.zmdi-shield-check:before{content:'\f1c7'}.zmdi-shield-security:before{content:'\f1c8'}.zmdi-shopping-basket:before{content:'\f1c9'}.zmdi-shopping-cart-plus:before{content:'\f1ca'}.zmdi-shopping-cart:before{content:'\f1cb'}.zmdi-sign-in:before{content:'\f1cc'}.zmdi-sort-amount-asc:before{content:'\f1cd'}.zmdi-sort-amount-desc:before{content:'\f1ce'}.zmdi-sort-asc:before{content:'\f1cf'}.zmdi-sort-desc:before{content:'\f1d0'}.zmdi-spellcheck:before{content:'\f1d1'}.zmdi-storage:before{content:'\f1d2'}.zmdi-store-24:before{content:'\f1d3'}.zmdi-store:before{content:'\f1d4'}.zmdi-subway:before{content:'\f1d5'}.zmdi-sun:before{content:'\f1d6'}.zmdi-tab-unselected:before{content:'\f1d7'}.zmdi-tab:before{content:'\f1d8'}.zmdi-tag-close:before{content:'\f1d9'}.zmdi-tag-more:before{content:'\f1da'}.zmdi-tag:before{content:'\f1db'}.zmdi-thumb-down:before{content:'\f1dc'}.zmdi-thumb-up-down:before{content:'\f1dd'}.zmdi-thumb-up:before{content:'\f1de'}.zmdi-ticket-star:before{content:'\f1df'}.zmdi-toll:before{content:'\f1e0'}.zmdi-toys:before{content:'\f1e1'}.zmdi-traffic:before{content:'\f1e2'}.zmdi-translate:before{content:'\f1e3'}.zmdi-triangle-down:before{content:'\f1e4'}.zmdi-triangle-up:before{content:'\f1e5'}.zmdi-truck:before{content:'\f1e6'}.zmdi-turning-sign:before{content:'\f1e7'}.zmdi-wallpaper:before{content:'\f1e8'}.zmdi-washing-machine:before{content:'\f1e9'}.zmdi-window-maximize:before{content:'\f1ea'}.zmdi-window-minimize:before{content:'\f1eb'}.zmdi-window-restore:before{content:'\f1ec'}.zmdi-wrench:before{content:'\f1ed'}.zmdi-zoom-in:before{content:'\f1ee'}.zmdi-zoom-out:before{content:'\f1ef'}.zmdi-alert-circle-o:before{content:'\f1f0'}.zmdi-alert-circle:before{content:'\f1f1'}.zmdi-alert-octagon:before{content:'\f1f2'}.zmdi-alert-polygon:before{content:'\f1f3'}.zmdi-alert-triangle:before{content:'\f1f4'}.zmdi-help-outline:before{content:'\f1f5'}.zmdi-help:before{content:'\f1f6'}.zmdi-info-outline:before{content:'\f1f7'}.zmdi-info:before{content:'\f1f8'}.zmdi-notifications-active:before{content:'\f1f9'}.zmdi-notifications-add:before{content:'\f1fa'}.zmdi-notifications-none:before{content:'\f1fb'}.zmdi-notifications-off:before{content:'\f1fc'}.zmdi-notifications-paused:before{content:'\f1fd'}.zmdi-notifications:before{content:'\f1fe'}.zmdi-account-add:before{content:'\f1ff'}.zmdi-account-box-mail:before{content:'\f200'}.zmdi-account-box-o:before{content:'\f201'}.zmdi-account-box-phone:before{content:'\f202'}.zmdi-account-box:before{content:'\f203'}.zmdi-account-calendar:before{content:'\f204'}.zmdi-account-circle:before{content:'\f205'}.zmdi-account-o:before{content:'\f206'}.zmdi-account:before{content:'\f207'}.zmdi-accounts-add:before{content:'\f208'}.zmdi-accounts-alt:before{content:'\f209'}.zmdi-accounts-list-alt:before{content:'\f20a'}.zmdi-accounts-list:before{content:'\f20b'}.zmdi-accounts-outline:before{content:'\f20c'}.zmdi-accounts:before{content:'\f20d'}.zmdi-face:before{content:'\f20e'}.zmdi-female:before{content:'\f20f'}.zmdi-male-alt:before{content:'\f210'}.zmdi-male-female:before{content:'\f211'}.zmdi-male:before{content:'\f212'}.zmdi-mood-bad:before{content:'\f213'}.zmdi-mood:before{content:'\f214'}.zmdi-run:before{content:'\f215'}.zmdi-walk:before{content:'\f216'}.zmdi-cloud-box:before{content:'\f217'}.zmdi-cloud-circle:before{content:'\f218'}.zmdi-cloud-done:before{content:'\f219'}.zmdi-cloud-download:before{content:'\f21a'}.zmdi-cloud-off:before{content:'\f21b'}.zmdi-cloud-outline-alt:before{content:'\f21c'}.zmdi-cloud-outline:before{content:'\f21d'}.zmdi-cloud-upload:before{content:'\f21e'}.zmdi-cloud:before{content:'\f21f'}.zmdi-download:before{content:'\f220'}.zmdi-file-plus:before{content:'\f221'}.zmdi-file-text:before{content:'\f222'}.zmdi-file:before{content:'\f223'}.zmdi-folder-outline:before{content:'\f224'}.zmdi-folder-person:before{content:'\f225'}.zmdi-folder-star-alt:before{content:'\f226'}.zmdi-folder-star:before{content:'\f227'}.zmdi-folder:before{content:'\f228'}.zmdi-gif:before{content:'\f229'}.zmdi-upload:before{content:'\f22a'}.zmdi-border-all:before{content:'\f22b'}.zmdi-border-bottom:before{content:'\f22c'}.zmdi-border-clear:before{content:'\f22d'}.zmdi-border-color:before{content:'\f22e'}.zmdi-border-horizontal:before{content:'\f22f'}.zmdi-border-inner:before{content:'\f230'}.zmdi-border-left:before{content:'\f231'}.zmdi-border-outer:before{content:'\f232'}.zmdi-border-right:before{content:'\f233'}.zmdi-border-style:before{content:'\f234'}.zmdi-border-top:before{content:'\f235'}.zmdi-border-vertical:before{content:'\f236'}.zmdi-copy:before{content:'\f237'}.zmdi-crop:before{content:'\f238'}.zmdi-format-align-center:before{content:'\f239'}.zmdi-format-align-justify:before{content:'\f23a'}.zmdi-format-align-left:before{content:'\f23b'}.zmdi-format-align-right:before{content:'\f23c'}.zmdi-format-bold:before{content:'\f23d'}.zmdi-format-clear-all:before{content:'\f23e'}.zmdi-format-clear:before{content:'\f23f'}.zmdi-format-color-fill:before{content:'\f240'}.zmdi-format-color-reset:before{content:'\f241'}.zmdi-format-color-text:before{content:'\f242'}.zmdi-format-indent-decrease:before{content:'\f243'}.zmdi-format-indent-increase:before{content:'\f244'}.zmdi-format-italic:before{content:'\f245'}.zmdi-format-line-spacing:before{content:'\f246'}.zmdi-format-list-bulleted:before{content:'\f247'}.zmdi-format-list-numbered:before{content:'\f248'}.zmdi-format-ltr:before{content:'\f249'}.zmdi-format-rtl:before{content:'\f24a'}.zmdi-format-size:before{content:'\f24b'}.zmdi-format-strikethrough-s:before{content:'\f24c'}.zmdi-format-strikethrough:before{content:'\f24d'}.zmdi-format-subject:before{content:'\f24e'}.zmdi-format-underlined:before{content:'\f24f'}.zmdi-format-valign-bottom:before{content:'\f250'}.zmdi-format-valign-center:before{content:'\f251'}.zmdi-format-valign-top:before{content:'\f252'}.zmdi-redo:before{content:'\f253'}.zmdi-select-all:before{content:'\f254'}.zmdi-space-bar:before{content:'\f255'}.zmdi-text-format:before{content:'\f256'}.zmdi-transform:before{content:'\f257'}.zmdi-undo:before{content:'\f258'}.zmdi-wrap-text:before{content:'\f259'}.zmdi-comment-alert:before{content:'\f25a'}.zmdi-comment-alt-text:before{content:'\f25b'}.zmdi-comment-alt:before{content:'\f25c'}.zmdi-comment-edit:before{content:'\f25d'}.zmdi-comment-image:before{content:'\f25e'}.zmdi-comment-list:before{content:'\f25f'}.zmdi-comment-more:before{content:'\f260'}.zmdi-comment-outline:before{content:'\f261'}.zmdi-comment-text-alt:before{content:'\f262'}.zmdi-comment-text:before{content:'\f263'}.zmdi-comment-video:before{content:'\f264'}.zmdi-comment:before{content:'\f265'}.zmdi-comments:before{content:'\f266'}.zmdi-check-all:before{content:'\f267'}.zmdi-check-circle-u:before{content:'\f268'}.zmdi-check-circle:before{content:'\f269'}.zmdi-check-square:before{content:'\f26a'}.zmdi-check:before{content:'\f26b'}.zmdi-circle-o:before{content:'\f26c'}.zmdi-circle:before{content:'\f26d'}.zmdi-dot-circle-alt:before{content:'\f26e'}.zmdi-dot-circle:before{content:'\f26f'}.zmdi-minus-circle-outline:before{content:'\f270'}.zmdi-minus-circle:before{content:'\f271'}.zmdi-minus-square:before{content:'\f272'}.zmdi-minus:before{content:'\f273'}.zmdi-plus-circle-o-duplicate:before{content:'\f274'}.zmdi-plus-circle-o:before{content:'\f275'}.zmdi-plus-circle:before{content:'\f276'}.zmdi-plus-square:before{content:'\f277'}.zmdi-plus:before{content:'\f278'}.zmdi-square-o:before{content:'\f279'}.zmdi-star-circle:before{content:'\f27a'}.zmdi-star-half:before{content:'\f27b'}.zmdi-star-outline:before{content:'\f27c'}.zmdi-star:before{content:'\f27d'}.zmdi-bluetooth-connected:before{content:'\f27e'}.zmdi-bluetooth-off:before{content:'\f27f'}.zmdi-bluetooth-search:before{content:'\f280'}.zmdi-bluetooth-setting:before{content:'\f281'}.zmdi-bluetooth:before{content:'\f282'}.zmdi-camera-add:before{content:'\f283'}.zmdi-camera-alt:before{content:'\f284'}.zmdi-camera-bw:before{content:'\f285'}.zmdi-camera-front:before{content:'\f286'}.zmdi-camera-mic:before{content:'\f287'}.zmdi-camera-party-mode:before{content:'\f288'}.zmdi-camera-rear:before{content:'\f289'}.zmdi-camera-roll:before{content:'\f28a'}.zmdi-camera-switch:before{content:'\f28b'}.zmdi-camera:before{content:'\f28c'}.zmdi-card-alert:before{content:'\f28d'}.zmdi-card-off:before{content:'\f28e'}.zmdi-card-sd:before{content:'\f28f'}.zmdi-card-sim:before{content:'\f290'}.zmdi-desktop-mac:before{content:'\f291'}.zmdi-desktop-windows:before{content:'\f292'}.zmdi-device-hub:before{content:'\f293'}.zmdi-devices-off:before{content:'\f294'}.zmdi-devices:before{content:'\f295'}.zmdi-dock:before{content:'\f296'}.zmdi-floppy:before{content:'\f297'}.zmdi-gamepad:before{content:'\f298'}.zmdi-gps-dot:before{content:'\f299'}.zmdi-gps-off:before{content:'\f29a'}.zmdi-gps:before{content:'\f29b'}.zmdi-headset-mic:before{content:'\f29c'}.zmdi-headset:before{content:'\f29d'}.zmdi-input-antenna:before{content:'\f29e'}.zmdi-input-composite:before{content:'\f29f'}.zmdi-input-hdmi:before{content:'\f2a0'}.zmdi-input-power:before{content:'\f2a1'}.zmdi-input-svideo:before{content:'\f2a2'}.zmdi-keyboard-hide:before{content:'\f2a3'}.zmdi-keyboard:before{content:'\f2a4'}.zmdi-laptop-chromebook:before{content:'\f2a5'}.zmdi-laptop-mac:before{content:'\f2a6'}.zmdi-laptop:before{content:'\f2a7'}.zmdi-mic-off:before{content:'\f2a8'}.zmdi-mic-outline:before{content:'\f2a9'}.zmdi-mic-setting:before{content:'\f2aa'}.zmdi-mic:before{content:'\f2ab'}.zmdi-mouse:before{content:'\f2ac'}.zmdi-network-alert:before{content:'\f2ad'}.zmdi-network-locked:before{content:'\f2ae'}.zmdi-network-off:before{content:'\f2af'}.zmdi-network-outline:before{content:'\f2b0'}.zmdi-network-setting:before{content:'\f2b1'}.zmdi-network:before{content:'\f2b2'}.zmdi-phone-bluetooth:before{content:'\f2b3'}.zmdi-phone-end:before{content:'\f2b4'}.zmdi-phone-forwarded:before{content:'\f2b5'}.zmdi-phone-in-talk:before{content:'\f2b6'}.zmdi-phone-locked:before{content:'\f2b7'}.zmdi-phone-missed:before{content:'\f2b8'}.zmdi-phone-msg:before{content:'\f2b9'}.zmdi-phone-paused:before{content:'\f2ba'}.zmdi-phone-ring:before{content:'\f2bb'}.zmdi-phone-setting:before{content:'\f2bc'}.zmdi-phone-sip:before{content:'\f2bd'}.zmdi-phone:before{content:'\f2be'}.zmdi-portable-wifi-changes:before{content:'\f2bf'}.zmdi-portable-wifi-off:before{content:'\f2c0'}.zmdi-portable-wifi:before{content:'\f2c1'}.zmdi-radio:before{content:'\f2c2'}.zmdi-reader:before{content:'\f2c3'}.zmdi-remote-control-alt:before{content:'\f2c4'}.zmdi-remote-control:before{content:'\f2c5'}.zmdi-router:before{content:'\f2c6'}.zmdi-scanner:before{content:'\f2c7'}.zmdi-smartphone-android:before{content:'\f2c8'}.zmdi-smartphone-download:before{content:'\f2c9'}.zmdi-smartphone-erase:before{content:'\f2ca'}.zmdi-smartphone-info:before{content:'\f2cb'}.zmdi-smartphone-iphone:before{content:'\f2cc'}.zmdi-smartphone-landscape-lock:before{content:'\f2cd'}.zmdi-smartphone-landscape:before{content:'\f2ce'}.zmdi-smartphone-lock:before{content:'\f2cf'}.zmdi-smartphone-portrait-lock:before{content:'\f2d0'}.zmdi-smartphone-ring:before{content:'\f2d1'}.zmdi-smartphone-setting:before{content:'\f2d2'}.zmdi-smartphone-setup:before{content:'\f2d3'}.zmdi-smartphone:before{content:'\f2d4'}.zmdi-speaker:before{content:'\f2d5'}.zmdi-tablet-android:before{content:'\f2d6'}.zmdi-tablet-mac:before{content:'\f2d7'}.zmdi-tablet:before{content:'\f2d8'}.zmdi-tv-alt-play:before{content:'\f2d9'}.zmdi-tv-list:before{content:'\f2da'}.zmdi-tv-play:before{content:'\f2db'}.zmdi-tv:before{content:'\f2dc'}.zmdi-usb:before{content:'\f2dd'}.zmdi-videocam-off:before{content:'\f2de'}.zmdi-videocam-switch:before{content:'\f2df'}.zmdi-videocam:before{content:'\f2e0'}.zmdi-watch:before{content:'\f2e1'}.zmdi-wifi-alt-2:before{content:'\f2e2'}.zmdi-wifi-alt:before{content:'\f2e3'}.zmdi-wifi-info:before{content:'\f2e4'}.zmdi-wifi-lock:before{content:'\f2e5'}.zmdi-wifi-off:before{content:'\f2e6'}.zmdi-wifi-outline:before{content:'\f2e7'}.zmdi-wifi:before{content:'\f2e8'}.zmdi-arrow-left-bottom:before{content:'\f2e9'}.zmdi-arrow-left:before{content:'\f2ea'}.zmdi-arrow-merge:before{content:'\f2eb'}.zmdi-arrow-missed:before{content:'\f2ec'}.zmdi-arrow-right-top:before{content:'\f2ed'}.zmdi-arrow-right:before{content:'\f2ee'}.zmdi-arrow-split:before{content:'\f2ef'}.zmdi-arrows:before{content:'\f2f0'}.zmdi-caret-down-circle:before{content:'\f2f1'}.zmdi-caret-down:before{content:'\f2f2'}.zmdi-caret-left-circle:before{content:'\f2f3'}.zmdi-caret-left:before{content:'\f2f4'}.zmdi-caret-right-circle:before{content:'\f2f5'}.zmdi-caret-right:before{content:'\f2f6'}.zmdi-caret-up-circle:before{content:'\f2f7'}.zmdi-caret-up:before{content:'\f2f8'}.zmdi-chevron-down:before{content:'\f2f9'}.zmdi-chevron-left:before{content:'\f2fa'}.zmdi-chevron-right:before{content:'\f2fb'}.zmdi-chevron-up:before{content:'\f2fc'}.zmdi-forward:before{content:'\f2fd'}.zmdi-long-arrow-down:before{content:'\f2fe'}.zmdi-long-arrow-left:before{content:'\f2ff'}.zmdi-long-arrow-return:before{content:'\f300'}.zmdi-long-arrow-right:before{content:'\f301'}.zmdi-long-arrow-tab:before{content:'\f302'}.zmdi-long-arrow-up:before{content:'\f303'}.zmdi-rotate-ccw:before{content:'\f304'}.zmdi-rotate-cw:before{content:'\f305'}.zmdi-rotate-left:before{content:'\f306'}.zmdi-rotate-right:before{content:'\f307'}.zmdi-square-down:before{content:'\f308'}.zmdi-square-right:before{content:'\f309'}.zmdi-swap-alt:before{content:'\f30a'}.zmdi-swap-vertical-circle:before{content:'\f30b'}.zmdi-swap-vertical:before{content:'\f30c'}.zmdi-swap:before{content:'\f30d'}.zmdi-trending-down:before{content:'\f30e'}.zmdi-trending-flat:before{content:'\f30f'}.zmdi-trending-up:before{content:'\f310'}.zmdi-unfold-less:before{content:'\f311'}.zmdi-unfold-more:before{content:'\f312'}.zmdi-apps:before{content:'\f313'}.zmdi-grid-off:before{content:'\f314'}.zmdi-grid:before{content:'\f315'}.zmdi-view-agenda:before{content:'\f316'}.zmdi-view-array:before{content:'\f317'}.zmdi-view-carousel:before{content:'\f318'}.zmdi-view-column:before{content:'\f319'}.zmdi-view-comfy:before{content:'\f31a'}.zmdi-view-compact:before{content:'\f31b'}.zmdi-view-dashboard:before{content:'\f31c'}.zmdi-view-day:before{content:'\f31d'}.zmdi-view-headline:before{content:'\f31e'}.zmdi-view-list-alt:before{content:'\f31f'}.zmdi-view-list:before{content:'\f320'}.zmdi-view-module:before{content:'\f321'}.zmdi-view-quilt:before{content:'\f322'}.zmdi-view-stream:before{content:'\f323'}.zmdi-view-subtitles:before{content:'\f324'}.zmdi-view-toc:before{content:'\f325'}.zmdi-view-web:before{content:'\f326'}.zmdi-view-week:before{content:'\f327'}.zmdi-widgets:before{content:'\f328'}.zmdi-alarm-check:before{content:'\f329'}.zmdi-alarm-off:before{content:'\f32a'}.zmdi-alarm-plus:before{content:'\f32b'}.zmdi-alarm-snooze:before{content:'\f32c'}.zmdi-alarm:before{content:'\f32d'}.zmdi-calendar-alt:before{content:'\f32e'}.zmdi-calendar-check:before{content:'\f32f'}.zmdi-calendar-close:before{content:'\f330'}.zmdi-calendar-note:before{content:'\f331'}.zmdi-calendar:before{content:'\f332'}.zmdi-time-countdown:before{content:'\f333'}.zmdi-time-interval:before{content:'\f334'}.zmdi-time-restore-setting:before{content:'\f335'}.zmdi-time-restore:before{content:'\f336'}.zmdi-time:before{content:'\f337'}.zmdi-timer-off:before{content:'\f338'}.zmdi-timer:before{content:'\f339'}.zmdi-android-alt:before{content:'\f33a'}.zmdi-android:before{content:'\f33b'}.zmdi-apple:before{content:'\f33c'}.zmdi-behance:before{content:'\f33d'}.zmdi-codepen:before{content:'\f33e'}.zmdi-dribbble:before{content:'\f33f'}.zmdi-dropbox:before{content:'\f340'}.zmdi-evernote:before{content:'\f341'}.zmdi-facebook-box:before{content:'\f342'}.zmdi-facebook:before{content:'\f343'}.zmdi-github-box:before{content:'\f344'}.zmdi-github:before{content:'\f345'}.zmdi-google-drive:before{content:'\f346'}.zmdi-google-earth:before{content:'\f347'}.zmdi-google-glass:before{content:'\f348'}.zmdi-google-maps:before{content:'\f349'}.zmdi-google-pages:before{content:'\f34a'}.zmdi-google-play:before{content:'\f34b'}.zmdi-google-plus-box:before{content:'\f34c'}.zmdi-google-plus:before{content:'\f34d'}.zmdi-google:before{content:'\f34e'}.zmdi-instagram:before{content:'\f34f'}.zmdi-language-css3:before{content:'\f350'}.zmdi-language-html5:before{content:'\f351'}.zmdi-language-javascript:before{content:'\f352'}.zmdi-language-python-alt:before{content:'\f353'}.zmdi-language-python:before{content:'\f354'}.zmdi-lastfm:before{content:'\f355'}.zmdi-linkedin-box:before{content:'\f356'}.zmdi-paypal:before{content:'\f357'}.zmdi-pinterest-box:before{content:'\f358'}.zmdi-pocket:before{content:'\f359'}.zmdi-polymer:before{content:'\f35a'}.zmdi-share:before{content:'\f35b'}.zmdi-stackoverflow:before{content:'\f35c'}.zmdi-steam-square:before{content:'\f35d'}.zmdi-steam:before{content:'\f35e'}.zmdi-twitter-box:before{content:'\f35f'}.zmdi-twitter:before{content:'\f360'}.zmdi-vk:before{content:'\f361'}.zmdi-wikipedia:before{content:'\f362'}.zmdi-windows:before{content:'\f363'}.zmdi-aspect-ratio-alt:before{content:'\f364'}.zmdi-aspect-ratio:before{content:'\f365'}.zmdi-blur-circular:before{content:'\f366'}.zmdi-blur-linear:before{content:'\f367'}.zmdi-blur-off:before{content:'\f368'}.zmdi-blur:before{content:'\f369'}.zmdi-brightness-2:before{content:'\f36a'}.zmdi-brightness-3:before{content:'\f36b'}.zmdi-brightness-4:before{content:'\f36c'}.zmdi-brightness-5:before{content:'\f36d'}.zmdi-brightness-6:before{content:'\f36e'}.zmdi-brightness-7:before{content:'\f36f'}.zmdi-brightness-auto:before{content:'\f370'}.zmdi-brightness-setting:before{content:'\f371'}.zmdi-broken-image:before{content:'\f372'}.zmdi-center-focus-strong:before{content:'\f373'}.zmdi-center-focus-weak:before{content:'\f374'}.zmdi-compare:before{content:'\f375'}.zmdi-crop-16-9:before{content:'\f376'}.zmdi-crop-3-2:before{content:'\f377'}.zmdi-crop-5-4:before{content:'\f378'}.zmdi-crop-7-5:before{content:'\f379'}.zmdi-crop-din:before{content:'\f37a'}.zmdi-crop-free:before{content:'\f37b'}.zmdi-crop-landscape:before{content:'\f37c'}.zmdi-crop-portrait:before{content:'\f37d'}.zmdi-crop-square:before{content:'\f37e'}.zmdi-exposure-alt:before{content:'\f37f'}.zmdi-exposure:before{content:'\f380'}.zmdi-filter-b-and-w:before{content:'\f381'}.zmdi-filter-center-focus:before{content:'\f382'}.zmdi-filter-frames:before{content:'\f383'}.zmdi-filter-tilt-shift:before{content:'\f384'}.zmdi-gradient:before{content:'\f385'}.zmdi-grain:before{content:'\f386'}.zmdi-graphic-eq:before{content:'\f387'}.zmdi-hdr-off:before{content:'\f388'}.zmdi-hdr-strong:before{content:'\f389'}.zmdi-hdr-weak:before{content:'\f38a'}.zmdi-hdr:before{content:'\f38b'}.zmdi-iridescent:before{content:'\f38c'}.zmdi-leak-off:before{content:'\f38d'}.zmdi-leak:before{content:'\f38e'}.zmdi-looks:before{content:'\f38f'}.zmdi-loupe:before{content:'\f390'}.zmdi-panorama-horizontal:before{content:'\f391'}.zmdi-panorama-vertical:before{content:'\f392'}.zmdi-panorama-wide-angle:before{content:'\f393'}.zmdi-photo-size-select-large:before{content:'\f394'}.zmdi-photo-size-select-small:before{content:'\f395'}.zmdi-picture-in-picture:before{content:'\f396'}.zmdi-slideshow:before{content:'\f397'}.zmdi-texture:before{content:'\f398'}.zmdi-tonality:before{content:'\f399'}.zmdi-vignette:before{content:'\f39a'}.zmdi-wb-auto:before{content:'\f39b'}.zmdi-eject-alt:before{content:'\f39c'}.zmdi-eject:before{content:'\f39d'}.zmdi-equalizer:before{content:'\f39e'}.zmdi-fast-forward:before{content:'\f39f'}.zmdi-fast-rewind:before{content:'\f3a0'}.zmdi-forward-10:before{content:'\f3a1'}.zmdi-forward-30:before{content:'\f3a2'}.zmdi-forward-5:before{content:'\f3a3'}.zmdi-hearing:before{content:'\f3a4'}.zmdi-pause-circle-outline:before{content:'\f3a5'}.zmdi-pause-circle:before{content:'\f3a6'}.zmdi-pause:before{content:'\f3a7'}.zmdi-play-circle-outline:before{content:'\f3a8'}.zmdi-play-circle:before{content:'\f3a9'}.zmdi-play:before{content:'\f3aa'}.zmdi-playlist-audio:before{content:'\f3ab'}.zmdi-playlist-plus:before{content:'\f3ac'}.zmdi-repeat-one:before{content:'\f3ad'}.zmdi-repeat:before{content:'\f3ae'}.zmdi-replay-10:before{content:'\f3af'}.zmdi-replay-30:before{content:'\f3b0'}.zmdi-replay-5:before{content:'\f3b1'}.zmdi-replay:before{content:'\f3b2'}.zmdi-shuffle:before{content:'\f3b3'}.zmdi-skip-next:before{content:'\f3b4'}.zmdi-skip-previous:before{content:'\f3b5'}.zmdi-stop:before{content:'\f3b6'}.zmdi-surround-sound:before{content:'\f3b7'}.zmdi-tune:before{content:'\f3b8'}.zmdi-volume-down:before{content:'\f3b9'}.zmdi-volume-mute:before{content:'\f3ba'}.zmdi-volume-off:before{content:'\f3bb'}.zmdi-volume-up:before{content:'\f3bc'}.zmdi-n-1-square:before{content:'\f3bd'}.zmdi-n-2-square:before{content:'\f3be'}.zmdi-n-3-square:before{content:'\f3bf'}.zmdi-n-4-square:before{content:'\f3c0'}.zmdi-n-5-square:before{content:'\f3c1'}.zmdi-n-6-square:before{content:'\f3c2'}.zmdi-neg-1:before{content:'\f3c3'}.zmdi-neg-2:before{content:'\f3c4'}.zmdi-plus-1:before{content:'\f3c5'}.zmdi-plus-2:before{content:'\f3c6'}.zmdi-sec-10:before{content:'\f3c7'}.zmdi-sec-3:before{content:'\f3c8'}.zmdi-zero:before{content:'\f3c9'}.zmdi-airline-seat-flat-angled:before{content:'\f3ca'}.zmdi-airline-seat-flat:before{content:'\f3cb'}.zmdi-airline-seat-individual-suite:before{content:'\f3cc'}.zmdi-airline-seat-legroom-extra:before{content:'\f3cd'}.zmdi-airline-seat-legroom-normal:before{content:'\f3ce'}.zmdi-airline-seat-legroom-reduced:before{content:'\f3cf'}.zmdi-airline-seat-recline-extra:before{content:'\f3d0'}.zmdi-airline-seat-recline-normal:before{content:'\f3d1'}.zmdi-airplay:before{content:'\f3d2'}.zmdi-closed-caption:before{content:'\f3d3'}.zmdi-confirmation-number:before{content:'\f3d4'}.zmdi-developer-board:before{content:'\f3d5'}.zmdi-disc-full:before{content:'\f3d6'}.zmdi-explicit:before{content:'\f3d7'}.zmdi-flight-land:before{content:'\f3d8'}.zmdi-flight-takeoff:before{content:'\f3d9'}.zmdi-flip-to-back:before{content:'\f3da'}.zmdi-flip-to-front:before{content:'\f3db'}.zmdi-group-work:before{content:'\f3dc'}.zmdi-hd:before{content:'\f3dd'}.zmdi-hq:before{content:'\f3de'}.zmdi-markunread-mailbox:before{content:'\f3df'}.zmdi-memory:before{content:'\f3e0'}.zmdi-nfc:before{content:'\f3e1'}.zmdi-play-for-work:before{content:'\f3e2'}.zmdi-power-input:before{content:'\f3e3'}.zmdi-present-to-all:before{content:'\f3e4'}.zmdi-satellite:before{content:'\f3e5'}.zmdi-tap-and-play:before{content:'\f3e6'}.zmdi-vibration:before{content:'\f3e7'}.zmdi-voicemail:before{content:'\f3e8'}.zmdi-group:before{content:'\f3e9'}.zmdi-rss:before{content:'\f3ea'}.zmdi-shape:before{content:'\f3eb'}.zmdi-spinner:before{content:'\f3ec'}.zmdi-ungroup:before{content:'\f3ed'}.zmdi-500px:before{content:'\f3ee'}.zmdi-8tracks:before{content:'\f3ef'}.zmdi-amazon:before{content:'\f3f0'}.zmdi-blogger:before{content:'\f3f1'}.zmdi-delicious:before{content:'\f3f2'}.zmdi-disqus:before{content:'\f3f3'}.zmdi-flattr:before{content:'\f3f4'}.zmdi-flickr:before{content:'\f3f5'}.zmdi-github-alt:before{content:'\f3f6'}.zmdi-google-old:before{content:'\f3f7'}.zmdi-linkedin:before{content:'\f3f8'}.zmdi-odnoklassniki:before{content:'\f3f9'}.zmdi-outlook:before{content:'\f3fa'}.zmdi-paypal-alt:before{content:'\f3fb'}.zmdi-pinterest:before{content:'\f3fc'}.zmdi-playstation:before{content:'\f3fd'}.zmdi-reddit:before{content:'\f3fe'}.zmdi-skype:before{content:'\f3ff'}.zmdi-slideshare:before{content:'\f400'}.zmdi-soundcloud:before{content:'\f401'}.zmdi-tumblr:before{content:'\f402'}.zmdi-twitch:before{content:'\f403'}.zmdi-vimeo:before{content:'\f404'}.zmdi-whatsapp:before{content:'\f405'}.zmdi-xbox:before{content:'\f406'}.zmdi-yahoo:before{content:'\f407'}.zmdi-youtube-play:before{content:'\f408'}.zmdi-youtube:before{content:'\f409'}.zmdi-import-export:before{content:'\f30c'}.zmdi-swap-vertical-:before{content:'\f30c'}.zmdi-airplanemode-inactive:before{content:'\f102'}.zmdi-airplanemode-active:before{content:'\f103'}.zmdi-rate-review:before{content:'\f103'}.zmdi-comment-sign:before{content:'\f25a'}.zmdi-network-warning:before{content:'\f2ad'}.zmdi-shopping-cart-add:before{content:'\f1ca'}.zmdi-file-add:before{content:'\f221'}.zmdi-network-wifi-scan:before{content:'\f2e4'}.zmdi-collection-add:before{content:'\f14e'}.zmdi-format-playlist-add:before{content:'\f3ac'}.zmdi-format-queue-music:before{content:'\f3ab'}.zmdi-plus-box:before{content:'\f277'}.zmdi-tag-backspace:before{content:'\f1d9'}.zmdi-alarm-add:before{content:'\f32b'}.zmdi-battery-charging:before{content:'\f114'}.zmdi-daydream-setting:before{content:'\f217'}.zmdi-more-horiz:before{content:'\f19c'}.zmdi-book-photo:before{content:'\f11b'}.zmdi-incandescent:before{content:'\f189'}.zmdi-wb-iridescent:before{content:'\f38c'}.zmdi-calendar-remove:before{content:'\f330'}.zmdi-refresh-sync-disabled:before{content:'\f1b7'}.zmdi-refresh-sync-problem:before{content:'\f1b6'}.zmdi-crop-original:before{content:'\f17e'}.zmdi-power-off:before{content:'\f1af'}.zmdi-power-off-setting:before{content:'\f1ae'}.zmdi-leak-remove:before{content:'\f38d'}.zmdi-star-border:before{content:'\f27c'}.zmdi-brightness-low:before{content:'\f36d'}.zmdi-brightness-medium:before{content:'\f36e'}.zmdi-brightness-high:before{content:'\f36f'}.zmdi-smartphone-portrait:before{content:'\f2d4'}.zmdi-live-tv:before{content:'\f2d9'}.zmdi-format-textdirection-l-to-r:before{content:'\f249'}.zmdi-format-textdirection-r-to-l:before{content:'\f24a'}.zmdi-arrow-back:before{content:'\f2ea'}.zmdi-arrow-forward:before{content:'\f2ee'}.zmdi-arrow-in:before{content:'\f2e9'}.zmdi-arrow-out:before{content:'\f2ed'}.zmdi-rotate-90-degrees-ccw:before{content:'\f304'}.zmdi-adb:before{content:'\f33a'}.zmdi-network-wifi:before{content:'\f2e8'}.zmdi-network-wifi-alt:before{content:'\f2e3'}.zmdi-network-wifi-lock:before{content:'\f2e5'}.zmdi-network-wifi-off:before{content:'\f2e6'}.zmdi-network-wifi-outline:before{content:'\f2e7'}.zmdi-network-wifi-info:before{content:'\f2e4'}.zmdi-layers-clear:before{content:'\f18b'}.zmdi-colorize:before{content:'\f15d'}.zmdi-format-paint:before{content:'\f1ba'}.zmdi-format-quote:before{content:'\f1b2'}.zmdi-camera-monochrome-photos:before{content:'\f285'}.zmdi-sort-by-alpha:before{content:'\f1cf'}.zmdi-folder-shared:before{content:'\f225'}.zmdi-folder-special:before{content:'\f226'}.zmdi-comment-dots:before{content:'\f260'}.zmdi-reorder:before{content:'\f31e'}.zmdi-dehaze:before{content:'\f197'}.zmdi-sort:before{content:'\f1ce'}.zmdi-pages:before{content:'\f34a'}.zmdi-stack-overflow:before{content:'\f35c'}.zmdi-calendar-account:before{content:'\f204'}.zmdi-paste:before{content:'\f109'}.zmdi-cut:before{content:'\f1bc'}.zmdi-save:before{content:'\f297'}.zmdi-smartphone-code:before{content:'\f139'}.zmdi-directions-bike:before{content:'\f117'}.zmdi-directions-boat:before{content:'\f11a'}.zmdi-directions-bus:before{content:'\f121'}.zmdi-directions-car:before{content:'\f125'}.zmdi-directions-railway:before{content:'\f1b3'}.zmdi-directions-run:before{content:'\f215'}.zmdi-directions-subway:before{content:'\f1d5'}.zmdi-directions-walk:before{content:'\f216'}.zmdi-local-hotel:before{content:'\f178'}.zmdi-local-activity:before{content:'\f1df'}.zmdi-local-play:before{content:'\f1df'}.zmdi-local-airport:before{content:'\f103'}.zmdi-local-atm:before{content:'\f198'}.zmdi-local-bar:before{content:'\f137'}.zmdi-local-cafe:before{content:'\f13b'}.zmdi-local-car-wash:before{content:'\f124'}.zmdi-local-convenience-store:before{content:'\f1d3'}.zmdi-local-dining:before{content:'\f153'}.zmdi-local-drink:before{content:'\f157'}.zmdi-local-florist:before{content:'\f168'}.zmdi-local-gas-station:before{content:'\f16f'}.zmdi-local-grocery-store:before{content:'\f1cb'}.zmdi-local-hospital:before{content:'\f177'}.zmdi-local-laundry-service:before{content:'\f1e9'}.zmdi-local-library:before{content:'\f18d'}.zmdi-local-mall:before{content:'\f195'}.zmdi-local-movies:before{content:'\f19d'}.zmdi-local-offer:before{content:'\f187'}.zmdi-local-parking:before{content:'\f1a5'}.zmdi-local-parking:before{content:'\f1a5'}.zmdi-local-pharmacy:before{content:'\f176'}.zmdi-local-phone:before{content:'\f2be'}.zmdi-local-pizza:before{content:'\f1ac'}.zmdi-local-post-office:before{content:'\f15a'}.zmdi-local-printshop:before{content:'\f1b0'}.zmdi-local-see:before{content:'\f28c'}.zmdi-local-shipping:before{content:'\f1e6'}.zmdi-local-store:before{content:'\f1d4'}.zmdi-local-taxi:before{content:'\f123'}.zmdi-local-wc:before{content:'\f211'}.zmdi-my-location:before{content:'\f299'}.zmdi-directions:before{content:'\f1e7'} \ No newline at end of file diff --git a/web/libs/css/material.style.css b/web/libs/css/material.style.css index 2cb8242..e971dee 100644 --- a/web/libs/css/material.style.css +++ b/web/libs/css/material.style.css @@ -608,15 +608,6 @@ _:-ms-input-placeholder, :root .demo-graph { opacity: 0.46; border-radius: 2px; } -.social-btn__twitter { - background-image: url('https://www.gstatic.com/images/icons/material/system/2x/post_twitter_black_24dp.png'); -} -.social-btn__blogger { - background-image: url('https://www.gstatic.com/images/icons/material/system/2x/post_facebook_black_24dp.png'); -} -.social-btn__gplus { - background-image: url('https://www.gstatic.com/images/icons/material/system/2x/post_gplus_black_24dp.png'); -} .social-btn__share { color: rgba(0, 0, 0, 0.54); background: transparent; diff --git a/web/libs/css/montserrat.css b/web/libs/css/montserrat.css new file mode 100644 index 0000000..62905ea --- /dev/null +++ b/web/libs/css/montserrat.css @@ -0,0 +1,48 @@ +/* Generated by Font Squirrel (http://www.fontsquirrel.com) on February 2, 2016 */ +/* Downloaded from https://github.com/Antpolis/Montserrat-Font */ + + +@font-face { + font-family: 'montserratbold'; + src: url('../fonts/montserrat-bold.eot'); + src: url('../fonts/montserrat-bold.eot?#iefix') format('embedded-opentype'), + url('../fonts/montserrat-bold.woff2') format('woff2'), + url('../fonts/montserrat-bold.woff') format('woff'), + url('../fonts/montserrat-bold.ttf') format('truetype'), + url('../fonts/montserrat-bold.svg#montserratbold') format('svg'); + font-weight: normal; + font-style: normal; + +} + + + + +@font-face { + font-family: 'montserratlight'; + src: url('../fonts/montserrat-light.eot'); + src: url('../fonts/montserrat-light.eot?#iefix') format('embedded-opentype'), + url('../fonts/montserrat-light.woff2') format('woff2'), + url('../fonts/montserrat-light.woff') format('woff'), + url('../fonts/montserrat-light.ttf') format('truetype'), + url('../fonts/montserrat-light.svg#montserratlight') format('svg'); + font-weight: normal; + font-style: normal; + +} + + + + +@font-face { + font-family: 'montserratregular'; + src: url('../fonts/montserrat-regular.eot'); + src: url('../fonts/montserrat-regular.eot?#iefix') format('embedded-opentype'), + url('../fonts/montserrat-regular.woff2') format('woff2'), + url('../fonts/montserrat-regular.woff') format('woff'), + url('../fonts/montserrat-regular.ttf') format('truetype'), + url('../fonts/montserrat-regular.svg#montserratregular') format('svg'); + font-weight: normal; + font-style: normal; + +} diff --git a/web/libs/css/poseidon.css b/web/libs/css/poseidon.css deleted file mode 100644 index e3285fe..0000000 --- a/web/libs/css/poseidon.css +++ /dev/null @@ -1,246 +0,0 @@ -/* bug: pseudo selectors for :fullscreen, :-moz-full-screen, and :-webkit-full-screen cannot be grouped together */ - -/* styles for container div */ - -div.mse-container { - position: relative; - float: left; - display: inline-block; - background: linear-gradient(black, grey, black); - border: 1px solid white; -} - -div.mse-container:fullscreen { - width: 100%; - height: 100%; -} - -div.mse-container:-ms-fullscreen { - width: 100%; - height: 100%; -} - -div.mse-container:-moz-full-screen { - width: 100%; - height: 100%; -} - -div.mse-container:-webkit-full-screen { - width: 100%; - height: 100%; -} - -div.mse-container.disabled { - pointer-events: none; - opacity: 0.4; -} - -/* styles for video */ - -video.mse-video { - pointer-events: none; - cursor: none; -} - -div.mse-container:fullscreen video { - width: 100%; - height: 100%; -} - -div.mse-container:-ms-fullscreen video { - width: 100%; - height: 100%; -} - -div.mse-container:-moz-full-screen video { - width: 100%; - height: 100%; -} - -div.mse-container:-webkit-full-screen video { - width: 100%; - height: 100%; -} - -/* styles for controls div */ - -div.mse-controls { - position: absolute; - background: black; - border: 1px solid white; - left: 5px; - right: 5px; - bottom: 5px; - padding: 3px; - border-radius: 5px; - opacity: 0; -} - -div.mse-controls:hover { - opacity: 0.8; -} - -div.mse-container:fullscreen div { - border: 2px solid white; - left: 10px; - right: 10px; - bottom: 10px; - padding: 6px; - border-radius: 10px; -} - -div.mse-container:-ms-fullscreen div { - border: 2px solid white; - left: 10px; - right: 10px; - bottom: 10px; - padding: 6px; - border-radius: 10px; -} - -div.mse-container:-moz-full-screen div { - border: 2px solid white; - left: 10px; - right: 10px; - bottom: 10px; - padding: 6px; - border-radius: 10px; -} - -div.mse-container:-webkit-full-screen div { - border: 2px solid white; - left: 10px; - right: 10px; - bottom: 10px; - padding: 6px; - border-radius: 10px; -} - -/* styles for buttons */ - -div.mse-container button { - background-color: transparent; - border: none; - outline: none; - opacity: 0.8; - cursor: pointer; - color: white; - font-size: 16px; - margin: 1px; -} - -div.mse-container button:hover { - opacity: 1; -} - -div.mse-container button:active { - opacity: 0.6; -} - -div.mse-container:fullscreen button { - font-size: 32px; -} - -div.mse-container:-ms-fullscreen button { - font-size: 32px; -} - -div.mse-container:-moz-full-screen button { - font-size: 32px; -} - -div.mse-container:-webkit-full-screen button { - font-size: 32px; -} - -button.mse-start, button.mse-stop, button.mse-snapshot { - float: left; -} - -button.mse-fullscreen, button.mse-cycle { - float: right; -} - -button.mse-start:before { - font-family: FontAwesome; - content: "\f04b"; -} - -button.mse-stop:before { - font-family: FontAwesome; - content: "\f04d"; -} - -button.mse-snapshot:before { - font-family: FontAwesome; - content: "\f030"; -} - -button.mse-fullscreen:before { - font-family: FontAwesome; - content: "\f065"; -} - -button.mse-stop.cycling { - pointer-events: none; - cursor: none; - opacity: 0.2; -} - -div.mse-container:fullscreen button.mse-fullscreen:before { - font-family: FontAwesome; - content: "\f066"; -} - -div.mse-container:-ms-fullscreen button.mse-fullscreen:before { - font-family: FontAwesome; - content: "\f066"; -} - -div.mse-container:-moz-full-screen button.mse-fullscreen:before { - font-family: FontAwesome; - content: "\f066"; -} - -div.mse-container:-webkit-full-screen button.mse-fullscreen:before { - font-family: FontAwesome; - content: "\f066"; -} - -button.mse-cycle:before { - font-family: FontAwesome; - content: "\f021";/* other cycle icon options : f021 f110 f01e f1ce */ -} - -button.mse-cycle.animated { - -webkit-animation: spin 5s linear infinite; - animation: spin 5s linear infinite; -} - -/* SPIN animation for cycle button */ - -@-webkit-keyframes spin { - 0% { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - } - - 100% { - -webkit-transform: rotate(359deg); - transform: rotate(359deg); - } -} - -@keyframes spin { - 0% { - -webkit-transform: rotate(0deg); - -ms-transform: rotate(0deg); - transform: rotate(0deg); - } - - 100% { - -webkit-transform: rotate(359deg); - -ms-transform: rotate(359deg); - transform: rotate(359deg); - } -} \ No newline at end of file diff --git a/web/libs/css/roboto.css b/web/libs/css/roboto.css new file mode 100644 index 0000000..455ad1b --- /dev/null +++ b/web/libs/css/roboto.css @@ -0,0 +1,106 @@ +/* BEGIN Thin */ +@font-face { + font-family: Roboto; + src: url("../fonts/Thin/Roboto-Thin.woff2?v=2.137") format("woff2"), url("../fonts/Thin/Roboto-Thin.woff?v=2.137") format("woff"); + font-weight: 100; + font-style: normal; } +/* END Thin */ +/* BEGIN Thin Italic */ +@font-face { + font-family: Roboto; + src: url("../fonts/ThinItalic/Roboto-ThinItalic.woff2?v=2.137") format("woff2"), url("../fonts/ThinItalic/Roboto-ThinItalic.woff?v=2.137") format("woff"); + font-weight: 100; + font-style: italic; } +/* END Thin Italic */ +/* BEGIN Light */ +@font-face { + font-family: Roboto; + src: url("../fonts/Light/Roboto-Light.woff2?v=2.137") format("woff2"), url("../fonts/Light/Roboto-Light.woff?v=2.137") format("woff"); + font-weight: 300; + font-style: normal; } +/* END Light */ +/* BEGIN Light Italic */ +@font-face { + font-family: Roboto; + src: url("../fonts/LightItalic/Roboto-LightItalic.woff2?v=2.137") format("woff2"), url("../fonts/LightItalic/Roboto-LightItalic.woff?v=2.137") format("woff"); + font-weight: 300; + font-style: italic; } +/* END Light Italic */ +/* BEGIN Regular */ +@font-face { + font-family: Roboto; + src: url("../fonts/Regular/Roboto-Regular.woff2?v=2.137") format("woff2"), url("../fonts/Regular/Roboto-Regular.woff?v=2.137") format("woff"); + font-weight: 400; + font-style: normal; } +@font-face { + font-family: Roboto; + src: url("../fonts/Regular/Roboto-Regular.woff2?v=2.137") format("woff2"), url("../fonts/Regular/Roboto-Regular.woff?v=2.137") format("woff"); + font-weight: normal; + font-style: normal; } +/* END Regular */ +/* BEGIN Italic */ +@font-face { + font-family: Roboto; + src: url("../fonts/Italic/Roboto-Italic.woff2?v=2.137") format("woff2"), url("../fonts/Italic/Roboto-Italic.woff?v=2.137") format("woff"); + font-weight: 400; + font-style: italic; } +@font-face { + font-family: Roboto; + src: url("../fonts/Italic/Roboto-Italic.woff2?v=2.137") format("woff2"), url("../fonts/Italic/Roboto-Italic.woff?v=2.137") format("woff"); + font-weight: normal; + font-style: italic; } +/* END Italic */ +/* BEGIN Medium */ +@font-face { + font-family: Roboto; + src: url("../fonts/Medium/Roboto-Medium.woff2?v=2.137") format("woff2"), url("../fonts/Medium/Roboto-Medium.woff?v=2.137") format("woff"); + font-weight: 500; + font-style: normal; } +/* END Medium */ +/* BEGIN Medium Italic */ +@font-face { + font-family: Roboto; + src: url("../fonts/MediumItalic/Roboto-MediumItalic.woff2?v=2.137") format("woff2"), url("../fonts/MediumItalic/Roboto-MediumItalic.woff?v=2.137") format("woff"); + font-weight: 500; + font-style: italic; } +/* END Medium Italic */ +/* BEGIN Bold */ +@font-face { + font-family: Roboto; + src: url("../fonts/Bold/Roboto-Bold.woff2?v=2.137") format("woff2"), url("../fonts/Bold/Roboto-Bold.woff?v=2.137") format("woff"); + font-weight: 700; + font-style: normal; } +@font-face { + font-family: Roboto; + src: url("../fonts/Bold/Roboto-Bold.woff2?v=2.137") format("woff2"), url("../fonts/Bold/Roboto-Bold.woff?v=2.137") format("woff"); + font-weight: bold; + font-style: normal; } +/* END Bold */ +/* BEGIN Bold Italic */ +@font-face { + font-family: Roboto; + src: url("../fonts/BoldItalic/Roboto-BoldItalic.woff2?v=2.137") format("woff2"), url("../fonts/BoldItalic/Roboto-BoldItalic.woff?v=2.137") format("woff"); + font-weight: 700; + font-style: italic; } +@font-face { + font-family: Roboto; + src: url("../fonts/BoldItalic/Roboto-BoldItalic.woff2?v=2.137") format("woff2"), url("../fonts/BoldItalic/Roboto-BoldItalic.woff?v=2.137") format("woff"); + font-weight: bold; + font-style: italic; } +/* END Bold Italic */ +/* BEGIN Black */ +@font-face { + font-family: Roboto; + src: url("../fonts/Black/Roboto-Black.woff2?v=2.137") format("woff2"), url("../fonts/Black/Roboto-Black.woff?v=2.137") format("woff"); + font-weight: 900; + font-style: normal; } +/* END Black */ +/* BEGIN Black Italic */ +@font-face { + font-family: Roboto; + src: url("../fonts/BlackItalic/Roboto-BlackItalic.woff2?v=2.137") format("woff2"), url("../fonts/BlackItalic/Roboto-BlackItalic.woff?v=2.137") format("woff"); + font-weight: 900; + font-style: italic; } +/* END Black Italic */ + +/*# sourceMappingURL=roboto.css.map */ diff --git a/web/libs/css/roboto.css.map b/web/libs/css/roboto.css.map new file mode 100644 index 0000000..85321e0 --- /dev/null +++ b/web/libs/css/roboto.css.map @@ -0,0 +1,7 @@ +{ +"version": 3, +"mappings": "AAAA,gBAAgB;AAChB,UAKC;EAJA,WAAW,EAAE,MAAM;ECDnB,GAAG,EAAE,0HAC6F;EDElG,WAAW,EAAE,GAAG;EAChB,UAAU,EAAE,MAAM;AAEnB,cAAc;AEPd,uBAAuB;AACvB,UAKC;EAJA,WAAW,EAAE,MAAM;EDDnB,GAAG,EAAE,kJAC6F;ECElG,WAAW,EAAE,GAAG;EAChB,UAAU,EAAE,MAAM;AAEnB,qBAAqB;ACPrB,iBAAiB;AACjB,UAKC;EAJA,WAAW,EAAE,MAAM;EFDnB,GAAG,EAAE,8HAC6F;EEElG,WAAW,EAAE,GAAG;EAChB,UAAU,EAAE,MAAM;AAEnB,eAAe;ACPf,wBAAwB;AACxB,UAKC;EAJA,WAAW,EAAE,MAAM;EHDnB,GAAG,EAAE,sJAC6F;EGElG,WAAW,EAAE,GAAG;EAChB,UAAU,EAAE,MAAM;AAEnB,sBAAsB;ACPtB,mBAAmB;AACnB,UAKC;EAJA,WAAW,EAAE,MAAM;EJDnB,GAAG,EAAE,sIAC6F;EIElG,WAAW,EAAE,GAAG;EAChB,UAAU,EAAE,MAAM;AAEnB,UAKC;EAJA,WAAW,EAAE,MAAM;EJPnB,GAAG,EAAE,sIAC6F;EIQlG,WAAW,EAAE,MAAM;EACnB,UAAU,EAAE,MAAM;AAEnB,iBAAiB;ACbjB,kBAAkB;AAClB,UAKC;EAJA,WAAW,EAAE,MAAM;ELDnB,GAAG,EAAE,kIAC6F;EKElG,WAAW,EAAE,GAAG;EAChB,UAAU,EAAE,MAAM;AAEnB,UAKC;EAJA,WAAW,EAAE,MAAM;ELPnB,GAAG,EAAE,kIAC6F;EKQlG,WAAW,EAAE,MAAM;EACnB,UAAU,EAAE,MAAM;AAEnB,gBAAgB;ACbhB,kBAAkB;AAClB,UAKC;EAJA,WAAW,EAAE,MAAM;ENDnB,GAAG,EAAE,kIAC6F;EMElG,WAAW,EAAE,GAAG;EAChB,UAAU,EAAE,MAAM;AAEnB,gBAAgB;ACPhB,yBAAyB;AACzB,UAKC;EAJA,WAAW,EAAE,MAAM;EPDnB,GAAG,EAAE,0JAC6F;EOElG,WAAW,EAAE,GAAG;EAChB,UAAU,EAAE,MAAM;AAEnB,uBAAuB;ACPvB,gBAAgB;AAChB,UAKC;EAJA,WAAW,EAAE,MAAM;ERDnB,GAAG,EAAE,0HAC6F;EQElG,WAAW,EAAE,GAAG;EAChB,UAAU,EAAE,MAAM;AAEnB,UAKC;EAJA,WAAW,EAAE,MAAM;ERPnB,GAAG,EAAE,0HAC6F;EQQlG,WAAW,EAAE,IAAI;EACjB,UAAU,EAAE,MAAM;AAEnB,cAAc;ACbd,uBAAuB;AACvB,UAKC;EAJA,WAAW,EAAE,MAAM;ETDnB,GAAG,EAAE,kJAC6F;ESElG,WAAW,EAAE,GAAG;EAChB,UAAU,EAAE,MAAM;AAEnB,UAKC;EAJA,WAAW,EAAE,MAAM;ETPnB,GAAG,EAAE,kJAC6F;ESQlG,WAAW,EAAE,IAAI;EACjB,UAAU,EAAE,MAAM;AAEnB,qBAAqB;ACbrB,iBAAiB;AACjB,UAKC;EAJA,WAAW,EAAE,MAAM;EVDnB,GAAG,EAAE,8HAC6F;EUElG,WAAW,EAAE,GAAG;EAChB,UAAU,EAAE,MAAM;AAEnB,eAAe;ACPf,wBAAwB;AACxB,UAKC;EAJA,WAAW,EAAE,MAAM;EXDnB,GAAG,EAAE,sJAC6F;EWElG,WAAW,EAAE,GAAG;EAChB,UAAU,EAAE,MAAM;AAEnB,sBAAsB", +"sources": ["../sass/_Thin.scss","../sass/_mixins.scss","../sass/_ThinItalic.scss","../sass/_Light.scss","../sass/_LightItalic.scss","../sass/_Regular.scss","../sass/_Italic.scss","../sass/_Medium.scss","../sass/_MediumItalic.scss","../sass/_Bold.scss","../sass/_BoldItalic.scss","../sass/_Black.scss","../sass/_BlackItalic.scss"], +"names": [], +"file": "roboto.css" +} diff --git a/web/libs/css/roboto.less b/web/libs/css/roboto.less new file mode 100644 index 0000000..ee48cd3 --- /dev/null +++ b/web/libs/css/roboto.less @@ -0,0 +1,15 @@ +@import (reference) "../less/_variables"; +@import (reference) "../less/_mixins"; + +@import "../less/_Thin"; +@import "../less/_ThinItalic"; +@import "../less/_Light"; +@import "../less/_LightItalic"; +@import "../less/_Regular"; +@import "../less/_Italic"; +@import "../less/_Medium"; +@import "../less/_MediumItalic"; +@import "../less/_Bold"; +@import "../less/_BoldItalic"; +@import "../less/_Black"; +@import "../less/_BlackItalic"; diff --git a/web/libs/css/roboto.scss b/web/libs/css/roboto.scss new file mode 100644 index 0000000..5d2a891 --- /dev/null +++ b/web/libs/css/roboto.scss @@ -0,0 +1,15 @@ +@import "../sass/variables"; +@import "../sass/mixins"; + +@import "../sass/Thin"; +@import "../sass/ThinItalic"; +@import "../sass/Light"; +@import "../sass/LightItalic"; +@import "../sass/Regular"; +@import "../sass/Italic"; +@import "../sass/Medium"; +@import "../sass/MediumItalic"; +@import "../sass/Bold"; +@import "../sass/BoldItalic"; +@import "../sass/Black"; +@import "../sass/BlackItalic"; diff --git a/web/libs/fonts/Black/Roboto-Black.ttf b/web/libs/fonts/Black/Roboto-Black.ttf new file mode 100644 index 0000000..689fe5c Binary files /dev/null and b/web/libs/fonts/Black/Roboto-Black.ttf differ diff --git a/web/libs/fonts/Black/Roboto-Black.woff b/web/libs/fonts/Black/Roboto-Black.woff new file mode 100644 index 0000000..1fe59ba Binary files /dev/null and b/web/libs/fonts/Black/Roboto-Black.woff differ diff --git a/web/libs/fonts/Black/Roboto-Black.woff2 b/web/libs/fonts/Black/Roboto-Black.woff2 new file mode 100644 index 0000000..41186d0 Binary files /dev/null and b/web/libs/fonts/Black/Roboto-Black.woff2 differ diff --git a/web/libs/fonts/BlackItalic/Roboto-BlackItalic.ttf b/web/libs/fonts/BlackItalic/Roboto-BlackItalic.ttf new file mode 100644 index 0000000..0b4e0ee Binary files /dev/null and b/web/libs/fonts/BlackItalic/Roboto-BlackItalic.ttf differ diff --git a/web/libs/fonts/BlackItalic/Roboto-BlackItalic.woff b/web/libs/fonts/BlackItalic/Roboto-BlackItalic.woff new file mode 100644 index 0000000..532150f Binary files /dev/null and b/web/libs/fonts/BlackItalic/Roboto-BlackItalic.woff differ diff --git a/web/libs/fonts/BlackItalic/Roboto-BlackItalic.woff2 b/web/libs/fonts/BlackItalic/Roboto-BlackItalic.woff2 new file mode 100644 index 0000000..df3c3f4 Binary files /dev/null and b/web/libs/fonts/BlackItalic/Roboto-BlackItalic.woff2 differ diff --git a/web/libs/fonts/Bold/Roboto-Bold.ttf b/web/libs/fonts/Bold/Roboto-Bold.ttf new file mode 100644 index 0000000..d3f01ad Binary files /dev/null and b/web/libs/fonts/Bold/Roboto-Bold.ttf differ diff --git a/web/libs/fonts/Bold/Roboto-Bold.woff b/web/libs/fonts/Bold/Roboto-Bold.woff new file mode 100644 index 0000000..83a333a Binary files /dev/null and b/web/libs/fonts/Bold/Roboto-Bold.woff differ diff --git a/web/libs/fonts/Bold/Roboto-Bold.woff2 b/web/libs/fonts/Bold/Roboto-Bold.woff2 new file mode 100644 index 0000000..76817cc Binary files /dev/null and b/web/libs/fonts/Bold/Roboto-Bold.woff2 differ diff --git a/web/libs/fonts/BoldItalic/Roboto-BoldItalic.ttf b/web/libs/fonts/BoldItalic/Roboto-BoldItalic.ttf new file mode 100644 index 0000000..41cc1e7 Binary files /dev/null and b/web/libs/fonts/BoldItalic/Roboto-BoldItalic.ttf differ diff --git a/web/libs/fonts/BoldItalic/Roboto-BoldItalic.woff b/web/libs/fonts/BoldItalic/Roboto-BoldItalic.woff new file mode 100644 index 0000000..7f8c135 Binary files /dev/null and b/web/libs/fonts/BoldItalic/Roboto-BoldItalic.woff differ diff --git a/web/libs/fonts/BoldItalic/Roboto-BoldItalic.woff2 b/web/libs/fonts/BoldItalic/Roboto-BoldItalic.woff2 new file mode 100644 index 0000000..45c9ef7 Binary files /dev/null and b/web/libs/fonts/BoldItalic/Roboto-BoldItalic.woff2 differ diff --git a/web/libs/fonts/COPYRIGHT.txt b/web/libs/fonts/COPYRIGHT.txt new file mode 100644 index 0000000..a7ef699 --- /dev/null +++ b/web/libs/fonts/COPYRIGHT.txt @@ -0,0 +1 @@ +Copyright 2011 Google Inc. All Rights Reserved. \ No newline at end of file diff --git a/web/libs/fonts/Italic/Roboto-Italic.ttf b/web/libs/fonts/Italic/Roboto-Italic.ttf new file mode 100644 index 0000000..6a1cee5 Binary files /dev/null and b/web/libs/fonts/Italic/Roboto-Italic.ttf differ diff --git a/web/libs/fonts/Italic/Roboto-Italic.woff b/web/libs/fonts/Italic/Roboto-Italic.woff new file mode 100644 index 0000000..6e4197d Binary files /dev/null and b/web/libs/fonts/Italic/Roboto-Italic.woff differ diff --git a/web/libs/fonts/Italic/Roboto-Italic.woff2 b/web/libs/fonts/Italic/Roboto-Italic.woff2 new file mode 100644 index 0000000..e7f173b Binary files /dev/null and b/web/libs/fonts/Italic/Roboto-Italic.woff2 differ diff --git a/web/libs/fonts/LICENSE.txt b/web/libs/fonts/LICENSE.txt new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/web/libs/fonts/LICENSE.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. diff --git a/web/libs/fonts/Light/Roboto-Light.ttf b/web/libs/fonts/Light/Roboto-Light.ttf new file mode 100644 index 0000000..219063a Binary files /dev/null and b/web/libs/fonts/Light/Roboto-Light.ttf differ diff --git a/web/libs/fonts/Light/Roboto-Light.woff b/web/libs/fonts/Light/Roboto-Light.woff new file mode 100644 index 0000000..d0158be Binary files /dev/null and b/web/libs/fonts/Light/Roboto-Light.woff differ diff --git a/web/libs/fonts/Light/Roboto-Light.woff2 b/web/libs/fonts/Light/Roboto-Light.woff2 new file mode 100644 index 0000000..ddbf4a9 Binary files /dev/null and b/web/libs/fonts/Light/Roboto-Light.woff2 differ diff --git a/web/libs/fonts/LightItalic/Roboto-LightItalic.ttf b/web/libs/fonts/LightItalic/Roboto-LightItalic.ttf new file mode 100644 index 0000000..0e81e87 Binary files /dev/null and b/web/libs/fonts/LightItalic/Roboto-LightItalic.ttf differ diff --git a/web/libs/fonts/LightItalic/Roboto-LightItalic.woff b/web/libs/fonts/LightItalic/Roboto-LightItalic.woff new file mode 100644 index 0000000..f20dfa7 Binary files /dev/null and b/web/libs/fonts/LightItalic/Roboto-LightItalic.woff differ diff --git a/web/libs/fonts/LightItalic/Roboto-LightItalic.woff2 b/web/libs/fonts/LightItalic/Roboto-LightItalic.woff2 new file mode 100644 index 0000000..ba70c2a Binary files /dev/null and b/web/libs/fonts/LightItalic/Roboto-LightItalic.woff2 differ diff --git a/web/libs/fonts/METADATA.pb b/web/libs/fonts/METADATA.pb new file mode 100644 index 0000000..a4d2bb2 --- /dev/null +++ b/web/libs/fonts/METADATA.pb @@ -0,0 +1,121 @@ +name: "Roboto" +designer: "Christian Robertson" +license: "APACHE2" +category: "SANS_SERIF" +date_added: "2013-01-09" +fonts { + name: "Roboto" + style: "normal" + weight: 100 + filename: "Roboto-Thin.ttf" + post_script_name: "Roboto-Thin" + full_name: "Roboto Thin" + copyright: "Copyright 2011 Google Inc. All Rights Reserved." +} +fonts { + name: "Roboto" + style: "italic" + weight: 100 + filename: "Roboto-ThinItalic.ttf" + post_script_name: "Roboto-ThinItalic" + full_name: "Roboto Thin Italic" + copyright: "Copyright 2011 Google Inc. All Rights Reserved." +} +fonts { + name: "Roboto" + style: "normal" + weight: 300 + filename: "Roboto-Light.ttf" + post_script_name: "Roboto-Light" + full_name: "Roboto Light" + copyright: "Copyright 2011 Google Inc. All Rights Reserved." +} +fonts { + name: "Roboto" + style: "italic" + weight: 300 + filename: "Roboto-LightItalic.ttf" + post_script_name: "Roboto-LightItalic" + full_name: "Roboto Light Italic" + copyright: "Copyright 2011 Google Inc. All Rights Reserved." +} +fonts { + name: "Roboto" + style: "normal" + weight: 400 + filename: "Roboto-Regular.ttf" + post_script_name: "Roboto-Regular" + full_name: "Roboto" + copyright: "Copyright 2011 Google Inc. All Rights Reserved." +} +fonts { + name: "Roboto" + style: "italic" + weight: 400 + filename: "Roboto-Italic.ttf" + post_script_name: "Roboto-Italic" + full_name: "Roboto Italic" + copyright: "Copyright 2011 Google Inc. All Rights Reserved." +} +fonts { + name: "Roboto" + style: "normal" + weight: 500 + filename: "Roboto-Medium.ttf" + post_script_name: "Roboto-Medium" + full_name: "Roboto Medium" + copyright: "Copyright 2011 Google Inc. All Rights Reserved." +} +fonts { + name: "Roboto" + style: "italic" + weight: 500 + filename: "Roboto-MediumItalic.ttf" + post_script_name: "Roboto-MediumItalic" + full_name: "Roboto Medium Italic" + copyright: "Copyright 2011 Google Inc. All Rights Reserved." +} +fonts { + name: "Roboto" + style: "normal" + weight: 700 + filename: "Roboto-Bold.ttf" + post_script_name: "Roboto-Bold" + full_name: "Roboto Bold" + copyright: "Copyright 2011 Google Inc. All Rights Reserved." +} +fonts { + name: "Roboto" + style: "italic" + weight: 700 + filename: "Roboto-BoldItalic.ttf" + post_script_name: "Roboto-BoldItalic" + full_name: "Roboto Bold Italic" + copyright: "Copyright 2011 Google Inc. All Rights Reserved." +} +fonts { + name: "Roboto" + style: "normal" + weight: 900 + filename: "Roboto-Black.ttf" + post_script_name: "Roboto-Black" + full_name: "Roboto Black" + copyright: "Copyright 2011 Google Inc. All Rights Reserved." +} +fonts { + name: "Roboto" + style: "italic" + weight: 900 + filename: "Roboto-BlackItalic.ttf" + post_script_name: "Roboto-BlackItalic" + full_name: "Roboto Black Italic" + copyright: "Copyright 2011 Google Inc. All Rights Reserved." +} +subsets: "menu" +subsets: "cyrillic" +subsets: "cyrillic-ext" +subsets: "greek" +subsets: "greek-ext" +subsets: "latin" +subsets: "latin-ext" +subsets: "vietnamese" diff --git a/web/libs/fonts/Material-Design-Iconic-Font.eot b/web/libs/fonts/Material-Design-Iconic-Font.eot new file mode 100644 index 0000000..5e25191 Binary files /dev/null and b/web/libs/fonts/Material-Design-Iconic-Font.eot differ diff --git a/web/libs/fonts/Material-Design-Iconic-Font.svg b/web/libs/fonts/Material-Design-Iconic-Font.svg new file mode 100644 index 0000000..8cb2673 --- /dev/null +++ b/web/libs/fonts/Material-Design-Iconic-Font.svg @@ -0,0 +1,787 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/web/libs/fonts/Material-Design-Iconic-Font.ttf b/web/libs/fonts/Material-Design-Iconic-Font.ttf new file mode 100644 index 0000000..5d489fd Binary files /dev/null and b/web/libs/fonts/Material-Design-Iconic-Font.ttf differ diff --git a/web/libs/fonts/Material-Design-Iconic-Font.woff b/web/libs/fonts/Material-Design-Iconic-Font.woff new file mode 100644 index 0000000..933b2bf Binary files /dev/null and b/web/libs/fonts/Material-Design-Iconic-Font.woff differ diff --git a/web/libs/fonts/Material-Design-Iconic-Font.woff2 b/web/libs/fonts/Material-Design-Iconic-Font.woff2 new file mode 100644 index 0000000..35970e2 Binary files /dev/null and b/web/libs/fonts/Material-Design-Iconic-Font.woff2 differ diff --git a/web/libs/fonts/Medium/Roboto-Medium.ttf b/web/libs/fonts/Medium/Roboto-Medium.ttf new file mode 100644 index 0000000..1a7f3b0 Binary files /dev/null and b/web/libs/fonts/Medium/Roboto-Medium.ttf differ diff --git a/web/libs/fonts/Medium/Roboto-Medium.woff b/web/libs/fonts/Medium/Roboto-Medium.woff new file mode 100644 index 0000000..cbac5e5 Binary files /dev/null and b/web/libs/fonts/Medium/Roboto-Medium.woff differ diff --git a/web/libs/fonts/Medium/Roboto-Medium.woff2 b/web/libs/fonts/Medium/Roboto-Medium.woff2 new file mode 100644 index 0000000..6a88805 Binary files /dev/null and b/web/libs/fonts/Medium/Roboto-Medium.woff2 differ diff --git a/web/libs/fonts/MediumItalic/Roboto-MediumItalic.ttf b/web/libs/fonts/MediumItalic/Roboto-MediumItalic.ttf new file mode 100644 index 0000000..0030295 Binary files /dev/null and b/web/libs/fonts/MediumItalic/Roboto-MediumItalic.ttf differ diff --git a/web/libs/fonts/MediumItalic/Roboto-MediumItalic.woff b/web/libs/fonts/MediumItalic/Roboto-MediumItalic.woff new file mode 100644 index 0000000..3e635c1 Binary files /dev/null and b/web/libs/fonts/MediumItalic/Roboto-MediumItalic.woff differ diff --git a/web/libs/fonts/MediumItalic/Roboto-MediumItalic.woff2 b/web/libs/fonts/MediumItalic/Roboto-MediumItalic.woff2 new file mode 100644 index 0000000..cf21729 Binary files /dev/null and b/web/libs/fonts/MediumItalic/Roboto-MediumItalic.woff2 differ diff --git a/web/libs/fonts/Regular/Roboto-Regular.ttf b/web/libs/fonts/Regular/Roboto-Regular.ttf new file mode 100644 index 0000000..2c97eea Binary files /dev/null and b/web/libs/fonts/Regular/Roboto-Regular.ttf differ diff --git a/web/libs/fonts/Regular/Roboto-Regular.woff b/web/libs/fonts/Regular/Roboto-Regular.woff new file mode 100644 index 0000000..f43dd1b Binary files /dev/null and b/web/libs/fonts/Regular/Roboto-Regular.woff differ diff --git a/web/libs/fonts/Regular/Roboto-Regular.woff2 b/web/libs/fonts/Regular/Roboto-Regular.woff2 new file mode 100644 index 0000000..9a0064e Binary files /dev/null and b/web/libs/fonts/Regular/Roboto-Regular.woff2 differ diff --git a/web/libs/fonts/Thin/Roboto-Thin.ttf b/web/libs/fonts/Thin/Roboto-Thin.ttf new file mode 100644 index 0000000..b74a4fd Binary files /dev/null and b/web/libs/fonts/Thin/Roboto-Thin.ttf differ diff --git a/web/libs/fonts/Thin/Roboto-Thin.woff b/web/libs/fonts/Thin/Roboto-Thin.woff new file mode 100644 index 0000000..c95f7b3 Binary files /dev/null and b/web/libs/fonts/Thin/Roboto-Thin.woff differ diff --git a/web/libs/fonts/Thin/Roboto-Thin.woff2 b/web/libs/fonts/Thin/Roboto-Thin.woff2 new file mode 100644 index 0000000..2fb9b5f Binary files /dev/null and b/web/libs/fonts/Thin/Roboto-Thin.woff2 differ diff --git a/web/libs/fonts/ThinItalic/Roboto-ThinItalic.ttf b/web/libs/fonts/ThinItalic/Roboto-ThinItalic.ttf new file mode 100644 index 0000000..dd0ddb8 Binary files /dev/null and b/web/libs/fonts/ThinItalic/Roboto-ThinItalic.ttf differ diff --git a/web/libs/fonts/ThinItalic/Roboto-ThinItalic.woff b/web/libs/fonts/ThinItalic/Roboto-ThinItalic.woff new file mode 100644 index 0000000..6284128 Binary files /dev/null and b/web/libs/fonts/ThinItalic/Roboto-ThinItalic.woff differ diff --git a/web/libs/fonts/ThinItalic/Roboto-ThinItalic.woff2 b/web/libs/fonts/ThinItalic/Roboto-ThinItalic.woff2 new file mode 100644 index 0000000..67c4240 Binary files /dev/null and b/web/libs/fonts/ThinItalic/Roboto-ThinItalic.woff2 differ diff --git a/web/libs/fonts/montserrat-bold.eot b/web/libs/fonts/montserrat-bold.eot new file mode 100644 index 0000000..2667207 Binary files /dev/null and b/web/libs/fonts/montserrat-bold.eot differ diff --git a/web/libs/fonts/montserrat-bold.svg b/web/libs/fonts/montserrat-bold.svg new file mode 100644 index 0000000..33bacfb --- /dev/null +++ b/web/libs/fonts/montserrat-bold.svg @@ -0,0 +1,706 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/web/libs/fonts/montserrat-bold.ttf b/web/libs/fonts/montserrat-bold.ttf new file mode 100644 index 0000000..3073bb2 Binary files /dev/null and b/web/libs/fonts/montserrat-bold.ttf differ diff --git a/web/libs/fonts/montserrat-bold.woff b/web/libs/fonts/montserrat-bold.woff new file mode 100644 index 0000000..10ef471 Binary files /dev/null and b/web/libs/fonts/montserrat-bold.woff differ diff --git a/web/libs/fonts/montserrat-bold.woff2 b/web/libs/fonts/montserrat-bold.woff2 new file mode 100644 index 0000000..64a5d52 Binary files /dev/null and b/web/libs/fonts/montserrat-bold.woff2 differ diff --git a/web/libs/fonts/montserrat-light.eot b/web/libs/fonts/montserrat-light.eot new file mode 100644 index 0000000..3c4834b Binary files /dev/null and b/web/libs/fonts/montserrat-light.eot differ diff --git a/web/libs/fonts/montserrat-light.svg b/web/libs/fonts/montserrat-light.svg new file mode 100644 index 0000000..e6f84d9 --- /dev/null +++ b/web/libs/fonts/montserrat-light.svg @@ -0,0 +1,725 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/web/libs/fonts/montserrat-light.ttf b/web/libs/fonts/montserrat-light.ttf new file mode 100644 index 0000000..b7abc1a Binary files /dev/null and b/web/libs/fonts/montserrat-light.ttf differ diff --git a/web/libs/fonts/montserrat-light.woff b/web/libs/fonts/montserrat-light.woff new file mode 100644 index 0000000..42e7ff7 Binary files /dev/null and b/web/libs/fonts/montserrat-light.woff differ diff --git a/web/libs/fonts/montserrat-light.woff2 b/web/libs/fonts/montserrat-light.woff2 new file mode 100644 index 0000000..43952ba Binary files /dev/null and b/web/libs/fonts/montserrat-light.woff2 differ diff --git a/web/libs/fonts/montserrat-regular.eot b/web/libs/fonts/montserrat-regular.eot new file mode 100644 index 0000000..5dda3a4 Binary files /dev/null and b/web/libs/fonts/montserrat-regular.eot differ diff --git a/web/libs/fonts/montserrat-regular.svg b/web/libs/fonts/montserrat-regular.svg new file mode 100644 index 0000000..222d5aa --- /dev/null +++ b/web/libs/fonts/montserrat-regular.svg @@ -0,0 +1,724 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/web/libs/fonts/montserrat-regular.ttf b/web/libs/fonts/montserrat-regular.ttf new file mode 100644 index 0000000..c35148c Binary files /dev/null and b/web/libs/fonts/montserrat-regular.ttf differ diff --git a/web/libs/fonts/montserrat-regular.woff b/web/libs/fonts/montserrat-regular.woff new file mode 100644 index 0000000..b589bee Binary files /dev/null and b/web/libs/fonts/montserrat-regular.woff differ diff --git a/web/libs/fonts/montserrat-regular.woff2 b/web/libs/fonts/montserrat-regular.woff2 new file mode 100644 index 0000000..31fe1d1 Binary files /dev/null and b/web/libs/fonts/montserrat-regular.woff2 differ diff --git a/web/libs/js/dash2.apiwindow.js b/web/libs/js/dash2.apiwindow.js new file mode 100644 index 0000000..5ca4658 --- /dev/null +++ b/web/libs/js/dash2.apiwindow.js @@ -0,0 +1,32 @@ +$(document).ready(function(e){ +//api window +$.apM={e:$('#apis')};$.apM.f=$.apM.e.find('form'); +$.apM.md=$.apM.f.find('[detail]'); +$.apM.md.change($.ccio.form.details).first().change(); +$.apM.f.submit(function(e){ + e.preventDefault();e.e=$(this),e.s=e.e.serializeObject(); + e.er=[]; + if(!e.s.ip||e.s.ip.length<7){e.er.push('Enter atleast one IP')} + if(e.er.length>0){$.apM.e.find('.msg').html(e.er.join('
'));return;} + $.each(e.s,function(n,v){e.s[n]=v.trim()}) + // e.s = { + // "ip": "", + // "details": "{\"get_monitors\":\"1\",\"control_monitors\":\"1\",\"get_logs\":\"1\",\"watch_stream\":\"1\",\"watch_snapshot\":\"1\",\"watch_videos\":\"1\",\"delete_videos\":\"1\"}" + // } + $.post($.ccio.init('location',$user)+$user.auth_token+'/api/'+$user.ke+'/add',{data:JSON.stringify(e.s)},function(d){ + $.ccio.log(d) + }) +}); +$.apM.e.on('click','.delete',function(e){ + e.e=$(this);e.p=e.e.parents('[api_key]'),e.code=e.p.attr('api_key'); + $.confirm.e.modal('show'); + $.confirm.title.text('Delete API Key'); + e.html='Do you want to delete this API key? You cannot recover it.'; + $.confirm.body.html(e.html); + $.confirm.click({title:'Delete',class:'btn-danger'},function(){ + $.post($.ccio.init('location',$user)+$user.auth_token+'/api/'+$user.ke+'/delete',{data:JSON.stringify({code:e.code})},function(d){ + $.ccio.log(d) + }) + }) +}) +}) diff --git a/web/libs/js/dash2.basic.js b/web/libs/js/dash2.basic.js new file mode 100644 index 0000000..71e7987 --- /dev/null +++ b/web/libs/js/dash2.basic.js @@ -0,0 +1,299 @@ +$.ccio.permissionCheck = function(toCheck,monitorId){ + var details = $user.details + if(details.sub && details.allmonitors === '0'){ + var chosenValue = details[toCheck] + if(details[toCheck] instanceof Array && chosenValue.indexOf(monitorId) > -1){ + return true + }else if(chosenValue === '1'){ + return true + } + }else{ + return true + } + return false +} +$.ccio.op = function(r,rr,rrr){ + if(!rrr){rrr={};};if(typeof rrr === 'string'){rrr={n:rrr}};if(!rrr.n){rrr.n='ShinobiOptions_'+location.host} + ii={o:localStorage.getItem(rrr.n)};try{ii.o=JSON.parse(ii.o)}catch(e){ii.o={}} + if(!ii.o){ii.o={}} + if(r&&rr&&!rrr.x){ + ii.o[r]=rr; + } + switch(rrr.x){ + case 0: + delete(ii.o[r]) + break; + case 1: + delete(ii.o[r][rr]) + break; + } + localStorage.setItem(rrr.n,JSON.stringify(ii.o)) + return ii.o +} +$.ccio.log = function(x,y,z){ + if($.ccio.op().browserLog==="1"){ + if(!y){y=''};if(!z){z=''}; + console.log(x,y,z) + } +} +$.ccio.gid = function(x){ + if(!x){x=10};var t = "";var p = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + for( var i=0; i < x; i++ ) + t += p.charAt(Math.floor(Math.random() * p.length)); + return t; +}; +$.ccio.downloadJSON = function(jsonToDownload,filename,errorResponse){ + var arr = jsonToDownload; + if(arr.length===0 && errorResponse){ + errorResponse.type = 'error' + $.ccio.init('note',errorResponse); + return + } + var dataStr = "data:text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(arr,null,3)); + $('#temp').html('') + .find('a') + .attr('href',dataStr) + .attr('download',filename) + [0].click() +} +$.ccio.timeObject = function(time,isUTC){ + if(isUTC === true){ + return moment(time).utc() + } + return moment(time) +} +$.ccio.base64ArrayBuffer = function(arrayBuffer) { + var base64 = '' + var encodings = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' + + var bytes = new Uint8Array(arrayBuffer) + var byteLength = bytes.byteLength + var byteRemainder = byteLength % 3 + var mainLength = byteLength - byteRemainder + + var a, b, c, d + var chunk + + // Main loop deals with bytes in chunks of 3 + for (var i = 0; i < mainLength; i = i + 3) { + // Combine the three bytes into a single integer + chunk = (bytes[i] << 16) | (bytes[i + 1] << 8) | bytes[i + 2] + + // Use bitmasks to extract 6-bit segments from the triplet + a = (chunk & 16515072) >> 18 // 16515072 = (2^6 - 1) << 18 + b = (chunk & 258048) >> 12 // 258048 = (2^6 - 1) << 12 + c = (chunk & 4032) >> 6 // 4032 = (2^6 - 1) << 6 + d = chunk & 63 // 63 = 2^6 - 1 + + // Convert the raw binary segments to the appropriate ASCII encoding + base64 += encodings[a] + encodings[b] + encodings[c] + encodings[d] + } + + // Deal with the remaining bytes and padding + if (byteRemainder == 1) { + chunk = bytes[mainLength] + + a = (chunk & 252) >> 2 // 252 = (2^6 - 1) << 2 + + // Set the 4 least significant bits to zero + b = (chunk & 3) << 4 // 3 = 2^2 - 1 + + base64 += encodings[a] + encodings[b] + '==' + } else if (byteRemainder == 2) { + chunk = (bytes[mainLength] << 8) | bytes[mainLength + 1] + + a = (chunk & 64512) >> 10 // 64512 = (2^6 - 1) << 10 + b = (chunk & 1008) >> 4 // 1008 = (2^6 - 1) << 4 + + // Set the 2 least significant bits to zero + c = (chunk & 15) << 2 // 15 = 2^4 - 1 + + base64 += encodings[a] + encodings[b] + encodings[c] + '=' + } + + return base64 +} +$.ccio.snapshot=function(e,cb){ + var image_data,url; + e.details=JSON.parse(e.mon.details); + if($.ccio.op().jpeg_on!==true){ + var extend=function(image_data,width,height){ + var len = image_data.length + var arraybuffer = new Uint8Array( len ); + for (var i = 0; i < len; i++) { + arraybuffer[i] = image_data.charCodeAt(i); + } + try { + var blob = new Blob([arraybuffer], {type: 'application/octet-stream'}); + } catch (e) { + var bb = new (window.WebKitBlobBuilder || window.MozBlobBuilder); + bb.append(arraybuffer); + var blob = bb.getBlob('application/octet-stream'); + } + url = (window.URL || window.webkitURL).createObjectURL(blob); + finish(url,image_data,width,height); + try{ + setTimeout(function(){ + URL.revokeObjectURL(url) + },10000) + }catch(er){} + } + var finish = function(url,image_data,width,height){ + cb(url,image_data,width,height); + } + switch(JSON.parse(e.mon.details).stream_type){ + case'hls':case'flv':case'mp4': + $.ccio.snapshotVideo($('[mid='+e.mon.mid+'].monitor_item video')[0],function(base64,video_data,width,height){ + extend(video_data,width,height) + }) + break; + case'mjpeg': + $('#temp').html('') + var c = $('#temp canvas')[0]; + var img = $('img',$('[mid='+e.mon.mid+'].monitor_item .stream-element').contents())[0]; + c.width = img.width; + c.height = img.height; + var ctx = c.getContext('2d'); + ctx.drawImage(img, 0, 0,c.width,c.height); + extend(atob(c.toDataURL('image/jpeg').split(',')[1]),c.width,c.height) + break; + case'h265': + var c = $('[mid='+e.mon.mid+'].monitor_item canvas')[0]; + var ctx = c.getContext('2d'); + extend(atob(c.toDataURL('image/jpeg').split(',')[1]),c.width,c.height) + break; + case'b64': + base64 = e.mon.last_frame.split(',')[1]; + var image_data = new Image(); + image_data.src = base64; + extend(atob(base64),image_data.width,image_data.height) + break; + case'jpeg':case'h265': + url=e.p.find('.stream-element').attr('src'); + image_data = new Image(); + image_data.src = url; + finish(url,image_data,image_data.width,image_data.height); + break; + } + }else{ + url=e.p.find('.stream-element').attr('src'); + image_data = new Image(); + image_data.src = url; + cb(url,image_data,image_data.width,image_data.height); + } +} +$.ccio.snapshotVideo=function(videoElement,cb){ + var image_data; + var base64 + $('#temp').html('') + var c = $('#temp canvas')[0]; + var img = videoElement; + c.width = img.videoWidth; + c.height = img.videoHeight; + var ctx = c.getContext('2d'); + ctx.drawImage(img, 0, 0,c.width,c.height); + base64=c.toDataURL('image/jpeg') + image_data=atob(base64.split(',')[1]); + var arraybuffer = new ArrayBuffer(image_data.length); + var view = new Uint8Array(arraybuffer); + for (var i=0; i'); + }else{ + e.p.append('
'; + break; + case'jpeg': + tmp+=''; + break; + default://base64//h265 + tmp+=''; + break; + } + } + k.e.append(tmp).find('.stream-element').resize(); + if($.ccio.op().switches.monitorMuteAudio === 1){ + k.e.find('video').each(function(n,el){ + el.muted = "muted" + }) + } + break; + case'user-row': + d.e=$('.user-row[uid="'+d.uid+'"][ke="'+d.ke+'"]') + if(d.e.length===0){ + tmp+='
  • '; + tmp+='
    '+d.mail+' : '+d.uid+'
    Logged in
    '; + tmp+='
  • '; + }else{ + d.e.find('.mail').text(d.mail) + d.e.find('.time').livestamp('destroy').toggleClass('livestamped livestamp').text(d.logged_in_at) + } + $.ccio.init('ls') + break; + case'detector-filters-where': + if(!d)d={}; + d.id=$('#filters_where .row').length; + if(!d.p1){d.p1='indifference'} + if(!d.p2){d.p2='='} + if(!d.p3){d.p3=''} + if(!d.p4){d.p4='&&'} + tmp+='
    ' + tmp+='
    ' + tmp+=' ' + tmp+='
    ' + tmp+='
    ' + tmp+=' ' + tmp+='
    ' + tmp+='
    ' + tmp+=' ' + tmp+='
    ' + tmp+='
    ' + tmp+=' ' + tmp+='
    ' + tmp+='
    ' + break; + case'filters-where': + if(!d)d={}; + d.id=$('#filters_where .row').length; + if(!d.p1){d.p1='mid'} + if(!d.p2){d.p2='='} + if(!d.p3){d.p3=''} + tmp+='
    '; + tmp+='
    '; + tmp+=' '; + tmp+='
    '; + tmp+='
    '; + tmp+=' '; + tmp+='
    '; + tmp+='
    '; + tmp+=' '; + tmp+='
    '; + tmp+='
    '; + break; + case 'link-set'://Link Shinobi - 1 set + if(!d.host){d.host=''} + if(!d.ke){d.ke=''} + if(!d.api){d.api=''} + if(!d.secure){d.secure="0"} + tmp+='
    ' + tmp+='

    '+d.host+' '+d.ke+' 

    ' + tmp+='
    ' + tmp+='
    ' + tmp+='
    ' + tmp+='
    ' + tmp+='
    '; + break; + case 'form-group'://Input Map Selector + var fields = [] + if(d.fields){ + if(d.fields instanceof Object){ + fields = [d] + }else{ + fields = d + } + } + $.each(fields,function(n,v){ + var value,hidden + if(!v.attribute)v.attribute=''; + if(!v.placeholder)v.placeholder=''; + if(!v.class)v.class=''; + if(!v.inputType)v.inputType='value'; + if(v.hidden){hidden='style="display:none"'}else{hidden=''}; + if(v.value){value='value=""'}else{value=''}; + tmp+='
    ' + tmp+=' ' + tmp+='
    ' + }) + break; + case 'input-map-selector'://Input Map Selector + if(!d.map){d.map=''} + tmp+='
    ' + tmp+=' ' + tmp+='
    ' + break; + case 'input-map'://Input Map Options + var tempID = $.ccio.gid(); + if(!d.channel){ + var numberOfChannelsDrawn = $('#monSectionInputMaps .input-map').length + d.channel=numberOfChannelsDrawn+1 + } + var fields = [ +// { +// name:'', +// class:'', +// placeholder:'', +// default:'', +// attribute:'', +// type:'text', +// }, + { + name:'type', + label:lang['Input Type'], + default:'h264', + attribute:'selector="h_i_'+tempID+'"', + type:'selector', + choices:[ + {label:lang['H.264 / H.265 / H.265+'],value:'h264'}, + {label:lang['JPEG'],value:'jpeg'}, + {label:lang['MJPEG'],value:'mjpeg'}, + {label:lang['HLS (.m3u8)'],value:'hls'}, + {label:lang['MPEG-4 (.mp4 / .ts)'],value:'mp4'}, + {label:lang['Local'],value:'local'}, + {label:lang['Raw'],value:'raw'}, + ] + }, + { + name:'fulladdress', + label:lang['Full URL Path'], + placeholder:'Example : rtsp://admin:password@123.123.123.123/stream/1', + type:'text', + }, + { + name:'sfps', + label:lang['Monitor Capture Rate'], + placeholder:'', + type:'text', + }, + { + name:'aduration', + label:lang['Analyzation Duration'], + placeholder:'Example : 1000000', + type:'text', + }, + { + name:'probesize', + label:lang['Probe Size'], + placeholder:'Example : 1000000', + type:'text', + }, + { + name:'stream_loop', + label:lang['Loop Stream'], + class:'h_i_'+tempID+'_input h_i_'+tempID+'_mp4 h_i_'+tempID+'_raw', + hidden:true, + default:'0', + type:'selector', + choices:[ + {label:'No',value:'0'}, + {label:'Yes',value:'1'} + ] + }, + { + name:'rtsp_transport', + label:lang['RTSP Transport'], + class:'h_i_'+tempID+'_input h_i_'+tempID+'_h264', + default:'0', + type:'selector', + choices:[ + {label:'Auto',value:''}, + {label:'TCP',value:'tcp'}, + {label:'UDP',value:'udp'} + ] + }, + { + name:'accelerator', + label:lang['Accelerator'], + attribute:'selector="h_accel_'+tempID+'"', + default:'0', + type:'selector', + choices:[ + {label:'No',value:'0'}, + {label:'Yes',value:'1'}, + ] + }, + { + name:'hwaccel', + label:lang['hwaccel'], + class:'h_accel_'+tempID+'_input h_accel_'+tempID+'_1', + hidden:true, + default:'', + type:'selector', + choices: $.ccio.HWAccelChoices + }, + { + name:'hwaccel_vcodec', + label:lang['hwaccel_vcodec'], + class:'h_accel_'+tempID+'_input h_accel_'+tempID+'_1', + hidden:true, + default:'auto', + type:'selector', + choices:[ + {label:lang['Auto'],value:'auto'}, + {label:lang['h264_cuvid'],value:'h264_cuvid',group:'NVIDIA'}, + {label:lang['hevc_cuvid'],value:'hevc_cuvid',group:'NVIDIA'}, + {label:lang['mjpeg_cuvid'],value:'mjpeg_cuvid',group:'NVIDIA'}, + {label:lang['mpeg4_cuvid'],value:'mpeg4_cuvid',group:'NVIDIA'}, + {label:lang['h264_qsv'],value:'h264_qsv',group:'Quick Sync Video'}, + {label:lang['hevc_qsv'],value:'hevc_qsv',group:'Quick Sync Video'}, + {label:lang['mpeg2_qsv'],value:'mpeg2_qsv',group:'Quick Sync Video'}, + {label:lang['h264_mmal'],value:'h264_mmal',group:'Raspberry Pi'}, + {label:lang['mpeg2_mmal'],value:'mpeg2_mmal',group:'Raspberry Pi'}, + {label:lang['mpeg4_mmal'],value:'mpeg4_mmal',group:'Raspberry Pi'}, + ] + }, + { + name:'hwaccel_device', + label:lang['hwaccel_device'], + class:'h_accel_'+tempID+'_input h_accel_'+tempID+'_1', + hidden:true, + placeholder:'Example : /dev/dri/video0', + type:'text', + }, + ]; + tmp+='
    ' + tmp+='

    '+lang["Input"]+' '+lang["Map"]+' : '+d.channel+'' + tmp+='
    ' + tmp+='

    ' + $.each(fields,function(n,v){ + if(!v.attribute)v.attribute=''; + if(!v.placeholder)v.placeholder=''; + if(!v.class)v.class=''; + if(v.hidden){v.hidden='style="display:none"'}else{v.hidden=''}; + tmp+='
    ' + tmp+=' ' + tmp+='
    ' + }) + tmp+='
    ' + break; + case 'stream-channel'://Stream Channel + var tempID = $.ccio.gid(); + if(!d.channel){ + var numberOfChannelsDrawn = $('#monSectionStreamChannels .stream-channel').length + d.channel=numberOfChannelsDrawn + } + tmp+='
    ' + tmp+='

    '+lang["Stream Channel"]+' '+d.channel+'' + tmp+='
    ' + tmp+='

    ' +// tmp+='
    ' +// tmp+=' ' +// tmp+='
    ' + tmp+='
    ' + tmp+='

    '+lang['Input Feed'] + tmp+='
    ' + tmp+=' ' + tmp+='
    ' + tmp+='

    ' + tmp+='
    ' + tmp+='
    ' + tmp+='
    ' + tmp+=' ' + tmp+='
    ' + tmp+='
    ' + tmp+='
    ' + tmp+=' ' + tmp+='
    ' + tmp+='
    ' + tmp+=' ' + tmp+='
    ' + tmp+='
    ' + tmp+=' ' + tmp+='
    ' + tmp+='
    ' + tmp+=' ' + tmp+='
    ' + tmp+='
    ' + tmp+=' ' + tmp+='
    ' + tmp+='
    ' + tmp+='
    ' + tmp+=' ' + tmp+='
    ' + tmp+=' ' + tmp+=' ' + tmp+='
    ' + break; + } + if(z && x !== 2){ + $(z).prepend(tmp) + } + switch(x){ + case 1: + z='#monitors_list .link-monitors-list[auth="'+user.auth_token+'"][ke="'+d.ke+'"]' + if($('.link-monitors-list[auth="'+user.auth_token+'"][ke="'+d.ke+'"]').length===0){ + $("#monitors_list").append('') + var options = { + cellHeight: 80, + verticalMargin: 10, + }; + $(z).sortable({ + stop : function(event,ui){ + var order = {} + $('.link-monitors-list').each(function(n,block){ + var el = $(this) + var ke = el.attr('ke') + var authToken = el.attr('auth') + var orderKey = ke + authToken + if(authToken === $user.auth_token)orderKey = 0 + if(!order[orderKey])order[orderKey] = [] + var monitorBlocks = $(this).find('.monitor_block') + $.each(monitorBlocks,function(n,block){ + var mid = $(block).attr('mid') + order[orderKey].push(mid) + }) + }) + $user.details.monitorListOrder = order + $.ccio.cx({f:'monitorListOrder',monitorListOrder:order},user) + }, + handle: '.title' + }) + } + $(z).prepend(tmp) + // componentHandler.upgradeAllRegistered() + break; + case 0:case 4: + $.ccio.init('ls'); + break; + case 2: + var x = 0; + var y = 0; + var width = $.grid.getMonitorsPerRow() + var height = width; + if(user.details && user.details.monitorOrder && user.details.monitorOrder[d.ke+d.mid]){ + var saved = user.details.monitorOrder[d.ke+d.mid]; + x = saved.x; + y = saved.y; + width = saved.width; + height = saved.height; + } + var autoPlacement = false + if($.ccio.op().switches.monitorOrder !== 1){ + autoPlacement = true + } + $(z).data('gridstack').addWidget($(tmp), x, y, width, height, autoPlacement); + k.e=$('#monitor_live_'+d.mid+user.auth_token); + try{ + if(JSON.parse(d.details).control=="1"){ + k.e.find('[monitor="control_toggle"]').show() + }else{ + k.e.find('.pad').remove(); + k.e.find('[monitor="control_toggle"]').hide() + } + $.ccio.tm('stream-element',d,null,user) + }catch(re){$.ccio.log(re)} + k.mid=d.mid + k.mon=$.ccio.mon[d.ke+d.mid+user.auth_token] + $.ccio.init('monitorInfo',k) + break; + case'detector-filters-where': + $('#detector_filters_where').append(tmp); + $('#detector_filters_where .row [where="p4"][disabled]').prop('disabled',false) + $('#detector_filters_where .row:last [where="p1"]').val(d.p1) + $('#detector_filters_where .row:last [where="p2"]').val(d.p2) + $('#detector_filters_where .row:last [where="p3"]').val(d.p3) + $('#detector_filters_where .row:last [where="p4"]').val(d.p4).prop('disabled',true) + break; + case'filters-where': + $('#filters_where').append(tmp); + $('#filters_where .row:last [where="p1"]').val(d.p1) + $('#filters_where .row:last [where="p2"]').val(d.p2) + $('#filters_where .row:last [where="p3"]').val(d.p3) + break; + case'input-map': + var mapsList = $.aM.maps + mapsList.append(tmp) + mapsList.find('.input-map').last().find('[map-detail="aduration"]').change() + return tempID; + break; + case'stream-channel': + var channeList = $.aM.channels + channeList.append(tmp) + channeList.find('.stream-channel').last().find('[channel-detail="stream_vcodec"]').change() + return tempID; + break; + case'link-set': + $('[links="'+d.host+'"] [link="secure"]').val(d.secure).change() + break; + } + return tmp; +} +$.ccio.pm=function(x,d,z,user){ + var tmp='';if(!d){d={}}; + if(!user){ + user=$user + } + switch(x){ + case 0: + d.mon=$.ccio.mon[d.ke+d.mid+user.auth_token]; + d.ev='.glM'+d.mid+user.auth_token+'.videos_list ul,.glM'+d.mid+user.auth_token+'.videos_monitor_list ul';d.fr=$.ccio.fr.find(d.ev),d.tmp=''; + if(d.fr.length===0){$.ccio.fr.append('

    '+d.mon.name+'

      ')} + if(d.videos&&d.videos.length>0){ + $.each(d.videos,function(n,v){ + if(v.status!==0){ + tmp+=$.ccio.tm(0,v,null,user) + } + }) + }else{ + $('.glM'+d.mid+user.auth_token+'.videos_list,.glM'+d.mid+user.auth_token+'.videos_monitor_list').appendTo($.ccio.fr) + tmp+='
    • No videos
    • '; + } + $(d.ev).html(tmp); + $.ccio.init('ls'); + break; + case 3: + z='#api_list'; + $(z).empty(); + $.each(d,function(n,v){ + tmp+=$.ccio.tm(3,v,null,user); + }) + break; + case'option': + $.each(d,function(n,v){ + tmp+=$.ccio.tm('option',v,null,user); + }) + break; + case'user-row': + $.each(d,function(n,v){ + tmp+=$.ccio.tm('user-row',v,null,user); + }) + z='#users_online' + break; + case'link-set': + $.sM.links.empty() + $.each(d,function(n,v){ + tmp+=$.ccio.tm('link-set',v,'#linkShinobi',user) + }) + break; + } + if(z){ + $(z).prepend(tmp) + } + return tmp; +} diff --git a/web/libs/js/dash2.elements.js b/web/libs/js/dash2.elements.js new file mode 100644 index 0000000..cbe9c0c --- /dev/null +++ b/web/libs/js/dash2.elements.js @@ -0,0 +1,801 @@ +$(document).ready(function(e){ + console.log("%cWarning!", "font: 2em monospace; color: red;"); + console.log('%cLeaving the developer console open is fine if you turn off "Network Recording". This is because it will keep a log of all files, including frames and videos segments.', "font: 1.2em monospace; "); + if(!$.ccio.permissionCheck('monitor_create')){ + $('#add_monitor_button_main').remove() + } + $.each(['user_change','monitor_create','view_logs'],function(n,permission){ + if(!$.ccio.permissionCheck(permission)){ + $('.permission_'+permission).remove() + } + }) + + //Group Selector + $.gR={e:$('#group_list'),b:$('#group_list_button')}; + $.gR.drawList=function(){ + var e={}; + e.tmp=''; + $.each($.ccio.init('monGroup'),function(n,v){ + if($user.mon_groups[n]){ + e.tmp+='
    • '+$user.mon_groups[n].name+'
    • ' + } + }) + $.gR.e.html(e.tmp) + } + $.gR.e.on('click','[groups]',function(){ + var e={}; + e.e=$(this), + e.a=e.e.attr('groups'); + var user=$.users[e.e.attr('auth')]; + if(!user){user=$user} + if(user===$user){ + e.chosen_set='watch_on' + }else{ + e.chosen_set='watch_on_links' + } + $.each($.ccio.op()[e.chosen_set],function(n,v){ + $.each(v,function(m,b){ + $.ccio.cx({f:'monitor',ff:'watch_off',id:m,ke:n},user) + }) + }) + $.each($.ccio.mon_groups[e.a],function(n,v){ + $.ccio.cx({f:'monitor',ff:'watch_on',id:v.mid,ke:v.ke},user) + }) + }) + $.ccio.sortListMonitors = function(user){ + var listKey = user.auth_token + if(user.auth_token === $user.auth_token){ + listKey = 0 + } + if(!user.details.monitorListOrder)user.details.monitorListOrder = {0:[]} + var getIdPlace = function(x){return user.details.monitorListOrder[listKey].indexOf(x)} + $(function() { + $('.link-monitors-list[auth="'+user.auth_token+'"] .monitor_block').sort(function(a, b) { + var contentA = getIdPlace($(a).attr('mid')) + var contentB = getIdPlace($(b).attr('mid')) + return contentA - contentB + }).each(function() { $('.link-monitors-list[auth="'+user.auth_token+'"]').append($(this)); }); + }) + } + //log stream writer + $.logWriter = {} + $.logWriter.floodTimeout = null + $.logWriter.floodCounter = 0 + $.logWriter.draw = function(id,d,user){ + if($.logWriter.floodLock)return $.ccio.log('logWriter.floodLock : Log was dropped'); + if($.logWriter.floodTimeout){ + ++$.logWriter.floodCounter + } + if($.logWriter.floodCounter > 10){ + $.logWriter.floodLock = setTimeout(function(){ + delete($.logWriter.floodLock) + },10000) + } + clearTimeout($.logWriter.floodTimeout) + $.logWriter.floodTimeout = setTimeout(function(){ + delete($.logWriter.floodTimeout) + $.logWriter.floodCounter = 0 + },1000) + $.ccio.tm(4,d,'#logs,'+id+'.monitor_item .logs:visible,'+id+'#add_monitor:visible .logs',user) + } + //open all monitors + $('[class_toggle="list-blocks"][data-target="#left_menu"]').dblclick(function(){ + $('#monitors_list .monitor_block').each(function(n,v){ + var el = $(v) + var ke = el.attr('ke') + var mid = el.attr('mid') + var auth = el.attr('auth') + var monItem = $('.monitor_item[ke='+ke+'][mid='+mid+'][auth='+auth+']') + if(monItem.length > 0){ + monItem.find('[monitor="watch_on"]').click() + }else{ + el.find('[monitor="watch"]').click() + } + }) + }) + //search monitors list + $('#monitors_list_search').keyup(function(){ + var monitorBlocks = $('.monitor_block'); + var searchTerms = $(this).val().toLowerCase().split(' ') + if(searchTerms.length === 0 || searchTerms[0] === ''){ + monitorBlocks.show() + return + } + monitorBlocks.hide() + $.each($.ccio.mon,function(n,monitor){ + var searchThis = JSON.stringify($.ccio.init('cleanMon',monitor)).toLowerCase().replace('"',''); + $.each(searchTerms,function(m,term){ + if(searchThis.indexOf(term) >-1 ){ + $('.monitor_block[ke="'+monitor.ke+'"][mid="'+monitor.mid+'"]').show() + } + }) + }) + }) + //dynamic bindings + $.ccio.windowFocus = true + $(window).focus(function() { + $.ccio.windowFocus = true + clearInterval($.ccio.soundAlarmInterval) + }).blur(function() { + $.ccio.windowFocus = false + }); + $('body') + .on('click','.logout',function(e){ + var logout = function(user,callback){ + $.get($.ccio.init('location',user)+user.auth_token+'/logout/'+user.ke+'/'+user.uid,callback) + } + $.each($.users,function(n,linkedShinobiUser){ + logout(linkedShinobiUser,function(){}); + }) + logout($user,function(data){ + console.log(data) + localStorage.removeItem('ShinobiLogin_'+location.host); + location.href=location.href; + }); + }) + .on('click','[video]',function(e){ + e.e=$(this), + e.a=e.e.attr('video'), + e.p=e.e.parents('[mid]'), + e.ke=e.p.attr('ke'), + e.mid=e.p.attr('mid'), + e.file=e.p.attr('file'); + e.auth=e.p.attr('auth'); + e.status=e.p.attr('status'); + if(!e.ke||!e.mid){ + //for calendar plugin + e.p=e.e.parents('[data-mid]'), + e.ke=e.p.data('ke'), + e.mid=e.p.data('mid'), + e.file=e.p.data('file'); + e.auth=e.p.data('auth'); + e.status=e.p.data('status'); + } + e.mon=$.ccio.mon[e.ke+e.mid+e.auth]; + switch(e.a){ + case'launch': + e.preventDefault(); + e.href=$(this).attr('href') + var el = $('#video_viewer') + var modalBody = el.find('.modal-body') + el.find('.modal-title span').html(e.mon.name+' - '+e.file) + var html = '
      ' + modalBody.html(html) + el.find('video')[0].onerror = function(){ + modalBody.find('.msg').text(lang.h265BrowserText1) + } + el.attr('mid',e.mid); + footer = el.find('.modal-footer'); + footer.find('.download_link').attr('href',e.href).attr('download',e.file); + footer.find('[monitor="download"][host="dropbox"]').attr('href',e.href); + el.modal('show') + .attr('ke',e.ke) + .attr('mid',e.mid) + .attr('auth',e.auth) + .attr('file',e.file); + if(e.status==1){ + $.get($.ccio.init('videoHrefToRead',e.href),function(d){ + if(d.ok !== true)console.log(d,new Error()) + }) + } + break; + case'delete': + e.preventDefault(); + var videoLink = e.p.find('[download]').attr('href') + var href = $(this).attr('href') + console.log('videoLink',videoLink) + console.log(href) + if(!href){ + href = $.ccio.init('location',$.users[e.auth])+e.auth+'/videos/'+e.ke+'/'+e.mid+'/'+e.file+'/delete<% if(config.useUTC === true){%>?isUTC=true<%}%>' + } + console.log(href) + $.confirm.e.modal('show'); + $.confirm.title.text(lang['Delete Video']+' : '+e.file) + e.html=lang.DeleteVideoMsg + e.html+=''; + $.confirm.body.html(e.html) + $.confirm.click({title:'Delete Video',class:'btn-danger'},function(){ + $.getJSON(href,function(d){ + $.ccio.log(d) + }) + }); + break; + case'download': + e.preventDefault(); + switch(e.e.attr('host')){ + case'dropbox': + if($.ccio.DropboxAppKey){ + Dropbox.save(e.e.attr('href'),e.e.attr('download'),{progress: function (progress) {$.ccio.log(progress)},success: function () { + $.ccio.log(lang.dropBoxSuccess); + }}); + } + break; + } + break; + } + }) + .on('change','[localStorage]',function(){ + e = {} + e.e=$(this) + e.localStorage = e.e.attr('localStorage') + e.value = e.e.val() + $.ccio.op(e.localStorage,e.value) + }) + .on('click','[system]',function(e){ + var e={}; + e.e=$(this), + e.a=e.e.attr('system');//the function + switch(e.a){ + case'switch': + e.switch=e.e.attr('switch'); + e.o=$.ccio.op().switches + if(!e.o){ + e.o={} + } + if(!e.o[e.switch]){ + e.o[e.switch]=0 + } + if(e.o[e.switch]===1){ + e.o[e.switch]=0 + }else{ + e.o[e.switch]=1 + } + $.ccio.op('switches',e.o) + switch(e.switch){ + case'monitorOrder': + if(e.o[e.switch] !== 1){ + $('.monitor_item').attr('data-gs-auto-position','yes') + }else{ + $('.monitor_item').attr('data-gs-auto-position','no') + } + break; + case'monitorMuteAudio': + $('.monitor_item video').each(function(n,el){ + if(e.o[e.switch] === 1){ + el.muted = true + }else{ + el.muted = false + } + }) + break; + } + switch(e.e.attr('type')){ + case'text': + if(e.o[e.switch]===1){ + e.e.addClass('text-success') + }else{ + e.e.removeClass('text-success') + } + break; + } + break; + case'cronStop': + $.ccio.cx({f:'cron',ff:'stop'}) + break; + case'cronRestart': + $.ccio.cx({f:'cron',ff:'restart'}) + break; + case'jpegToggle': + e.cx={f:'monitor',ff:'jpeg_on'}; + if($.ccio.op().jpeg_on===true){ + e.cx.ff='jpeg_off'; + } + $.ccio.cx(e.cx) + break; + } + }) + .on('click','[class_toggle]',function(e){ + e.e=$(this); + e.n=e.e.attr('data-target'); + e.v=e.e.attr('class_toggle'); + e.o=$.ccio.op().class_toggle; + if($(e.n).hasClass(e.v)){e.t=0}else{e.t=1} + if(!e.o)e.o={}; + e.o[e.n]=[e.v,e.t]; + $.ccio.op('class_toggle',e.o) + $(e.n).toggleClass(e.v); + }) + .on('change','[dropdown_toggle]',function(e){ + e.e=$(this); + e.n=e.e.attr('dropdown_toggle'); + e.v=e.e.val(); + e.o=$.ccio.op().dropdown_toggle; + if(!e.o)e.o={}; + e.o[e.n]=e.v; + $.ccio.op('dropdown_toggle',e.o) + }) + //monitor functions + .on('click','[monitor]',function(){ + var e={}; + e.e=$(this), + e.a=e.e.attr('monitor'),//the function + e.p=e.e.parents('[mid]'),//the parent element for monitor item + e.ke=e.p.attr('ke'),//group key + e.mid=e.p.attr('mid'),//monitor id + e.auth=e.p.attr('auth'),//authkey + e.mon=$.ccio.mon[e.ke+e.mid+e.auth];//monitor configuration + var user + if($.users[e.auth]){user=$.users[e.auth]}else{user=$user} + if(!user){ + user=$user + } + switch(e.a){ + case'show_data': + e.p.toggleClass('show_data') + var dataBlocks = e.p.find('.stream-block,.mdl-data_window') + if(e.p.hasClass('show_data')){ + dataBlocks.addClass('col-md-6').removeClass('col-md-12') + }else{ + dataBlocks.addClass('col-md-12').removeClass('col-md-6') + } + break; + case'motion': + if(!e.mon.motionDetectionRunning){ + $.ccio.init('streamMotionDetectOn',e,user) + }else{ + $.ccio.init('streamMotionDetectOff',e,user) + } + break; + case'pop': + e.fin=function(img){ + if($.ccio.mon[e.ke+e.mid+user.auth_token].popOut){ + $.ccio.mon[e.ke+e.mid+user.auth_token].popOut.close() + } + $.ccio.mon[e.ke+e.mid+user.auth_token].popOut = window.open($.ccio.init('location',user)+user.auth_token+'/embed/'+e.ke+'/'+e.mid+'/fullscreen|jquery|relative|gui','pop_'+e.mid+user.auth_token,'height='+img.height+',width='+img.width); + } + if(e.mon.watch===1){ + $.ccio.snapshot(e,function(url){ + $('#temp').html('') + var img=$('#temp img')[0] + img.onload=function(){ + e.fin(img) + } + img.src=url + }) + }else{ + var img={height:720,width:1280} + e.fin(img) + } + break; + case'mode': + e.mode=e.e.attr('mode') + if(e.mode){ + $.getJSON($.ccio.init('location',user)+user.auth_token+'/monitor/'+e.ke+'/'+e.mid+'/'+e.mode,function(d){ + $.ccio.log(d) + }) + } + break; + case'timelapse': + $.timelapse.e.modal('show') + $.timelapse.monitors.find('.monitor').remove() + $.each($.ccio.mon,function(n,v){ + $.timelapse.monitors.append('') + }) + e.e=$.timelapse.monitors.find('.monitor').prop('selected',false) + if(e.mid!==''){ + e.e=$.timelapse.monitors.find('.monitor[value="'+e.mid+'"]') + } + e.e.first().prop('selected',true) + $.timelapse.f.submit() + break; + case'powerview': + $.pwrvid.e.modal('show') + $.pwrvid.m.empty() + $.each($.ccio.mon,function(n,v){ + $.pwrvid.m.append('') + }) + e.e=$.pwrvid.m.find('option').prop('selected',false) + if(e.mid!==''){ + e.e=$.pwrvid.m.find('[value="'+e.mid+'"]') + } + e.e.first().prop('selected',true) + $.pwrvid.f.submit() + break; + case'region': + if(!e.mon){ + $.ccio.init('note',{title:lang['Unable to Launch'],text:lang.UnabletoLaunchText,type:'error'}); + return; + } + e.d=JSON.parse(e.mon.details); + e.width=$.aM.e.find('[detail="detector_scale_x"]'); + e.height=$.aM.e.find('[detail="detector_scale_y"]'); + e.d.cords=$.aM.e.find('[detail="cords"]').val(); + if(e.width.val()===''){ + e.d.detector_scale_x=320; + e.d.detector_scale_y=240; + $.aM.e.find('[detail="detector_scale_x"]').val(e.d.detector_scale_x); + $.aM.e.find('[detail="detector_scale_y"]').val(e.d.detector_scale_y); + }else{ + e.d.detector_scale_x=e.width.val(); + e.d.detector_scale_y=e.height.val(); + } + + $.zO.e.modal('show'); + $.zO.o().attr('width',e.d.detector_scale_x).attr('height',e.d.detector_scale_y); + $.zO.c.css({width:e.d.detector_scale_x,height:e.d.detector_scale_y}); + if(e.d.cords&&(e.d.cords instanceof Object)===false){ + try{e.d.cords=JSON.parse(e.d.cords);}catch(er){} + } + if(!e.d.cords||e.d.cords===''){ + e.d.cords={ + red:{ name:"red",sensitivity:0.0005, max_sensitivity:"",color_threshold:"",points:[[0,0],[0,100],[100,0]] }, + } + } + $.zO.regionViewerDetails=e.d; + $.zO.initRegionList() + break; + case'detector_filters': + $.detectorFilters.e.modal('show'); + break; + case'snapshot': + $.ccio.snapshot(e,function(url){ + $('#temp').html('a').find('a')[0].click(); + }); + break; + case'control': + e.a=e.e.attr('control') + $.ccio.cx({f:'monitor',ff:'control',direction:e.a,mid:e.mid,ke:e.ke},user) + break; + case'videos_table':case'calendar':case'video_grid'://call videos table or calendar or video grid + $.vidview.launcher=$(this); + e.limit=$.vidview.limit.val(); + if(!$.vidview.current_mid||$.vidview.current_mid!==e.mid){ + $.vidview.current_mid=e.mid + $.vidview.current_page=1; + if(e.limit.replace(/ /g,'')===''){ + e.limit='100'; + } + if(e.limit.indexOf(',')===-1){ + e.limit='0,'+e.limit + }else{ + e.limit='0,'+e.limit.split(',')[1] + } + if(e.limit=='0,0'){ + e.limit='0' + } + $.vidview.limit.val(e.limit) + } + e.dateRange=$('#videos_viewer_daterange').data('daterangepicker'); + var videoSet = 'videos' + switch($.vidview.set.val()){ + case'cloud': + videoSet = 'cloudVideos' + break; + } + e.videoURL=$.ccio.init('location',user)+user.auth_token+'/'+videoSet+'/'+e.ke+'/'+e.mid+'?limit='+e.limit+'&start='+$.ccio.init('th',e.dateRange.startDate)+'&end='+$.ccio.init('th',e.dateRange.endDate); + $.getJSON(e.videoURL,function(d){ + d.pages=d.total/100; + $('.video_viewer_total').text(d.total) + if(d.pages+''.indexOf('.')>-1){++d.pages} + $.vidview.page_count=d.pages; + d.count=1 + $.vidview.pages.empty() + d.fn=function(drawOne){ + if(d.count<=$.vidview.page_count){ + $.vidview.pages.append(''+d.count+' ') + ++d.count; + d.fn() + } + } + d.fn() + $.vidview.pages.find('[page="'+$.vidview.current_page+'"]').addClass('active') + e.v=$.vidview.e; + $.vidview.loadedVideos = {} + e.b=e.v.modal('show').find('.modal-body .contents'); + e.t=e.v.find('.modal-title i'); + switch(e.a){ + case'calendar': + $.vidview.e.removeClass('dark') + e.t.attr('class','fa fa-calendar') + e.ar=[]; + if(d.videos[0]){ + $.each(d.videos,function(n,v){ + if(v.status !== 0){ + $.vidview.loadedVideos[v.filename] = Object.assign(v,{}) + var n=$.ccio.mon[v.ke+v.mid+user.auth_token]; + if(n){v.title=n.name+' - '+(parseInt(v.size)/1000000).toFixed(2)+'mb';} + v.start=v.time; + // v.filename=$.ccio.init('tf',v.time)+'.'+v.ext; + e.ar.push(v); + } + }) + e.b.html('') + try{e.b.fullCalendar('destroy')}catch(er){} + e.b.fullCalendar({ + header: { + left: 'prev,next today', + center: 'title', + right: 'month,agendaWeek,agendaDay,listWeek' + }, + defaultDate: $.ccio.timeObject(d.videos[0].time).format('YYYY-MM-DD'), + navLinks: true, + eventLimit: true, + events:e.ar, + eventClick:function(f){ + $('#temp').html('
      ').find('[video="launch"]').click(); + $(this).css('border-color', 'red'); + } + }); + setTimeout(function(){e.b.fullCalendar('changeView','month');e.b.find('.fc-scroller').css('height','auto')},500) + }else{ + e.b.html('
      '+lang.NoVideosFoundForDateRange+'
      ') + } + break; + case'video_grid': + $.vidview.e.addClass('dark') + var tmp = ''; + $.each(d.videos,function(n,v){ + var href = $.ccio.init('videoUrlBuild',v) + v.mon = $.ccio.mon[v.ke+v.mid+user.auth_token] + var parentTag = 'ke="'+v.ke+'" status="'+v.status+'" mid="'+v.mid+'" file="'+v.filename+'" auth="'+v.mon.user.auth_token+'"' + tmp += '
      ' + tmp += '
      ' + tmp += '
      '+$.ccio.timeObject(v.time).format('h:mm:ss A, MMMM Do YYYY')+'
      ' + tmp += '
      ' + tmp += '
      ' + tmp += '  ' + tmp += '  ' + tmp += '  ' + tmp += '
      ' + tmp += '
      ' + tmp += '
      ' + tmp += '
      ' + }) + tmp += '
      ' + e.b.html(tmp) + var i = 0 + var getThumbnail = function(){ + var v = d.videos[i] + if(v){ + tool.getVideoImage($.ccio.init('videoUrlBuild',v),0,function(err,base64){ + if(base64){ + $('[ke="'+v.ke+'"][mid="'+v.mid+'"][file="'+v.filename+'"] .thumb').css('background-image','url('+base64+')') + } + ++i + getThumbnail() + }) + } + } + getThumbnail() + break; + case'videos_table': + var showThumbnail = $.ccio.op().showThumbnail === '1' + $.vidview.e.removeClass('dark') + e.t.attr('class','fa fa-film') + var tmp = ''; + tmp+=''; + tmp+=''; + tmp+=''; + if(showThumbnail)tmp+=''; + tmp+=''; + tmp+=''; + tmp+=''; + tmp+=''; + tmp+=''; + tmp+=''; + tmp+=''; + tmp+=''; + tmp+=''; + tmp+=''; + // tmp+=''; + tmp+=''; + tmp+=''; + tmp+=''; + $.each(d.videos,function(n,v){ + if(v.status!==0){ + $.vidview.loadedVideos[v.filename] = Object.assign(v,{}) + var href = $.ccio.init('videoUrlBuild',v) + v.mon=$.ccio.mon[v.ke+v.mid+user.auth_token]; + v.start=v.time; + // v.filename=$.ccio.init('tf',v.time)+'.'+v.ext; + tmp+=''; + tmp+=''; + if(showThumbnail)tmp+=''; + tmp+=''; + tmp+=''; + tmp+=''; + tmp+=''; + tmp+=''; + tmp+=''; + tmp+=''; + tmp+=''; + tmp+=''; + tmp+=''; + // tmp+=''; + tmp+=''; + } + }) + tmp+=''; + tmp+='
      '+lang.Thumbnail+''+lang.Closed+''+lang.Ended+''+lang.Started+''+lang.Monitor+''+lang.Filename+''+lang['Size (mb)']+''+lang.Preview+''+lang.Watch+''+lang.Download+''+lang.Delete+''+lang.Fix+'
      '+$.ccio.timeObject(v.end).format('h:mm:ss A, MMMM Do YYYY')+''+$.ccio.timeObject(v.time).format('h:mm:ss A, MMMM Do YYYY')+''+v.mon.name+''+v.filename+''+(parseInt(v.size)/1000000).toFixed(2)+'          
      '; + e.b.html(tmp) + if(showThumbnail){ + var i = 0 + var getThumbnail = function(){ + var v = d.videos[i] + if(v){ + tool.getVideoImage($.ccio.init('videoUrlBuild',v),0,function(err,base64){ + if(base64){ + $('[data-ke="'+v.ke+'"][data-mid="'+v.mid+'"][data-file="'+v.filename+'"] .thumbnail')[0].src = base64 + } + ++i + getThumbnail() + }) + } + } + getThumbnail() + } + $.ccio.init('ls'); + $.vidview.e.find('table').bootstrapTable(); + break; + } + }) + break; + case'fullscreen': + e.e=e.e.parents('.monitor_item'); + e.e.addClass('fullscreen') + e.vid=e.e.find('.stream-element') + if(e.vid.is('canvas')){ + e.doc=$('body') + e.vid.attr('height',e.doc.height()) + e.vid.attr('width',e.doc.width()) + } + $.ccio.init('fullscreen',e.vid[0]) + break; + case'watch_on': + $.ccio.cx({f:'monitor',ff:'watch_on',id:e.mid},user) + break; + case'control_toggle': + e.e=e.p.find('.PTZ_controls'); + if(e.e.length>0){ + e.e.remove() + }else{ + var html = '
      ' + html += '
      ' + html += '
      ' + html += '
      ' + html += '
      ' + html += '
      ' + html += '
      ' + html += '
      ' + html += '
      ' + html += '' + html += '' + html += '
      ' + html += '
      ' + html += '' + html += '' + html += '
      ' + html += '
      ' + e.p.append(html) + } + break; + case'watch': + if($("#monitor_live_"+e.mid+user.auth_token).length===0||$.ccio.mon[e.ke+e.mid+user.auth_token].watch!==1){ + $.ccio.cx({f:'monitor',ff:'watch_on',id:e.mid},user) + }else{ + $("#main_canvas").animate({scrollTop:$("#monitor_live_"+e.mid+user.auth_token).offset().top-($('#main_header').height()+10)},500); + } + break; + case'watch_off': + $.ccio.cx({f:'monitor',ff:'watch_off',id:e.mid},user) + break; + case'delete': + e.m=$('#confirm_window').modal('show');e.f=e.e.attr('file'); + $.confirm.title.text(lang['Delete Monitor']+' : '+e.mon.name) + e.html=lang.DeleteMonitorText + e.html+=''; + $.each($.ccio.init('cleanMon',e.mon),function(n,v,g){ + if(n==='host'&&v.indexOf('@')>-1){g=v.split('@')[1]}else{g=v}; + try{JSON.parse(g);return}catch(err){} + e.html+=''; + }) + e.html+='
      '+n+''+g+'
      '; + $.confirm.body.html(e.html) + $.confirm.click([ + { + title:'Delete Monitor', + class:'btn-danger', + callback:function(){ + $.get($.ccio.init('location',user)+user.auth_token+'/configureMonitor/'+user.ke+'/'+e.mon.mid+'/delete',function(d){ + $.ccio.log(d) + }) + } + }, + { + title:'Delete Monitor and Files', + class:'btn-danger', + callback:function(){ + $.get($.ccio.init('location',user)+user.auth_token+'/configureMonitor/'+user.ke+'/'+e.mon.mid+'/delete?deleteFiles=true',function(d){ + $.ccio.log(d) + }) + } + } + ]) + break; + case'edit': + e.p=$('#add_monitor'),e.mt=e.p.find('.modal-title') + e.p.find('.am_notice').hide() + e.p.find('[detailcontainer="detector_cascades"]').prop('checked',false).parents('.mdl-js-switch').removeClass('is-checked') + if(!$.ccio.mon[e.ke+e.mid+user.auth_token]){ + e.p.find('.am_notice_new').show() + //new monitor + e.p.find('[monitor="delete"]').hide() + e.mt.find('span').text('Add'),e.mt.find('i').attr('class','fa fa-plus'); + //default values + e.values=$.aM.generateDefaultMonitorSettings(); + }else{ + e.p.find('.am_notice_edit').show() + //edit monitor + e.p.find('[monitor="delete"]').show() + e.mt.find('span').text(lang.Edit); + e.mt.find('i').attr('class','fa fa-wrench'); + e.values=$.ccio.mon[e.ke+e.mid+user.auth_token]; + } + $.aM.selected=e.values; + // e.openTabs=$.ccio.op().tabsOpen + // if(e.openTabs[e.mid]){ + // e.values=e.openTabs[e.mid] + // } + $.aM.import(e) + $('#add_monitor').modal('show') + break; + } + }) + .on('dblclick','[type="password"],.password_field',function(){ + var _this = $(this) + var type = 'password' + _this.addClass('password_field') + if(_this.attr('type') === 'password'){ + type = 'text' + } + _this.attr('type',type) + }) + + $('.modal').on('hidden.bs.modal',function(){ + $(this).find('video').remove(); + $(this).find('iframe').attr('src','about:blank'); + }); + $('.modal').on('shown.bs.modal',function(){ + e={e:$(this).find('.flex-container-modal-body')} + if(e.e.length>0){ + e.e.resize() + } + }); + + $('body') + .on('click','.scrollTo',function(ee){ + ee.preventDefault() + var e = {e:$(this)}; + e.parent=e.e.attr('scrollToParent') + if(!e.parent){ + e.parent='body,html' + } + $(e.parent).animate({ + scrollTop: $(e.e.attr('href')).position().top + }, 400); + }) + .on('resize','.flex-container-modal-body',function(e){ + e=$(this) + e.find('.flex-modal-block').css('height',e.height()) + }) + .on('resize','#monitors_live .monitor_item',function(e){ + e.e=$(this).find('.stream-block'); + e.c=e.e.find('canvas'); + e.c.attr('height',e.e.height()); + e.c.attr('width',e.e.width()); + }) + .on('keyup','.search-parent .search-controller',function(){ + _this = this; + $.each($(".search-parent .search-body .search-row"), function() { + if($(this).text().toLowerCase().indexOf($(_this).val().toLowerCase()) === -1) + $(this).hide(); + else + $(this).show(); + }); + }) + .on('dblclick','.stream-hud',function(){ + $(this).parents('[mid]').find('[monitor="fullscreen"]').click(); + }) + //.on('mousemove',".magnifyStream",$.ccio.magnifyStream) + //.on('touchmove',".magnifyStream",$.ccio.magnifyStream); +}) diff --git a/web/libs/js/dash2.gridstack.js b/web/libs/js/dash2.gridstack.js new file mode 100644 index 0000000..878bc91 --- /dev/null +++ b/web/libs/js/dash2.gridstack.js @@ -0,0 +1,61 @@ +$(document).ready(function(e){ +//monitor grid +$.grid={e:$('#monitors_live')} +$.grid.data = function(){ + return $.grid.e.data('gridstack') +} +$.grid.getMonitorsPerRow = function(){ + var x + switch($.ccio.op().montage){ + case'1': + x = '12' + break; + case'2': + x = '6' + break; + case'3': + x = '4' + break; + case'4': + x = '3' + break; + case'5': + x = '5' + break; + case'6': + x = '2' + break; + default://3 + x = '4' + break; + } + return x +} +$.grid.saveElementPositions = function() { + var monitors = {} + $.grid.e.find(" .monitor_item").each(function(n,v){ + var el = $(v) + var item = {} + item.ke = el.attr('ke') + item.mid = el.attr('mid') + item.x = el.attr('data-gs-x') + item.y = el.attr('data-gs-y') + item.height = el.attr('data-gs-height') + item.width = el.attr('data-gs-width') + monitors[item.ke+item.mid] = item + }) + $user.details.monitorOrder=monitors; + $.ccio.cx({f:'monitorOrder',monitorOrder:monitors}) +} +$.grid.e +.gridstack({ + cellHeight: 80, + verticalMargin: 0, +}) +.on('dragstop', function(event,ui){ + setTimeout(function(){ + $.grid.saveElementPositions() + },700) +}) +.on('gsresizestop', $.grid.saveElementPositions); +}) diff --git a/web/libs/js/dash2.init.js b/web/libs/js/dash2.init.js new file mode 100644 index 0000000..da42d6a --- /dev/null +++ b/web/libs/js/dash2.init.js @@ -0,0 +1,612 @@ +$.ccio.init=function(x,d,user,k){ + if(!k){k={}};k.tmp=''; + if(d&&d.user){ + user=d.user + } + if(!user){ + user=$user + } + switch(x){ + case'cleanMon': + var acceptedFields = [ + 'mid', + 'ke', + 'name', + 'shto', + 'shfr', + 'details', + 'type', + 'ext', + 'protocol', + 'host', + 'path', + 'port', + 'fps', + 'mode', + 'width', + 'height' + ] + var row = {}; + $.each(d,function(m,b){ + if(acceptedFields.indexOf(m)>-1){ + row[m]=b; + } + }) + return row + break; + case'cleanMons': + if(d==='object'){ + var arr={} + }else{ + var arr=[] + } + $.each($.ccio.mon,function(n,v){ + var row = $.ccio.init('cleanMon',v) + if(d==='object'){ + arr[n]=row + }else{ + arr.push(row) + } + }) + return arr; + break; + case'location': + var url + if(d&&d.info&&d.info.URL){ + url=d.info.URL + if(url.charAt(url.length-1)!=='/'){ + url=url+'/' + } + }else{ + url = $.ccio.libURL + } + return url + break; + case'videoUrlBuild': + var url + if(d.href){ + url = d.href + }else if(!d.href && d.hrefNoAuth){ + url = $.ccio.init('location',user)+user.auth_token+d.hrefNoAuth + } + if(user!==$user&&url.charAt(0)==='/'){ + url = $.ccio.init('location',user)+d.href.substring(1) + } + return url + break; + case'videoHrefToDelete': + var urlSplit = d.split('?') + var url = urlSplit[0]+'/delete' + if(urlSplit[1])url += '?' + urlSplit[1] + return url + break; + case'videoHrefToUnread': + var urlSplit = d.split('?') + var url = urlSplit[0]+'/status/1' + if(urlSplit[1])url += '?' + urlSplit[1] + return url + break; + case'videoHrefToRead': + var urlSplit = d.split('?') + var url = urlSplit[0]+'/status/2' + if(urlSplit[1])url += '?' + urlSplit[1] + return url + break; +// case'streamWindow': +// return $('.monitor_item[mid="'+d.id+'"][ke="'+d.ke+'"][auth="'+user.auth_token+'"]') +// break; + case'streamMotionDetectRestart': + $.ccio.init('streamMotionDetectOff',d,user) + $.ccio.init('streamMotionDetectOn',d,user) + break; + case'streamMotionDetectOff': + d.mon.motionDetectionRunning = false + $('.monitor_item[mid="'+d.mid+'"][ke="'+d.ke+'"][auth="'+user.auth_token+'"]').find('.stream-detected-object,.zoomGlass').remove() + clearInterval(d.mon.motionDetector) + break; + case'streamMotionDetectOn': + switch(JSON.parse(d.mon.details).stream_type){ + case'hls':case'flv':case'mp4': + //pass + break; + default: + return $.ccio.init('note',{title:'Client-side Detector',text:'Could not be started. Only FLV and HLS can use this feature.',type:'error'}); + break; + + } + d.mon.motionDetectorNextDraw = true + d.mon.motionDetectionRunning = true + $.ccio.snapshot(d,function(url){ + $('#temp').html('') + var img=$('#temp img')[0] + img.onload=function(){ + var frameNumber = 0, + mainWindow = $('.monitor_item[mid="'+d.mid+'"][ke="'+d.ke+'"][auth="'+user.auth_token+'"]'), + blenderCanvas = mainWindow.find(".blenderCanvas"), + motionVision = mainWindow.find(".motionVision"), + streamElement = mainWindow.find('.stream-element'), + streamElementTag = streamElement[0], + lastURL = null, + currentImage = null, + f = [], + drawMatrices = { + e:mainWindow, + monitorDetails:JSON.parse(d.mon.details), + stream:streamElement, + streamObjects:mainWindow.find('.stream-objects'), + details:{ + name:'clientSideDetection', + } + }; + widthRatio = streamElement.width() / img.width + heightRatio = streamElement.height() / img.height + drawMatrices.monitorDetails.detector_scale_x = img.width; + drawMatrices.monitorDetails.detector_scale_y = img.height; + function checkForMotion() { + blenderCanvas.width = img.width; + blenderCanvas.height = img.height; + blenderCanvasContext.drawImage(streamElementTag, 0, 0); + f[frameNumber] = blenderCanvasContext.getImageData(0, 0, blenderCanvas.width, blenderCanvas.height); + frameNumber = 0 == frameNumber ? 1 : 0; + currentImage = blenderCanvasContext.getImageData(0, 0, blenderCanvas.width, blenderCanvas.height); + foundPixels = []; + for (var currentImageLength = currentImage.data.length * 0.25, b = 0; b < currentImageLength;){ + var pos = b * 4 + currentImage.data[pos] = .5 * (255 - currentImage.data[pos]) + .5 * f[frameNumber].data[pos]; + currentImage.data[pos + 1] = .5 * (255 - currentImage.data[pos + 1]) + .5 * f[frameNumber].data[pos + 1]; + currentImage.data[pos + 2] = .5 * (255 - currentImage.data[pos + 2]) + .5 * f[frameNumber].data[pos + 2]; + currentImage.data[pos + 3] = 255; + var score = (currentImage.data[pos] + currentImage.data[pos + 1] + currentImage.data[pos + 2]) / 3; + if(score>170){ + var x = (pos / 4) % img.width; + var y = Math.floor((pos / 4) / img.width); + foundPixels.push([x,y]) + } + b += 4; + } + var groupedPoints = Object.assign({},Cluster); + groupedPoints.iterations(25); + groupedPoints.data(foundPixels); + var groupedPoints = groupedPoints.clusters() + drawMatrices.details.matrices=[] + var mostHeight = 0; + var mostWidth = 0; + var mostWithMotion = null; + groupedPoints.forEach(function(v,n){ + var matrix = { + topLeft:[img.width,img.height], + topRight:[0,img.height], + bottomRight:[0,0], + bottomLeft:[img.width,0], + } + v.points.forEach(function(b){ + var x = b[0] + var y = b[1] + if(xmatrix.topRight[0])matrix.topRight[0]=x; + if(ymatrix.bottomRight[0])matrix.bottomRight[0]=x; + if(y>matrix.bottomRight[1])matrix.bottomRight[1]=y; + //Bottom Left point + if(xmatrix.bottomLeft[1])matrix.bottomLeft[1]=y; + }) + matrix.x = matrix.topLeft[0]; + matrix.y = matrix.topLeft[1]; + matrix.width = matrix.topRight[0] - matrix.topLeft[0] + matrix.height = matrix.bottomLeft[1] - matrix.topLeft[1] + + if(matrix.width>mostWidth&&matrix.height>mostHeight){ + mostWidth = matrix.width; + mostHeight = matrix.height; + mostWithMotion = matrix; + } + + drawMatrices.details.matrices.push(matrix) + }) + $.ccio.magnifyStream({ + p:mainWindow, + useCanvas:true, + zoomAmount:1, + auto:true, + animate:true, + pageX:((mostWithMotion.width / 2) + mostWithMotion.x) * widthRatio, + pageY:((mostWithMotion.height / 2) + mostWithMotion.y) * heightRatio + }) + $.ccio.init('drawMatrices',drawMatrices) + if(d.mon.motionDetectorNextDraw===true){ + clearTimeout(d.mon.motionDetectorNextDrawTimeout) + d.mon.motionDetectorNextDrawTimeout=setTimeout(function(){ + d.mon.motionDetectorNextDraw = true; + },1000) + d.mon.motionDetectorNextDraw = false; +// console.log({ +// p:mainWindow, +// pageX:((matrix.width / 2) + matrix.x) * widthRatio, +// pageY:((matrix.height / 2) + matrix.y) * heightRatio +// }) + } + return drawMatrices.details.matrices; + } + if(blenderCanvas.length === 0){ + mainWindow.append('
      ') + blenderCanvas = mainWindow.find(".blenderCanvas") + } + blenderCanvas = blenderCanvas[0]; + var blenderCanvasContext = blenderCanvas.getContext("2d"); + clearInterval(d.mon.motionDetector) + d.mon.motionDetector = setInterval(checkForMotion,2000) + } + img.src=url + }) + break; + case'streamURL': + var streamURL + switch(JSON.parse(d.details).stream_type){ + case'jpeg': + streamURL=$.ccio.init('location',user)+user.auth_token+'/jpeg/'+d.ke+'/'+d.mid+'/s.jpg' + break; + case'mjpeg': + streamURL=$.ccio.init('location',user)+user.auth_token+'/mjpeg/'+d.ke+'/'+d.mid + break; + case'hls': + streamURL=$.ccio.init('location',user)+user.auth_token+'/hls/'+d.ke+'/'+d.mid+'/s.m3u8' + break; + case'flv': + streamURL=$.ccio.init('location',user)+user.auth_token+'/flv/'+d.ke+'/'+d.mid+'/s.flv' + break; + case'h265': + streamURL=$.ccio.init('location',user)+user.auth_token+'/h265/'+d.ke+'/'+d.mid+'/s.hevc' + break; + case'mp4': + streamURL=$.ccio.init('location',user)+user.auth_token+'/mp4/'+d.ke+'/'+d.mid+'/s.mp4' + break; + case'b64': + streamURL='Websocket' + break; + case'pam': + streamURL='Websocket' + break; + } + return streamURL + break; + case'humanReadMode': + switch(d){ + case'idle': + k.mode=lang['Idle'] + break; + case'stop': + k.mode=lang['Disabled'] + break; + case'record': + k.mode=lang['Record'] + break; + case'start': + k.mode=lang['Watch Only'] + break; + } + return k.mode + break; + case'monitorInfo': + d.e=$('.glM'+d.mon.mid+user.auth_token); + if(JSON.parse(d.mon.details).vcodec!=='copy'&&d.mon.mode=='record'){ + d.e.find('.monitor_not_record_copy').show() + }else{ + d.e.find('.monitor_not_record_copy').hide() + } + d.e.find('.monitor_name').text(d.mon.name) + d.e.find('.monitor_mid').text(d.mon.mid) + d.e.find('.monitor_ext').text(d.mon.ext); + d.mode=$.ccio.init('humanReadMode',d.mon.mode,user) + d.e.find('.monitor_mode').text(d.mode) + d.e.find('.monitor_status').text(d.status) + d.e.attr('mode',d.mode) + d.e.find('.lamp').attr('title',d.mode) + break; + case'fullscreen': + if (d.requestFullscreen) { + d.requestFullscreen(); + } else if (d.mozRequestFullScreen) { + d.mozRequestFullScreen(); + } else if (d.webkitRequestFullscreen) { + d.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT); + } + break; + case'drawPoints': + d.height=d.stream.height() + d.width=d.stream.width() + if(d.monitorDetails.detector_scale_x===''){d.monitorDetails.detector_scale_x=320} + if(d.monitorDetails.detector_scale_y===''){d.monitorDetails.detector_scale_y=240} + + d.widthRatio=d.width/d.monitorDetails.detector_scale_x + d.heightRatio=d.height/d.monitorDetails.detector_scale_y + + d.streamObjects.find('.stream-detected-point[name="'+d.details.name+'"]').remove() + d.tmp='' + $.each(d.details.points,function(n,v){ + d.tmp+='
      ' + if(v.tag){d.tmp+=''+v.tag+''} + d.tmp+='
      ' + }) + d.streamObjects.append(d.tmp) + break; + case'drawMatrices': + d.height=d.stream.height() + d.width=d.stream.width() + if(d.monitorDetails.detector_scale_x===''){d.monitorDetails.detector_scale_x=320} + if(d.monitorDetails.detector_scale_y===''){d.monitorDetails.detector_scale_y=240} + + d.widthRatio=d.width/d.monitorDetails.detector_scale_x + d.heightRatio=d.height/d.monitorDetails.detector_scale_y + + d.streamObjects.find('.stream-detected-object[name="'+d.details.name+'"]').remove() + d.tmp='' + $.each(d.details.matrices,function(n,v){ + d.tmp+='
      ' + if(v.tag){d.tmp+=''+v.tag+''} + d.tmp+='
      ' + }) + d.streamObjects.append(d.tmp) + break; + case'clearTimers': + if(!d.mid){d.mid=d.id} + if($.ccio.mon[d.ke+d.mid+user.auth_token]){ + clearTimeout($.ccio.mon[d.ke+d.mid+user.auth_token]._signal); + clearInterval($.ccio.mon[d.ke+d.mid+user.auth_token].hlsGarbageCollectorTimer) + clearTimeout($.ccio.mon[d.ke+d.mid+user.auth_token].jpegInterval); + clearInterval($.ccio.mon[d.ke+d.mid+user.auth_token].signal); + clearInterval($.ccio.mon[d.ke+d.mid+user.auth_token].m3uCheck); + if($.ccio.mon[d.ke+d.mid+user.auth_token].Base64 && $.ccio.mon[d.ke+d.mid+user.auth_token].Base64.connected){ + $.ccio.mon[d.ke+d.mid+user.auth_token].Base64.disconnect() + } + if($.ccio.mon[d.ke+d.mid+user.auth_token].Poseidon){ + $.ccio.mon[d.ke+d.mid+user.auth_token].Poseidon.stop() + } + } + break; + case'note': + k.o=$.ccio.op().switches + if(k.o&&k.o.notifyHide!==1){ + new PNotify(d) + if(user.details.audio_note && user.details.audio_note !== ''){ + var audio = new Audio('libs/audio/'+user.details.audio_note); + audio.play() + } + } + break; + case'monGroup': + $.ccio.mon_groups={}; + $.each($.ccio.mon,function(n,v,x){ + if(typeof v.details==='string'){ + k.d=JSON.parse(v.details) + }else{ + k.d=v.details + } + try{ + k.groups=JSON.parse(k.d.groups) + $.each(k.groups,function(m,b){ + if(!$.ccio.mon_groups[b])$.ccio.mon_groups[b]={} + $.ccio.mon_groups[b][v.mid]=v; + }) + }catch(er){ + + } + }) + return $.ccio.mon_groups; + break; + case'closeVideo': + var el = $('#monitor_live_'+d.mid+user.auth_token) + var video = el.find('video') + if(video.length === 1){ + if(!video[0].paused){ + video[0].onerror = function(){} + video[0].pause() + } + video.prop('src',''); + video.find('source').remove(); + video.remove(); + } + break; + case'jpegModeStop': + clearTimeout($.ccio.mon[d.ke+d.mid+user.auth_token].jpegInterval); + delete($.ccio.mon[d.ke+d.mid+user.auth_token].jpegInterval); + $('#monitor_live_'+d.mid+user.auth_token+' .stream-element').unbind('load') + break; + case'jpegMode': + if(d.watch===1){ + k=JSON.parse(d.details); + k.jpegInterval=parseFloat(k.jpegInterval); + if(!k.jpegInterval||k.jpegInterval===''||isNaN(k.jpegInterval)){k.jpegInterval=1} + $.ccio.tm('stream-element',$.ccio.mon[d.ke+d.mid+user.auth_token]); + k.e=$('#monitor_live_'+d.mid+user.auth_token+' .stream-element'); + $.ccio.init('jpegModeStop',d,user); + k.run=function(){ + k.e.attr('src',$.ccio.init('location',user)+user.auth_token+'/jpeg/'+d.ke+'/'+d.mid+'/s.jpg?time='+(new Date()).getTime()) + } + k.e.load(function(){ + $.ccio.mon[d.ke+d.mid+user.auth_token].jpegInterval=setTimeout(k.run,1000/k.jpegInterval); + }).error(function(){ + $.ccio.mon[d.ke+d.mid+user.auth_token].jpegInterval=setTimeout(k.run,1000/k.jpegInterval); + }) + k.run() + }; + break; + case'jpegModeAll': + $.each($.ccio.mon,function(n,v){ + $.ccio.init('jpegMode',v,user) + }); + break; + case'getLocation': + var l = document.createElement("a"); + l.href = d; + return l; + break; + case 'ls'://livestamp all + g={e:jQuery('.livestamp')}; + g.e.each(function(){g.v=jQuery(this),g.t=g.v.attr('title');if(!g.t){return};g.v.toggleClass('livestamp livestamped').attr('title',$.ccio.init('t',g.t,user)).livestamp(g.t);}) + return g.e + break; + case't'://format time + if(!d){d=new Date();} + return $.ccio.timeObject(d).format('YYYY-MM-DD HH:mm:ss') + break; + case'th'://format time hy + if(!d){d=new Date();} + return $.ccio.timeObject(d).format('YYYY-MM-DDTHH:mm:ss') + break; + case'tf'://time to filename + if(!d){d=new Date();} + return $.ccio.timeObject(d).format('YYYY-MM-DDTHH-mm-ss') + break; + case'fn'://row to filename + return $.ccio.init('tf',d.time,user)+'.'+d.ext + break; + case'filters': + k.tmp=''; + $.each(user.details.filters,function(n,v){ + k.tmp+='' + }); + $('#saved_filters').html(k.tmp) + break; + case'id': + $('.usermail').html(d.mail) + try{k.d=JSON.parse(d.details);}catch(er){k.d=d.details;} + try{user.mon_groups=JSON.parse(k.d.mon_groups);}catch(er){} + if(!user.mon_groups)user.mon_groups={}; + $.sM.reDrawMonGroups() + $.each(user,function(n,v){$.sM.e.find('[name="'+n+'"]').val(v).change()}) + $.each(k.d,function(n,v){$.sM.e.find('[detail="'+n+'"]').val(v).change()}) + $.gR.drawList(); + $.ccio.pm('link-set',k.d.links,null,user) + break; + case'jsontoblock'://draw json as block + if(d instanceof Object){ + $.each(d,function(n,v){ + k.tmp+='
      '; + k.tmp+=''+n+' : '+$.ccio.init('jsontoblock',v,user); + k.tmp+='
      '; + }) + }else{ + k.tmp+=''; + k.tmp+=d; + k.tmp+=''; + } + break; + case'url': + var porty + if(d.port && d.port !== ''){ + porty = ':' + d.port + }else{ + porty = '' + } + d.url = d.protocol + '://' + d.host + porty + return d.url + break; + case'data-video': + if(!d){ + $('[data-mid]').each(function(n,v){ + v=$(v);v.attr('mid',v.attr('data-mid')) + }); + $('[data-ke]').each(function(n,v){ + v=$(v);v.attr('ke',v.attr('data-ke')) + }); + $('[data-file]').each(function(n,v){ + v=$(v);v.attr('file',v.attr('data-file')) + }); + $('[data-status]').each(function(n,v){ + v=$(v);v.attr('status',v.attr('data-status')) + }); + $('[data-auth]').each(function(n,v){ + v=$(v);v.attr('auth',v.attr('data-auth')) + }); + }else{ + $('[data-ke="'+d.ke+'"][data-mid="'+d.mid+'"][data-file="'+d.filename+'"][auth="'+user.auth_token+'"]').attr('mid',d.mid).attr('ke',d.ke).attr('status',d.status).attr('file',d.filename).attr('auth',user.auth_token); + } + break; + case'signal': + d.mon=$.ccio.mon[d.ke+d.id+user.auth_token];d.e=$('#monitor_live_'+d.id+user.auth_token+' .signal').addClass('btn-success').removeClass('btn-danger');d.signal=parseFloat(JSON.parse(d.mon.details).signal_check); + if(!d.signal||d.signal==NaN){d.signal=10;};d.signal=d.signal*1000*60; + clearTimeout($.ccio.mon[d.ke+d.id+user.auth_token]._signal);$.ccio.mon[d.ke+d.id+user.auth_token]._signal=setTimeout(function(){d.e.addClass('btn-danger').removeClass('btn-success');},d.signal) + break; + case'signal-check': + try{ + d.mon=$.ccio.mon[d.ke+d.id+user.auth_token];d.p=$('#monitor_live_'+d.id+user.auth_token); + try{d.d=JSON.parse(d.mon.details)}catch(er){d.d=d.mon.details;} + d.check={c:0}; + d.fn=function(){ + if(!d.speed){d.speed=1000} + switch(d.d.stream_type){ + case'b64':case'h265': + d.p.resize() + break; + case'hls':case'flv':case'mp4': + if(d.p.find('video')[0].paused){ + if(d.d.signal_check_log==1){ + d.log={type:'Stream Check',msg:lang.clientStreamFailedattemptingReconnect} + $.ccio.tm(4,d,'#logs,.monitor_item[mid="'+d.id+'"][ke="'+d.ke+'"][auth="'+user.auth_token+'"] .logs') + } + $.ccio.cx({f:'monitor',ff:'watch_on',id:d.id},user); + }else{ + if(d.d.signal_check_log==1){ + d.log={type:'Stream Check',msg:'Success'} + $.ccio.tm(4,d,'#logs,.monitor_item[mid="'+d.id+'"][ke="'+d.ke+'"][auth="'+user.auth_token+'"] .logs') + } + $.ccio.init('signal',d,user); + } + break; + default: + if($.ccio.op().jpeg_on===true){return} + $.ccio.snapshot(d,function(url){ + d.check.f=url; + setTimeout(function(){ + $.ccio.snapshot(d,function(url){ + if(d.check.f===url){ + if(d.check.c<3){ + ++d.check.c; + setTimeout(function(){ + d.fn(); + },d.speed) + }else{ + if(d.d.signal_check_log==1){ + d.log={type:'Stream Check',msg:'Client side ctream check failed, attempting reconnect.'} + $.ccio.tm(4,d,'#logs,.monitor_item[mid="'+d.id+'"][ke="'+d.ke+'"][auth="'+user.auth_token+'"] .logs') + } + delete(d.check) + $.ccio.cx({f:'monitor',ff:'watch_on',id:d.id},user); + } + }else{ + if(d.d.signal_check_log==1){ + d.log={type:'Stream Check',msg:'Success'} + $.ccio.tm(4,d,'#logs,.monitor_item[mid="'+d.id+'"][ke="'+d.ke+'"][auth="'+user.auth_token+'"] .logs') + } + delete(d.check) + $.ccio.init('signal',d,user); + } + }); + },d.speed) + }); + break; + } + } + d.fn(); + }catch(er){ + er=er.stack; + d.in=function(x){return er.indexOf(x)>-1} + switch(true){ + case d.in("The HTMLImageElement provided is in the 'broken' state."): + delete(d.check) + $.ccio.cx({f:'monitor',ff:'watch_on',id:d.id},user); + break; + default: + $.ccio.log('signal-check',er) + break; + } + clearInterval($.ccio.mon[d.ke+d.id+user.auth_token].signal);delete($.ccio.mon[d.ke+d.id+user.auth_token].signal); + } + break; + } + return k.tmp; +} diff --git a/web/libs/js/dash2.logviewer.js b/web/libs/js/dash2.logviewer.js new file mode 100644 index 0000000..40ec0eb --- /dev/null +++ b/web/libs/js/dash2.logviewer.js @@ -0,0 +1,66 @@ +$(document).ready(function(e){ +//log viewer +$.log = { + e : $('#logs_modal'), + lm : $('#log_monitors'), + dateRange : $('#logs_daterange'), + loaded : {} +} +$.log.dateRange.daterangepicker({ + startDate:$.ccio.timeObject().subtract(moment.duration("5:00:00")), + endDate:$.ccio.timeObject().add(moment.duration("24:00:00")), + timePicker: true, + timePicker24Hour: true, + timePickerSeconds: true, + timePickerIncrement: 30, + locale: { + format: 'MM/DD/YYYY h:mm A' + } +},function(start, end, label){ + //change daterange + $.log.lm.change() +}); +$.log.table = $.log.e.find('table') +$.log.e.on('shown.bs.modal', function () { + $.log.lm.find('option:not(.hard)').remove() + $.each($.ccio.mon,function(n,v){ + v.id = v.mid + $.ccio.tm('option',v,'#log_monitors') + }) + $.log.lm.change() +}) +$.log.lm.change(function(){ + e = {} + e.v = $(this).val(); + e.urlSelector = e.v+''; + if(e.v === 'all'){ + e.urlSelector = '' + } + e.dateRange = $.log.dateRange.data('daterangepicker'); + $.log.loaded.startDate = e.dateRange.startDate + $.log.loaded.endDate = e.dateRange.endDate + var url = $.ccio.init('location',$user)+$user.auth_token+'/logs/'+$user.ke+'/'+e.urlSelector+'?start='+$.ccio.init('th',$.log.loaded.startDate)+'&end='+$.ccio.init('th',$.log.loaded.endDate) + $.get(url,function(d){ + $.log.loaded.url = url + $.log.loaded.query = e.v + $.log.loaded.rows = d + e.tmp=''; + if(d.length === 0){ + e.tmp = ''+lang.NoLogsFoundForDateRange+'' + }else{ + $.each(d,function(n,v){ + e.tmp+=''+v.time+''+v.mid+''+$.ccio.init('jsontoblock',v.info)+'' + }) + } + $.log.table.find('tbody').html(e.tmp) +// $.log.table.bootstrapTable() + $.ccio.init('ls') + }) +}) +$.log.e.find('[download]').click(function(){ + $.ccio.downloadJSON($.log.loaded,'Shinobi_Logs_'+(new Date())+'.json',{ + title : 'No Logs Found', + text : 'No file will be downloaded.', + }) +}) +}) diff --git a/web/libs/js/dash2.monitoredit.js b/web/libs/js/dash2.monitoredit.js new file mode 100644 index 0000000..fe04c99 --- /dev/null +++ b/web/libs/js/dash2.monitoredit.js @@ -0,0 +1,830 @@ +$(document).ready(function(e){ + +//Monitor Editor +$.aM={e:$('#add_monitor'),monitorsForCopy:$('#copy_settings_monitors')}; +$.aM.f=$.aM.e.find('form') +$.aM.channels=$('#monSectionStreamChannels') +$.aM.maps=$('#monSectionInputMaps') +$.aM.e.find('.follow-list ul').affix(); +$.each($.ccio.definitions["Monitor Settings"].blocks,function(n,v){ + $.each(v.info,function(m,b){ + if(!b.name){ + console.log(b) + return + } + if(b.name.indexOf('detail=')>-1){ + b.name=b.name.replace('detail=','') + v.element=$.aM.e.find('[detail="'+b.name+'"]') + }else{ + v.element=$.aM.e.find('[name="'+b.name+'"]') + } + v.parent=v.element.parents('.form-group').find('label div:first-child span') + v.parent.find('small').remove() + v.parent.append(''+b.description+'') + }) +}) +$.aM.generateDefaultMonitorSettings=function(){ + return { + "mode": "start", + "mid": $.ccio.gid(), + "name": "Some Stream", + "type": "h264", + "protocol": "rtsp", + "host": "", + "port": "", + "path": "", + "ext": "mp4", + "fps": "1", + "width": "640", + "height": "480", + "details": JSON.stringify({ + "fatal_max": "0", + "notes": "", + "dir": "", + "auto_host_enable": "1", + "auto_host": "", + "rtsp_transport": "tcp", + "muser": "", + "mpass": "", + "port_force": "0", + "aduration": "1000000", + "probesize": "1000000", + "stream_loop": "0", + "sfps": "", + "accelerator": "0", + "hwaccel": "auto", + "hwaccel_vcodec": "", + "hwaccel_device": "", + "stream_type": "mp4", + "stream_flv_type": "ws", + "stream_mjpeg_clients": "", + "stream_vcodec": "copy", + "stream_acodec": "no", + "hls_time": "2", + "preset_stream": "ultrafast", + "hls_list_size": "3", + "signal_check": "10", + "signal_check_log": "0", + "stream_quality": "15", + "stream_fps": "2", + "stream_scale_x": "", + "stream_scale_y": "", + "rotate_stream": "no", + "svf": "", + "rtmp_vcodec": "h264", + "rtmp_acodec": "aac", + "stream_timestamp": "0", + "stream_timestamp_font": "", + "stream_timestamp_font_size": "", + "stream_timestamp_color": "", + "stream_timestamp_box_color": "", + "stream_timestamp_x": "", + "stream_timestamp_y": "", + "stream_watermark": "0", + "stream_watermark_location": "", + "stream_watermark_position": "tr", + "snap": "0", + "snap_fps": "", + "snap_scale_x": "", + "snap_scale_y": "", + "snap_vf": "", + "rawh264": "0", + "rawh264_vcodec": "copy", + "rawh264_acodec": "", + "rawh264_fps": "", + "rawh264_scale_x": "", + "rawh264_scale_y": "", + "rawh264_crf": "", + "rawh264_vf": "", + "vcodec": "copy", + "crf": "1", + "preset_record": "", + "acodec": "no", + "dqf": "0", + "cutoff": "15", + "rotate_record": "no", + "vf": "", + "timestamp": "0", + "timestamp_font": "", + "timestamp_font_size": "10", + "timestamp_color": "white", + "timestamp_box_color": "0x00000000@1", + "timestamp_x": "(w-tw)/2", + "timestamp_y": "0", + "watermark": "0", + "watermark_location": "", + "watermark_position": "tr", + "cust_input": "", + "cust_snap": "", + "cust_rawh264": "", + "cust_detect": "", + "cust_stream": "", + "cust_stream_server": "", + "cust_record": "", + "custom_output": "", + "detector": "0", + "detector_pam": "1", + "detector_webhook": "0", + "detector_webhook_url": "", + "detector_command_enable": "0", + "detector_command": "", + "detector_command_timeout": "", + "detector_lock_timeout": "", + "detector_save": "0", + "detector_frame_save": "0", + "detector_mail": "0", + "detector_mail_timeout": "", + "detector_record_method": "sip", + "detector_trigger": "1", + "detector_trigger_record_fps": "", + "detector_timeout": "10", + "watchdog_reset": "0", + "detector_delete_motionless_videos": "0", + "detector_send_frames": "1", + "detector_region_of_interest": "0", + "detector_fps": "", + "detector_scale_x": "640", + "detector_scale_y": "480", + "detector_use_motion": "1", + "detector_use_detect_object": "0", + "detector_frame": "0", + "detector_sensitivity": "", + "detector_max_sensitivity": "", + "detector_threshold": "1", + "detector_color_threshold": "", + "cords": "[]", + "detector_buffer_vcodec": "auto", + "detector_buffer_fps": "", + "detector_buffer_hls_time": "", + "detector_buffer_hls_list_size": "", + "detector_buffer_start_number": "", + "detector_buffer_live_start_index": "", + "detector_lisence_plate": "0", + "detector_lisence_plate_country": "us", + "detector_notrigger": "0", + "detector_notrigger_mail": "0", + "detector_notrigger_timeout": "", + "control": "0", + "control_base_url": "", + "control_stop": "0", + "control_url_stop_timeout": "", + "control_url_center": "", + "control_url_left": "", + "control_url_left_stop": "", + "control_url_right": "", + "control_url_right_stop": "", + "control_url_up": "", + "control_url_up_stop": "", + "control_url_down": "", + "control_url_down_stop": "", + "control_url_enable_nv": "", + "control_url_disable_nv": "", + "control_url_zoom_out": "", + "control_url_zoom_out_stop": "", + "control_url_zoom_in": "", + "control_url_zoom_in_stop": "", + "tv_channel": "0", + "groups": "[]", + "loglevel": "warning", + "sqllog": "0", + "detector_cascades": "" + }), + "shto": "[]", + "shfr": "[]" +} +} +$.aM.drawList=function(){ + e={list:$.aM.e.find('.follow-list ul'),html:''} + $.aM.e.find('[section]:visible').each(function(n,v){ + e.e=$(v) + e.id = e.e.attr('id'); + e.title = e.e.find('h4').first().html(); + var div = document.createElement('div'); + div.innerHTML = e.title; + var elements = div.getElementsByTagName('a'); + while (elements[0]) + elements[0].parentNode.removeChild(elements[0]) + var elements = div.getElementsByTagName('small'); + while (elements[0]) + elements[0].parentNode.removeChild(elements[0]) + var repl = div.innerHTML; + e.html += '
    • '+repl+'
    • ' + }) + e.list.html(e.html) +} +$.aM.import=function(e){ + $.get($.ccio.init('location',$user)+$user.auth_token+'/hls/'+e.values.ke+'/'+e.values.mid+'/detectorStream.m3u8',function(data){ + $('#monEditBufferPreview').html(data) + }) + $.aM.e.find('.edit_id').text(e.values.mid); + $.aM.e.attr('mid',e.values.mid).attr('ke',e.values.ke).attr('auth',e.auth) + $.each(e.values,function(n,v){ + $.aM.e.find('[name="'+n+'"]').val(v).change() + }) + e.ss=JSON.parse(e.values.details); + //get maps + $.aM.maps.empty() + if(e.ss.input_maps&&e.ss.input_maps!==''){ + var input_maps + try{ + input_maps = JSON.parse(e.ss.input_maps) + }catch(er){ + input_maps = e.ss.input_maps; + } + if(input_maps.length>0){ + $.aM.showInputMappingFields() + $.each(input_maps,function(n,v){ + var tempID = $.ccio.tm('input-map') + var parent = $('#monSectionMap'+tempID) + $.each(v,function(m,b){ + parent.find('[map-detail="'+m+'"]').val(b).change() + }) + }) + }else{ + $.aM.showInputMappingFields(false) + } + } + //get channels + $.aM.channels.empty() + if(e.ss.stream_channels&&e.ss.stream_channels!==''){ + var stream_channels + try{ + stream_channels = JSON.parse(e.ss.stream_channels) + }catch(er){ + stream_channels = e.ss.stream_channels; + } + $.each(stream_channels,function(n,v){ + var tempID = $.ccio.tm('stream-channel') + var parent = $('#monSectionChannel'+tempID) + $.each(v,function(m,b){ + parent.find('[channel-detail="'+m+'"]').val(b) + }) + }) + } + //get map choices for outputs + $('[input-mapping] .choices').empty() + if(e.ss.input_map_choices&&e.ss.input_map_choices!==''){ + var input_map_choices + try{ + input_map_choices = JSON.parse(e.ss.input_map_choices) + }catch(er){ + input_map_choices = e.ss.input_map_choices; + } + $.each(input_map_choices,function(n,v){ + $.each(v,function(m,b){ + var parent = $('[input-mapping="'+n+'"] .choices') + $.ccio.tm('input-map-selector',b,parent) + }) + }) + } + $.aM.e.find('[detail]').each(function(n,v){ + v=$(v).attr('detail');if(!e.ss[v]){e.ss[v]=''} + }) + $.each(e.ss,function(n,v){ + var theVal = v; + if(v instanceof Object){ + theVal = JSON.stringify(v); + } + $.aM.e.find('[detail="'+n+'"]').val(theVal).change(); + }); + $.each(e.ss,function(n,v){ + try{ + var variable=JSON.parse(v) + }catch(err){ + var variable=v + } + if(variable instanceof Object){ + $('[detailContainer="'+n+'"][detailObject]').prop('checked',false) + $('[detailContainer="'+n+'"][detailObject]').parents('.mdl-js-switch').removeClass('is-checked') + if(variable instanceof Array){ + $.each(variable,function(m,b,parentOfObject){ + $('[detailContainer="'+n+'"][detailObject="'+b+'"]').prop('checked',true) + parentOfObject=$('[detailContainer="'+n+'"][detailObject="'+b+'"]').parents('.mdl-js-switch') + parentOfObject.addClass('is-checked') + }) + }else{ + $.each(variable,function(m,b){ + if(typeof b ==='string'){ + $('[detailContainer="'+n+'"][detailObject="'+m+'"]').val(b).change() + }else{ + $('[detailContainer="'+n+'"][detailObject="'+m+'"]').prop('checked',true) + parentOfObject=$('[detailContainer="'+n+'"][detailObject="'+m+'"]').parents('.mdl-js-switch') + parentOfObject.addClass('is-checked') + } + }) + } + } + }); + try{ + $.each(['groups','group_detector_multi'],function(m,b){ + var tmp='' + $.each($user.mon_groups,function(n,v){ + tmp+='
    • '; + tmp+=''; + tmp+=v.name; + tmp+=''; + tmp+=''; + tmp+=''; + tmp+=''; + tmp+='
    • '; + }) + $('#monitor_'+b).html(tmp) + }) + componentHandler.upgradeAllRegistered() + }catch(er){ + console.log(er) + //no group, this 'try' will be removed in future. + }; + $('#copy_settings').val('0').change() + var tmp = ''; + $.each($.ccio.mon,function(n,v){ + if(v.ke === $user.ke){ + tmp += $.ccio.tm('option',{auth_token:$user.auth_token,id:v.mid,name:v.name},null,$user); + } + }) + $.aM.monitorsForCopy.find('optgroup').html(tmp) + setTimeout(function(){$.aM.drawList()},1000) +} +//parse "Automatic" field in "Input" Section +$.aM.e.on('change','.auto_host_fill input,.auto_host_fill select',function(e){ + var theSwitch = $.aM.e.find('[detail="auto_host_enable"]').val() + if(!theSwitch||theSwitch===''){ + theSwitch='1' + } + if(theSwitch==='1'){ + return + } + if($.aM.e.find('[name="host"]').val() !== ''){ + $.aM.e.find('[detail="auto_host"]').val($.aM.buildMonitorURL()) + } +}) +$.aM.e.on('change','[detail="auto_host"]',function(e){ + var isRTSP = false + var inputType = $.aM.e.find('[name="type"]').val() + var url = $(this).val() + var theSwitch = $.aM.e.find('[detail="auto_host_enable"]') + var disabled = theSwitch.val() + if(!disabled||disabled===''){ + //if no value, then probably old version of monitor config. Set to Manual to avoid confusion. + disabled='0' + theSwitch.val('0').change() + } + if(disabled==='0'){ + return + } + if(inputType === 'local'){ + $.aM.e.find('[name="path"]').val(url).change() + }else{ + var urlSplitByDots = url.split('.') + var has = function(query,searchIn){if(!searchIn){searchIn=url;};return url.indexOf(query)>-1} + var protocol = url.split('://')[0] + console.log(url.split('://')) + //switch RTSP, RTMP and RTMPS to parse URL + if(has('rtsp://')){ + isRTSP = true; + url = url.replace('rtsp://','http://') + } + if(has('rtmp://')){ + isRTMP = true; + url = url.replace('rtmp://','http://') + } + if(has('rtmps://')){ + isRTMPS = true; + url = url.replace('rtmps://','http://') + } + //parse URL + var parsedURL = document.createElement('a'); + parsedURL.href = url; + var pathname = parsedURL.pathname + if(url.indexOf('?') > -1){ + pathname += '?'+url.split('?')[1] + } + $.aM.e.find('[name="protocol"]').val(protocol).change() + if(isRTSP){ + $.aM.e.find('[detail="rtsp_transport"]').val('tcp').change() + $.aM.e.find('[detail="aduration"]').val(1000000).change() + $.aM.e.find('[detail="probesize"]').val(1000000).change() + } + $.aM.e.find('[detail="muser"]').val(parsedURL.username).change() + $.aM.e.find('[detail="mpass"]').val(parsedURL.password).change() + $.aM.e.find('[name="host"]').val(parsedURL.hostname).change() + $.aM.e.find('[name="port"]').val(parsedURL.port).change() + $.aM.e.find('[name="path"]').val(pathname).change() + delete(parsedURL) + } +}) +$.aM.e.find('.refresh_cascades').click(function(e){ + $.ccio.cx({f:'ocv_in',data:{f:'refreshPlugins',ke:$user.ke}}) +}) +$.aM.f.submit(function(ee){ + ee.preventDefault(); + e={e:$(this)}; + e.s=e.e.serializeObject(); + e.er=[]; + $.each(e.s,function(n,v){e.s[n]=v.trim()}); + e.s.mid=e.s.mid.replace(/[^\w\s]/gi,'').replace(/ /g,'') + if(e.s.mid.length<3){e.er.push('Monitor ID too short')} + if(e.s.port==''){ + if(e.s.protocol === 'https'){ + e.s.port = 443 + }else{ + e.s.port = 80 + } + } + if(e.s.name==''){e.er.push('Monitor Name cannot be blank')} +// if(e.s.protocol=='rtsp'){e.s.ext='mp4',e.s.type='rtsp'} + if(e.er.length>0){ + $.sM.e.find('.msg').html(e.er.join('
      ')); + $.ccio.init('note',{title:'Configuration Invalid',text:e.er.join('
      '),type:'error'}); + return; + } + $.post($.ccio.init('location',$user)+$user.auth_token+'/configureMonitor/'+$user.ke+'/'+e.s.mid,{data:JSON.stringify(e.s)},function(d){ + $.ccio.log(d) + }) + // + if($('#copy_settings').val() === '1'){ + e.s.details = JSON.parse(e.s.details); + var copyMonitors = $.aM.monitorsForCopy.val(); + var chosenSections = []; + var chosenMonitors = {}; + + if(!copyMonitors||copyMonitors.length===0){ + $.ccio.init('note',{title:lang['No Monitors Selected'],text:lang.monSavedButNotCopied}) + return + } + + $.aM.e.find('[copy]').each(function(n,v){ + var el = $(v) + if(el.val() === '1'){ + chosenSections.push(el.attr('copy')) + } + }) + var alterSettings = function(settingsToAlter,monitor){ + monitor.details = JSON.parse(monitor.details); + $.aM.e.find(settingsToAlter).find('input,select,textarea').each(function(n,v){ + var el = $(v); + var name = el.attr('name') + var detail = el.attr('detail') + var value + switch(true){ + case !!name: + var value = e.s[name] + monitor[name] = value; + break; + case !!detail: + detail = detail.replace('"','') + var value = e.s.details[detail] + monitor.details[detail] = value; + break; + } + }) + monitor.details = JSON.stringify(monitor.details); + return monitor; + } + $.each(copyMonitors,function(n,id){ + var monitor + if(id === '$New'){ + monitor = $.aM.generateDefaultMonitorSettings(); + //connection + monitor.name = e.s.name+' - '+monitor.mid + monitor.type = e.s.type + monitor.protocol = e.s.protocol + monitor.host = e.s.host + monitor.port = e.s.port + monitor.path = e.s.path + monitor.details.fatal_max = e.s.details.fatal_max + monitor.details.port_force = e.s.details.port_force + monitor.details.muser = e.s.details.muser + monitor.details.password = e.s.details.password + monitor.details.rtsp_transport = e.s.details.rtsp_transport + monitor.details.auto_host = e.s.details.auto_host + monitor.details.auto_host_enable = e.s.details.auto_host_enable + //input + monitor.details.aduration = e.s.details.aduration + monitor.details.probesize = e.s.details.probesize + monitor.details.stream_loop = e.s.details.stream_loop + monitor.details.sfps = e.s.details.sfps + monitor.details.accelerator = e.s.details.accelerator + monitor.details.hwaccel = e.s.details.hwaccel + monitor.details.hwaccel_vcodec = e.s.details.hwaccel_vcodec + monitor.details.hwaccel_device = e.s.details.hwaccel_device + }else{ + monitor = Object.assign({},$.ccio.init('cleanMon',$.ccio.mon[$user.ke+id+$user.auth_token])); + } + $.each(chosenSections,function(n,section){ + monitor = alterSettings(section,monitor) + }) + console.log(monitor) + $.post($.ccio.init('location',$user)+$user.auth_token+'/configureMonitor/'+$user.ke+'/'+monitor.mid,{data:JSON.stringify(monitor)},function(d){ + $.ccio.log(d) + }) + chosenMonitors[monitor.mid] = monitor; + }) + console.log(chosenMonitors) + } + + $.aM.e.modal('hide') + return false; +}); +////////////////// +//Input Map (Feed) +$.aM.mapPlacementInit = function(){ + $('.input-map').each(function(n,v){ + var _this = $(this) + _this.find('.place').text(n+1) + }) +} +$.aM.mapSave = function(){ + var e={}; + var mapContainers = $('[input-mapping]'); + var stringForSave={} + mapContainers.each(function(q,t){ + var mapRowElement = $(t).find('.map-row'); + var mapRow = [] + mapRowElement.each(function(n,v){ + var map={} + $.each($(v).find('[map-input]'),function(m,b){ + map[$(b).attr('map-input')]=$(b).val() + }); + mapRow.push(map) + }); + stringForSave[$(t).attr('input-mapping')] = mapRow; + }); + $.aM.e.find('[detail="input_map_choices"]').val(JSON.stringify(stringForSave)).change(); +} +$.aM.maps.on('click','.delete',function(){ + $(this).parents('.input-map').remove() + var inputs = $('[map-detail]') + if(inputs.length===0){ + $.aM.e.find('[detail="input_maps"]').val('[]').change() + $.aM.showInputMappingFields(false) + }else{ + inputs.first().change() + $.aM.showInputMappingFields() + } + $.aM.mapPlacementInit() +}) +$.aM.e.on('change','[map-detail]',function(){ + var e={}; + e.e=$.aM.maps.find('.input-map') + e.s=[] + e.e.each(function(n,v){ + var map={} + $.each($(v).find('[map-detail]'),function(m,b){ + map[$(b).attr('map-detail')]=$(b).val() + }); + e.s.push(map) + }); + $.aM.e.find('[detail="input_maps"]').val(JSON.stringify(e.s)).change() +}) +$.aM.e.on('click','[input-mapping] .add_map_row',function(){ + $.ccio.tm('input-map-selector',{},$(this).parents('[input-mapping]').find('.choices')) + $.aM.mapSave() +}) +$.aM.e.on('click','[input-mapping] .delete_map_row',function(){ + $(this).parents('.map-row').remove() + $.aM.mapSave() +}) +$.aM.e.on('change','[map-input]',function(){ + $.aM.mapSave() +}) +////////////////// +//Stream Channels +$.aM.channelSave = function(){ + var e={}; + e.e=$.aM.channels.find('.stream-channel') + e.s=[] + e.e.each(function(n,v){ + var channel={} + $.each($(v).find('[channel-detail]'),function(m,b){ + channel[$(b).attr('channel-detail')]=$(b).val() + }); + e.s.push(channel) + }); + $.aM.e.find('[detail="stream_channels"]').val(JSON.stringify(e.s)).change() +} +$.aM.channelPlacementInit = function(){ + $('.stream-channel').each(function(n,v){ + var _this = $(this) + _this.attr('stream-channel',n) + _this.find('.place').text(n) + _this.find('[input-mapping]').attr('input-mapping','stream_channel-'+n) + $.aM.mapSave() + }) +} +$.aM.buildMonitorURL = function(){ + var e={}; + e.user=$.aM.e.find('[detail="muser"]').val(); + e.pass=$.aM.e.find('[detail="mpass"]').val(); + e.host=$.aM.e.find('[name="host"]').val(); + e.protocol=$.aM.e.find('[name="protocol"]').val(); + e.port=$.aM.e.find('[name="port"]').val(); + e.path=$.aM.e.find('[name="path"]').val(); + if($.aM.e.find('[name="type"]').val()==='local'){ + e.url=e.path; + }else{ + if(e.host.indexOf('@')===-1&&e.user!==''){ + e.host=e.user+':'+e.pass+'@'+e.host; + } + e.url=$.ccio.init('url',e)+e.path; + } + return e.url +} +$.aM.showInputMappingFields = function(showMaps){ + var el = $('[input-mapping],.input-mapping') + if(showMaps === undefined)showMaps = true + if(showMaps){ + el.show() + }else{ + el.hide() + } + $.aM.drawList() +} +$.aM.channels.on('click','.delete',function(){ + $(this).parents('.stream-channel').remove() + $.aM.channelSave() + $.aM.channelPlacementInit() +}) +$.aM.e.on('change','[channel-detail]',function(){ + $.aM.channelSave() +}) +////////////////// +$.aM.e.on('change','[groups]',function(){ + var e={}; + e.e=$.aM.e.find('[groups]:checked'); + e.s=[]; + e.e.each(function(n,v){ + e.s.push($(v).val()) + }); + $.aM.e.find('[detail="groups"]').val(JSON.stringify(e.s)).change() +}) +$.aM.e.on('change','[group_detector_multi]',function(){ + var e={}; + e.e=$.aM.e.find('[group_detector_multi]:checked'); + e.s=[]; + e.e.each(function(n,v){ + e.s.push($(v).val()) + }); + $.aM.e.find('[detail="group_detector_multi"]').val(JSON.stringify(e.s)).change() +}) +$.aM.e.on('change','.detector_cascade_selection',function(){ + var e={}; + e.e=$.aM.e.find('.detector_cascade_selection:checked'); + e.s={}; + e.e.each(function(n,v){ + e.s[$(v).val()]={} + }); + $.aM.e.find('[detail="detector_cascades"]').val(JSON.stringify(e.s)).change() +}) +//$.aM.e.on('change','.detector_cascade_selection',function(){ +// var e={}; +// e.details=$.aM.e.find('[name="details"]') +// try{ +// e.detailsVal=JSON.parse(e.details.val()) +// }catch(err){ +// e.detailsVal={} +// } +// e.detailsVal.detector_cascades=[]; +// e.e=$.aM.e.find('.detector_cascade_selection:checked'); +// e.e.each(function(n,v){ +// e.detailsVal.detector_cascades.push($(v).val()) +// }); +// e.details.val(JSON.stringify(e.detailsVal)) +//}) +$.aM.e.find('.probe_config').click(function(){ + $.pB.e.find('[name="url"]').val($.aM.buildMonitorURL()); + $.pB.f.submit(); + $.pB.e.modal('show'); +}) +$.aM.e.find('.import_config').click(function(e){ + var e={};e.e=$(this);e.mid=e.e.parents('[mid]').attr('mid'); + $.confirm.e.modal('show'); + $.confirm.title.text(lang['Import Monitor Configuration']) + e.html=lang.ImportMonitorConfigurationText+'
      '; + $.confirm.body.html(e.html) + $.confirm.e.find('.upload').change(function(e){ + var files = e.target.files; // FileList object + f = files[0]; + var reader = new FileReader(); + reader.onload = function(ee) { + $.confirm.e.find('textarea').val(ee.target.result); + } + reader.readAsText(f); + }); + $.confirm.click({title:'Import',class:'btn-primary'},function(){ + try{ + e.values=JSON.parse($.confirm.e.find('textarea').val()); + $.aM.import(e) + $.aM.e.modal('show') + }catch(err){ + $.ccio.log(err) + $.ccio.init('note',{title:lang['Invalid JSON'],text:lang.InvalidJSONText,type:'error'}) + } + }); +}); +$.aM.e.find('.save_config').click(function(e){ + var e={};e.e=$(this);e.mid=e.e.parents('[mid]').attr('mid');e.s=$.aM.f.serializeObject(); + if(!e.mid||e.mid===''){ + e.mid='NewMonitor' + } + e.dataStr = "data:text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(e.s)); + $('#temp').html('') + .find('a') + .attr('href',e.dataStr) + .attr('download','Shinobi_'+e.mid+'_config.json') + [0].click() +}); +$.aM.e.find('.add_map').click(function(e){ + $.aM.showInputMappingFields() + $.ccio.tm('input-map') +}); +$.aM.e.find('.add_channel').click(function(e){ + $.ccio.tm('stream-channel') +}); +$.aM.f.find('[detail="stream_type"]').change(function(e){ + e.e=$(this); + if(e.e.val()==='jpeg'){$.aM.f.find('[detail="snap"]').val('1').change()} +}) +$.aM.f.find('[name="type"]').change(function(e){ + e.e=$(this); + if(e.e.val()==='h264'){$.aM.f.find('[name="protocol"]').val('rtsp').change()} +}) +$.aM.md=$.aM.f.find('[detail]'); +$.aM.md.change($.ccio.form.details) +$.aM.f.on('change','[selector]',function(){ + e={e:$(this)} + e.v=e.e.val(); + e.a=e.e.attr('selector') + e.triggerChange=e.e.attr('triggerchange') + e.triggerChangeIgnore=e.e.attr('triggerChangeIgnore') + $.aM.f.find('.'+e.a+'_input').hide() + $.aM.f.find('.'+e.a+'_'+e.v).show(); + $.aM.f.find('.'+e.a+'_text').text($(this).find('option:selected').text()) + if(e.triggerChange && e.triggerChange !== '' && !e.triggerChangeIgnore || (e.triggerChangeIgnore && e.triggerChangeIgnore.split(',').indexOf(e.v) === -1)){ + console.log(e.triggerChange) + $(e.triggerChange).trigger('change') + } + $.aM.drawList() +}); +$.aM.f.find('[name="type"]').change(function(e){ + e.e=$(this); + e.v=e.e.val(); + e.h=$.aM.f.find('[name="path"]'); + e.p=e.e.parents('.form-group'); + switch(e.v){ + case'local':case'socket': + e.h.attr('placeholder','/dev/video0') + break; + default: + e.h.attr('placeholder','/videostream.cgi?1') + break; + } +}); + $.aM.connectedDetectorPlugins = {} + $.aM.addDetectorPlugin = function(name,d){ + $.aM.connectedDetectorPlugins[d.plug] = { + id: d.id, + plug: d.plug, + notice: d.notice, + connectionType: d.connectionType + } + $.aM.drawPluginElements() + } + $.aM.removeDetectorPlugin = function(name){ + delete($.aM.connectedDetectorPlugins[name]) + $.aM.drawPluginElements(name) + } + $.aM.drawPluginElements = function(){ + if(Object.keys($.aM.connectedDetectorPlugins).length === 0){ + $('.stream-objects .stream-detected-object').remove() + $('.shinobi-detector').hide() + $('.shinobi-detector-msg').empty() + $('.shinobi-detector_name').empty() + $('.shinobi-detector_plug').hide() + $('.shinobi-detector-invert').show() + $.aM.drawList() + }else{ + var pluginTitle = [] + var pluginNotice = [] + $.each($.aM.connectedDetectorPlugins,function(name,d){ + pluginTitle.push(name) + if(d.notice){ + pluginNotice.push('' + d.plug + ' : ' + d.notice) + } + $('.shinobi-detector-'+d.plug).show() + }) + $('.shinobi-detector').show() + $('.shinobi-detector-invert').hide() + $('.shinobi-detector_name').text(pluginTitle.join(', ')) + if(pluginNotice.length > 0)$('.shinobi-detector-msg').text(pluginNotice.join('
      ')) + $.aM.drawList() + } + } +}) diff --git a/web/libs/js/dash2.multimon.js b/web/libs/js/dash2.multimon.js new file mode 100644 index 0000000..669d4fa --- /dev/null +++ b/web/libs/js/dash2.multimon.js @@ -0,0 +1,192 @@ +$(document).ready(function(e){ +//multi monitor manager +$.multimon={e:$('#multi_mon')}; +$.multimon.table=$.multimon.e.find('.tableData tbody'); +$.multimon.f=$.multimon.e.find('form'); +$.multimon.f.on('change','#multimon_select_all',function(e){ + e.e=$(this); + e.p=e.e.prop('checked') + e.a=$.multimon.f.find('input[type=checkbox][name]') + if(e.p===true){ + e.a.prop('checked',true) + }else{ + e.a.prop('checked',false) + } +}) +$.multimon.e.find('.import_config').click(function(){ + var e={};e.e=$(this);e.mid=e.e.parents('[mid]').attr('mid'); + $.confirm.e.modal('show'); + $.confirm.title.text(lang['Import Monitor Configuration']) + e.html=lang.ImportMultiMonitorConfigurationText+'
      '; + $.confirm.body.html(e.html) + $.confirm.e.find('.upload').change(function(e){ + var files = e.target.files; // FileList object + f = files[0]; + var reader = new FileReader(); + reader.onload = function(ee) { + $.confirm.e.find('textarea').val(ee.target.result); + } + reader.readAsText(f); + }); + $.confirm.click({title:'Import',class:'btn-primary'},function(){ +// setTimeout(function(){ +// $.confirm.e.modal('show'); +// },1000) +// $.confirm.title.text(lang['Are you sure?']) +// $.confirm.body.html(lang.ImportMultiMonitorConfigurationText) +// $.confirm.click({title:'Save Set',class:'btn-danger'},function(){ + try{ + var postMonitor = function(v){ + $.post($.ccio.init('location',$user)+$user.auth_token+'/configureMonitor/'+$user.ke+'/'+v.mid,{data:JSON.stringify(v,null,3)},function(d){ + $.ccio.log(d) + }) + } + var parseZmMonitor = function(Monitor){ + console.log(Monitor) + var newMon = $.aM.generateDefaultMonitorSettings() + newMon.details = JSON.parse(newMon.details) + newMon.details.stream_type = 'jpeg' + switch(Monitor.Type.toLowerCase()){ + case'ffmpeg':case'libvlc': + newMon.details.auto_host_enable = '1' + newMon.details.auto_host = Monitor.Path + if(newMon.auto_host.indexOf('rtsp://') > -1 || newMon.auto_host.indexOf('rtmp://') > -1 || newMon.auto_host.indexOf('rtmps://') > -1){ + newMon.type = 'h264' + }else{ + $.ccio.init('note',{title:lang['Please Check Your Settings'],text:lang.migrateText1,type:'error'}) + } + break; + case'local': + newMon.details.auto_host = Monitor.Device + break; + case'remote': + + break; + } + newMon.details = JSON.stringify(newMon.details) + console.log(newMon) + return newMon + } + parsedData=JSON.parse($.confirm.e.find('textarea').val()); + //zoneminder one monitor + if(parsedData.monitor){ + $.aM.import({ + values : parseZmMonitor(parsedData.monitor.Monitor) + }) + $.aM.e.modal('show') + }else + //zoneminder multiple monitors + if(parsedData.monitors){ + $.each(parsedData.monitors,function(n,v){ + $.aM.import({ + values : parseZmMonitor(parsedData.Monitor) + }) + parseZmMonitor(v.Monitor) + }) + }else + //shinobi one monitor + if(parsedData.mid){ + postMonitor(parsedData) + }else + //shinobi multiple monitors + if(parsedData[0] && parsedData[0].mid){ + $.each(parsedData,function(n,v){ + postMonitor(v) + }) + } + }catch(err){ + $.ccio.log(err) + $.ccio.init('note',{title:lang['Invalid JSON'],text:lang.InvalidJSONText,type:'error'}) + } +// }); + }); +}) +$.multimon.getSelectedMonitors = function(unclean){ + var arr=[]; + if(unclean === true){ + var monitors = $.ccio.mon + }else{ + var monitors = $.ccio.init('cleanMons','object') + } + $.each($.multimon.f.serializeObject(),function(n,v){ + arr.push(monitors[n]) + }) + return arr; +} +$.multimon.e.find('.delete').click(function(){ + var arr=$.multimon.getSelectedMonitors(true); + if(arr.length===0){ + $.ccio.init('note',{title:'No Monitors Selected',text:'Select atleast one monitor to delete.',type:'error'}); + return + } + $.confirm.e.modal('show'); + $.confirm.title.text(lang['Delete']+' '+lang['Monitors']) + e.html='

      '+lang.DeleteMonitorsText+'

      '; + $.confirm.body.html(e.html) + $.confirm.click([ + { + title:'Delete Monitors', + class:'btn-danger', + callback:function(){ + $.each(arr,function(n,v){ + $.get($.ccio.init('location',$user)+v.user.auth_token+'/configureMonitor/'+v.ke+'/'+v.mid+'/delete',function(data){ + console.log(data) + }) + }) + } + }, + { + title:'Delete Monitors and Files', + class:'btn-danger', + callback:function(){ + $.each(arr,function(n,v){ + $.get($.ccio.init('location',$user)+v.user.auth_token+'/configureMonitor/'+v.ke+'/'+v.mid+'/delete?deleteFiles=true',function(data){ + console.log(data) + }) + }) + } + } + ]); +}) +//$.multimon.e.find('.edit_all').click(function(){ +// var arr=$.multimon.getSelectedMonitors(); +// var arrObject={} +// if(arr.length===0){ +// $.ccio.init('note',{title:'No Monitors Selected',text:'Select atleast one monitor to delete.',type:'error'}); +// return +// } +// $.multimonedit.selectedList = arr; +// $.multimonedit.e.modal('show') +//}) +$.multimon.e.find('.save_config').click(function(){ + var e={};e.e=$(this); + var arr=$.multimon.getSelectedMonitors(); + if(arr.length===0){ + $.ccio.init('note',{title:'No Monitors Selected',text:'Select atleast one monitor to delete.',type:'error'}); + return + } + e.dataStr = "data:text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(arr)); + $('#temp').html('') + .find('a') + .attr('href',e.dataStr) + .attr('download','Shinobi_Monitors_'+(new Date())+'.json') + [0].click() +}) +$.multimon.e.on('shown.bs.modal',function() { + var tmp='' + $.each($.ccio.mon,function(n,v){ + var streamURL = $.ccio.init('streamURL',v) + if(streamURL!=='Websocket'&&v.mode!==('idle'&&'stop')){ + streamURL=''+streamURL+'' + } + var img = $('#left_menu [mid="'+v.mid+'"][auth="'+v.user.auth_token+'"] [monitor="watch"]').attr('src') + tmp+='' + tmp+='
      ' + tmp+=''+v.name+'
      '+v.mid+''+v.status+''+streamURL+'' + //buttons + tmp+=' ' + tmp+='' + }) + $.multimon.table.html(tmp) +}) +}) diff --git a/web/libs/js/dash2.onvifscanner.js b/web/libs/js/dash2.onvifscanner.js new file mode 100644 index 0000000..a9ce152 --- /dev/null +++ b/web/libs/js/dash2.onvifscanner.js @@ -0,0 +1,60 @@ +$(document).ready(function(e){ +//onvif probe +$.oB={ + e:$('#onvif_probe'), + v:$('#onvif_video'), +}; +$.oB.f=$.oB.e.find('form');$.oB.o=$.oB.e.find('.output_data'); +$.oB.f.submit(function(ee){ + ee.preventDefault(); + e={}; + $.oB.foundMonitors={} + e.e=$(this),e.s=e.e.serializeObject(); + $.oB.o.empty(); + $.oB.e.find('._loading').show() + $.oB.e.find('[type="submit"]').prop('disabled',true) + $.ccio.cx({f:'onvif',ip:e.s.ip,port:e.s.port,user:e.s.user,pass:e.s.pass}) + clearTimeout($.oB.checkTimeout) + $.oB.checkTimeout=setTimeout(function(){ + if($.oB.o.find('tr').length===0){ + $.oB.e.find('._loading').hide() + $.oB.e.find('[type="submit"]').prop('disabled',false) + $.oB.o.append('Sorry, nothing was found.') + } + },5000) + return false; +}); +$.oB.e.on('click','.copy',function(){ + $('.hidden-xs [monitor="edit"]').click(); + e={}; + e.e = $(this).parents('[onvif_row]'); + var id = e.e.attr('onvif_row'); + var onvifRecord = $.oB.foundMonitors[id]; + var streamURL = onvifRecord.uri; + if($.oB.e.find('[name="user"]').val()!==''){ + streamURL = streamURL.split('://') + streamURL = streamURL[0]+'://'+$.oB.e.find('[name="user"]').val()+':'+$.oB.e.find('[name="pass"]').val()+'@'+streamURL[1]; + } + $.aM.e.find('[detail="auto_host"]').val(streamURL).change() + $.aM.e.find('[name="mode"]').val('start') + $.oB.e.modal('hide') +}) +$.oB.e.find('[name="ip"]').change(function(e){ + $.ccio.op('onvif_probe_ip',$(this).val()); +}) +if($.ccio.op().onvif_probe_ip){ + $.oB.e.find('[name="ip"]').val($.ccio.op().onvif_probe_ip) +} +$.oB.e.find('[name="port"]').change(function(e){ + $.ccio.op('onvif_probe_port',$(this).val()); +}) +if($.ccio.op().onvif_probe_port){ + $.oB.e.find('[name="port"]').val($.ccio.op().onvif_probe_port) +} +$.oB.e.find('[name="user"]').change(function(e){ + $.ccio.op('onvif_probe_user',$(this).val()); +}) +if($.ccio.op().onvif_probe_user){ + $.oB.e.find('[name="user"]').val($.ccio.op().onvif_probe_user) +} +}) diff --git a/web/libs/js/dash2.powervideo.js b/web/libs/js/dash2.powervideo.js new file mode 100644 index 0000000..ecd4e15 --- /dev/null +++ b/web/libs/js/dash2.powervideo.js @@ -0,0 +1,298 @@ +$(document).ready(function(e){ +//POWER videos window +$.pwrvid={e:$('#pvideo_viewer')}; +$.pwrvid.f=$.pwrvid.e.find('form'), +$.pwrvid.d=$('#vis_pwrvideo'), +$.pwrvid.mL=$('#motion_list'), +$.pwrvid.m=$('#vis_monitors'), +$.pwrvid.lv=$('#live_view'), +$.pwrvid.dr=$('#pvideo_daterange'), +$.pwrvid.vp=$('#video_preview'), +$.pwrvid.seekBar=$('#pwrvid_seekBar'), +$.pwrvid.seekBarProgress=$.pwrvid.seekBar.find('.progress-bar'), +$.pwrvid.playRate = 1; +$.pwrvid.dr.daterangepicker({ + startDate:$.ccio.timeObject().subtract(moment.duration("24:00:00")), + endDate:$.ccio.timeObject().add(moment.duration("24:00:00")), + timePicker: true, + timePicker24Hour: true, + timePickerSeconds: true, + timePickerIncrement: 30, + locale: { + format: 'MM/DD/YYYY h:mm A' + } +},function(start, end, label){ + $.pwrvid.drawTimeline() + $.pwrvid.dr.focus() +}); +$('#pvideo_show_events').change(function(){ + $.pwrvid.drawTimeline() +}) +$.pwrvid.e.on('click','[preview]',function(e){ + e.e=$(this); + e.video=$.pwrvid.vp.find('video')[0]; + if(e.video){ + e.duration=e.video.duration; + e.now=e.video.currentTime; + } + if($.pwrvid.video){ + clearInterval($.pwrvid.video.interval); + } + switch(e.e.attr('preview')){ + case'fullscreen': + $.ccio.init('fullscreen',e.video) + break; + case'mute': + e.video.muted = !e.video.muted + e.e.find('i').toggleClass('fa-volume-off fa-volume-up') + e.e.toggleClass('btn-danger') + break; + case'play': + e.video.playbackRate = 1; + $.pwrvid.vpOnPlayPause(1) + break; + case'stepFrontFront': + e.add=e.e.attr('add') + e.stepFrontFront=parseInt(e.e.attr('stepFrontFront')) + if(!e.stepFrontFront||isNaN(e.stepFrontFront)){e.stepFrontFront = 5} + if(e.add==="0"){ + $.pwrvid.playRate = e.stepFrontFront + }else{ + $.pwrvid.playRate += e.stepFrontFront + } + e.video.playbackRate = $.pwrvid.playRate; + e.video.play() + break; + case'stepFront': + e.video.currentTime += 1; + e.video.pause() + break; + case'stepBackBack': + $.pwrvid.video.interval = setInterval(function(){ + e.video.playbackRate = 1.0; + if(e.video.currentTime == 0){ + clearInterval($.pwrvid.video.interval); + e.video.pause(); + } + else{ + e.video.currentTime += -.2; + } + },30); + break; + case'stepBack': + e.video.currentTime += -1; + e.video.pause() + break; + case'video': +// e.preventDefault(); + e.p=e.e.parents('[mid]'); + e.filename=e.p.attr('file'); + $.pwrvid.vp.find('h3').text(e.filename) + e.href=e.e.attr('href'); + e.status=e.p.attr('status'); + e.mon=$.ccio.mon[e.p.attr('ke')+e.p.attr('mid')+$user.auth_token]; + $.pwrvid.vp.find('.holder').html(''); + $.pwrvid.vp + .attr('mid',e.mon.mid) + .attr('mid',e.mon.user.auth_token) + .attr('ke',e.mon.ke) + .attr('status',e.status) + .attr('file',e.filename) + .find('[download],[video="download"]') + .attr('download',e.filename) + .attr('href',e.href) + $.pwrvid.vp.find('video').off('loadeddata').on('loadeddata',function(){ + $.pwrvid.vp.find('.stream-objects .stream-detected-object').remove() + }) + if(e.status==1){ + $.get($.ccio.init('videoHrefToRead',e.href),function(d){ + + }) + } + var labels=[] + var Dataset1=[] + var events=$.pwrvid.currentDataObject[e.filename].motion + var eventsLabeledByTime={} + $.each(events,function(n,v){ + if(!v.details.confidence){v.details.confidence=0} + var time=$.ccio.timeObject(v.time).format('MM/DD/YYYY HH:mm:ss') + labels.push(time) + Dataset1.push(v.details.confidence) + eventsLabeledByTime[time]=v; + }) + if(events.length>0){ + $.pwrvid.mL.html("") + var timeFormat = 'MM/DD/YYYY HH:mm:ss'; + var color = Chart.helpers.color; + Chart.defaults.global.defaultFontColor = '#fff'; + var config = { + type: 'bar', + data: { + labels: labels, + datasets: [{ + type: 'line', + label: 'Motion Confidence', + backgroundColor: color(window.chartColors.red).alpha(0.2).rgbString(), + borderColor: window.chartColors.red, + data: Dataset1, + }] + }, + options: { + maintainAspectRatio: false, + title: { + fontColor: "white", + text:"Events in this video" + }, + scales: { + xAxes: [{ + type: "time", + display: true, + time: { + format: timeFormat, + // round: 'day' + } + }], + }, + } + }; + var ctx = $.pwrvid.mL.find('canvas')[0].getContext("2d"); + $.pwrvid.miniChart = new Chart(ctx, config); + $.pwrvid.mL.find('canvas').click(function(f) { + var target = $.pwrvid.miniChart.getElementsAtEvent(f)[0]; + if(!target){return false} + var video = $.pwrvid.currentDataObject[e.filename]; + var event = video.motion[target._index]; + var video1 = $('#video_preview video')[0]; + video1.currentTime=$.ccio.timeObject(event.time).diff($.ccio.timeObject(video.row.time),'seconds') + video1.play() + }); + var colorNames = Object.keys(window.chartColors); + + }else{ + $.pwrvid.mL.html('
      '+lang['No Events found for this video']+'
      ') + } + $.pwrvid.video={filename:e.filename,href:e.href,mid:e.mon.mid,ke:e.mon.ke} + $.pwrvid.vpOnPlayPause=function(x,e){ + var e={} + e.video=$.pwrvid.vp.find('video')[0] + e.i=$.pwrvid.vp.find('[preview="play"]').find('i') + if(e.video.paused===true){ + e.i.removeClass('fa-pause').addClass('fa-play') + if(x==1)e.video.play(); + }else{ + e.i.removeClass('fa-play').addClass('fa-pause') + if(x==1)e.video.pause(); + } + } + var videoElement=$.pwrvid.vp.find('video')[0] + $.pwrvid.vp.find('video') + .off('loadeddata').on('loadeddata', function() { + this.playbackRate = $.pwrvid.playRate; + this.play() + }) + .off("pause").on("pause",$.pwrvid.vpOnPlayPause) + .off("play").on("play",$.pwrvid.vpOnPlayPause) + .off("timeupdate").on("timeupdate",function(){ + var video = $.pwrvid.currentDataObject[e.filename]; + var videoTime=$.ccio.timeObject(video.row.time).add(parseInt(videoElement.currentTime),'seconds').format('MM/DD/YYYY HH:mm:ss'); + var event = eventsLabeledByTime[videoTime]; + if(event){ + if(event.details.plates){ + console.log('licensePlateVideo',event) + } + if(event.details.matrices){ + event.monitorDetails=JSON.parse(e.mon.details) + event.stream=$(videoElement) + event.streamObjects=$.pwrvid.vp.find('.stream-objects') + $.ccio.init('drawMatrices',event) + } + if(event.details.confidence){ + $.pwrvid.vp.find('.motion-meter .progress-bar').css('width',event.details.confidence+'px').find('span').text(event.details.confidence) + } + } + var value= (( videoElement.currentTime / videoElement.duration ) * 100)+"%" + $.pwrvid.seekBarProgress.css("width",value); + }) + $.pwrvid.seekBar.off("click").on("click", function(seek){ + var offset = $(this).offset(); + var left = (seek.pageX - offset.left); + var totalWidth = $.pwrvid.seekBar.width(); + var percentage = ( left / totalWidth ); + var vidTime = videoElement.duration * percentage; + videoElement.currentTime = vidTime; + }); + break; + } +}) +$.pwrvid.drawTimeline=function(getData){ + var e={}; + $.pwrvid.e.find('.nodata').hide() + if(getData===undefined){getData=true} + var mid=$.pwrvid.m.val(); + $.pwrvid.e.find('.loading').show() + e.live_header=$.pwrvid.lv.find('h3 span'); + e.live=$.pwrvid.lv.find('iframe'); + e.dateRange=$.pwrvid.dr.data('daterangepicker'); + e.videoLimit = $('#pvideo_video_limit').val(); + e.eventLimit = $('#pvideo_event_limit').val(); + if(e.eventLimit===''||isNaN(e.eventLimit)){e.eventLimit=500} + if(e.videoLimit===''||isNaN(e.videoLimit)){e.videoLimit=0} + + var getTheData = function(){ + e.live_header.text($.ccio.mon[$user.ke+mid+$user.auth_token].name) + e.live.attr('src',$.ccio.init('location',$user)+$user.auth_token+'/embed/'+$user.ke+'/'+mid+'/fullscreen|jquery|relative|gui') + + var pulseLoading = function(){ + var loading = $.pwrvid.e.find('.loading') + var currentColor = loading.css('color') + loading.animate('color','red') + setTimeout(function(){ + loading.css('color',currentColor) + },500) + } + if(getData===true){ + $.ccio.cx({ + f:'monitor', + ff:'get', + fff:'videos&events', + videoLimit:e.videoLimit, + eventLimit:e.eventLimit, + startDate:$.ccio.init('th',e.dateRange.startDate), + endDate:$.ccio.init('th',e.dateRange.endDate), + ke:e.ke, + mid:mid + }); + }else{ + $.pwrvid.e.find('.loading').hide() + e.next($.pwrvid.currentVideos,$.pwrvid.currentEvents) + } + } + if(parseInt(e.eventLimit) >= 1000){ + $.confirm.e.modal('show'); + $.confirm.title.text(lang['Warning']+'!') + e.html=lang.powerVideoEventLimit + $.confirm.body.html(e.html) + $.confirm.click({title:lang.Request,class:'btn-primary'},function(){ + getTheData() + }); + }else{ + getTheData() + } +} +$('#vis_monitors,#pvideo_event_limit,#pvideo_video_limit').change(function(){ + $.pwrvid.f.submit() +}) +$.pwrvid.f.submit(function(e){ + e.preventDefault(); + $.pwrvid.drawTimeline() + return false; +}) +$.pwrvid.e.on('hidden.bs.modal',function(e){ + $(this).find('iframe').attr('src','about:blank') + $.pwrvid.vp.find('.holder').empty() + delete($.pwrvid.currentDataObject) + delete($.pwrvid.currentData) + $.pwrvid.mL.empty() + $.pwrvid.d.empty() +}) +}) diff --git a/web/libs/js/dash2.probe.js b/web/libs/js/dash2.probe.js new file mode 100644 index 0000000..e7ad267 --- /dev/null +++ b/web/libs/js/dash2.probe.js @@ -0,0 +1,48 @@ +$(document).ready(function(e){ +//probe +$.pB={e:$('#probe')};$.pB.f=$.pB.e.find('form');$.pB.o=$.pB.e.find('.output_data'); +$.pB.f.submit(function(e){ + + $.pB.e.find('._loading').show() + $.pB.o.empty(); + $.pB.e.find('.stop').show(); + $.pB.e.find('[type="submit"]').hide(); + + e.preventDefault();e.e=$(this),e.s=e.e.serializeObject(); + e.s.url=e.s.url.trim(); + var flags = ''; + switch(e.s.mode){ + case'json': + flags = '-v quiet -print_format json -show_format -show_streams'; + break; + } +// if(e.s.url.indexOf('{{JSON}}')>-1){ +// e.s.url='-v quiet -print_format json -show_format -show_streams '+e.s.url +// } + $.get($.ccio.init('location',$user)+$user.auth_token+'/probe/'+$user.ke+'?url='+e.s.url+'&flags='+flags,function(data){ + if(data.ok===true){ + var html + try{ + html = $.ccio.init('jsontoblock',JSON.parse(data.result)) + }catch(err){ + html = data.result + } + $.pB.o.append(html) + }else{ + $.ccio.init('note',{title:'Failed to Probe',text:data.error,type:'error'}); + } + $.pB.e.find('._loading').hide() + $.pB.o.append('
      END
      '); + $.pB.e.find('.stop').hide(); + $.pB.e.find('[type="submit"]').show(); + }) + return false; +}); +$.pB.e.on('hidden.bs.modal',function(){ + $.pB.o.empty() +}) +$.pB.e.find('.stop').click(function(e){ + e.e=$(this); +// $.ccio.cx({f:'ffprobe',ff:'stop'}) +}); +}) diff --git a/web/libs/js/dash2.regioneditor.js b/web/libs/js/dash2.regioneditor.js new file mode 100644 index 0000000..2ae99b5 --- /dev/null +++ b/web/libs/js/dash2.regioneditor.js @@ -0,0 +1,200 @@ +$(document).ready(function(e){ +//Region Editor +$.zO={e:$('#region_editor')}; +$.zO.f=$.zO.e.find('form'); +$.zO.o=function(){return $.zO.e.find('canvas')}; +$.zO.c=$.zO.e.find('.canvas_holder'); +$.zO.name=$.zO.e.find('[name="name"]'); +$.zO.rl=$('#regions_list'); +$.zO.rp=$('#regions_points'); +$.zO.ca=$('#regions_canvas'); +$.zO.saveCoords=function(){ + $.aM.e.find('[detail="cords"]').val(JSON.stringify($.zO.regionViewerDetails.cords)).change() +} +$.zO.initRegionList=function(){ + $('#regions_list,#region_points').empty(); + $.each($.zO.regionViewerDetails.cords,function(n,v){ + if(v&&v.name){ + $.zO.rl.append('') + } + }); + $.zO.rl.change(); +} +$.zO.rl.change(function(e){ + $.zO.initCanvas(); +}) +$.zO.initLiveStream=function(e){ + var e={} + e.re=$('#region_editor_live'); + e.re.find('iframe,img').attr('src','about:blank').hide() + if($('#region_still_image').is(':checked')){ + e.re=e.re.find('img') + e.choice='jpeg' + }else{ + e.re=e.re.find('iframe') + e.choice='embed' + } + e.src=$.ccio.init('location',$user)+$user.auth_token+'/'+e.choice+'/'+$user.ke+'/'+$.aM.selected.mid + if(e.choice=='embed'){ + e.src+='/fullscreen|jquery|relative' + }else{ + e.src+='/s.jpg' + } + if(e.re.attr('src')!==e.src){ + e.re.attr('src',e.src).show() + } + e.re.attr('width',$.zO.regionViewerDetails.detector_scale_x) + e.re.attr('height',$.zO.regionViewerDetails.detector_scale_y) +} +$('#region_still_image').change(function(e){ + e.o=$.ccio.op().switches + if(!e.o){e.o={}} + if($(this).is(':checked')){ + e.o.regionStillImage=1 + }else{ + e.o.regionStillImage="0" + } + $.ccio.op('switches',e.o) + $.zO.initLiveStream() +}).ready(function(e){ + e.switches=$.ccio.op().switches + if(e.switches&&e.switches.regionStillImage===1){ + $('#region_still_image').prop('checked',true) + } +}) +$.zO.initCanvas=function(){ + var e={}; + e.ar=[]; + e.val=$.zO.rl.val(); + if(!e.val){ + $.zO.f.find('[name="name"]').val('') + $.zO.f.find('[name="sensitivity"]').val('') + $.zO.f.find('[name="max_sensitivity"]').val('') + $.zO.f.find('[name="threshold"]').val('') + $.zO.f.find('[name="color_threshold"]').val('') + $.zO.rp.empty() + }else{ + e.cord=$.zO.regionViewerDetails.cords[e.val]; + if(!e.cord.points){e.cord.points=[[0,0],[0,100],[100,0]]} + $.each(e.cord.points,function(n,v){ + e.ar=e.ar.concat(v) + }); + if(isNaN(e.cord.sensitivity)){ + e.cord.sensitivity=$.zO.regionViewerDetails.detector_sensitivity; + } + $.zO.f.find('[name="name"]').val(e.val) + $.zO.e.find('.cord_name').text(e.val) + $.zO.f.find('[name="sensitivity"]').val(e.cord.sensitivity) + $.zO.f.find('[name="max_sensitivity"]').val(e.cord.max_sensitivity) + $.zO.f.find('[name="threshold"]').val(e.cord.threshold) + $.zO.f.find('[name="color_threshold"]').val(e.cord.color_threshold) + $.zO.e.find('.canvas_holder canvas').remove(); + + $.zO.initLiveStream() + e.e=$.zO.ca.val(e.ar.join(',')) + e.e.canvasAreaDraw({ + imageUrl:placeholder.getData(placeholder.plcimg({ + bgcolor:'transparent', + text:' ', + size:$.zO.regionViewerDetails.detector_scale_x+'x'+$.zO.regionViewerDetails.detector_scale_y + })) + }); + e.e.change(); + } +} +$.zO.e.on('change','[name]:not([name="name"])',function(){ + var el = $(this) + var val = el.val() + var key = el.attr('name') + $.zO.regionViewerDetails.cords[$.zO.rl.val()][key] = val + $.zO.saveCoords() +}) +$.zO.e.on('change','[name="name"]',function(e){ + e.old=$.zO.rl.val(); + e.new=$.zO.name.val(); + $.zO.regionViewerDetails.cords[e.new]=$.zO.regionViewerDetails.cords[e.old]; + delete($.zO.regionViewerDetails.cords[e.old]); + $.zO.rl.find('option[value="'+e.old+'"]').attr('value',e.new).text(e.new) + $.zO.saveCoords() +}) +$.zO.e.on('change','[point]',function(e){ + e.points=[]; + $('[points]').each(function(n,v){ + v=$(v); + n=v.find('[point="x"]').val(); + if(n){ + e.points.push([n,v.find('[point="y"]').val()]) + } + }) + $.zO.regionViewerDetails.cords[$.zO.name.val()].points=e.points; + $.zO.initCanvas(); +}) +$.zO.e.find('.erase').click(function(e){ + e.arr=[] + $.each($.zO.regionViewerDetails.cords,function(n,v){ + if(v&&v!==$.zO.regionViewerDetails.cords[$.zO.rl.val()]){ + e.arr.push(v) + } + }) + $.zO.regionViewerDetails.cords=e.arr.concat([]); + if(Object.keys($.zO.regionViewerDetails.cords).length>0){ + $.zO.initRegionList(); + }else{ + $.zO.f.find('input').prop('disabled',true) + $('#regions_points tbody').empty() + $('#regions_list [value="'+$.zO.rl.val()+'"]').remove() + $.aM.e.find('[detail="cords"]').val('[]') + } +}); +//$.zO.e.find('.new').click(function(e){ +// $.zO.regionViewerDetails.cords[$.zO.rl.val()] +// $.zO.initRegionList(); +//}) +$.zO.e.on('changed','#regions_canvas',function(e){ + e.val=$(this).val().replace(/(,[^,]*),/g, '$1;').split(';'); + e.ar=[]; + $.each(e.val,function(n,v){ + v=v.split(',') + if(v[1]){ + e.ar.push([v[0],v[1]]) + } + }) + $.zO.regionViewerDetails.cords[$.zO.rl.val()].points=e.ar; + e.selected=$.zO.regionViewerDetails.cords[$.zO.rl.val()]; + e.e=$('#regions_points tbody').empty(); + $.each($.zO.regionViewerDetails.cords[$.zO.rl.val()].points,function(n,v){ + if(isNaN(v[0])){v[0]=20} + if(isNaN(v[1])){v[1]=20} + e.e.append('') + }); + $.zO.saveCoords() +}) +$.zO.f.submit(function(e){ + e.preventDefault();e.e=$(this),e.s=e.e.serializeObject(); + + return false; +}); +$('#regions_points') +.on('click','.delete',function(e){ + e.p=$(this).parents('tr'),e.row=e.p.attr('points'); + delete($.zO.regionViewerDetails.cords[$.zO.rl.val()].points[e.row]) + $.zO.saveCoords() + e.p.remove(); + $.zO.rl.change(); +}) +$.zO.e.on('click','.add',function(e){ + $.zO.f.find('input').prop('disabled',false) + e.gid=$.ccio.gid(5); + e.save={}; + $.each($.zO.regionViewerDetails.cords,function(n,v){ + if(v&&v!==null&&v!=='null'){ + e.save[n]=v; + } + }) + $.zO.regionViewerDetails.cords=e.save; + $.zO.regionViewerDetails.cords[e.gid]={name:e.gid,sensitivity:0.0005,max_sensitivity:'',threshold:1,color_threshold:9,points:[[0,0],[0,100],[100,0]]}; + $.zO.rl.append(''); + $.zO.rl.val(e.gid) + $.zO.rl.change(); +}); +}) diff --git a/web/libs/js/dash2.socketio.js b/web/libs/js/dash2.socketio.js new file mode 100644 index 0000000..4827b3c --- /dev/null +++ b/web/libs/js/dash2.socketio.js @@ -0,0 +1,917 @@ +$(document).ready(function(e){ +//websocket functions +$.users = {} +$.ccio.cx=function(x,user){ + if(!user){user=$user} + if(!x.ke){x.ke=user.ke;}; + if(!x.uid){x.uid=user.uid;}; + return user.ws.emit('f',x) +} +$.ccio.globalWebsocket=function(d,user){ + if(d.f!=='monitor_frame'&&d.f!=='os'&&d.f!=='video_delete'&&d.f!=='detector_trigger'&&d.f!=='detector_record_timeout_start'&&d.f!=='log'){$.ccio.log(d);} + if(!user){ + user=$user + } + if(d.viewers){ + $('[ke="'+d.ke+'"][mid="'+d.id+'"][auth="'+user.auth_token+'"] .viewers').html(d.viewers); + } + switch(d.f){ + case'note': + $.ccio.init('note',d.note,user); + break; + case'monitor_status': + console.log(d) + $('[ke="'+d.ke+'"][mid="'+d.id+'"][auth="'+user.auth_token+'"] .monitor_status').html(d.status); + break; + case'detector_trigger': + d.e=$('.monitor_item[ke="'+d.ke+'"][mid="'+d.id+'"][auth="'+user.auth_token+'"]') + if($.ccio.mon[d.ke+d.id+user.auth_token]&&d.e.length>0){ + if(d.doObjectDetection === true){ + d.e.addClass('doObjectDetection') + clearTimeout($.ccio.mon[d.ke+d.id+user.auth_token].detector_trigger_doObjectDetection_timeout) + $.ccio.mon[d.ke+d.id+user.auth_token].detector_trigger_doObjectDetection_timeout = setTimeout(function(){ + d.e.removeClass('doObjectDetection') + },3000) + }else{ + d.e.removeClass('doObjectDetection') + } + if(d.details.plates&&d.details.plates.length>0){ + console.log('licensePlateStream',d.id,d) + } + if(d.details.matrices&&d.details.matrices.length>0){ + d.monitorDetails=JSON.parse($.ccio.mon[d.ke+d.id+user.auth_token].details) + d.stream=d.e.find('.stream-element') + d.streamObjects=d.e.find('.stream-objects') + $.ccio.init('drawMatrices',d) + } + if(d.details.points&&Object.keys(d.details.points).length>0){ + d.monitorDetails=JSON.parse($.ccio.mon[d.ke+d.id+user.auth_token].details) + d.stream=d.e.find('.stream-element') + d.streamObjects=d.e.find('.stream-objects') + $.ccio.init('drawPoints',d) + } + if(d.details.confidence){ + d.tt=d.details.confidence; + if (d.tt > 100) { d.tt = 100 } + d.e.find('.indifference .progress-bar').css('width',d.tt + '%').find('span').html(d.details.confidence+'% change in '+d.details.name+'') + } + d.e.addClass('detector_triggered') + clearTimeout($.ccio.mon[d.ke+d.id+user.auth_token].detector_trigger_timeout); + $.ccio.mon[d.ke+d.id+user.auth_token].detector_trigger_timeout=setTimeout(function(){ + $('.monitor_item[ke="'+d.ke+'"][mid="'+d.id+'"][auth="'+user.auth_token+'"]').removeClass('detector_triggered').find('.stream-detected-object,.stream-detected-point').remove() + },5000); + //noise alert + if(user.details.audio_alert && user.details.audio_alert !== '' && $.ccio.soundAlarmed !== true){ + $.ccio.soundAlarmed = true + var audio = new Audio('libs/audio/'+user.details.audio_alert); + audio.onended = function(){ + setTimeout(function(){ + $.ccio.soundAlarmed = false + },user.details.audio_delay * 1000) + } + if($.ccio.windowFocus = true){ + audio.play() + }else{ + clearInterval($.ccio.soundAlarmInterval) + if(!user.details.audio_delay || user.details.audio_delay === ''){ + user.details.audio_delay = 1 + }else{ + user.details.audio_delay = parseFloat(user.details.audio_delay) + } + $.ccio.soundAlarmInterval = setInterval(function(){ + audio.play() + },user.details.audio_delay * 1000) + } + } + if(user.details.event_mon_pop === '1' && (!$.ccio.mon[d.ke+d.id+user.auth_token].popOut || $.ccio.mon[d.ke+d.id+user.auth_token].popOut.closed === true)){ + d.e.find('[monitor="pop"]').click() + } + } + break; + case'init_success': + $('#monitors_list .link-monitors-list[auth="'+user.auth_token+'"][ke="'+user.ke+'"]').empty(); + if(user===$user){ + d.chosen_set='watch_on' + }else{ + d.chosen_set='watch_on_links' + } + d.o=$.ccio.op()[d.chosen_set]; + if(!d.o){d.o={}}; + $.getJSON($.ccio.init('location',user)+user.auth_token+'/monitor/'+user.ke,function(f,g){ + g=function(n,v){ + $.ccio.mon[v.ke+v.mid+user.auth_token]=v; + v.user=user; + $.ccio.tm(1,v,null,user) + if(d.o[v.ke]&&d.o[v.ke][v.mid]===1){ + $.ccio.cx({f:'monitor',ff:'watch_on',id:v.mid},user) + } + } + if(f.mid){ + g(null,f) + }else{ + $.each(f,g); + } + setTimeout(function(){ + $.ccio.sortListMonitors(user) + },1000) + if($.ccio.op().jpeg_on === true){ + $.ccio.cx({f:'monitor',ff:'jpeg_on'},user) + } + $.gR.drawList() + }) + $.ccio.pm(3,d.apis,null,user); + $('.os_platform').html(d.os.platform) + $('.os_cpuCount').html(d.os.cpuCount) + $('.os_totalmem').html((d.os.totalmem/1000000).toFixed(2)) + if(d.os.cpuCount>1){ + $('.os_cpuCount_trailer').html('s') + } + break; + case'get_videos': + $.ccio.pm(0,d,null,user) + break; + case'log': + $.logWriter.draw('[mid="'+d.mid+'"][ke="'+d.ke+'"][auth="'+user.auth_token+'"]',d,user) + break; + case'camera_cpu_usage': + var el = $('.monitor_item[auth="'+user.auth_token+'"][ke="'+d.ke+'"][mid="'+d.id+'"] .camera_cpu_usage') + .attr('title',d.percent + '% ' + lang['CPU used by this stream']) + el.find('.progress-bar').css('width',d.percent) + el.find('.percent').html(d.percent + '%') + break; + case'os'://indicator + //cpu + d.cpu=parseFloat(d.cpu).toFixed(0)+'%'; + $('.cpu_load .progress-bar').css('width',d.cpu); + $('.cpu_load .percent').html(d.cpu); + //ram + d.ram=(100-parseFloat(d.ram)).toFixed(0)+'%'; + $('.ram_load .progress-bar').css('width',d.ram); + $('.ram_load .percent').html(d.ram); + break; + case'diskUsed': + if(!d.limit||d.limit===''){d.limit=10000} + d.percent=parseInt((d.size/d.limit)*100)+'%'; + d.human=parseFloat(d.size) + if(d.human>1000){d.human=(d.human/1000).toFixed(2)+' GB'}else{d.human=d.human.toFixed(2)+' MB'} + $('.diskUsed .value').html(d.human) + $('.diskUsed .percent').html(d.percent) + $('.diskUsed .progress-bar').css('width',d.percent) + break; + case'video_fix_success':case'video_fix_start': + switch(d.f){ + case'video_fix_success': + d.addClass='fa-wrench' + d.removeClass='fa-pulse fa-spinner' + break; + case'video_fix_start': + d.removeClass='fa-wrench' + d.addClass='fa-pulse fa-spinner' + break; + } + $('[mid="'+d.mid+'"][ke="'+d.ke+'"][file="'+d.filename+'"][auth="'+user.auth_token+'"] [video="fix"] i,[data-mid="'+d.mid+'"][data-ke="'+d.ke+'"][data-file="'+d.filename+'"][data-auth="'+user.auth_token+'"] [video="fix"] i').addClass(d.addClass).removeClass(d.removeClass) + break; + case'video_edit':case'video_archive': + $.ccio.init('data-video',d) + d.e=$('[file="'+d.filename+'"][mid="'+d.mid+'"][ke="'+d.ke+'"][auth="'+user.auth_token+'"],[data-file="'+d.filename+'"][data-mid="'+d.mid+'"][data-ke="'+d.ke+'"][data-auth="'+user.auth_token+'"]'); + d.e.attr('status',d.status),d.e.attr('data-status',d.status); + console.log(d) + + break; + case'video_delete': +// if($('.modal[mid="'+d.mid+'"][auth="'+user.auth_token+'"]').length>0){$('#video_viewer[mid="'+d.mid+'"]').attr('file',null).attr('ke',null).attr('mid',null).attr('auth',null).modal('hide')} + $('[file="'+d.filename+'"][mid="'+d.mid+'"][ke="'+d.ke+'"][auth="'+user.auth_token+'"]:not(.modal)').remove(); + $('[data-file="'+d.filename+'"][data-mid="'+d.mid+'"][data-ke="'+d.ke+'"][data-auth="'+user.auth_token+'"]:not(.modal)').remove(); + if($.pwrvid.currentDataObject&&$.pwrvid.currentDataObject[d.filename]){ + delete($.timelapse.currentVideos[$.pwrvid.currentDataObject[d.filename].position]) + $.pwrvid.drawTimeline(false) + } + if($.timelapse.currentVideos&&$.timelapse.currentVideos[d.filename]){ + delete($.timelapse.currentVideosArray.videos[$.timelapse.currentVideos[d.filename].position]) + $.timelapse.drawTimeline(false) + } + if($.vidview.loadedVideos && $.vidview.loadedVideos[d.filename])delete($.vidview.loadedVideos[d.filename]) + break; + case'video_build_success': + if(!d.mid){d.mid=d.id;};d.status=1; + d.e='.glM'+d.mid+user.auth_token+'.videos_list ul,.glM'+d.mid+user.auth_token+'.videos_monitor_list ul';$(d.e).find('.notice.novideos').remove(); + $.ccio.tm(0,d,d.e,user) + break; + case'monitor_snapshot': + setTimeout(function(){ + var snapElement = $('[mid="'+d.mid+'"][ke="'+d.ke+'"][auth="'+user.auth_token+'"] .snapshot') + switch(d.snapshot_format){ + case'plc': + snapElement.attr('src',placeholder.getData(placeholder.plcimg(d.snapshot))) + break; + case'ab': + d.reader = new FileReader(); + d.reader.addEventListener("loadend",function(){snapElement.attr('src',d.reader.result)}); + d.reader.readAsDataURL(new Blob([d.snapshot],{type:"image/jpeg"})); + break; + case'b64': + snapElement.attr('src','data:image/jpeg;base64,'+d.snapshot) + break; + } + },1000) + break; + case'monitor_delete': + $('[mid="'+d.mid+'"][ke="'+d.ke+'"][auth="'+user.auth_token+'"]:not(.modal)').remove(); + $.ccio.init('clearTimers',d) + delete($.ccio.mon[d.ke+d.mid+user.auth_token]); + break; + case'monitor_watch_off':case'monitor_stopping': + if(user===$user){ + d.chosen_set='watch_on' + }else{ + d.chosen_set='watch_on_links' + } + d.o=$.ccio.op()[d.chosen_set]; + if(!d.o[d.ke]){d.o[d.ke]={}};d.o[d.ke][d.id]=0;$.ccio.op(d.chosen_set,d.o); + $.ccio.destroyStream(d,user,(d.f === 'monitor_watch_off')) + break; + case'monitor_watch_on': + if(user===$user){ + d.chosen_set='watch_on' + }else{ + d.chosen_set='watch_on_links' + } + d.o=$.ccio.op()[d.chosen_set]; + if(!d.o){d.o={}};if(!d.o[d.ke]){d.o[d.ke]={}};d.o[d.ke][d.id]=1;$.ccio.op(d.chosen_set,d.o); + $.ccio.mon[d.ke+d.id+user.auth_token].watch=1; + delete($.ccio.mon[d.ke+d.id+user.auth_token].image) + delete($.ccio.mon[d.ke+d.id+user.auth_token].ctx) + d.e=$('#monitor_live_'+d.id+user.auth_token); + d.e.find('.stream-detected-object').remove() + $.ccio.init('clearTimers',d) + if(d.e.length === 1){ + $.ccio.init('closeVideo',{mid:d.id,ke:d.ke},user); + } + if(d.e.length === 0){ + $.ccio.tm(2,$.ccio.mon[d.ke+d.id+user.auth_token],'#monitors_live',user); + } + d.d=JSON.parse($.ccio.mon[d.ke+d.id+user.auth_token].details); + $.ccio.tm('stream-element',$.ccio.mon[d.ke+d.id+user.auth_token],null,user); + if($.ccio.op().jpeg_on===true){ + $.ccio.init('jpegMode',$.ccio.mon[d.ke+d.id+user.auth_token]); + }else{ + var path = tool.checkCorrectPathEnding(location.pathname)+'socket.io' + switch(d.d.stream_type){ + case'jpeg': + $.ccio.init('jpegMode',$.ccio.mon[d.ke+d.id+user.auth_token]); + break; + case'b64': + if($.ccio.mon[d.ke+d.id+user.auth_token].Base64 && $.ccio.mon[d.ke+d.id+user.auth_token].Base64.connected){ + $.ccio.mon[d.ke+d.id+user.auth_token].Base64.disconnect() + } + $.ccio.mon[d.ke+d.id+user.auth_token].Base64 = io(location.origin,{ path: path, transports: ['websocket'], forceNew: false}) + var ws = $.ccio.mon[d.ke+d.id+user.auth_token].Base64 + var buffer + ws.on('diconnect',function(){ + console.log('Base64 Stream Disconnected') + }) + ws.on('connect',function(){ + ws.emit('Base64',{ + auth: user.auth_token, + uid: user.uid, + ke: d.ke, + id: d.id, +// channel: channel + }) + if(!$.ccio.mon[d.ke+d.id+user.auth_token].ctx||$.ccio.mon[d.ke+d.id+user.auth_token].ctx.length===0){ + $.ccio.mon[d.ke+d.id+user.auth_token].ctx = $('#monitor_live_'+d.id+user.auth_token+' canvas'); + } + var ctx = $.ccio.mon[d.ke+d.id+user.auth_token].ctx[0] + var ctx2d = ctx.getContext("2d") + $.ccio.mon[d.ke+d.id+user.auth_token].image = new Image() + var image = $.ccio.mon[d.ke+d.id+user.auth_token].image + image.onload = function() { + $.ccio.mon[d.ke+d.id+user.auth_token].imageLoading = false + d.x = 0 + d.y = 0 + // d.ratio = Math.min(ctx.width/image.width,ctx.height/image.height) + // d.height = image.height * d.ratio + // d.width = image.width * d.ratio + // if(d.width < ctx.width){ + // d.x = (ctx.width / 2) - (d.width / 2) + // } + // if(d.height < ctx.height){ + // d.y = (ctx.height / 2) - (d.height / 2) + // } + // ctx.getContext("2d").drawImage(image,d.x,d.y,d.width,d.height) + ctx.getContext("2d").drawImage(image,d.x,d.y,ctx.width,ctx.height) + URL.revokeObjectURL($.ccio.mon[d.ke+d.id+user.auth_token].imageUrl) + } + ws.on('data',function(imageData){ + try{ + if($.ccio.mon[d.ke+d.id+user.auth_token].imageLoading === true)return console.log('drop'); +// var base64Frame = 'data:image/jpeg;base64,'+$.ccio.base64ArrayBuffer(imageData) + $.ccio.mon[d.ke+d.id+user.auth_token].imageLoading = true +// $.ccio.mon[d.ke+d.id+user.auth_token].image.src = base64Frame + var arrayBufferView = new Uint8Array(imageData); + var blob = new Blob( [ arrayBufferView ], { type: "image/jpeg" } ); + $.ccio.mon[d.ke+d.id+user.auth_token].imageUrl = URL.createObjectURL( blob ); + $.ccio.mon[d.ke+d.id+user.auth_token].image.src = $.ccio.mon[d.ke+d.id+user.auth_token].imageUrl + $.ccio.mon[d.ke+d.id+user.auth_token].last_frame = 'data:image/jpeg;base64,'+$.ccio.base64ArrayBuffer(imageData) + }catch(er){ + console.log(er) + $.ccio.log('base64 frame') + } + $.ccio.init('signal',d); + }) + }) + break; + case'mp4': + setTimeout(function(){ + var stream = d.e.find('.stream-element'); + var onPoseidonError = function(){ + // setTimeout(function(){ + // $.ccio.cx({f:'monitor',ff:'watch_on',id:d.id},user) + // },5000) + } + if(!$.ccio.mon[d.ke+d.id+user.auth_token].PoseidonErrorCount)$.ccio.mon[d.ke+d.id+user.auth_token].PoseidonErrorCount = 0 + if($.ccio.mon[d.ke+d.id+user.auth_token].PoseidonErrorCount >= 5)return + if(d.d.stream_flv_type==='ws'){ + if($.ccio.mon[d.ke+d.id+user.auth_token].Poseidon){ + $.ccio.mon[d.ke+d.id+user.auth_token].Poseidon.stop() + } + try{ + $.ccio.mon[d.ke+d.id+user.auth_token].Poseidon = new Poseidon({ + video: stream[0], + auth_token:user.auth_token, + ke:d.ke, + uid:user.uid, + id:d.id, + url: location.origin, + path: path, + onError : onPoseidonError + }) + $.ccio.mon[d.ke+d.id+user.auth_token].Poseidon.start(); + }catch(err){ + // onPoseidonError() + console.log('onTryPoseidonError',err) + } + }else{ + stream.attr('src',$.ccio.init('location',user)+user.auth_token+'/mp4/'+d.ke+'/'+d.id+'/s.mp4') + stream[0].onerror = function(err){ + console.error(err) + } + } + },2000) + break; + case'flv': + if (flvjs.isSupported()) { + if($.ccio.mon[d.ke+d.id+user.auth_token].flv){ + $.ccio.mon[d.ke+d.id+user.auth_token].flv.destroy() + } + var options = {}; + if(d.d.stream_flv_type==='ws'){ + if(d.d.stream_flv_maxLatency&&d.d.stream_flv_maxLatency!==''){ + d.d.stream_flv_maxLatency = parseInt(d.d.stream_flv_maxLatency) + }else{ + d.d.stream_flv_maxLatency = 20000; + } + options = { + type: 'flv', + isLive: true, + auth_token:user.auth_token, + ke:d.ke, + uid:user.uid, + id:d.id, + maxLatency:d.d.stream_flv_maxLatency, + hasAudio:false, + url: location.origin, + path: path + } + }else{ + options = { + type: 'flv', + isLive: true, + url: $.ccio.init('location',user)+user.auth_token+'/flv/'+d.ke+'/'+d.id+'/s.flv' + } + } + $.ccio.mon[d.ke+d.id+user.auth_token].flv = flvjs.createPlayer(options); + $.ccio.mon[d.ke+d.id+user.auth_token].flv.attachMediaElement($('#monitor_live_'+d.id+user.auth_token+' .stream-element')[0]); + $.ccio.mon[d.ke+d.id+user.auth_token].flv.on('error',function(err){ + console.log(err) + }); + $.ccio.mon[d.ke+d.id+user.auth_token].flv.load(); + $.ccio.mon[d.ke+d.id+user.auth_token].flv.play(); + }else{ + $.ccio.init('note',{title:'Stream cannot be started',text:'FLV.js is not supported on this browser. Try another stream type.',type:'error'}); + } + break; + case'hls': + d.fn=function(){ + clearTimeout($.ccio.mon[d.ke+d.id+user.auth_token].m3uCheck) + d.url=$.ccio.init('location',user)+user.auth_token+'/hls/'+d.ke+'/'+d.id+'/s.m3u8'; + $.get(d.url,function(m3u){ + if(m3u=='File Not Found'){ + $.ccio.mon[d.ke+d.id+user.auth_token].m3uCheck=setTimeout(function(){ + d.fn() + },2000) + }else{ + var video = $('#monitor_live_'+d.id+user.auth_token+' .stream-element')[0]; + if (navigator.userAgent.match(/(iPod|iPhone|iPad)/)||(navigator.userAgent.match(/(Safari)/)&&!navigator.userAgent.match('Chrome'))) { + video.src=d.url; + if (video.paused) { + video.play(); + } + }else{ + $.ccio.mon[d.ke+d.id+user.auth_token].hlsGarbageCollector=function(){ + if($.ccio.mon[d.ke+d.id+user.auth_token].hls){$.ccio.mon[d.ke+d.id+user.auth_token].hls.destroy();URL.revokeObjectURL(video.src)} + $.ccio.mon[d.ke+d.id+user.auth_token].hls = new Hls(); + $.ccio.mon[d.ke+d.id+user.auth_token].hls.loadSource(d.url); + $.ccio.mon[d.ke+d.id+user.auth_token].hls.attachMedia(video); + $.ccio.mon[d.ke+d.id+user.auth_token].hls.on(Hls.Events.MANIFEST_PARSED,function() { + if (video.paused) { + video.play(); + } + }); + } + $.ccio.mon[d.ke+d.id+user.auth_token].hlsGarbageCollector() + $.ccio.mon[d.ke+d.id+user.auth_token].hlsGarbageCollectorTimer=setInterval($.ccio.mon[d.ke+d.id+user.auth_token].hlsGarbageCollector,1000*60*20) + } + } + }) + } + d.fn() + break; + case'mjpeg': + $('#monitor_live_'+d.id+user.auth_token+' .stream-element').attr('src',$.ccio.init('location',user)+user.auth_token+'/mjpeg/'+d.ke+'/'+d.id+'/?full=true') + break; + case'h265': + var player = $.ccio.mon[d.ke+d.id+user.auth_token].h265Player + var video = $('#monitor_live_'+d.id+user.auth_token+' .stream-element')[0] + if (player) { + player.stop() + } + $.ccio.mon[d.ke+d.id+user.auth_token].h265Player = new libde265.RawPlayer(video) + var player = $.ccio.mon[d.ke+d.id+user.auth_token].h265Player + player.set_status_callback(function(msg, fps) { + }) + player.launch() + if($.ccio.mon[d.ke+d.id+user.auth_token].h265Socket && $.ccio.mon[d.ke+d.id+user.auth_token].h265Socket.connected){ + $.ccio.mon[d.ke+d.id+user.auth_token].h265Socket.disconnect() + } + if($.ccio.mon[d.ke+d.id+user.auth_token].h265HttpStream && $.ccio.mon[d.ke+d.id+user.auth_token].abort){ + $.ccio.mon[d.ke+d.id+user.auth_token].h265HttpStream.abort() + } + if(d.d.stream_flv_type==='ws'){ + $.ccio.mon[d.ke+d.id+user.auth_token].h265Socket = io(location.origin,{ path: path, transports: ['websocket'], forceNew: false}) + var ws = $.ccio.mon[d.ke+d.id+user.auth_token].h265Socket + ws.on('diconnect',function(){ + console.log('h265Socket Stream Disconnected') + }) + ws.on('connect',function(){ + ws.emit('h265',{ + auth: user.auth_token, + uid: user.uid, + ke: d.ke, + id: d.id, + // channel: channel + }) + ws.on('data',function(imageData){ + player._handle_onChunk(imageData) + }) + }) + }else{ + var url = $.ccio.init('location',user)+user.auth_token+'/h265/'+d.ke+'/'+d.id+'/s.hevc'; + $.ccio.mon[d.ke+d.id+user.auth_token].h265HttpStream = player.createHttpStream(url) + } + break; + } + } + d.signal=parseFloat(d.d.signal_check); + if(!d.signal||d.signal==NaN){d.signal=10;};d.signal=d.signal*1000*60; + if(d.signal>0){ + $.ccio.mon[d.ke+d.id+user.auth_token].signal=setInterval(function(){$.ccio.init('signal-check',{id:d.id,ke:d.ke})},d.signal); + } + d.e=$('.monitor_item[mid="'+d.id+'"][ke="'+d.ke+'"][auth="'+user.auth_token+'"]').resize() + if(d.e.find('.videos_monitor_list li').length===0){ + d.dr=$('#videos_viewer_daterange').data('daterangepicker'); + $.getJSON($.ccio.init('location',user)+user.auth_token+'/videos/'+d.ke+'/'+d.id+'?limit=10',function(f){ + $.ccio.pm(0,{videos:f.videos,ke:d.ke,mid:d.id},null,user) + }) + } + setTimeout(function(){ + if($.ccio.mon[d.ke+d.id+user.auth_token].motionDetectionRunning===true){ + $.ccio.init('streamMotionDetectRestart',{mid:d.id,ke:d.ke,mon:$.ccio.mon[d.ke+d.id+user.auth_token]},user); + } + },3000) + break; + case'pam_frame': + if(!$.ccio.mon[d.ke+d.id+user.auth_token].ctx||$.ccio.mon[d.ke+d.id+user.auth_token].ctx.length===0){ + $.ccio.mon[d.ke+d.id+user.auth_token].ctx = $('#monitor_live_'+d.id+user.auth_token+' canvas'); + $.ccio.mon[d.ke+d.id+user.auth_token].ctxContext = $.ccio.mon[d.ke+d.id+user.auth_token].ctx[0].getContext('2d'); + } + var ctx = $.ccio.mon[d.ke+d.id+user.auth_token].ctxContext; + d.x = 0,d.y = 0; + d.ratio = Math.min($.ccio.mon[d.ke+d.id+user.auth_token].ctx.width()/d.imageData.width,$.ccio.mon[d.ke+d.id+user.auth_token].ctx.height()/d.imageData.height); + d.height = d.imageData.height*d.ratio; + d.width = d.imageData.width*d.ratio; + if( d.width < $.ccio.mon[d.ke+d.id+user.auth_token].ctx.width() ) + d.x = ($.ccio.mon[d.ke+d.id+user.auth_token].ctx.width() / 2) - (d.width / 2); + if( d.height < $.ccio.mon[d.ke+d.id+user.auth_token].ctx.height() ) + d.y = ($.ccio.mon[d.ke+d.id+user.auth_token].ctx.height() / 2) - (d.height / 2); + var imageData = ctx.createImageData(d.width,d.height) + imageData.data.set(new Uint8ClampedArray(d.imageData.data)) + console.log(imageData) + ctx.putImageData(imageData, 0, 0); + break; + case'monitor_frame': + try{ + if($.ccio.mon[d.ke+d.id+user.auth_token].imageLoading === true)return + if(!$.ccio.mon[d.ke+d.id+user.auth_token].ctx||$.ccio.mon[d.ke+d.id+user.auth_token].ctx.length===0){ + $.ccio.mon[d.ke+d.id+user.auth_token].ctx = $('#monitor_live_'+d.id+user.auth_token+' canvas'); + } + var ctx = $.ccio.mon[d.ke+d.id+user.auth_token].ctx[0] + if(!$.ccio.mon[d.ke+d.id+user.auth_token].image){ + $.ccio.mon[d.ke+d.id+user.auth_token].image = new Image() + var image = $.ccio.mon[d.ke+d.id+user.auth_token].image + image.onload = function() { + $.ccio.mon[d.ke+d.id+user.auth_token].imageLoading = false + d.x = 0 + d.y = 0 +// d.ratio = Math.min(ctx.width/image.width,ctx.height/image.height) +// d.height = image.height * d.ratio +// d.width = image.width * d.ratio +// if(d.width < ctx.width){ +// d.x = (ctx.width / 2) - (d.width / 2) +// } +// if(d.height < ctx.height){ +// d.y = (ctx.height / 2) - (d.height / 2) +// } +// ctx.getContext("2d").drawImage(image,d.x,d.y,d.width,d.height) + ctx.getContext("2d").drawImage(image,d.x,d.y,ctx.width,ctx.height) + } + } + var base64Frame = 'data:image/jpeg;base64,'+d.frame + $.ccio.mon[d.ke+d.id+user.auth_token].imageLoading = true + $.ccio.mon[d.ke+d.id+user.auth_token].image.src = base64Frame + $.ccio.mon[d.ke+d.id+user.auth_token].last_frame = base64Frame + }catch(er){ + console.log(er) + $.ccio.log('base64 frame') + } + $.ccio.init('signal',d); + break; + case'monitor_edit': + $.ccio.init('clearTimers',d) + d.e=$('[mid="'+d.mon.mid+'"][ke="'+d.mon.ke+'"][auth="'+user.auth_token+'"]'); + d.e=$('#monitor_live_'+d.mid+user.auth_token); + d.e.find('.stream-detected-object').remove() + if(d.mon.details.control=="1"){d.e.find('[monitor="control_toggle"]').show()}else{d.e.find('.pad').remove();d.e.find('[monitor="control_toggle"]').hide()} + if(user===$user){ + d.chosen_set='watch_on' + }else{ + d.chosen_set='watch_on_links' + } + d.o=$.ccio.op()[d.chosen_set]; + if(!d.o){d.o={}} + if(d.mon.details.cords instanceof Object){d.mon.details.cords=JSON.stringify(d.mon.details.cords);} + d.mon.details=JSON.stringify(d.mon.details); + if(!$.ccio.mon[d.ke+d.mid+user.auth_token]){$.ccio.mon[d.ke+d.mid+user.auth_token]={}} + $.ccio.init('jpegModeStop',d); + $.ccio.mon[d.ke+d.mid+user.auth_token].previousStreamType=d.mon.details.stream_type + $.each(d.mon,function(n,v){ + $.ccio.mon[d.ke+d.mid+user.auth_token][n]=v; + }); + $.ccio.mon[d.ke+d.mid+user.auth_token].user=user + if(d.new===true){$.ccio.tm(1,d.mon,null,user)} + switch(d.mon.mode){ + case'start':case'record': + if(d.o[d.ke]&&d.o[d.ke][d.mid]===1){ + $.ccio.cx({f:'monitor',ff:'watch_on',id:d.mid},user) + } + break; + } + $.ccio.init('monitorInfo',d) + $.gR.drawList(); + if(!d.silenceNote){ + $.ccio.init('note',{title:'Monitor Saved',text:''+d.mon.name+' '+d.mon.mid+' has been saved.',type:'success'}); + } + break; + case'monitor_starting': +// switch(d.mode){case'start':d.mode='Watch';break;case'record':d.mode='Record';break;} +// $.ccio.init('note',{title:'Monitor Starting',text:'Monitor '+d.mid+' is now running in mode '+d.mode+'',type:'success'}); + d.e=$('#monitor_live_'+d.mid+user.auth_token) + if(d.e.length>0){$.ccio.cx({f:'monitor',ff:'watch_on',id:d.mid},user)} + break; + case'mode_jpeg_off': + $.ccio.op('jpeg_on',"0"); + $.each($.ccio.mon,function(n,v,x){ + $.ccio.init('jpegModeStop',v); + if(v.watch===1){ + $.ccio.cx({f:'monitor',ff:'watch_on',id:v.mid},user) + } + }); + $('body').removeClass('jpegMode') + break; + case'mode_jpeg_on': + $.ccio.op('jpeg_on',true); + $.ccio.init('jpegModeAll'); + $('body').addClass('jpegMode') + break; + case'drawPowerVideoMainTimeLine': + var videos = d.videos; + var events = d.events; +// $.pwrvid.currentlyLoading = false + $.pwrvid.currentVideos=videos + $.pwrvid.currentEvents=events + $.pwrvid.e.find('.loading').hide() + $.pwrvid.e.find('.nodata').hide() + //$.pwrvid.drawTimeLine + if($.pwrvid.t&&$.pwrvid.t.destroy){$.pwrvid.t.destroy()} + data={}; + $.each(videos.videos,function(n,v){ + if(!v||!v.mid){return} + v.mon=$.ccio.mon[v.ke+v.mid+$user.auth_token]; +// v.filename=$.ccio.init('tf',v.time)+'.'+v.ext; + if(v.status>0){ + // data.push({src:v,x:v.time,y:$.ccio.timeObject(v.time).diff($.ccio.timeObject(v.end),'minutes')/-1}) + data[v.filename]={ + filename:v.filename, + time:v.time, + timeFormatted:$.ccio.timeObject(v.time).format('MM/DD/YYYY HH:mm'), + endTime:v.end, + close:$.ccio.timeObject(v.time).diff($.ccio.timeObject(v.end),'minutes')/-1, + motion:[], + row:v, + position:n + } + } + }); + + var eventsToCheck = Object.assign({},events) + $.each(data,function(m,b){ + startTimeFormatted = $.ccio.timeObject(b.time).format('YYYY-MM-DD HH:mm:ss'); + startTime = $.ccio.timeObject(b.time).format(); + endTime = $.ccio.timeObject(b.endTime).format(); + var newSetOfEventsWithoutChecked = {}; + var eventTime + $.each(eventsToCheck,function(n,v){ + if(typeof v.time === 'string' && v.time.indexOf('T') > -1){ + eventTime = v.time.split('T') + }else if(typeof v.time === 'number'){ + eventTime = moment(v.time).format('YYYY-MM-DD HH:mm:ss').split(' ') + }else{ + eventTime = v.time.split(' ') + } + eventTime[1] = eventTime[1].replace(/-/g,':'),eventTime = eventTime.join(' '); + if(eventTime === startTimeFormatted){ + data[m].motion.push(v) + }else if ($.ccio.timeObject(v.time).isBetween(startTime,$.ccio.timeObject(b.endTime).format())) { + data[m].motion.push(v) + }else{ + newSetOfEventsWithoutChecked[n] = v; + } + }) + eventsToCheck = newSetOfEventsWithoutChecked; + }); + $.pwrvid.currentDataObject=data; + if($.pwrvid.chart){ + $.pwrvid.d.empty() + delete($.pwrvid.chart) + } + $.pwrvid.currentData=Object.values(data); + if($.pwrvid.currentData.length>0){ + var labels=[] + var Dataset1=[] + var Dataset2=[] + $.each(data,function(n,v){ + labels.push(v.timeFormatted) + Dataset1.push(v.close) + Dataset2.push(v.motion.length) + }) + $.pwrvid.d.html("") + var timeFormat = 'MM/DD/YYYY HH:mm'; + var color = Chart.helpers.color; + Chart.defaults.global.defaultFontColor = '#fff'; + var config = { + type: 'bar', + data: { + labels: labels, + datasets: [{ + type: 'line', + label: lang['Video and Time Span (Minutes)'], + backgroundColor: color(window.chartColors.blue).alpha(0.2).rgbString(), + borderColor: window.chartColors.blue, + data: Dataset1, + }, { + type: 'bar', + showTooltip: false, + label: lang['Counts of Motion'], + backgroundColor: color(window.chartColors.red).alpha(0.5).rgbString(), + borderColor: window.chartColors.red, + data:Dataset2, + }, ] + }, + options: { + maintainAspectRatio: false, + title: { + fontColor: "white", + text: lang['Video Length (minutes) and Motion Count per video'] + }, + tooltips: { + callbacks: { + + }, + }, + scales: { + xAxes: [{ + type: "time", + display: true, + time: { + format: timeFormat, + // round: 'day' + } + }], + }, + } + }; + + var ctx = $.pwrvid.d.find('canvas')[0].getContext("2d"); + $.pwrvid.chart = new Chart(ctx, config); + $.pwrvid.d.find('canvas').click(function(e) { + var target = $.pwrvid.chart.getElementsAtEvent(e)[0]; + if(!target){return false} + target = $.pwrvid.currentData[target._index]; + $.pwrvid.e.find('.temp').html('
    • ').find('a').click() + }); + var colorNames = Object.keys(window.chartColors); + }else{ + $.pwrvid.e.find('.nodata').show() + } + break; + } +} +$user.ws=io(location.origin,{ + path : tool.checkCorrectPathEnding(location.pathname)+'socket.io' +}); +$user.ws.on('connect',function (d){ + $(document).ready(function(e){ + $.ccio.init('id',$user); + $.ccio.cx({f:'init',ke:$user.ke,auth:$user.auth_token,uid:$user.uid}) + if($user.details&&$user.details.links){ + $.each($user.details.links,function(n,v){ + if(v.secure==='0'){ + v.protocol='http' + }else{ + v.protocol='https' + } + if(v.host.indexOf('://')>-1){ + v.URL=v.protocol+'://'+v.host.split('://')[1] + }else{ + v.URL=v.protocol+'://'+v.host + } + $.get(v.URL+'/'+v.api+'/userInfo/'+v.ke,function(e){ + if(e.ok===true){ + e.user.auth_token=v.api + $.users[v.api]=e.user + $.users[v.api].info=v + $.users[v.api].ws=io(v.host) + $.users[v.api].ws.on('ping', function(d){ + $.users[v.api].ws.emit('pong',{beat:1}); + }); + $.users[v.api].ws.on('connect',function (d){ + console.log(v.host,'connected') + $.ccio.cx({f:'init',ke:e.user.ke,auth:v.api,uid:e.user.uid},$.users[v.api]) + }) + $.users[v.api].ws.on('f',function (d){ + $.ccio.globalWebsocket(d,$.users[v.api]) + }) + } + }) + }) + } + }) +}) +PNotify.prototype.options.styling = "fontawesome"; +$user.ws.on('ping', function(d){ + $user.ws.emit('pong',{beat:1}); +}); +$user.ws.on('f',function (d){ + $.ccio.globalWebsocket(d) + switch(d.f){ + case'api_key_deleted': + if($user.uid === d.uid){ + $.ccio.init('note',{title:lang['API Key Deleted'],text:lang.APIKeyDeletedText,type:'notice'}); + $('[api_key="'+d.form.code+'"]').remove() + } + break; + case'api_key_added': + if($user.uid === d.uid){ + $.ccio.init('note',{title:lang['API Key Added'],text:lang.FiltersUpdatedText,type:'success'}); + $.ccio.tm(3,d.form,'#api_list') + } + break; + case'filters_change': + $.ccio.init('note',{title:lang['Filters Updated'],text:lang.FiltersUpdatedText,type:'success'}); + $user.details.filters=d.filters; + $.ccio.init('filters'); + break; + case'user_settings_change': + $.ccio.init('note',{title:lang['Settings Changed'],text:lang.SettingsChangedText,type:'success'}); + $.ccio.init('id',d.form); + d.form.details=JSON.parse(d.form.details) + $('#custom_css').append(d.form.details.css) + if(d.form.details){ + $user.details=d.form.details + } + break; + case'users_online': + $.ccio.pm('user-row',d.users); + break; + case'user_status_change': + if(d.status===1){ + $.ccio.tm('user-row',d.user,null) + }else{ + $('.user-row[uid="'+d.uid+'"][ke="'+d.ke+'"]').remove() + } + break; + case'ffprobe_stop': + $.pB.e.find('._loading').hide() + $.pB.o.append('
      END
      '); + $.pB.e.find('.stop').hide(); + $.pB.e.find('[type="submit"]').show(); + break; + case'ffprobe_start': + $.pB.e.find('._loading').show() + $.pB.o.empty(); + $.pB.e.find('.stop').show(); + $.pB.e.find('[type="submit"]').hide(); + break; + case'ffprobe_data': + $.pB.results=JSON.parse(d.data) + $.pB.o.append($.ccio.init('jsontoblock',$.pB.results)) + break; + case'detector_cascade_list': + d.tmp='' + $.each(d.cascades,function(n,v){ + d.tmp+='
    • '; + d.tmp+=''; + d.tmp+=v; + d.tmp+=''; + d.tmp+=''; + d.tmp+=''; + d.tmp+=''; + d.tmp+='
    • '; + }) + $('#detector_cascade_list').html(d.tmp) + componentHandler.upgradeAllRegistered() + //add auto select for preferences + d.currentlyEditing=$.aM.e.attr('mid') + if(d.currentlyEditing&&d.currentlyEditing!==''){ + d.currentlyEditing=JSON.parse(JSON.parse($.ccio.mon[d.currentlyEditing].details).detector_cascades) + $.each(d.currentlyEditing,function(m,b){ + d.e=$('.detector_cascade_selection[value="'+m+'"]').prop('checked',true) + d.p=d.e.parents('.mdl-js-switch') + if(d.p.length>0){ + d.p.addClass('is-checked') + } + }) + } + break; + case'detector_plugged': + $.aM.addDetectorPlugin(d.plug,d) + break; + case'detector_unplugged': + $.aM.removeDetectorPlugin(d.plug) + break; + case'monitor_edit_failed': + d.pnote={title:'Monitor Not Saved',text:''+d.mon.name+' '+d.mon.mid+' has not been saved.',type:'error'} + switch(d.ff){ + case'max_reached': + d.pnote.text+=' '+lang.monitorEditFailedMaxReached + break; + } + $.ccio.init('note',d.pnote); + break; +// case'onvif_end': +// if(Object.keys($.oB.foundMonitorsCount).length===0){ +// $.oB.e.find('._loading').hide() +// $.oB.e.find('[type="submit"]').prop('disabled',false) +// $.oB.o.append('Sorry, nothing was found.') +// } +// break; + case'onvif': + var tempID = $.ccio.gid(); + $.oB.foundMonitors[tempID] = Object.assign({},d); + $.oB.e.find('._loading').hide() + $.oB.e.find('._notfound').remove() + $.oB.e.find('[type="submit"]').prop('disabled',false) + d.info=$.ccio.init('jsontoblock',d.info) + if(d.uri){ + d.stream=d.uri + }else{ + d.stream='URL not Found' + } + $('#onvif_probe .output_data').append('  '+d.ip+''+d.port+''+$.ccio.init('jsontoblock',d.info)+''+d.stream+'') + break; + } + delete(d); +}); +}) diff --git a/web/libs/js/dash2.timelapse.js b/web/libs/js/dash2.timelapse.js new file mode 100644 index 0000000..0334d9e --- /dev/null +++ b/web/libs/js/dash2.timelapse.js @@ -0,0 +1,334 @@ +$(document).ready(function(e){ + //Timelapse Window + $.timelapse={e:$('#timelapse')} + $.timelapse.f=$.timelapse.e.find('form'), + $.timelapse.meter=$.timelapse.e.find('.motion-meter'), + $.timelapse.line=$('#timelapse_video_line'), + $.timelapse.display=$('#timelapse_video_display'), + $.timelapse.seekBar=$('#timelapse_seekBar'), + $.timelapse.seekBarProgress=$.timelapse.seekBar.find('.progress-bar'), + $.timelapse.dr=$('#timelapse_daterange'), + $.timelapse.mL=$.timelapse.e.find('.motion_list'), + $.timelapse.monitors=$.timelapse.e.find('.monitors_list'); + $.timelapse.playDirection='videoAfter' + $.timelapse.playRate=15 + $.timelapse.placeholder=placeholder.getData(placeholder.plcimg({bgcolor:'#b57d00',text:'...'})) + $.timelapse.dr.daterangepicker({ + startDate:$.ccio.timeObject().subtract(moment.duration("24:00:00")), + endDate:$.ccio.timeObject().add(moment.duration("24:00:00")), + timePicker: true, + timePicker24Hour: true, + timePickerSeconds: true, + timePickerIncrement: 30, + locale: { + format: 'MM/DD/YYYY h:mm A' + } + },function(start, end, label){ + $.timelapse.drawTimeline() + $.timelapse.dr.focus() + }); + $.timelapse.f.find('input,select').change(function(){ + $.timelapse.f.submit() + }) + $.timelapse.f.submit(function(e){ + e.preventDefault(); + $.timelapse.drawTimeline() + return false; + }) + $.timelapse.drawTimeline=function(getData){ + var e={}; + if(getData===undefined){getData=true} + var mid = $.timelapse.monitors.val() + e.dateRange=$.timelapse.dr.data('daterangepicker'); + e.dateRange={startDate:e.dateRange.startDate,endDate:e.dateRange.endDate} + e.videoURL=$.ccio.init('location',$user)+$user.auth_token+'/videos/'+$user.ke+'/'+mid; + e.videoURL+='?limit=100&start='+$.ccio.init('th',e.dateRange.startDate)+'&end='+$.ccio.init('th',e.dateRange.endDate); + e.next=function(videos){ + $.timelapse.currentVideos={} + e.tmp='' + $.each(videos.videos,function(n,v){ + if(!v||!v.time){return} + // v.filename=$.ccio.init('tf',v.time)+'.'+v.ext; + v.videoBefore=videos.videos[n-1]; + v.videoAfter=videos.videos[n+1]; + // if(v.href.charAt(0)==='/'){ + // v.href=$.ccio.init('location',user)+(v.href.substring(1)) + // v.videoURL=$.ccio.init('location',user)+(v.videoURL.substring(1)) + // } + v.position=n; + $.timelapse.currentVideos[v.filename]=v; + e.tmp+='
    • ' + e.tmp+='
      ' + e.tmp+='
      ' + e.tmp+='
      '+v.filename+'
      ' + e.tmp+='' + e.tmp+='
      ' + e.tmp+='
      ' + e.tmp+='
      ' + e.tmp+='
      ' + e.tmp+='
    • ' + }) + $.timelapse.line.html(e.tmp) + $.ccio.init('ls') + if(getData===true){ + e.timeout=50 + }else{ + e.timeout=2000 + } + setTimeout(function(){ + if($.timelapse.e.find('.timelapse_video.active').length===0){ + $.timelapse.e.find('[timelapse="video"]').first().click() + } + },e.timeout) + } + if(getData===true){ + $.getJSON(e.videoURL,function(videos){ + videos.videos=videos.videos.reverse() + $.timelapse.currentVideosArray=videos + e.next(videos) + }) + }else{ + e.next($.timelapse.currentVideosArray) + } + } + $.timelapse.playButtonIcon = $.timelapse.e.find('[timelapse="play"]').find('i') + $.timelapse.timelapseSpeedUseBasicSwitch = $('#timelapseSpeedUseBasic') + $.timelapse.timelapseSpeedUseBasicSwitch.on('change',function(){ + var el = $.timelapse.e.find('.timelapseSpeedUseBasicSwitch') + if($(this).is(':checked')){ + el.hide() + }else{ + el.show() + } + $.timelapse.play() + }) + $.timelapse.getUseBasicStatus = function(){return $.timelapse.timelapseSpeedUseBasicSwitch.prop('checked')} + $.timelapse.onPlayPause = function(toggleGui,secondWind){ + if($.timelapse.paused === true){ + $.timelapse.paused = false + if(toggleGui === true)$.timelapse.play(); + }else{ + $.timelapse.paused = true + if(toggleGui === true)$.timelapse.pause(secondWind); + } + } + $.timelapse.pause = function(secondWind){ + //secondWind is used because sometimes pause can be pressed just as a video ends and the pause command does not register on the next video. + var videoNow = $.timelapse.display.find('video.videoNow')[0] + var pause = function(){ + if(videoNow.paused == false)videoNow.pause() + clearInterval($.timelapse.interval) + $.timelapse.playButtonIcon.removeClass('fa-pause').addClass('fa-play') + } + pause() + if(secondWind === true)setTimeout(pause,250); + } + $.timelapse.play = function(x){ + var videoNow = $.timelapse.display.find('video.videoNow')[0] + $.timelapse.pause() + clearInterval($.timelapse.interval) + if($.timelapse.getUseBasicStatus()){ + videoNow.playbackRate = $.timelapse.playRate + if(videoNow.paused)videoNow.play() + }else{ + videoNow.playbackRate = 1.0 + $.timelapse.interval = setInterval(function(){ + if(videoNow.currentTime >= videoNow.duration - .2){ + clearInterval($.timelapse.interval) + videoNow.currentTime = videoNow.duration + }else{ + videoNow.currentTime += .5 + } + },500 / $.timelapse.playRate) + } + $.timelapse.playButtonIcon.removeClass('fa-play').addClass('fa-pause') + } + $.timelapse.rewind = function(e){ + var videoNow = $.timelapse.display.find('video.videoNow')[0] + $.timelapse.pause() + videoNow.playbackRate = 1.0 + clearInterval($.timelapse.interval) + $.timelapse.interval = setInterval(function(){ + if(videoNow.currentTime <= 0.2){ + clearInterval($.timelapse.interval) + videoNow.currentTime = 0 + $('[timelapse][href="'+e.videoCurrentBefore.attr('video')+'"]').click() + var videoNowNew = $.timelapse.display.find('video.videoNow')[0] + videoNowNew.pause() + videoNowNew.currentTime = videoNowNew.duration - 0.1 + $.timelapse.e.find('[timelapse="stepBackBack"]').click() + }else{ + videoNow.currentTime += -.5 + } + },500 / $.timelapse.playRate) + $.timelapse.playButtonIcon.removeClass('fa-play').addClass('fa-pause') + } + $.timelapse.e.on('click','[timelapse]',function(){ + var e={} + e.e=$(this) + e.videoCurrentNow=$.timelapse.display.find('.videoNow') + e.videoCurrentAfter=$.timelapse.display.find('.videoAfter') + e.videoCurrentBefore=$.timelapse.display.find('.videoBefore') + if($.timelapse.videoInterval){ + clearInterval($.timelapse.videoInterval); + } + switch(e.e.attr('timelapse')){ + case'download': + $.timelapse.line.find('.active [download]').click() + break; + case'mute': + e.videoCurrentNow[0].muted = !e.videoCurrentNow[0].muted + $.timelapse.videoNowIsMuted = e.videoCurrentNow[0].muted + e.e.find('i').toggleClass('fa-volume-off fa-volume-up') + e.e.toggleClass('btn-danger') + break; + case'play': + e.videoCurrentNow[0].playbackRate = $.timelapse.playRate; + $.timelapse.onPlayPause(true,true) + break; + case'setPlayBackRate': + $.timelapse.pause() + $.timelapse.playRate = parseFloat(e.e.attr('playRate')) + $.timelapse.play() + break; + case'stepFrontFront': + e.add=e.e.attr('add') + e.stepFrontFront=parseInt(e.e.attr('stepFrontFront')) + if(!e.stepFrontFront||isNaN(e.stepFrontFront)){e.stepFrontFront = 5} + if(e.add==="0"){ + $.timelapse.playRate = e.stepFrontFront + }else{ + $.timelapse.playRate += e.stepFrontFront + } + e.videoCurrentNow[0].playbackRate = $.timelapse.playRate; + e.videoCurrentNow[0].play() + break; + case'stepFront': + e.videoCurrentNow[0].currentTime += 5; + e.videoCurrentNow[0].pause() + break; + case'stepBackBack': + // e.videoCurrentNow=$.timelapse.display.find('.videoNow') + // e.videoCurrentAfter=$.timelapse.display.find('.videoAfter') + // e.videoCurrentBefore=$.timelapse.display.find('.videoBefore') + $.timelapse.rewind(e) + break; + case'stepBack': + e.videoCurrentNow[0].currentTime += -5; + e.videoCurrentNow[0].pause() + break; + case'video': + $.timelapse.e.find('video').each(function(n,v){ + v.pause() + }) + e.drawVideoHTML=function(position){ + var video + var exisitingElement=$.timelapse.display.find('.'+position) + if(position){ + video=e.video[position] + }else{ + position='videoNow' + video=e.video + } + if(video){ + $.timelapse.display.append('') + } + } + e.filename=e.e.attr('file') + e.video=$.timelapse.currentVideos[e.filename] + e.videoIsSame=(e.video.href==e.videoCurrentNow.attr('video')) + e.videoIsAfter=(e.video.href==e.videoCurrentAfter.attr('video')) + e.videoIsBefore=(e.video.href==e.videoCurrentBefore.attr('video')) + if(e.videoIsSame||e.videoIsAfter||e.videoIsBefore){ + switch(true){ + case e.videoIsSame: + $.ccio.log('$.timelapse','videoIsSame') + e.videoNow=$.timelapse.display.find('video.videoNow') + if(e.videoNow[0].paused===true){ + e.videoNow[0].play() + }else{ + e.videoNow[0].pause() + } + return + break; + case e.videoIsAfter: + $.ccio.log('$.timelapse','videoIsAfter') + e.videoCurrentBefore.remove() + e.videoCurrentAfter.removeClass('videoAfter').addClass('videoNow') + e.videoCurrentNow.removeClass('videoNow').addClass('videoBefore') + e.drawVideoHTML('videoAfter') + break; + case e.videoIsBefore: + $.ccio.log('$.timelapse','videoIsBefore') + e.videoCurrentAfter.remove() + e.videoCurrentBefore.removeClass('videoBefore').addClass('videoNow') + e.videoCurrentNow.removeClass('videoNow').addClass('videoAfter') + e.drawVideoHTML('videoBefore') + break; + } + }else{ + $.ccio.log('$.timelapse','newSetOf3') + $.timelapse.display.empty() + e.drawVideoHTML()//videoNow + e.drawVideoHTML('videoBefore') + e.drawVideoHTML('videoAfter') + } + $.timelapse.display.find('video').each(function(n,v){ + v.addEventListener('loadeddata', function() { + e.videoCurrentAfterPreview=$('.timelapse_video[href="'+$(v).attr('video')+'"] .frame') + if(e.videoCurrentAfterPreview.attr('set')!=='1'){ + $.ccio.snapshotVideo(v,function(url,buffer){ + e.videoCurrentAfterPreview.attr('set','1').css('background-image','url('+url+')') + if($(v).hasClass('videoAfter')){ + v.currentTime=0 + v.pause() + } + }) + } + }, false); + }) + e.videoNow=$.timelapse.display.find('video.videoNow')[0] + if($.timelapse.videoNowIsMuted){ + e.videoNow.muted=true + } + $.timelapse.playButtonIcon.removeClass('fa-pause').addClass('fa-play') + $.timelapse.onended = function() { + $.timelapse.line.find('[file="'+e.video[$.timelapse.playDirection].filename+'"]').click() + }; + e.videoNow.onended = $.timelapse.onended + e.videoNow.onerror = $.timelapse.onended + // + $(e.videoNow) + .off('play').on('play',$.timelapse.play) + .off('pause').on('pause',$.timelapse.onPlayPause) + .off('timeupdate').on('timeupdate',function(){ + var value= (( e.videoNow.currentTime / e.videoNow.duration ) * 100)+"%" + $.timelapse.seekBarProgress.css("width",value); + $.timelapse.e.find('.timelapse_video[file="'+e.filename+'"] .progress-bar').css("width",value); + }) + $.timelapse.play() + $.timelapse.seekBar.off("click").on("click", function(seek){ + var offset = $(this).offset(); + var left = (seek.pageX - offset.left); + var totalWidth = $.timelapse.seekBar.width(); + var percentage = ( left / totalWidth ); + var vidTime = e.videoNow.duration * percentage; + e.videoNow.currentTime = vidTime; + }); + + $.ccio.log('$.timelapse',e.video) + $.timelapse.line.find('.timelapse_video').removeClass('active') + e.videoCurrentNow=$.timelapse.display.find('.videoNow') + e.e.addClass('active') + if ($('#timelapse_video_line:hover').length === 0) { + $.timelapse.line.animate({scrollTop:$.timelapse.line.scrollTop() + e.e.position().top - $.timelapse.line.height()/2 + e.e.height()/2 - 40}); + } + break; + } + $.timelapse.e.find('.timelapse_playRate').text('x'+$.timelapse.playRate) + }) + $.timelapse.e.on('hidden.bs.modal',function(e){ + delete($.timelapse.currentVideos) + delete($.timelapse.currentVideosArray) + }) +}) diff --git a/web/libs/js/dash2.usersettings.js b/web/libs/js/dash2.usersettings.js new file mode 100644 index 0000000..388f6db --- /dev/null +++ b/web/libs/js/dash2.usersettings.js @@ -0,0 +1,101 @@ +$(document).ready(function(e){ +//settings window +$.sM={e:$('#settings')}; +$.sM.f=$.sM.e.find('form'); +$.sM.links=$('#linkShinobi'); +$.sM.g=$('#settings_mon_groups'); +$.sM.md=$.sM.f.find('[detail]'); +$.sM.md.change($.ccio.form.details); +$.sM.f.find('[selector]').change(function(e){ + e.v=$(this).val();e.a=$(this).attr('selector') + $.sM.f.find('.'+e.a+'_input').hide() + $.sM.f.find('.'+e.a+'_'+e.v).show(); + $.sM.f.find('.'+e.a+'_text').text($(this).find('option:selected').text()) +}); +$.sM.writewMonGroups=function(){ + $.sM.f.find('[detail="mon_groups"]').val(JSON.stringify($user.mon_groups)).change() +} +$.sM.reDrawMonGroups=function(){ + $.sM.g.empty(); + $.ccio.pm('option',$user.mon_groups,'#settings_mon_groups') + $.sM.g.change(); +}; +$.sM.f.submit(function(e){ + e.preventDefault(); + $.sM.writewMonGroups() + $.sM.linkChange() + e.e=$(this),e.s=e.e.serializeObject(); + e.er=[]; + if(e.s.pass!==''&&e.password_again===e.s.pass){e.er.push(lang['Passwords don\'t match'])}; + if(e.er.length>0){$.sM.e.find('.msg').html(e.er.join('
      '));return;} + $.each(e.s,function(n,v){e.s[n]=v.trim()}) + $.ccio.cx({f:'settings',ff:'edit',form:e.s}) + $.sM.e.modal('hide') +}); +$.sM.e.on('shown.bs.modal',function(){ + $.sM.reDrawMonGroups() +}) +$.sM.g.change(function(e){ + e.v=$(this).val(); + e.group=$user.mon_groups[e.v]; + if(!e.group){return} + $.sM.selectedMonGroup=e.group; + $.each(e.group,function(n,v){ + $.sM.f.find('[group="'+n+'"]').val(v) + }) +}); +$.sM.f.find('[group]').change(function(){ + e = {} + e.v = $.sM.g.val() + if(!e.v||e.v==''){ + e.e = $.sM.f.find('[group="name"]') + e.name = e.e.val() + $('.mon_groups .add').click(); + e.v = $.sM.g.val() + e.e.val(e.name) + } + e.group=$user.mon_groups[e.v]; + $.sM.f.find('[group]').each(function(n,v){ + v=$(v) + e.group[v.attr('group')]=v.val() + }); + $user.mon_groups[e.v]=e.group; + $.sM.g.find('option[value="'+$.sM.g.val()+'"]').text(e.group.name) + $.sM.writewMonGroups() +}) +$.sM.f.on('click','.mon_groups .delete',function(e){ + e.v=$.sM.g.val(); + delete($user.mon_groups[e.v]); + $.sM.reDrawMonGroups() +}) +$.sM.f.on('click','.mon_groups .add',function(e){ + e.gid=$.ccio.gid(5); + $user.mon_groups[e.gid]={id:e.gid,name:e.gid}; + $.sM.g.append($.ccio.tm('option',$user.mon_groups[e.gid])); + $.sM.g.val(e.gid) + $.sM.g.change(); +}); +$.sM.linkChange=function(){ + var e={}; + e.e=$.sM.e.find('[name="details"]') + e.details=JSON.parse(e.e.val()) + e.details.links=[] + $.sM.links.find('.linksGroup').each(function(n,v){ + var arr={} + $(v).find('[link]').each(function(m,b){ + arr[$(b).attr('link')]=$(b).val() + }) + e.details.links.push(arr) + }) + e.e.val(JSON.stringify(e.details)) +} +$.sM.f.on('change','[link]',$.sM.linkChange) +$.sM.e.on('click','.linkShinobi .delete',function(){ + $(this).parents('.linksGroup').remove() + $.sM.linkChange() +}) +$.sM.e.find('.linkShinobi .add').click(function(){ + $.ccio.tm('link-set',{},'#linkShinobi') + $.sM.linkChange() +}) +}) diff --git a/web/libs/js/dash2.vidview.js b/web/libs/js/dash2.vidview.js new file mode 100644 index 0000000..aa75476 --- /dev/null +++ b/web/libs/js/dash2.vidview.js @@ -0,0 +1,174 @@ +$(document).ready(function(e){ +//videos window +$.vidview={ + e:$('#videos_viewer'), + pages:$('#videos_viewer_pages'), + limit:$('#videos_viewer_limit'), + dr:$('#videos_viewer_daterange'), + preview:$('#videos_viewer_preview'), + set:$('#videos_viewer_set') +} +$.vidview.set.change(function(){ + var el = $(this) + var isCloud = (el.val() === 'cloud') + var zipDlButton = $.vidview.e.find('.export_selected,.merge_selected') + if(isCloud){ + zipDlButton.hide() + }else{ + zipDlButton.show() + } + +}) +$.vidview.f=$.vidview.e.find('form') +$.vidview.dr.daterangepicker({ + startDate:$.ccio.timeObject().subtract(moment.duration("24:00:00")), + endDate:$.ccio.timeObject().add(moment.duration("24:00:00")), + timePicker: true, + timePicker24Hour: true, + timePickerSeconds: true, + timePickerIncrement: 30, + locale: { + format: 'MM/DD/YYYY h:mm A' + } +},function(start, end, label){ + $.vidview.launcher.click() + $.vidview.dr.focus() +}); +$.vidview.e.on('change','#videos_select_all',function(e){ + e.e=$(this); + e.p=e.e.prop('checked') + e.a=$.vidview.e.find('input[type=checkbox][name]') + if(e.p===true){ + e.a.prop('checked',true) + }else{ + e.a.prop('checked',false) + } +}) +$.vidview.f.submit(function(e){ + e.preventDefault(); + $.vidview.launcher.click() + return false; +}) +$('#videos_viewer_limit,#videos_viewer_daterange,#videos_viewer_set').change(function(){ + $.vidview.f.submit() +}) +$.vidview.getSelected = function(getArray){ + var arr = {} + if(getArray){ + arr = [] + } + $.vidview.f.find('[data-ke] input:checked').each(function(n,v){ + v=$(v).parents('tr') + if(getArray){ + arr.push({filename:v.attr('data-file'),mid:v.attr('data-mid'),auth:v.attr('data-auth')}) + }else{ + arr[v.attr('data-file')]={mid:v.attr('data-mid'),auth:v.attr('data-auth')} + } + }) + return arr +} +$.vidview.e.find('.delete_selected').click(function(){ + e = {} + e.s = $.vidview.getSelected() + if(Object.keys(e.s).length === 0){ + $.ccio.init('note',{ + title:'No Videos Selected', + text:'You must choose at least one video.', + type:'error' + },$user); + return + } + $.confirm.e.modal('show'); + $.confirm.title.text(lang['Delete Selected Videos']) + e.html=lang.DeleteSelectedVideosMsg+'
      ' + var deleteLinks = [] + $.each(e.s,function(n,v){ + e.html+=n+'
      '; + if($.vidview.loadedVideos[n])deleteLinks.push($.vidview.loadedVideos[n].links.deleteVideo) + }) + $.confirm.body.html(e.html) + $.confirm.click({title:'Delete Video',class:'btn-danger'},function(){ + $.each(deleteLinks,function(n,link){ + $.getJSON(link,function(d){ + $.ccio.log(d) + }) + }) + }); +}) +$.vidview.e.find('.export_selected').click(function(){ + e = {} + var videos = $.vidview.getSelected(true) + if(videos.length === 0){ + $.ccio.init('note',{ + title:'No Videos Selected', + text:'You must choose at least one video.', + type:'error' + },$user); + return + } + $.confirm.e.modal('show'); + $.confirm.title.text(lang['Export Selected Videos']) + var html = lang.ExportSelectedVideosMsg+'
      ' + $.each(videos,function(n,v){ + html+=v.filename+'
      '; + }) + $.confirm.body.html(html) + $.confirm.click({title:'Export Video',class:'btn-danger'},function(){ + var queryVariables = [] + queryVariables.push('videos='+JSON.stringify(videos)) + if($.ccio.useUTC === true){ + queryVariables.push('isUTC=true') + } + var downloadZip = $.ccio.init('location',$user)+$user.auth_token+'/zipVideos/'+$user.ke+'?'+queryVariables.join('&') + $('#temp').html('').find('iframe').attr('src',downloadZip); + }); +}) +$.vidview.e.find('.merge_selected').click(function(){ + e = {} + var videos = $.vidview.getSelected(true) + if(videos.length === 0){ + $.ccio.init('note',{ + title:'No Videos Selected', + text:'You must choose at least one video.', + type:'error' + },$user); + return + } + $.confirm.e.modal('show'); + $.confirm.title.text(lang['Merge Selected Videos']) + var html = lang.MergeSelectedVideosMsg+'
      ' + $.each(videos,function(n,v){ + html+=v.filename+'
      '; + }) + $.confirm.body.html(html) + $.confirm.click({title:'Merge Video',class:'btn-danger'},function(){ + var queryVariables = [] + queryVariables.push('videos='+JSON.stringify(videos)) + if($.ccio.useUTC === true){ + queryVariables.push('isUTC=true') + } + var downloadZip = $.ccio.init('location',$user)+$user.auth_token+'/videosMerge/'+$user.ke+'?'+queryVariables.join('&') + $('#temp').html('').find('iframe').attr('src',downloadZip) + }); +}) +$.vidview.pages.on('click','[page]',function(e){ + e.limit=$.vidview.limit.val(); + e.page=$(this).attr('page'); + $.vidview.current_page=e.page; + if(e.limit.replace(/ /g,'')===''){ + e.limit='100'; + } + if(e.limit.indexOf(',')>-1){ + e.limit=parseInt(e.limit.split(',')[1]) + }else{ + e.limit=parseInt(e.limit) + } + $.vidview.limit.val((parseInt(e.page)-1)+'00,'+e.limit) + $.vidview.launcher.click() +}) +$.vidview.e.on('click','.preview',function(e){ + e.preventDefault() + e=$(this) + $.vidview.preview.html('') +}) +}) diff --git a/web/libs/js/main.dash2.js b/web/libs/js/main.dash2.js index 1f5bbd3..7b7e7c9 100644 --- a/web/libs/js/main.dash2.js +++ b/web/libs/js/main.dash2.js @@ -1156,7 +1156,9 @@ switch($user.details.lang){ tmp+=''; break; case'option': - tmp+='' + var selected = '' + if(d.selected === true){selected = ' selected'} + tmp+='' break; case'stream-element': try{k.d=JSON.parse(d.details);}catch(er){k.d=d.details} @@ -5839,13 +5841,14 @@ $('body') getThumbnail() break; case'videos_table': + var showThumbnail = $.ccio.op().showThumbnail === '1' $.vidview.e.removeClass('dark') e.t.attr('class','fa fa-film') var tmp = ''; tmp+=''; tmp+=''; tmp+=''; - tmp+=''; + if(showThumbnail)tmp+=''; tmp+=''; tmp+=''; tmp+=''; @@ -5869,7 +5872,7 @@ $('body') // v.filename=$.ccio.init('tf',v.time)+'.'+v.ext; tmp+=''; tmp+=''; - tmp+=''; + if(showThumbnail)tmp+=''; tmp+=''; tmp+=''; tmp+=''; @@ -5887,20 +5890,22 @@ $('body') tmp+=''; tmp+='
      '+lang.Thumbnail+''+lang.Thumbnail+''+lang.Closed+''+lang.Ended+''+lang.Started+'
      '+$.ccio.timeObject(v.end).format('h:mm:ss A, MMMM Do YYYY')+''+$.ccio.timeObject(v.time).format('h:mm:ss A, MMMM Do YYYY')+'
      '; e.b.html(tmp) - var i = 0 - var getThumbnail = function(){ - var v = d.videos[i] - if(v){ - tool.getVideoImage($.ccio.init('videoUrlBuild',v),0,function(err,base64){ - if(base64){ - $('[data-ke="'+v.ke+'"][data-mid="'+v.mid+'"][data-file="'+v.filename+'"] .thumbnail')[0].src = base64 - } - ++i - getThumbnail() - }) + if(showThumbnail){ + var i = 0 + var getThumbnail = function(){ + var v = d.videos[i] + if(v){ + tool.getVideoImage($.ccio.init('videoUrlBuild',v),0,function(err,base64){ + if(base64){ + $('[data-ke="'+v.ke+'"][data-mid="'+v.mid+'"][data-file="'+v.filename+'"] .thumbnail')[0].src = base64 + } + ++i + getThumbnail() + }) + } } + getThumbnail() } - getThumbnail() $.ccio.init('ls'); $.vidview.e.find('table').bootstrapTable(); break; diff --git a/web/libs/less/_Black.less b/web/libs/less/_Black.less new file mode 100644 index 0000000..df3af5f --- /dev/null +++ b/web/libs/less/_Black.less @@ -0,0 +1,8 @@ +/* BEGIN Black */ +@font-face { + font-family: Roboto; + .fontdef-woff(@FontPath, @FontName, @FontVersion, "Black"); + font-weight: 900; + font-style: normal; +} +/* END Black */ diff --git a/web/libs/less/_BlackItalic.less b/web/libs/less/_BlackItalic.less new file mode 100644 index 0000000..96b5f74 --- /dev/null +++ b/web/libs/less/_BlackItalic.less @@ -0,0 +1,8 @@ +/* BEGIN Black Italic */ +@font-face { + font-family: Roboto; + .fontdef-woff(@FontPath, @FontName, @FontVersion, "BlackItalic"); + font-weight: 900; + font-style: italic; +} +/* END Black Italic */ diff --git a/web/libs/less/_Bold.less b/web/libs/less/_Bold.less new file mode 100644 index 0000000..0a265bf --- /dev/null +++ b/web/libs/less/_Bold.less @@ -0,0 +1,14 @@ +/* BEGIN Bold */ +@font-face { + font-family: Roboto; + .fontdef-woff(@FontPath, @FontName, @FontVersion, "Bold"); + font-weight: 700; + font-style: normal; +} +@font-face { + font-family: Roboto; + .fontdef-woff(@FontPath, @FontName, @FontVersion, "Bold"); + font-weight: bold; + font-style: normal; +} +/* END Bold */ diff --git a/web/libs/less/_BoldItalic.less b/web/libs/less/_BoldItalic.less new file mode 100644 index 0000000..ce17850 --- /dev/null +++ b/web/libs/less/_BoldItalic.less @@ -0,0 +1,14 @@ +/* BEGIN Bold Italic */ +@font-face { + font-family: Roboto; + .fontdef-woff(@FontPath, @FontName, @FontVersion, "BoldItalic"); + font-weight: 700; + font-style: italic; +} +@font-face { + font-family: Roboto; + .fontdef-woff(@FontPath, @FontName, @FontVersion, "BoldItalic"); + font-weight: bold; + font-style: italic; +} +/* END Bold Italic */ diff --git a/web/libs/less/_Italic.less b/web/libs/less/_Italic.less new file mode 100644 index 0000000..03a8c84 --- /dev/null +++ b/web/libs/less/_Italic.less @@ -0,0 +1,14 @@ +/* BEGIN Italic */ +@font-face { + font-family: Roboto; + .fontdef-woff(@FontPath, @FontName, @FontVersion, "Italic"); + font-weight: 400; + font-style: italic; +} +@font-face { + font-family: Roboto; + .fontdef-woff(@FontPath, @FontName, @FontVersion, "Italic"); + font-weight: normal; + font-style: italic; +} +/* END Italic */ diff --git a/web/libs/less/_Light.less b/web/libs/less/_Light.less new file mode 100644 index 0000000..7f3d5c9 --- /dev/null +++ b/web/libs/less/_Light.less @@ -0,0 +1,8 @@ +/* BEGIN Light */ +@font-face { + font-family: Roboto; + .fontdef-woff(@FontPath, @FontName, @FontVersion, "Light"); + font-weight: 300; + font-style: normal; +} +/* END Light */ diff --git a/web/libs/less/_LightItalic.less b/web/libs/less/_LightItalic.less new file mode 100644 index 0000000..7b18230 --- /dev/null +++ b/web/libs/less/_LightItalic.less @@ -0,0 +1,8 @@ +/* BEGIN Light Italic */ +@font-face { + font-family: Roboto; + .fontdef-woff(@FontPath, @FontName, @FontVersion, "LightItalic"); + font-weight: 300; + font-style: italic; +} +/* END Light Italic */ diff --git a/web/libs/less/_Medium.less b/web/libs/less/_Medium.less new file mode 100644 index 0000000..51fab61 --- /dev/null +++ b/web/libs/less/_Medium.less @@ -0,0 +1,8 @@ +/* BEGIN Medium */ +@font-face { + font-family: Roboto; + .fontdef-woff(@FontPath, @FontName, @FontVersion, "Medium"); + font-weight: 500; + font-style: normal; +} +/* END Medium */ diff --git a/web/libs/less/_MediumItalic.less b/web/libs/less/_MediumItalic.less new file mode 100644 index 0000000..7733b98 --- /dev/null +++ b/web/libs/less/_MediumItalic.less @@ -0,0 +1,8 @@ +/* BEGIN Medium Italic */ +@font-face { + font-family: Roboto; + .fontdef-woff(@FontPath, @FontName, @FontVersion, "MediumItalic"); + font-weight: 500; + font-style: italic; +} +/* END Medium Italic */ diff --git a/web/libs/less/_Regular.less b/web/libs/less/_Regular.less new file mode 100644 index 0000000..263ea51 --- /dev/null +++ b/web/libs/less/_Regular.less @@ -0,0 +1,14 @@ +/* BEGIN Regular */ +@font-face { + font-family: Roboto; + .fontdef-woff(@FontPath, @FontName, @FontVersion, "Regular"); + font-weight: 400; + font-style: normal; +} +@font-face { + font-family: Roboto; + .fontdef-woff(@FontPath, @FontName, @FontVersion, "Regular"); + font-weight: normal; + font-style: normal; +} +/* END Regular */ diff --git a/web/libs/less/_Thin.less b/web/libs/less/_Thin.less new file mode 100644 index 0000000..3655c24 --- /dev/null +++ b/web/libs/less/_Thin.less @@ -0,0 +1,8 @@ +/* BEGIN Thin */ +@font-face { + font-family: Roboto; + .fontdef-woff(@FontPath, @FontName, @FontVersion, "Thin"); + font-weight: 100; + font-style: normal; +} +/* END Thin */ diff --git a/web/libs/less/_ThinItalic.less b/web/libs/less/_ThinItalic.less new file mode 100644 index 0000000..3de5aa8 --- /dev/null +++ b/web/libs/less/_ThinItalic.less @@ -0,0 +1,8 @@ +/* BEGIN Thin Italic */ +@font-face { + font-family: Roboto; + .fontdef-woff(@FontPath, @FontName, @FontVersion, "ThinItalic"); + font-weight: 100; + font-style: italic; +} +/* END Thin Italic */ diff --git a/web/libs/less/_mixins.less b/web/libs/less/_mixins.less new file mode 100644 index 0000000..e65a13d --- /dev/null +++ b/web/libs/less/_mixins.less @@ -0,0 +1,4 @@ +.fontdef-woff(@FontPath, @FontName, @FontVersion:"1.0.0", @FontType:"Regular") { + src: url('@{FontPath}/@{FontType}/@{FontName}-@{FontType}.woff2?v=@{FontVersion}') format('woff2'), + url('@{FontPath}/@{FontType}/@{FontName}-@{FontType}.woff?v=@{FontVersion}') format('woff'); +} diff --git a/web/libs/less/_variables.less b/web/libs/less/_variables.less new file mode 100644 index 0000000..d930fb4 --- /dev/null +++ b/web/libs/less/_variables.less @@ -0,0 +1,3 @@ +@FontPath: "./fonts"; +@FontName: "Roboto"; +@FontVersion: "2.137"; diff --git a/web/libs/sass/_Black.scss b/web/libs/sass/_Black.scss new file mode 100644 index 0000000..3efd7d0 --- /dev/null +++ b/web/libs/sass/_Black.scss @@ -0,0 +1,8 @@ +/* BEGIN Black */ +@font-face { + font-family: Roboto; + @include fontdef-woff($FontPath, $FontName, $FontVersion, "Black"); + font-weight: 900; + font-style: normal; +} +/* END Black */ diff --git a/web/libs/sass/_BlackItalic.scss b/web/libs/sass/_BlackItalic.scss new file mode 100644 index 0000000..9c68cec --- /dev/null +++ b/web/libs/sass/_BlackItalic.scss @@ -0,0 +1,8 @@ +/* BEGIN Black Italic */ +@font-face { + font-family: Roboto; + @include fontdef-woff($FontPath, $FontName, $FontVersion, "BlackItalic"); + font-weight: 900; + font-style: italic; +} +/* END Black Italic */ diff --git a/web/libs/sass/_Bold.scss b/web/libs/sass/_Bold.scss new file mode 100644 index 0000000..5e8e91b --- /dev/null +++ b/web/libs/sass/_Bold.scss @@ -0,0 +1,14 @@ +/* BEGIN Bold */ +@font-face { + font-family: Roboto; + @include fontdef-woff($FontPath, $FontName, $FontVersion, "Bold"); + font-weight: 700; + font-style: normal; +} +@font-face { + font-family: Roboto; + @include fontdef-woff($FontPath, $FontName, $FontVersion, "Bold"); + font-weight: bold; + font-style: normal; +} +/* END Bold */ diff --git a/web/libs/sass/_BoldItalic.scss b/web/libs/sass/_BoldItalic.scss new file mode 100644 index 0000000..21e2d8f --- /dev/null +++ b/web/libs/sass/_BoldItalic.scss @@ -0,0 +1,14 @@ +/* BEGIN Bold Italic */ +@font-face { + font-family: Roboto; + @include fontdef-woff($FontPath, $FontName, $FontVersion, "BoldItalic"); + font-weight: 700; + font-style: italic; +} +@font-face { + font-family: Roboto; + @include fontdef-woff($FontPath, $FontName, $FontVersion, "BoldItalic"); + font-weight: bold; + font-style: italic; +} +/* END Bold Italic */ diff --git a/web/libs/sass/_Italic.scss b/web/libs/sass/_Italic.scss new file mode 100644 index 0000000..ecc967e --- /dev/null +++ b/web/libs/sass/_Italic.scss @@ -0,0 +1,14 @@ +/* BEGIN Italic */ +@font-face { + font-family: Roboto; + @include fontdef-woff($FontPath, $FontName, $FontVersion, "Italic"); + font-weight: 400; + font-style: italic; +} +@font-face { + font-family: Roboto; + @include fontdef-woff($FontPath, $FontName, $FontVersion, "Italic"); + font-weight: normal; + font-style: italic; +} +/* END Italic */ diff --git a/web/libs/sass/_Light.scss b/web/libs/sass/_Light.scss new file mode 100644 index 0000000..3fee95f --- /dev/null +++ b/web/libs/sass/_Light.scss @@ -0,0 +1,8 @@ +/* BEGIN Light */ +@font-face { + font-family: Roboto; + @include fontdef-woff($FontPath, $FontName, $FontVersion, "Light"); + font-weight: 300; + font-style: normal; +} +/* END Light */ diff --git a/web/libs/sass/_LightItalic.scss b/web/libs/sass/_LightItalic.scss new file mode 100644 index 0000000..e93d59f --- /dev/null +++ b/web/libs/sass/_LightItalic.scss @@ -0,0 +1,8 @@ +/* BEGIN Light Italic */ +@font-face { + font-family: Roboto; + @include fontdef-woff($FontPath, $FontName, $FontVersion, "LightItalic"); + font-weight: 300; + font-style: italic; +} +/* END Light Italic */ diff --git a/web/libs/sass/_Medium.scss b/web/libs/sass/_Medium.scss new file mode 100644 index 0000000..2ac335a --- /dev/null +++ b/web/libs/sass/_Medium.scss @@ -0,0 +1,8 @@ +/* BEGIN Medium */ +@font-face { + font-family: Roboto; + @include fontdef-woff($FontPath, $FontName, $FontVersion, "Medium"); + font-weight: 500; + font-style: normal; +} +/* END Medium */ diff --git a/web/libs/sass/_MediumItalic.scss b/web/libs/sass/_MediumItalic.scss new file mode 100644 index 0000000..5351542 --- /dev/null +++ b/web/libs/sass/_MediumItalic.scss @@ -0,0 +1,8 @@ +/* BEGIN Medium Italic */ +@font-face { + font-family: Roboto; + @include fontdef-woff($FontPath, $FontName, $FontVersion, "MediumItalic"); + font-weight: 500; + font-style: italic; +} +/* END Medium Italic */ diff --git a/web/libs/sass/_Regular.scss b/web/libs/sass/_Regular.scss new file mode 100644 index 0000000..f8caf4b --- /dev/null +++ b/web/libs/sass/_Regular.scss @@ -0,0 +1,14 @@ +/* BEGIN Regular */ +@font-face { + font-family: Roboto; + @include fontdef-woff($FontPath, $FontName, $FontVersion, "Regular"); + font-weight: 400; + font-style: normal; +} +@font-face { + font-family: Roboto; + @include fontdef-woff($FontPath, $FontName, $FontVersion, "Regular"); + font-weight: normal; + font-style: normal; +} +/* END Regular */ diff --git a/web/libs/sass/_Thin.scss b/web/libs/sass/_Thin.scss new file mode 100644 index 0000000..3e88458 --- /dev/null +++ b/web/libs/sass/_Thin.scss @@ -0,0 +1,8 @@ +/* BEGIN Thin */ +@font-face { + font-family: Roboto; + @include fontdef-woff($FontPath, $FontName, $FontVersion, "Thin"); + font-weight: 100; + font-style: normal; +} +/* END Thin */ diff --git a/web/libs/sass/_ThinItalic.scss b/web/libs/sass/_ThinItalic.scss new file mode 100644 index 0000000..9d56e5d --- /dev/null +++ b/web/libs/sass/_ThinItalic.scss @@ -0,0 +1,8 @@ +/* BEGIN Thin Italic */ +@font-face { + font-family: Roboto; + @include fontdef-woff($FontPath, $FontName, $FontVersion, "ThinItalic"); + font-weight: 100; + font-style: italic; +} +/* END Thin Italic */ diff --git a/web/libs/sass/_mixins.scss b/web/libs/sass/_mixins.scss new file mode 100644 index 0000000..49b18d4 --- /dev/null +++ b/web/libs/sass/_mixins.scss @@ -0,0 +1,4 @@ +@mixin fontdef-woff($FontPath, $FontName, $FontVersion:"1.0.0", $FontType:"Regular") { + src: url('#{$FontPath}/#{$FontType}/#{$FontName}-#{$FontType}.woff2?v=#{$FontVersion}') format('woff2'), + url('#{$FontPath}/#{$FontType}/#{$FontName}-#{$FontType}.woff?v=#{$FontVersion}') format('woff'); +} diff --git a/web/libs/sass/_variables.scss b/web/libs/sass/_variables.scss new file mode 100644 index 0000000..d8dfc6f --- /dev/null +++ b/web/libs/sass/_variables.scss @@ -0,0 +1,3 @@ +$FontPath: "./fonts" !default; +$FontName: "Roboto" !default; +$FontVersion: "2.137" !default; diff --git a/web/libs/sass/roboto.scss b/web/libs/sass/roboto.scss new file mode 100644 index 0000000..a0c0ec2 --- /dev/null +++ b/web/libs/sass/roboto.scss @@ -0,0 +1,15 @@ +@import "variables"; +@import "mixins"; + +@import "Thin"; +@import "ThinItalic"; +@import "Light"; +@import "LightItalic"; +@import "Regular"; +@import "Italic"; +@import "Medium"; +@import "MediumItalic"; +@import "Bold"; +@import "BoldItalic"; +@import "Black"; +@import "BlackItalic"; diff --git a/web/pages/admin.ejs b/web/pages/admin.ejs index 0a29f86..5298e01 100644 --- a/web/pages/admin.ejs +++ b/web/pages/admin.ejs @@ -12,6 +12,9 @@ +<% customAutoLoad.adminLibsCss.forEach(function(lib){ %> + +<% }) %>
      @@ -80,8 +83,14 @@
      + <% include blocks/confirm.ejs %> <% include blocks/subpermissions.ejs %> +<% customAutoLoad.adminPageBlocks.forEach(function(block){ %> + <%- include(block) %> +<% }) %> @@ -275,3 +284,6 @@ $('body') localStorage.removeItem('ShinobiLogin_'+location.host);location.href=location.href; }) +<% customAutoLoad.adminLibsJs.forEach(function(lib){ %> + +<% }) %> diff --git a/web/pages/blocks/api.ejs b/web/pages/blocks/api.ejs index 2fdbb4e..a654345 100644 --- a/web/pages/blocks/api.ejs +++ b/web/pages/blocks/api.ejs @@ -93,3 +93,4 @@ + diff --git a/web/pages/blocks/detectorfilters.ejs b/web/pages/blocks/detectorfilters.ejs index d5d7e2a..e76291b 100644 --- a/web/pages/blocks/detectorfilters.ejs +++ b/web/pages/blocks/detectorfilters.ejs @@ -259,3 +259,4 @@ + diff --git a/web/pages/blocks/filters.ejs b/web/pages/blocks/filters.ejs index f29892b..0350d59 100644 --- a/web/pages/blocks/filters.ejs +++ b/web/pages/blocks/filters.ejs @@ -28,8 +28,8 @@

      <%- lang['Find Where'] %>
      -    -    +    +   

      @@ -39,20 +39,20 @@
      @@ -68,8 +68,8 @@
      @@ -77,24 +77,24 @@
      @@ -115,4 +115,5 @@
      - \ No newline at end of file + + diff --git a/web/pages/blocks/header.ejs b/web/pages/blocks/header.ejs index 98a1dc2..680072e 100644 --- a/web/pages/blocks/header.ejs +++ b/web/pages/blocks/header.ejs @@ -9,6 +9,7 @@ + <% include header-favicon.ejs %> diff --git a/web/pages/blocks/logs.ejs b/web/pages/blocks/logs.ejs index d2870a6..cddecdf 100644 --- a/web/pages/blocks/logs.ejs +++ b/web/pages/blocks/logs.ejs @@ -35,7 +35,7 @@
      - +
      @@ -48,4 +48,5 @@ - \ No newline at end of file + + diff --git a/web/pages/blocks/mainpermissions.ejs b/web/pages/blocks/mainpermissions.ejs index 2f31428..4b4042a 100644 --- a/web/pages/blocks/mainpermissions.ejs +++ b/web/pages/blocks/mainpermissions.ejs @@ -119,6 +119,22 @@ +
      + +
      +
      + +
      @@ -185,7 +201,7 @@ \ No newline at end of file diff --git a/web/pages/blocks/monitorStates.ejs b/web/pages/blocks/monitorStates.ejs new file mode 100644 index 0000000..c734e87 --- /dev/null +++ b/web/pages/blocks/monitorStates.ejs @@ -0,0 +1,182 @@ + + diff --git a/web/pages/blocks/monitoredit.ejs b/web/pages/blocks/monitoredit.ejs index d112d56..5f3e5bd 100644 --- a/web/pages/blocks/monitoredit.ejs +++ b/web/pages/blocks/monitoredit.ejs @@ -87,9 +87,15 @@ + <% if(config.rtmpServer){ %><% } %> +
      + +
      @@ -198,6 +204,17 @@

      <%-lang['Input Settings']%>

      +
      +
      + +
      @@ -842,6 +867,11 @@
      +
      +
      + +
      +
      + +
      +
      +
      -

      <%-lang['"No Motion" Detector']%>

      @@ -1141,6 +1189,29 @@
      + +
      +

      <%-lang['Audio Detector']%>

      +
      + +
      +
      + +
      +
      + +
      +
      +

      <%-lang['Object Detection']%> <%-lang['Plugin']%> : <%-lang['Not Connected']%>

      @@ -1151,6 +1222,22 @@
      +
      + +
      +
      + +
      + + diff --git a/web/pages/blocks/settings.ejs b/web/pages/blocks/settings.ejs index b758fc7..8afca75 100644 --- a/web/pages/blocks/settings.ejs +++ b/web/pages/blocks/settings.ejs @@ -174,199 +174,318 @@ <% if(details.use_webdav!=='0'){ %>

      <%-lang.WebDAV%>

      -
      - -
      -
      -
      - -
      -
      - -
      -
      -
      - -
      -
      +
      - +
      +
      +
      + +
      +
      + +
      +
      +
      +
      -
      -
      -
      - -
      <% } %> <% if(details.use_aws_s3!=='0'){ %>

      <%-lang['Amazon S3']%>

      -
      - -
      -
      -
      - -
      -
      - -
      -
      -
      - -
      -
      - -
      -
      +
      - +
      +
      +
      + +
      +
      + +
      +
      +
      + +
      +
      +
      -
      -
      -
      - -
      <% } %> <% if(details.use_bb_b2!=='0'){ %>

      <%-lang['Backblaze B2']%>

      -
      - -
      -
      -
      - -
      -
      - -
      -
      -
      - -
      -
      +
      - +
      +
      +
      + +
      +
      + +
      +
      +
      +
      -
      -
      +
      + <% } %> + <% if(details.use_whcs!=='0'){ %> +
      +

      <%-lang['Wasabi Hot Cloud Storage']%>

      -
      +
      +
      + +
      +
      +
      + +
      +
      + +
      +
      +
      + +
      +
      + +
      +
      +
      + +
      +
      + +
      +
      +
      + +
      +
      +
      + <% } %> + <% if(details.use_sftp!=='0'){ %> +
      +

      <%-lang['SFTP (SSH File Transfer)']%>

      +
      + +
      +
      +
      + +
      +
      + +
      +
      + +
      +
      + +
      +
      + +
      +
      + +
      +
      <% } %> <% if(details.use_discordbot!=='0'){ %> @@ -471,6 +590,14 @@
      +
      + +
      +
      + <% }) %> + + +
      +
      +
      + +
      + +
      +
      +
      +
      + diff --git a/web/pages/blocks/timelapse.ejs b/web/pages/blocks/timelapse.ejs index 730e70f..d844fb4 100644 --- a/web/pages/blocks/timelapse.ejs +++ b/web/pages/blocks/timelapse.ejs @@ -77,4 +77,5 @@
      - \ No newline at end of file + + diff --git a/web/pages/blocks/videoview.ejs b/web/pages/blocks/videoview.ejs index 6baa5f1..65db05a 100644 --- a/web/pages/blocks/videoview.ejs +++ b/web/pages/blocks/videoview.ejs @@ -43,6 +43,7 @@
      @@ -77,3 +78,4 @@
      + diff --git a/web/pages/dashcam.ejs b/web/pages/dashcam.ejs index b52694f..289ea1d 100644 --- a/web/pages/dashcam.ejs +++ b/web/pages/dashcam.ejs @@ -21,6 +21,7 @@ requires https or firefox + + + @@ -14,7 +16,22 @@ + + +<% customAutoLoad.LibsCss.forEach(function(lib){ %> + +<% }) %> @@ -32,12 +49,6 @@ <% } %> - - - - - -
      @@ -121,6 +132,8 @@ <% if(!details.sub){ %>
    • <%- lang.ONVIF %>
    • <%- lang.FFprobe %>
    • +
    • <%- lang['Monitor States'] %>
    • +
    • <%- lang['Schedules'] %>
    • <%- lang.Filters %>
    • <% } %>
    • <%- lang.Logs %>
    • @@ -167,7 +180,12 @@ <% include blocks/probe.ejs %> <% include blocks/region.ejs %> <% include blocks/detectorfilters.ejs %> +<% include blocks/monitorStates.ejs %> +<% include blocks/schedules.ejs %> <% include blocks/confirm.ejs %> +<% customAutoLoad.PageBlocks.forEach(function(block){ %> + <%- include(block) %> +<% }) %> <% if(config.DropboxAppKey){ %> @@ -198,5 +216,15 @@ - + + + + + + + + +<% customAutoLoad.LibsJs.forEach(function(lib){ %> + +<% }) %> <% include blocks/help.ejs %> diff --git a/web/pages/robots.txt b/web/pages/robots.txt new file mode 100644 index 0000000..1f53798 --- /dev/null +++ b/web/pages/robots.txt @@ -0,0 +1,2 @@ +User-agent: * +Disallow: / diff --git a/web/pages/streamer.ejs b/web/pages/streamer.ejs index 7158610..921dadc 100644 --- a/web/pages/streamer.ejs +++ b/web/pages/streamer.ejs @@ -17,6 +17,7 @@ requires https or firefox
      + diff --git a/web/pages/super.ejs b/web/pages/super.ejs index 2796365..1e3572b 100644 --- a/web/pages/super.ejs +++ b/web/pages/super.ejs @@ -8,8 +8,8 @@ - - + + @@ -27,6 +27,9 @@ .list-group li .form-group {margin:0} a {cursor:pointer} + <% customAutoLoad.superLibsCss.forEach(function(lib){ %> + + <% }) %> @@ -62,7 +65,7 @@
      -
      + + <% include blocks/confirm.ejs %> +<% customAutoLoad.superPageBlocks.forEach(function(block){ %> + <%- include(block) %> +<% }) %> @@ -178,6 +188,7 @@ <% include blocks/mainpermissions.ejs %> +<% customAutoLoad.superLibsJs.forEach(function(lib){ %> + +<% }) %> diff --git a/web/templates/boilerplate/README.md b/web/templates/boilerplate/README.md deleted file mode 100644 index 84e2d66..0000000 --- a/web/templates/boilerplate/README.md +++ /dev/null @@ -1,58 +0,0 @@ -# Boilerplate Template - -> This template is based on the "Now UI Dashboard". https://www.creative-tim.com/product/now-ui-dashboard - - -*Image From Creative-Tim* - -1. You must copy the folder named `boilerplate` to your Shinobi directory in the `web/templates` folder. If you do not have a templates folder then you must create one. - -2. Create the `renderPaths` object inside `conf.json`. If it already exists then remove the old one and place this one. -``` -"renderPaths": { - "home" : "templates/boilerplate/views/index", - "handler" : "templates/boilerplate/handler" -} -``` -3. Your `conf.json` file may look like this afterward. - -``` -{ - "port": 8080, - "addStorage": [ - { - "name": "second", - "path": "__DIR__/videos2" - } - ], - "db": { - "host": "127.0.0.1", - "user": "majesticflame", - "password": "", - "database": "ccio", - "port": 3306 - }, - "mail": { - "service": "gmail", - "auth": { - "user": "your_email@gmail.com", - "pass": "your_password_or_app_specific_password" - } - }, - "cron": { - "key": "change_this_to_something_very_random__just_anything_other_than_this" - }, - "pluginKeys": { - "Motion": "change_this_to_something_very_random____make_sure_to_match__/plugins/motion/conf.json", - "OpenCV": "change_this_to_something_very_random____make_sure_to_match__/plugins/opencv/conf.json", - }, - "renderPaths": { - "home" : "templates/boilerplate/views/index", - "handler" : "templates/boilerplate/handler" - } -} -``` -4. Restart Shinobi -``` -pm2 restart camera -``` \ No newline at end of file diff --git a/web/templates/boilerplate/assets/css/bootstrap.min.css b/web/templates/boilerplate/assets/css/bootstrap.min.css deleted file mode 100644 index 7f4d935..0000000 --- a/web/templates/boilerplate/assets/css/bootstrap.min.css +++ /dev/null @@ -1,7 +0,0 @@ -/*! - * Bootstrap v4.0.0-beta (https://getbootstrap.com) - * Copyright 2011-2017 The Bootstrap Authors - * Copyright 2011-2017 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - */@media print{*,::after,::before{text-shadow:none!important;box-shadow:none!important}a,a:visited{text-decoration:underline}abbr[title]::after{content:" (" attr(title) ")"}pre{white-space:pre-wrap!important}blockquote,pre{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}.navbar{display:none}.badge{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}}html{box-sizing:border-box;font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;-ms-overflow-style:scrollbar;-webkit-tap-highlight-color:transparent}*,::after,::before{box-sizing:inherit}@-ms-viewport{width:device-width}article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}body{margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;font-size:1rem;font-weight:400;line-height:1.5;color:#212529;background-color:#fff}[tabindex="-1"]:focus{outline:0!important}hr{box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem}p{margin-top:0;margin-bottom:1rem}abbr[data-original-title],abbr[title]{text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;border-bottom:0}address{margin-bottom:1rem;font-style:normal;line-height:inherit}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}dfn{font-style:italic}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#007bff;text-decoration:none;background-color:transparent;-webkit-text-decoration-skip:objects}a:hover{color:#0056b3;text-decoration:underline}a:not([href]):not([tabindex]){color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus,a:not([href]):not([tabindex]):hover{color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus{outline:0}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}pre{margin-top:0;margin-bottom:1rem;overflow:auto}figure{margin:0 0 1rem}img{vertical-align:middle;border-style:none}svg:not(:root){overflow:hidden}[role=button],a,area,button,input,label,select,summary,textarea{-ms-touch-action:manipulation;touch-action:manipulation}table{border-collapse:collapse}caption{padding-top:.75rem;padding-bottom:.75rem;color:#868e96;text-align:left;caption-side:bottom}th{text-align:left}label{display:inline-block;margin-bottom:.5rem}button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,input{overflow:visible}button,select{text-transform:none}[type=reset],[type=submit],button,html [type=button]{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{padding:0;border-style:none}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=date],input[type=datetime-local],input[type=month],input[type=time]{-webkit-appearance:listbox}textarea{overflow:auto;resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;max-width:100%;padding:0;margin-bottom:.5rem;font-size:1.5rem;line-height:inherit;color:inherit;white-space:normal}progress{vertical-align:baseline}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:none}[type=search]::-webkit-search-cancel-button,[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}summary{display:list-item}template{display:none}[hidden]{display:none!important}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{margin-bottom:.5rem;font-family:inherit;font-weight:500;line-height:1.1;color:inherit}.h1,h1{font-size:2.5rem}.h2,h2{font-size:2rem}.h3,h3{font-size:1.75rem}.h4,h4{font-size:1.5rem}.h5,h5{font-size:1.25rem}.h6,h6{font-size:1rem}.lead{font-size:1.25rem;font-weight:300}.display-1{font-size:6rem;font-weight:300;line-height:1.1}.display-2{font-size:5.5rem;font-weight:300;line-height:1.1}.display-3{font-size:4.5rem;font-weight:300;line-height:1.1}.display-4{font-size:3.5rem;font-weight:300;line-height:1.1}hr{margin-top:1rem;margin-bottom:1rem;border:0;border-top:1px solid rgba(0,0,0,.1)}.small,small{font-size:80%;font-weight:400}.mark,mark{padding:.2em;background-color:#fcf8e3}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none}.list-inline-item{display:inline-block}.list-inline-item:not(:last-child){margin-right:5px}.initialism{font-size:90%;text-transform:uppercase}.blockquote{margin-bottom:1rem;font-size:1.25rem}.blockquote-footer{display:block;font-size:80%;color:#868e96}.blockquote-footer::before{content:"\2014 \00A0"}.img-fluid{max-width:100%;height:auto}.img-thumbnail{padding:.25rem;background-color:#fff;border:1px solid #ddd;border-radius:.25rem;transition:all .2s ease-in-out;max-width:100%;height:auto}.figure{display:inline-block}.figure-img{margin-bottom:.5rem;line-height:1}.figure-caption{font-size:90%;color:#868e96}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace}code{padding:.2rem .4rem;font-size:90%;color:#bd4147;background-color:#f8f9fa;border-radius:.25rem}a>code{padding:0;color:inherit;background-color:inherit}kbd{padding:.2rem .4rem;font-size:90%;color:#fff;background-color:#212529;border-radius:.2rem}kbd kbd{padding:0;font-size:100%;font-weight:700}pre{display:block;margin-top:0;margin-bottom:1rem;font-size:90%;color:#212529}pre code{padding:0;font-size:inherit;color:inherit;background-color:transparent;border-radius:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{margin-right:auto;margin-left:auto;padding-right:15px;padding-left:15px;width:100%}@media (min-width:576px){.container{max-width:540px}}@media (min-width:768px){.container{max-width:720px}}@media (min-width:992px){.container{max-width:960px}}@media (min-width:1200px){.container{max-width:1140px}}.container-fluid{width:100%;margin-right:auto;margin-left:auto;padding-right:15px;padding-left:15px;width:100%}.row{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-right:-15px;margin-left:-15px}.no-gutters{margin-right:0;margin-left:0}.no-gutters>.col,.no-gutters>[class*=col-]{padding-right:0;padding-left:0}.col,.col-1,.col-10,.col-11,.col-12,.col-2,.col-3,.col-4,.col-5,.col-6,.col-7,.col-8,.col-9,.col-auto,.col-lg,.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.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-auto,.col-md,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.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-auto,.col-sm,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.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-auto,.col-xl,.col-xl-1,.col-xl-10,.col-xl-11,.col-xl-12,.col-xl-2,.col-xl-3,.col-xl-4,.col-xl-5,.col-xl-6,.col-xl-7,.col-xl-8,.col-xl-9,.col-xl-auto{position:relative;width:100%;min-height:1px;padding-right:15px;padding-left:15px}.col{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:none}.col-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-1{-ms-flex-order:1;order:1}.order-2{-ms-flex-order:2;order:2}.order-3{-ms-flex-order:3;order:3}.order-4{-ms-flex-order:4;order:4}.order-5{-ms-flex-order:5;order:5}.order-6{-ms-flex-order:6;order:6}.order-7{-ms-flex-order:7;order:7}.order-8{-ms-flex-order:8;order:8}.order-9{-ms-flex-order:9;order:9}.order-10{-ms-flex-order:10;order:10}.order-11{-ms-flex-order:11;order:11}.order-12{-ms-flex-order:12;order:12}@media (min-width:576px){.col-sm{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-sm-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:none}.col-sm-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-sm-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-sm-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-sm-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-sm-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-sm-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-sm-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-sm-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-sm-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-sm-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-sm-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-sm-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-sm-1{-ms-flex-order:1;order:1}.order-sm-2{-ms-flex-order:2;order:2}.order-sm-3{-ms-flex-order:3;order:3}.order-sm-4{-ms-flex-order:4;order:4}.order-sm-5{-ms-flex-order:5;order:5}.order-sm-6{-ms-flex-order:6;order:6}.order-sm-7{-ms-flex-order:7;order:7}.order-sm-8{-ms-flex-order:8;order:8}.order-sm-9{-ms-flex-order:9;order:9}.order-sm-10{-ms-flex-order:10;order:10}.order-sm-11{-ms-flex-order:11;order:11}.order-sm-12{-ms-flex-order:12;order:12}}@media (min-width:768px){.col-md{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-md-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:none}.col-md-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-md-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-md-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-md-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-md-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-md-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-md-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-md-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-md-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-md-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-md-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-md-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-md-1{-ms-flex-order:1;order:1}.order-md-2{-ms-flex-order:2;order:2}.order-md-3{-ms-flex-order:3;order:3}.order-md-4{-ms-flex-order:4;order:4}.order-md-5{-ms-flex-order:5;order:5}.order-md-6{-ms-flex-order:6;order:6}.order-md-7{-ms-flex-order:7;order:7}.order-md-8{-ms-flex-order:8;order:8}.order-md-9{-ms-flex-order:9;order:9}.order-md-10{-ms-flex-order:10;order:10}.order-md-11{-ms-flex-order:11;order:11}.order-md-12{-ms-flex-order:12;order:12}}@media (min-width:992px){.col-lg{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-lg-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:none}.col-lg-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-lg-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-lg-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-lg-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-lg-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-lg-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-lg-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-lg-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-lg-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-lg-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-lg-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-lg-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-lg-1{-ms-flex-order:1;order:1}.order-lg-2{-ms-flex-order:2;order:2}.order-lg-3{-ms-flex-order:3;order:3}.order-lg-4{-ms-flex-order:4;order:4}.order-lg-5{-ms-flex-order:5;order:5}.order-lg-6{-ms-flex-order:6;order:6}.order-lg-7{-ms-flex-order:7;order:7}.order-lg-8{-ms-flex-order:8;order:8}.order-lg-9{-ms-flex-order:9;order:9}.order-lg-10{-ms-flex-order:10;order:10}.order-lg-11{-ms-flex-order:11;order:11}.order-lg-12{-ms-flex-order:12;order:12}}@media (min-width:1200px){.col-xl{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-xl-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:none}.col-xl-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-xl-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-xl-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-xl-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-xl-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-xl-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-xl-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-xl-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-xl-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-xl-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-xl-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-xl-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-xl-1{-ms-flex-order:1;order:1}.order-xl-2{-ms-flex-order:2;order:2}.order-xl-3{-ms-flex-order:3;order:3}.order-xl-4{-ms-flex-order:4;order:4}.order-xl-5{-ms-flex-order:5;order:5}.order-xl-6{-ms-flex-order:6;order:6}.order-xl-7{-ms-flex-order:7;order:7}.order-xl-8{-ms-flex-order:8;order:8}.order-xl-9{-ms-flex-order:9;order:9}.order-xl-10{-ms-flex-order:10;order:10}.order-xl-11{-ms-flex-order:11;order:11}.order-xl-12{-ms-flex-order:12;order:12}}.table{width:100%;max-width:100%;margin-bottom:1rem;background-color:transparent}.table td,.table th{padding:.75rem;vertical-align:top;border-top:1px solid #e9ecef}.table thead th{vertical-align:bottom;border-bottom:2px solid #e9ecef}.table tbody+tbody{border-top:2px solid #e9ecef}.table .table{background-color:#fff}.table-sm td,.table-sm th{padding:.3rem}.table-bordered{border:1px solid #e9ecef}.table-bordered td,.table-bordered th{border:1px solid #e9ecef}.table-bordered thead td,.table-bordered thead th{border-bottom-width:2px}.table-striped tbody tr:nth-of-type(odd){background-color:rgba(0,0,0,.05)}.table-hover tbody tr:hover{background-color:rgba(0,0,0,.075)}.table-primary,.table-primary>td,.table-primary>th{background-color:#b8daff}.table-hover .table-primary:hover{background-color:#9fcdff}.table-hover .table-primary:hover>td,.table-hover .table-primary:hover>th{background-color:#9fcdff}.table-secondary,.table-secondary>td,.table-secondary>th{background-color:#dddfe2}.table-hover .table-secondary:hover{background-color:#cfd2d6}.table-hover .table-secondary:hover>td,.table-hover .table-secondary:hover>th{background-color:#cfd2d6}.table-success,.table-success>td,.table-success>th{background-color:#c3e6cb}.table-hover .table-success:hover{background-color:#b1dfbb}.table-hover .table-success:hover>td,.table-hover .table-success:hover>th{background-color:#b1dfbb}.table-info,.table-info>td,.table-info>th{background-color:#bee5eb}.table-hover .table-info:hover{background-color:#abdde5}.table-hover .table-info:hover>td,.table-hover .table-info:hover>th{background-color:#abdde5}.table-warning,.table-warning>td,.table-warning>th{background-color:#ffeeba}.table-hover .table-warning:hover{background-color:#ffe8a1}.table-hover .table-warning:hover>td,.table-hover .table-warning:hover>th{background-color:#ffe8a1}.table-danger,.table-danger>td,.table-danger>th{background-color:#f5c6cb}.table-hover .table-danger:hover{background-color:#f1b0b7}.table-hover .table-danger:hover>td,.table-hover .table-danger:hover>th{background-color:#f1b0b7}.table-light,.table-light>td,.table-light>th{background-color:#fdfdfe}.table-hover .table-light:hover{background-color:#ececf6}.table-hover .table-light:hover>td,.table-hover .table-light:hover>th{background-color:#ececf6}.table-dark,.table-dark>td,.table-dark>th{background-color:#c6c8ca}.table-hover .table-dark:hover{background-color:#b9bbbe}.table-hover .table-dark:hover>td,.table-hover .table-dark:hover>th{background-color:#b9bbbe}.table-active,.table-active>td,.table-active>th{background-color:rgba(0,0,0,.075)}.table-hover .table-active:hover{background-color:rgba(0,0,0,.075)}.table-hover .table-active:hover>td,.table-hover .table-active:hover>th{background-color:rgba(0,0,0,.075)}.thead-inverse th{color:#fff;background-color:#212529}.thead-default th{color:#495057;background-color:#e9ecef}.table-inverse{color:#fff;background-color:#212529}.table-inverse td,.table-inverse th,.table-inverse thead th{border-color:#32383e}.table-inverse.table-bordered{border:0}.table-inverse.table-striped tbody tr:nth-of-type(odd){background-color:rgba(255,255,255,.05)}.table-inverse.table-hover tbody tr:hover{background-color:rgba(255,255,255,.075)}@media (max-width:991px){.table-responsive{display:block;width:100%;overflow-x:auto;-ms-overflow-style:-ms-autohiding-scrollbar}.table-responsive.table-bordered{border:0}}.form-control{display:block;width:100%;padding:.5rem .75rem;font-size:1rem;line-height:1.25;color:#495057;background-color:#fff;background-image:none;background-clip:padding-box;border:1px solid rgba(0,0,0,.15);border-radius:.25rem;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s}.form-control::-ms-expand{background-color:transparent;border:0}.form-control:focus{color:#495057;background-color:#fff;border-color:#80bdff;outline:0}.form-control::-webkit-input-placeholder{color:#868e96;opacity:1}.form-control:-ms-input-placeholder{color:#868e96;opacity:1}.form-control::placeholder{color:#868e96;opacity:1}.form-control:disabled,.form-control[readonly]{background-color:#e9ecef;opacity:1}select.form-control:not([size]):not([multiple]){height:calc(2.25rem + 2px)}select.form-control:focus::-ms-value{color:#495057;background-color:#fff}.form-control-file,.form-control-range{display:block}.col-form-label{padding-top:calc(.5rem - 1px * 2);padding-bottom:calc(.5rem - 1px * 2);margin-bottom:0}.col-form-label-lg{padding-top:calc(.5rem - 1px * 2);padding-bottom:calc(.5rem - 1px * 2);font-size:1.25rem}.col-form-label-sm{padding-top:calc(.25rem - 1px * 2);padding-bottom:calc(.25rem - 1px * 2);font-size:.875rem}.col-form-legend{padding-top:.5rem;padding-bottom:.5rem;margin-bottom:0;font-size:1rem}.form-control-plaintext{padding-top:.5rem;padding-bottom:.5rem;margin-bottom:0;line-height:1.25;border:solid transparent;border-width:1px 0}.form-control-plaintext.form-control-lg,.form-control-plaintext.form-control-sm,.input-group-lg>.form-control-plaintext.form-control,.input-group-lg>.form-control-plaintext.input-group-addon,.input-group-lg>.input-group-btn>.form-control-plaintext.btn,.input-group-sm>.form-control-plaintext.form-control,.input-group-sm>.form-control-plaintext.input-group-addon,.input-group-sm>.input-group-btn>.form-control-plaintext.btn{padding-right:0;padding-left:0}.form-control-sm,.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.input-group-sm>.input-group-btn>select.btn:not([size]):not([multiple]),.input-group-sm>select.form-control:not([size]):not([multiple]),.input-group-sm>select.input-group-addon:not([size]):not([multiple]),select.form-control-sm:not([size]):not([multiple]){height:calc(1.8125rem + 2px)}.form-control-lg,.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}.input-group-lg>.input-group-btn>select.btn:not([size]):not([multiple]),.input-group-lg>select.form-control:not([size]):not([multiple]),.input-group-lg>select.input-group-addon:not([size]):not([multiple]),select.form-control-lg:not([size]):not([multiple]){height:calc(2.3125rem + 2px)}.form-group{margin-bottom:1rem}.form-text{display:block;margin-top:.25rem}.form-row{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-right:-5px;margin-left:-5px}.form-row>.col,.form-row>[class*=col-]{padding-right:5px;padding-left:5px}.form-check{position:relative;display:block;margin-bottom:.5rem}.form-check.disabled .form-check-label{color:#868e96}.form-check-label{padding-left:1.25rem;margin-bottom:0}.form-check-input{position:absolute;margin-top:.25rem;margin-left:-1.25rem}.form-check-input:only-child{position:static}.form-check-inline{display:inline-block}.form-check-inline .form-check-label{vertical-align:middle}.form-check-inline+.form-check-inline{margin-left:.75rem}.invalid-feedback{display:none;margin-top:.25rem;font-size:.875rem;color:#dc3545}.invalid-tooltip{position:absolute;top:100%;z-index:5;display:none;width:250px;padding:.5rem;margin-top:.1rem;font-size:.875rem;line-height:1;color:#fff;background-color:rgba(220,53,69,.8);border-radius:.2rem}.custom-select.is-valid,.form-control.is-valid,.was-validated .custom-select:valid,.was-validated .form-control:valid{border-color:#28a745}.custom-select.is-valid:focus,.form-control.is-valid:focus,.was-validated .custom-select:valid:focus,.was-validated .form-control:valid:focus{box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.custom-select.is-valid~.invalid-feedback,.custom-select.is-valid~.invalid-tooltip,.form-control.is-valid~.invalid-feedback,.form-control.is-valid~.invalid-tooltip,.was-validated .custom-select:valid~.invalid-feedback,.was-validated .custom-select:valid~.invalid-tooltip,.was-validated .form-control:valid~.invalid-feedback,.was-validated .form-control:valid~.invalid-tooltip{display:block}.form-check-input.is-valid+.form-check-label,.was-validated .form-check-input:valid+.form-check-label{color:#28a745}.custom-control-input.is-valid~.custom-control-indicator,.was-validated .custom-control-input:valid~.custom-control-indicator{background-color:rgba(40,167,69,.25)}.custom-control-input.is-valid~.custom-control-description,.was-validated .custom-control-input:valid~.custom-control-description{color:#28a745}.custom-file-input.is-valid~.custom-file-control,.was-validated .custom-file-input:valid~.custom-file-control{border-color:#28a745}.custom-file-input.is-valid~.custom-file-control::before,.was-validated .custom-file-input:valid~.custom-file-control::before{border-color:inherit}.custom-file-input.is-valid:focus,.was-validated .custom-file-input:valid:focus{box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.custom-select.is-invalid,.form-control.is-invalid,.was-validated .custom-select:invalid,.was-validated .form-control:invalid{border-color:#dc3545}.custom-select.is-invalid:focus,.form-control.is-invalid:focus,.was-validated .custom-select:invalid:focus,.was-validated .form-control:invalid:focus{box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.custom-select.is-invalid~.invalid-feedback,.custom-select.is-invalid~.invalid-tooltip,.form-control.is-invalid~.invalid-feedback,.form-control.is-invalid~.invalid-tooltip,.was-validated .custom-select:invalid~.invalid-feedback,.was-validated .custom-select:invalid~.invalid-tooltip,.was-validated .form-control:invalid~.invalid-feedback,.was-validated .form-control:invalid~.invalid-tooltip{display:block}.form-check-input.is-invalid+.form-check-label,.was-validated .form-check-input:invalid+.form-check-label{color:#dc3545}.custom-control-input.is-invalid~.custom-control-indicator,.was-validated .custom-control-input:invalid~.custom-control-indicator{background-color:rgba(220,53,69,.25)}.custom-control-input.is-invalid~.custom-control-description,.was-validated .custom-control-input:invalid~.custom-control-description{color:#dc3545}.custom-file-input.is-invalid~.custom-file-control,.was-validated .custom-file-input:invalid~.custom-file-control{border-color:#dc3545}.custom-file-input.is-invalid~.custom-file-control::before,.was-validated .custom-file-input:invalid~.custom-file-control::before{border-color:inherit}.custom-file-input.is-invalid:focus,.was-validated .custom-file-input:invalid:focus{box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.form-inline{display:-ms-flexbox;display:flex;-ms-flex-flow:row wrap;flex-flow:row wrap;-ms-flex-align:center;align-items:center}.form-inline .form-check{width:100%}@media (min-width:576px){.form-inline label{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center;margin-bottom:0}.form-inline .form-group{display:-ms-flexbox;display:flex;-ms-flex:0 0 auto;flex:0 0 auto;-ms-flex-flow:row wrap;flex-flow:row wrap;-ms-flex-align:center;align-items:center;margin-bottom:0}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-plaintext{display:inline-block}.form-inline .input-group{width:auto}.form-inline .form-control-label{margin-bottom:0;vertical-align:middle}.form-inline .form-check{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center;width:auto;margin-top:0;margin-bottom:0}.form-inline .form-check-label{padding-left:0}.form-inline .form-check-input{position:relative;margin-top:0;margin-right:.25rem;margin-left:0}.form-inline .custom-control{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center;padding-left:0}.form-inline .custom-control-indicator{position:static;display:inline-block;margin-right:.25rem;vertical-align:text-bottom}.form-inline .has-feedback .form-control-feedback{top:0}}.btn{display:inline-block;font-weight:400;text-align:center;white-space:nowrap;vertical-align:middle;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;border:1px solid transparent;padding:.5rem .75rem;font-size:1rem;line-height:1.25;border-radius:.25rem;transition:all .15s ease-in-out}.btn:focus,.btn:hover{text-decoration:none}.btn.focus,.btn:focus{outline:0;box-shadow:0 0 0 3px rgba(0,123,255,.25)}.btn.disabled,.btn:disabled{opacity:.65}.btn.active,.btn:active{background-image:none}a.btn.disabled,fieldset[disabled] a.btn{pointer-events:none}.btn-primary{color:#fff;background-color:#007bff;border-color:#007bff}.btn-primary:hover{color:#fff;background-color:#0069d9;border-color:#0062cc}.btn-primary.focus,.btn-primary:focus{box-shadow:0 0 0 3px rgba(0,123,255,.5)}.btn-primary.disabled,.btn-primary:disabled{background-color:#007bff;border-color:#007bff}.btn-primary.active,.btn-primary:active,.show>.btn-primary.dropdown-toggle{background-color:#0069d9;background-image:none;border-color:#0062cc}.btn-secondary{color:#fff;background-color:#868e96;border-color:#868e96}.btn-secondary:hover{color:#fff;background-color:#727b84;border-color:#6c757d}.btn-secondary.focus,.btn-secondary:focus{box-shadow:0 0 0 3px rgba(134,142,150,.5)}.btn-secondary.disabled,.btn-secondary:disabled{background-color:#868e96;border-color:#868e96}.btn-secondary.active,.btn-secondary:active,.show>.btn-secondary.dropdown-toggle{background-color:#727b84;background-image:none;border-color:#6c757d}.btn-success{color:#fff;background-color:#28a745;border-color:#28a745}.btn-success:hover{color:#fff;background-color:#218838;border-color:#1e7e34}.btn-success.focus,.btn-success:focus{box-shadow:0 0 0 3px rgba(40,167,69,.5)}.btn-success.disabled,.btn-success:disabled{background-color:#28a745;border-color:#28a745}.btn-success.active,.btn-success:active,.show>.btn-success.dropdown-toggle{background-color:#218838;background-image:none;border-color:#1e7e34}.btn-info{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-info:hover{color:#fff;background-color:#138496;border-color:#117a8b}.btn-info.focus,.btn-info:focus{box-shadow:0 0 0 3px rgba(23,162,184,.5)}.btn-info.disabled,.btn-info:disabled{background-color:#17a2b8;border-color:#17a2b8}.btn-info.active,.btn-info:active,.show>.btn-info.dropdown-toggle{background-color:#138496;background-image:none;border-color:#117a8b}.btn-warning{color:#111;background-color:#ffc107;border-color:#ffc107}.btn-warning:hover{color:#111;background-color:#e0a800;border-color:#d39e00}.btn-warning.focus,.btn-warning:focus{box-shadow:0 0 0 3px rgba(255,193,7,.5)}.btn-warning.disabled,.btn-warning:disabled{background-color:#ffc107;border-color:#ffc107}.btn-warning.active,.btn-warning:active,.show>.btn-warning.dropdown-toggle{background-color:#e0a800;background-image:none;border-color:#d39e00}.btn-danger{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-danger:hover{color:#fff;background-color:#c82333;border-color:#bd2130}.btn-danger.focus,.btn-danger:focus{box-shadow:0 0 0 3px rgba(220,53,69,.5)}.btn-danger.disabled,.btn-danger:disabled{background-color:#dc3545;border-color:#dc3545}.btn-danger.active,.btn-danger:active,.show>.btn-danger.dropdown-toggle{background-color:#c82333;background-image:none;border-color:#bd2130}.btn-light{color:#111;background-color:#f8f9fa;border-color:#f8f9fa}.btn-light:hover{color:#111;background-color:#e2e6ea;border-color:#dae0e5}.btn-light.focus,.btn-light:focus{box-shadow:0 0 0 3px rgba(248,249,250,.5)}.btn-light.disabled,.btn-light:disabled{background-color:#f8f9fa;border-color:#f8f9fa}.btn-light.active,.btn-light:active,.show>.btn-light.dropdown-toggle{background-color:#e2e6ea;background-image:none;border-color:#dae0e5}.btn-dark{color:#fff;background-color:#343a40;border-color:#343a40}.btn-dark:hover{color:#fff;background-color:#23272b;border-color:#1d2124}.btn-dark.focus,.btn-dark:focus{box-shadow:0 0 0 3px rgba(52,58,64,.5)}.btn-dark.disabled,.btn-dark:disabled{background-color:#343a40;border-color:#343a40}.btn-dark.active,.btn-dark:active,.show>.btn-dark.dropdown-toggle{background-color:#23272b;background-image:none;border-color:#1d2124}.btn-outline-primary{color:#007bff;background-color:transparent;background-image:none;border-color:#007bff}.btn-outline-primary:hover{color:#fff;background-color:#007bff;border-color:#007bff}.btn-outline-primary.focus,.btn-outline-primary:focus{box-shadow:0 0 0 3px rgba(0,123,255,.5)}.btn-outline-primary.disabled,.btn-outline-primary:disabled{color:#007bff;background-color:transparent}.btn-outline-primary.active,.btn-outline-primary:active,.show>.btn-outline-primary.dropdown-toggle{color:#fff;background-color:#007bff;border-color:#007bff}.btn-outline-secondary{color:#868e96;background-color:transparent;background-image:none;border-color:#868e96}.btn-outline-secondary:hover{color:#fff;background-color:#868e96;border-color:#868e96}.btn-outline-secondary.focus,.btn-outline-secondary:focus{box-shadow:0 0 0 3px rgba(134,142,150,.5)}.btn-outline-secondary.disabled,.btn-outline-secondary:disabled{color:#868e96;background-color:transparent}.btn-outline-secondary.active,.btn-outline-secondary:active,.show>.btn-outline-secondary.dropdown-toggle{color:#fff;background-color:#868e96;border-color:#868e96}.btn-outline-success{color:#28a745;background-color:transparent;background-image:none;border-color:#28a745}.btn-outline-success:hover{color:#fff;background-color:#28a745;border-color:#28a745}.btn-outline-success.focus,.btn-outline-success:focus{box-shadow:0 0 0 3px rgba(40,167,69,.5)}.btn-outline-success.disabled,.btn-outline-success:disabled{color:#28a745;background-color:transparent}.btn-outline-success.active,.btn-outline-success:active,.show>.btn-outline-success.dropdown-toggle{color:#fff;background-color:#28a745;border-color:#28a745}.btn-outline-info{color:#17a2b8;background-color:transparent;background-image:none;border-color:#17a2b8}.btn-outline-info:hover{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-outline-info.focus,.btn-outline-info:focus{box-shadow:0 0 0 3px rgba(23,162,184,.5)}.btn-outline-info.disabled,.btn-outline-info:disabled{color:#17a2b8;background-color:transparent}.btn-outline-info.active,.btn-outline-info:active,.show>.btn-outline-info.dropdown-toggle{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-outline-warning{color:#ffc107;background-color:transparent;background-image:none;border-color:#ffc107}.btn-outline-warning:hover{color:#fff;background-color:#ffc107;border-color:#ffc107}.btn-outline-warning.focus,.btn-outline-warning:focus{box-shadow:0 0 0 3px rgba(255,193,7,.5)}.btn-outline-warning.disabled,.btn-outline-warning:disabled{color:#ffc107;background-color:transparent}.btn-outline-warning.active,.btn-outline-warning:active,.show>.btn-outline-warning.dropdown-toggle{color:#fff;background-color:#ffc107;border-color:#ffc107}.btn-outline-danger{color:#dc3545;background-color:transparent;background-image:none;border-color:#dc3545}.btn-outline-danger:hover{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-outline-danger.focus,.btn-outline-danger:focus{box-shadow:0 0 0 3px rgba(220,53,69,.5)}.btn-outline-danger.disabled,.btn-outline-danger:disabled{color:#dc3545;background-color:transparent}.btn-outline-danger.active,.btn-outline-danger:active,.show>.btn-outline-danger.dropdown-toggle{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-outline-light{color:#f8f9fa;background-color:transparent;background-image:none;border-color:#f8f9fa}.btn-outline-light:hover{color:#fff;background-color:#f8f9fa;border-color:#f8f9fa}.btn-outline-light.focus,.btn-outline-light:focus{box-shadow:0 0 0 3px rgba(248,249,250,.5)}.btn-outline-light.disabled,.btn-outline-light:disabled{color:#f8f9fa;background-color:transparent}.btn-outline-light.active,.btn-outline-light:active,.show>.btn-outline-light.dropdown-toggle{color:#fff;background-color:#f8f9fa;border-color:#f8f9fa}.btn-outline-dark{color:#343a40;background-color:transparent;background-image:none;border-color:#343a40}.btn-outline-dark:hover{color:#fff;background-color:#343a40;border-color:#343a40}.btn-outline-dark.focus,.btn-outline-dark:focus{box-shadow:0 0 0 3px rgba(52,58,64,.5)}.btn-outline-dark.disabled,.btn-outline-dark:disabled{color:#343a40;background-color:transparent}.btn-outline-dark.active,.btn-outline-dark:active,.show>.btn-outline-dark.dropdown-toggle{color:#fff;background-color:#343a40;border-color:#343a40}.btn-link{font-weight:400;color:#007bff;border-radius:0}.btn-link,.btn-link.active,.btn-link:active,.btn-link:disabled{background-color:transparent}.btn-link,.btn-link:active,.btn-link:focus{border-color:transparent;box-shadow:none}.btn-link:hover{border-color:transparent}.btn-link:focus,.btn-link:hover{color:#0056b3;text-decoration:underline;background-color:transparent}.btn-link:disabled{color:#868e96}.btn-link:disabled:focus,.btn-link:disabled:hover{text-decoration:none}.btn-group-lg>.btn,.btn-lg{padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}.btn-group-sm>.btn,.btn-sm{padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:.5rem}input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-block{width:100%}.fade{opacity:0;transition:opacity .15s linear}.fade.show{opacity:1}.collapse{display:none}.collapse.show{display:block}tr.collapse.show{display:table-row}tbody.collapse.show{display:table-row-group}.collapsing{position:relative;height:0;overflow:hidden;transition:height .35s ease}.dropdown,.dropup{position:relative}.dropdown-toggle::after{display:inline-block;width:0;height:0;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid;border-right:.3em solid transparent;border-left:.3em solid transparent}.dropdown-toggle:empty::after{margin-left:0}.dropup .dropdown-menu{margin-top:0;margin-bottom:.125rem}.dropup .dropdown-toggle::after{border-top:0;border-bottom:.3em solid}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:10rem;padding:.5rem 0;margin:.125rem 0 0;font-size:1rem;color:#212529;text-align:left;list-style:none;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.15);border-radius:.25rem}.dropdown-divider{height:0;margin:.5rem 0;overflow:hidden;border-top:1px solid #e9ecef}.dropdown-item{display:block;width:100%;padding:.25rem 1.5rem;clear:both;font-weight:400;color:#212529;text-align:inherit;white-space:nowrap;background:0 0;border:0}.dropdown-item:focus,.dropdown-item:hover{color:#16181b;text-decoration:none;background-color:#f8f9fa}.dropdown-item.active,.dropdown-item:active{color:#fff;text-decoration:none;background-color:#007bff}.dropdown-item.disabled,.dropdown-item:disabled{color:#868e96;background-color:transparent}.show>a{outline:0}.dropdown-menu.show{display:block}.dropdown-header{display:block;padding:.5rem 1.5rem;margin-bottom:0;font-size:.875rem;color:#868e96;white-space:nowrap}.btn-group,.btn-group-vertical{position:relative;display:-ms-inline-flexbox;display:inline-flex;vertical-align:middle}.btn-group-vertical>.btn,.btn-group>.btn{position:relative;-ms-flex:0 1 auto;flex:0 1 auto;margin-bottom:0}.btn-group-vertical>.btn:hover,.btn-group>.btn:hover{z-index:2}.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus{z-index:2}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group,.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-left:-1px}.btn-toolbar{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-pack:start;justify-content:flex-start}.btn-toolbar .input-group{width:auto}.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-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-top-left-radius:0;border-bottom-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-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-bottom-left-radius:0}.btn+.dropdown-toggle-split{padding-right:.5625rem;padding-left:.5625rem}.btn+.dropdown-toggle-split::after{margin-left:0}.btn-group-sm>.btn+.dropdown-toggle-split,.btn-sm+.dropdown-toggle-split{padding-right:.375rem;padding-left:.375rem}.btn-group-lg>.btn+.dropdown-toggle-split,.btn-lg+.dropdown-toggle-split{padding-right:.75rem;padding-left:.75rem}.btn-group-vertical{display:-ms-inline-flexbox;display:inline-flex;-ms-flex-direction:column;flex-direction:column;-ms-flex-align:start;align-items:flex-start;-ms-flex-pack:center;justify-content:center}.btn-group-vertical .btn,.btn-group-vertical .btn-group{width:100%}.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-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-child){border-top-left-radius:0;border-top-right-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-left-radius:0;border-top-right-radius:0}[data-toggle=buttons]>.btn input[type=checkbox],[data-toggle=buttons]>.btn input[type=radio],[data-toggle=buttons]>.btn-group>.btn input[type=checkbox],[data-toggle=buttons]>.btn-group>.btn input[type=radio]{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.input-group{position:relative;display:-ms-flexbox;display:flex;width:100%}.input-group .form-control{position:relative;z-index:2;-ms-flex:1 1 auto;flex:1 1 auto;width:1%;margin-bottom:0}.input-group .form-control:active,.input-group .form-control:focus,.input-group .form-control:hover{z-index:3}.input-group .form-control,.input-group-addon,.input-group-btn{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center}.input-group .form-control:not(:first-child):not(:last-child),.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{white-space:nowrap;vertical-align:middle}.input-group-addon{padding:.5rem .75rem;margin-bottom:0;font-size:1rem;font-weight:400;line-height:1.25;color:#495057;text-align:center;background-color:#e9ecef;border:1px solid rgba(0,0,0,.15);border-radius:.25rem}.input-group-addon.form-control-sm,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.input-group-addon.btn{padding:.25rem .5rem;font-size:.875rem;border-radius:.2rem}.input-group-addon.form-control-lg,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.input-group-addon.btn{padding:.5rem 1rem;font-size:1.25rem;border-radius:.3rem}.input-group-addon input[type=checkbox],.input-group-addon input[type=radio]{margin-top:0}.input-group .form-control:not(:last-child),.input-group-addon:not(:last-child),.input-group-btn:not(:first-child)>.btn-group:not(:last-child)>.btn,.input-group-btn:not(:first-child)>.btn:not(:last-child):not(.dropdown-toggle),.input-group-btn:not(:last-child)>.btn,.input-group-btn:not(:last-child)>.btn-group>.btn,.input-group-btn:not(:last-child)>.dropdown-toggle{border-top-right-radius:0;border-bottom-right-radius:0}.input-group-addon:not(:last-child){border-right:0}.input-group .form-control:not(:first-child),.input-group-addon:not(:first-child),.input-group-btn:not(:first-child)>.btn,.input-group-btn:not(:first-child)>.btn-group>.btn,.input-group-btn:not(:first-child)>.dropdown-toggle,.input-group-btn:not(:last-child)>.btn-group:not(:first-child)>.btn,.input-group-btn:not(:last-child)>.btn:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.form-control+.input-group-addon:not(:first-child){border-left:0}.input-group-btn{position:relative;font-size:0;white-space:nowrap}.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:3}.input-group-btn:not(:last-child)>.btn,.input-group-btn:not(:last-child)>.btn-group{margin-right:-1px}.input-group-btn:not(:first-child)>.btn,.input-group-btn:not(:first-child)>.btn-group{z-index:2;margin-left:-1px}.input-group-btn:not(:first-child)>.btn-group:active,.input-group-btn:not(:first-child)>.btn-group:focus,.input-group-btn:not(:first-child)>.btn-group:hover,.input-group-btn:not(:first-child)>.btn:active,.input-group-btn:not(:first-child)>.btn:focus,.input-group-btn:not(:first-child)>.btn:hover{z-index:3}.custom-control{position:relative;display:-ms-inline-flexbox;display:inline-flex;min-height:1.5rem;padding-left:1.5rem;margin-right:1rem}.custom-control-input{position:absolute;z-index:-1;opacity:0}.custom-control-input:checked~.custom-control-indicator{color:#fff;background-color:#007bff}.custom-control-input:focus~.custom-control-indicator{box-shadow:0 0 0 1px #fff,0 0 0 3px #007bff}.custom-control-input:active~.custom-control-indicator{color:#fff;background-color:#b3d7ff}.custom-control-input:disabled~.custom-control-indicator{background-color:#e9ecef}.custom-control-input:disabled~.custom-control-description{color:#868e96}.custom-control-indicator{position:absolute;top:.25rem;left:0;display:block;width:1rem;height:1rem;pointer-events:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-color:#ddd;background-repeat:no-repeat;background-position:center center;background-size:50% 50%}.custom-checkbox .custom-control-indicator{border-radius:.25rem}.custom-checkbox .custom-control-input:checked~.custom-control-indicator{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E")}.custom-checkbox .custom-control-input:indeterminate~.custom-control-indicator{background-color:#007bff;background-image:url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 4'%3E%3Cpath stroke='%23fff' d='M0 2h4'/%3E%3C/svg%3E")}.custom-radio .custom-control-indicator{border-radius:50%}.custom-radio .custom-control-input:checked~.custom-control-indicator{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23fff'/%3E%3C/svg%3E")}.custom-controls-stacked{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column}.custom-controls-stacked .custom-control{margin-bottom:.25rem}.custom-controls-stacked .custom-control+.custom-control{margin-left:0}.custom-select{display:inline-block;max-width:100%;height:calc(2.25rem + 2px);padding:.375rem 1.75rem .375rem .75rem;line-height:1.25;color:#495057;vertical-align:middle;background:#fff url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3E%3Cpath fill='%23333' d='M2 0L0 2h4zm0 5L0 3h4z'/%3E%3C/svg%3E") no-repeat right .75rem center;background-size:8px 10px;border:1px solid rgba(0,0,0,.15);border-radius:.25rem;-webkit-appearance:none;-moz-appearance:none;appearance:none}.custom-select:focus{border-color:#80bdff;outline:0}.custom-select:focus::-ms-value{color:#495057;background-color:#fff}.custom-select:disabled{color:#868e96;background-color:#e9ecef}.custom-select::-ms-expand{opacity:0}.custom-select-sm{height:calc(1.8125rem + 2px);padding-top:.375rem;padding-bottom:.375rem;font-size:75%}.custom-file{position:relative;display:inline-block;max-width:100%;height:2.5rem;margin-bottom:0}.custom-file-input{min-width:14rem;max-width:100%;height:2.5rem;margin:0;opacity:0}.custom-file-control{position:absolute;top:0;right:0;left:0;z-index:5;height:2.5rem;padding:.5rem 1rem;line-height:1.5;color:#495057;pointer-events:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-color:#fff;border:1px solid rgba(0,0,0,.15);border-radius:.25rem}.custom-file-control:lang(en):empty::after{content:"Choose file..."}.custom-file-control::before{position:absolute;top:-1px;right:-1px;bottom:-1px;z-index:6;display:block;height:2.5rem;padding:.5rem 1rem;line-height:1.5;color:#495057;background-color:#e9ecef;border:1px solid rgba(0,0,0,.15);border-radius:0 .25rem .25rem 0}.custom-file-control:lang(en)::before{content:"Browse"}.nav{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;padding-left:0;margin-bottom:0;list-style:none}.nav-link{display:block;padding:.5rem 1rem}.nav-link:focus,.nav-link:hover{text-decoration:none}.nav-link.disabled{color:#868e96}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs .nav-item{margin-bottom:-1px}.nav-tabs .nav-link{border:1px solid transparent;border-top-left-radius:.25rem;border-top-right-radius:.25rem}.nav-tabs .nav-link:focus,.nav-tabs .nav-link:hover{border-color:#e9ecef #e9ecef #ddd}.nav-tabs .nav-link.disabled{color:#868e96;background-color:transparent;border-color:transparent}.nav-tabs .nav-item.show .nav-link,.nav-tabs .nav-link.active{color:#495057;background-color:#fff;border-color:#ddd #ddd #fff}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.nav-pills .nav-link{border-radius:.25rem}.nav-pills .nav-link.active,.show>.nav-pills .nav-link{color:#fff;background-color:#007bff}.nav-fill .nav-item{-ms-flex:1 1 auto;flex:1 1 auto;text-align:center}.nav-justified .nav-item{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;text-align:center}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.navbar{position:relative;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-align:center;align-items:center;-ms-flex-pack:justify;justify-content:space-between;padding:.5rem 1rem}.navbar>.container,.navbar>.container-fluid{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-align:center;align-items:center;-ms-flex-pack:justify;justify-content:space-between}.navbar-brand{display:inline-block;padding-top:.3125rem;padding-bottom:.3125rem;margin-right:1rem;font-size:1.25rem;line-height:inherit;white-space:nowrap}.navbar-brand:focus,.navbar-brand:hover{text-decoration:none}.navbar-nav{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;padding-left:0;margin-bottom:0;list-style:none}.navbar-nav .nav-link{padding-right:0;padding-left:0}.navbar-nav .dropdown-menu{position:static;float:none}.navbar-text{display:inline-block;padding-top:.5rem;padding-bottom:.5rem}.navbar-collapse{-ms-flex-preferred-size:100%;flex-basis:100%;-ms-flex-align:center;align-items:center}.navbar-toggler{padding:.25rem .75rem;font-size:1.25rem;line-height:1;background:0 0;border:1px solid transparent;border-radius:.25rem}.navbar-toggler:focus,.navbar-toggler:hover{text-decoration:none}.navbar-toggler-icon{display:inline-block;width:1.5em;height:1.5em;vertical-align:middle;content:"";background:no-repeat center center;background-size:100% 100%}@media (max-width:575px){.navbar-expand-sm>.container,.navbar-expand-sm>.container-fluid{padding-right:0;padding-left:0}}@media (min-width:576px){.navbar-expand-sm{-ms-flex-direction:row;flex-direction:row;-ms-flex-wrap:nowrap;flex-wrap:nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-sm .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand-sm .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-sm .navbar-nav .dropdown-menu-right{right:0;left:auto}.navbar-expand-sm .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-sm>.container,.navbar-expand-sm>.container-fluid{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-sm .navbar-collapse{display:-ms-flexbox!important;display:flex!important}.navbar-expand-sm .navbar-toggler{display:none}}@media (max-width:767px){.navbar-expand-md>.container,.navbar-expand-md>.container-fluid{padding-right:0;padding-left:0}}@media (min-width:768px){.navbar-expand-md{-ms-flex-direction:row;flex-direction:row;-ms-flex-wrap:nowrap;flex-wrap:nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-md .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand-md .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-md .navbar-nav .dropdown-menu-right{right:0;left:auto}.navbar-expand-md .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-md>.container,.navbar-expand-md>.container-fluid{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-md .navbar-collapse{display:-ms-flexbox!important;display:flex!important}.navbar-expand-md .navbar-toggler{display:none}}@media (max-width:991px){.navbar-expand-lg>.container,.navbar-expand-lg>.container-fluid{padding-right:0;padding-left:0}}@media (min-width:992px){.navbar-expand-lg{-ms-flex-direction:row;flex-direction:row;-ms-flex-wrap:nowrap;flex-wrap:nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-lg .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand-lg .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-lg .navbar-nav .dropdown-menu-right{right:0;left:auto}.navbar-expand-lg .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-lg>.container,.navbar-expand-lg>.container-fluid{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-lg .navbar-collapse{display:-ms-flexbox!important;display:flex!important}.navbar-expand-lg .navbar-toggler{display:none}}@media (max-width:1199px){.navbar-expand-xl>.container,.navbar-expand-xl>.container-fluid{padding-right:0;padding-left:0}}@media (min-width:1200px){.navbar-expand-xl{-ms-flex-direction:row;flex-direction:row;-ms-flex-wrap:nowrap;flex-wrap:nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-xl .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand-xl .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-xl .navbar-nav .dropdown-menu-right{right:0;left:auto}.navbar-expand-xl .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-xl>.container,.navbar-expand-xl>.container-fluid{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-xl .navbar-collapse{display:-ms-flexbox!important;display:flex!important}.navbar-expand-xl .navbar-toggler{display:none}}.navbar-expand{-ms-flex-direction:row;flex-direction:row;-ms-flex-wrap:nowrap;flex-wrap:nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand>.container,.navbar-expand>.container-fluid{padding-right:0;padding-left:0}.navbar-expand .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand .navbar-nav .dropdown-menu{position:absolute}.navbar-expand .navbar-nav .dropdown-menu-right{right:0;left:auto}.navbar-expand .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand>.container,.navbar-expand>.container-fluid{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand .navbar-collapse{display:-ms-flexbox!important;display:flex!important}.navbar-expand .navbar-toggler{display:none}.navbar-light .navbar-brand{color:rgba(0,0,0,.9)}.navbar-light .navbar-brand:focus,.navbar-light .navbar-brand:hover{color:rgba(0,0,0,.9)}.navbar-light .navbar-nav .nav-link{color:rgba(0,0,0,.5)}.navbar-light .navbar-nav .nav-link:focus,.navbar-light .navbar-nav .nav-link:hover{color:rgba(0,0,0,.7)}.navbar-light .navbar-nav .nav-link.disabled{color:rgba(0,0,0,.3)}.navbar-light .navbar-nav .active>.nav-link,.navbar-light .navbar-nav .nav-link.active,.navbar-light .navbar-nav .nav-link.show,.navbar-light .navbar-nav .show>.nav-link{color:rgba(0,0,0,.9)}.navbar-light .navbar-toggler{color:rgba(0,0,0,.5);border-color:rgba(0,0,0,.1)}.navbar-light .navbar-toggler-icon{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='rgba(0, 0, 0, 0.5)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E")}.navbar-light .navbar-text{color:rgba(0,0,0,.5)}.navbar-dark .navbar-brand{color:#fff}.navbar-dark .navbar-brand:focus,.navbar-dark .navbar-brand:hover{color:#fff}.navbar-dark .navbar-nav .nav-link{color:rgba(255,255,255,.5)}.navbar-dark .navbar-nav .nav-link:focus,.navbar-dark .navbar-nav .nav-link:hover{color:rgba(255,255,255,.75)}.navbar-dark .navbar-nav .nav-link.disabled{color:rgba(255,255,255,.25)}.navbar-dark .navbar-nav .active>.nav-link,.navbar-dark .navbar-nav .nav-link.active,.navbar-dark .navbar-nav .nav-link.show,.navbar-dark .navbar-nav .show>.nav-link{color:#fff}.navbar-dark .navbar-toggler{color:rgba(255,255,255,.5);border-color:rgba(255,255,255,.1)}.navbar-dark .navbar-toggler-icon{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='rgba(255, 255, 255, 0.5)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E")}.navbar-dark .navbar-text{color:rgba(255,255,255,.5)}.card{position:relative;display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;min-width:0;word-wrap:break-word;background-color:#fff;background-clip:border-box;border:1px solid rgba(0,0,0,.125);border-radius:.25rem}.card-body{-ms-flex:1 1 auto;flex:1 1 auto;padding:1.25rem}.card-title{margin-bottom:.75rem}.card-subtitle{margin-top:-.375rem;margin-bottom:0}.card-text:last-child{margin-bottom:0}.card-link:hover{text-decoration:none}.card-link+.card-link{margin-left:1.25rem}.card>.list-group:first-child .list-group-item:first-child{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.card>.list-group:last-child .list-group-item:last-child{border-bottom-right-radius:.25rem;border-bottom-left-radius:.25rem}.card-header{padding:.75rem 1.25rem;margin-bottom:0;background-color:rgba(0,0,0,.03);border-bottom:1px solid rgba(0,0,0,.125)}.card-header:first-child{border-radius:calc(.25rem - 1px) calc(.25rem - 1px) 0 0}.card-footer{padding:.75rem 1.25rem;background-color:rgba(0,0,0,.03);border-top:1px solid rgba(0,0,0,.125)}.card-footer:last-child{border-radius:0 0 calc(.25rem - 1px) calc(.25rem - 1px)}.card-header-tabs{margin-right:-.625rem;margin-bottom:-.75rem;margin-left:-.625rem;border-bottom:0}.card-header-pills{margin-right:-.625rem;margin-left:-.625rem}.card-img-overlay{position:absolute;top:0;right:0;bottom:0;left:0;padding:1.25rem}.card-img{width:100%;border-radius:calc(.25rem - 1px)}.card-img-top{width:100%;border-top-left-radius:calc(.25rem - 1px);border-top-right-radius:calc(.25rem - 1px)}.card-img-bottom{width:100%;border-bottom-right-radius:calc(.25rem - 1px);border-bottom-left-radius:calc(.25rem - 1px)}@media (min-width:576px){.card-deck{display:-ms-flexbox;display:flex;-ms-flex-flow:row wrap;flex-flow:row wrap;margin-right:-15px;margin-left:-15px}.card-deck .card{display:-ms-flexbox;display:flex;-ms-flex:1 0 0%;flex:1 0 0%;-ms-flex-direction:column;flex-direction:column;margin-right:15px;margin-left:15px}}@media (min-width:576px){.card-group{display:-ms-flexbox;display:flex;-ms-flex-flow:row wrap;flex-flow:row wrap}.card-group .card{-ms-flex:1 0 0%;flex:1 0 0%}.card-group .card+.card{margin-left:0;border-left:0}.card-group .card:first-child{border-top-right-radius:0;border-bottom-right-radius:0}.card-group .card:first-child .card-img-top{border-top-right-radius:0}.card-group .card:first-child .card-img-bottom{border-bottom-right-radius:0}.card-group .card:last-child{border-top-left-radius:0;border-bottom-left-radius:0}.card-group .card:last-child .card-img-top{border-top-left-radius:0}.card-group .card:last-child .card-img-bottom{border-bottom-left-radius:0}.card-group .card:not(:first-child):not(:last-child){border-radius:0}.card-group .card:not(:first-child):not(:last-child) .card-img-bottom,.card-group .card:not(:first-child):not(:last-child) .card-img-top{border-radius:0}}.card-columns .card{margin-bottom:.75rem}@media (min-width:576px){.card-columns{-webkit-column-count:3;column-count:3;-webkit-column-gap:1.25rem;column-gap:1.25rem}.card-columns .card{display:inline-block;width:100%}}.breadcrumb{padding:.75rem 1rem;margin-bottom:1rem;list-style:none;background-color:#e9ecef;border-radius:.25rem}.breadcrumb::after{display:block;clear:both;content:""}.breadcrumb-item{float:left}.breadcrumb-item+.breadcrumb-item::before{display:inline-block;padding-right:.5rem;padding-left:.5rem;color:#868e96;content:"/"}.breadcrumb-item+.breadcrumb-item:hover::before{text-decoration:underline}.breadcrumb-item+.breadcrumb-item:hover::before{text-decoration:none}.breadcrumb-item.active{color:#868e96}.pagination{display:-ms-flexbox;display:flex;padding-left:0;list-style:none;border-radius:.25rem}.page-item:first-child .page-link{margin-left:0;border-top-left-radius:.25rem;border-bottom-left-radius:.25rem}.page-item:last-child .page-link{border-top-right-radius:.25rem;border-bottom-right-radius:.25rem}.page-item.active .page-link{z-index:2;color:#fff;background-color:#007bff;border-color:#007bff}.page-item.disabled .page-link{color:#868e96;pointer-events:none;background-color:#fff;border-color:#ddd}.page-link{position:relative;display:block;padding:.5rem .75rem;margin-left:-1px;line-height:1.25;color:#007bff;background-color:#fff;border:1px solid #ddd}.page-link:focus,.page-link:hover{color:#0056b3;text-decoration:none;background-color:#e9ecef;border-color:#ddd}.pagination-lg .page-link{padding:.75rem 1.5rem;font-size:1.25rem;line-height:1.5}.pagination-lg .page-item:first-child .page-link{border-top-left-radius:.3rem;border-bottom-left-radius:.3rem}.pagination-lg .page-item:last-child .page-link{border-top-right-radius:.3rem;border-bottom-right-radius:.3rem}.pagination-sm .page-link{padding:.25rem .5rem;font-size:.875rem;line-height:1.5}.pagination-sm .page-item:first-child .page-link{border-top-left-radius:.2rem;border-bottom-left-radius:.2rem}.pagination-sm .page-item:last-child .page-link{border-top-right-radius:.2rem;border-bottom-right-radius:.2rem}.badge{display:inline-block;padding:.25em .4em;font-size:75%;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25rem}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.badge-pill{padding-right:.6em;padding-left:.6em;border-radius:10rem}.badge-primary{color:#fff;background-color:#007bff}.badge-primary[href]:focus,.badge-primary[href]:hover{color:#fff;text-decoration:none;background-color:#0062cc}.badge-secondary{color:#fff;background-color:#868e96}.badge-secondary[href]:focus,.badge-secondary[href]:hover{color:#fff;text-decoration:none;background-color:#6c757d}.badge-success{color:#fff;background-color:#28a745}.badge-success[href]:focus,.badge-success[href]:hover{color:#fff;text-decoration:none;background-color:#1e7e34}.badge-info{color:#fff;background-color:#17a2b8}.badge-info[href]:focus,.badge-info[href]:hover{color:#fff;text-decoration:none;background-color:#117a8b}.badge-warning{color:#111;background-color:#ffc107}.badge-warning[href]:focus,.badge-warning[href]:hover{color:#111;text-decoration:none;background-color:#d39e00}.badge-danger{color:#fff;background-color:#dc3545}.badge-danger[href]:focus,.badge-danger[href]:hover{color:#fff;text-decoration:none;background-color:#bd2130}.badge-light{color:#111;background-color:#f8f9fa}.badge-light[href]:focus,.badge-light[href]:hover{color:#111;text-decoration:none;background-color:#dae0e5}.badge-dark{color:#fff;background-color:#343a40}.badge-dark[href]:focus,.badge-dark[href]:hover{color:#fff;text-decoration:none;background-color:#1d2124}.jumbotron{padding:2rem 1rem;margin-bottom:2rem;background-color:#e9ecef;border-radius:.3rem}@media (min-width:576px){.jumbotron{padding:4rem 2rem}}.jumbotron-fluid{padding-right:0;padding-left:0;border-radius:0}.alert{padding:.75rem 1.25rem;margin-bottom:1rem;border:1px solid transparent;border-radius:.25rem}.alert-heading{color:inherit}.alert-link{font-weight:700}.alert-dismissible .close{position:relative;top:-.75rem;right:-1.25rem;padding:.75rem 1.25rem;color:inherit}.alert-primary{color:#004085;background-color:#cce5ff;border-color:#b8daff}.alert-primary hr{border-top-color:#9fcdff}.alert-primary .alert-link{color:#002752}.alert-secondary{color:#464a4e;background-color:#e7e8ea;border-color:#dddfe2}.alert-secondary hr{border-top-color:#cfd2d6}.alert-secondary .alert-link{color:#2e3133}.alert-success{color:#155724;background-color:#d4edda;border-color:#c3e6cb}.alert-success hr{border-top-color:#b1dfbb}.alert-success .alert-link{color:#0b2e13}.alert-info{color:#0c5460;background-color:#d1ecf1;border-color:#bee5eb}.alert-info hr{border-top-color:#abdde5}.alert-info .alert-link{color:#062c33}.alert-warning{color:#856404;background-color:#fff3cd;border-color:#ffeeba}.alert-warning hr{border-top-color:#ffe8a1}.alert-warning .alert-link{color:#533f03}.alert-danger{color:#721c24;background-color:#f8d7da;border-color:#f5c6cb}.alert-danger hr{border-top-color:#f1b0b7}.alert-danger .alert-link{color:#491217}.alert-light{color:#818182;background-color:#fefefe;border-color:#fdfdfe}.alert-light hr{border-top-color:#ececf6}.alert-light .alert-link{color:#686868}.alert-dark{color:#1b1e21;background-color:#d6d8d9;border-color:#c6c8ca}.alert-dark hr{border-top-color:#b9bbbe}.alert-dark .alert-link{color:#040505}@-webkit-keyframes progress-bar-stripes{from{background-position:1rem 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:1rem 0}to{background-position:0 0}}.progress{display:-ms-flexbox;display:flex;overflow:hidden;font-size:.75rem;line-height:1rem;text-align:center;background-color:#e9ecef;border-radius:.25rem}.progress-bar{height:1rem;line-height:1rem;color:#fff;background-color:#007bff;transition:width .6s ease}.progress-bar-striped{background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-size:1rem 1rem}.progress-bar-animated{-webkit-animation:progress-bar-stripes 1s linear infinite;animation:progress-bar-stripes 1s linear infinite}.media{display:-ms-flexbox;display:flex;-ms-flex-align:start;align-items:flex-start}.media-body{-ms-flex:1;flex:1}.list-group{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;padding-left:0;margin-bottom:0}.list-group-item-action{width:100%;color:#495057;text-align:inherit}.list-group-item-action:focus,.list-group-item-action:hover{color:#495057;text-decoration:none;background-color:#f8f9fa}.list-group-item-action:active{color:#212529;background-color:#e9ecef}.list-group-item{position:relative;display:block;padding:.75rem 1.25rem;margin-bottom:-1px;background-color:#fff;border:1px solid rgba(0,0,0,.125)}.list-group-item:first-child{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:.25rem;border-bottom-left-radius:.25rem}.list-group-item:focus,.list-group-item:hover{text-decoration:none}.list-group-item.disabled,.list-group-item:disabled{color:#868e96;background-color:#fff}.list-group-item.active{z-index:2;color:#fff;background-color:#007bff;border-color:#007bff}.list-group-flush .list-group-item{border-right:0;border-left:0;border-radius:0}.list-group-flush:first-child .list-group-item:first-child{border-top:0}.list-group-flush:last-child .list-group-item:last-child{border-bottom:0}.list-group-item-primary{color:#004085;background-color:#b8daff}a.list-group-item-primary,button.list-group-item-primary{color:#004085}a.list-group-item-primary:focus,a.list-group-item-primary:hover,button.list-group-item-primary:focus,button.list-group-item-primary:hover{color:#004085;background-color:#9fcdff}a.list-group-item-primary.active,button.list-group-item-primary.active{color:#fff;background-color:#004085;border-color:#004085}.list-group-item-secondary{color:#464a4e;background-color:#dddfe2}a.list-group-item-secondary,button.list-group-item-secondary{color:#464a4e}a.list-group-item-secondary:focus,a.list-group-item-secondary:hover,button.list-group-item-secondary:focus,button.list-group-item-secondary:hover{color:#464a4e;background-color:#cfd2d6}a.list-group-item-secondary.active,button.list-group-item-secondary.active{color:#fff;background-color:#464a4e;border-color:#464a4e}.list-group-item-success{color:#155724;background-color:#c3e6cb}a.list-group-item-success,button.list-group-item-success{color:#155724}a.list-group-item-success:focus,a.list-group-item-success:hover,button.list-group-item-success:focus,button.list-group-item-success:hover{color:#155724;background-color:#b1dfbb}a.list-group-item-success.active,button.list-group-item-success.active{color:#fff;background-color:#155724;border-color:#155724}.list-group-item-info{color:#0c5460;background-color:#bee5eb}a.list-group-item-info,button.list-group-item-info{color:#0c5460}a.list-group-item-info:focus,a.list-group-item-info:hover,button.list-group-item-info:focus,button.list-group-item-info:hover{color:#0c5460;background-color:#abdde5}a.list-group-item-info.active,button.list-group-item-info.active{color:#fff;background-color:#0c5460;border-color:#0c5460}.list-group-item-warning{color:#856404;background-color:#ffeeba}a.list-group-item-warning,button.list-group-item-warning{color:#856404}a.list-group-item-warning:focus,a.list-group-item-warning:hover,button.list-group-item-warning:focus,button.list-group-item-warning:hover{color:#856404;background-color:#ffe8a1}a.list-group-item-warning.active,button.list-group-item-warning.active{color:#fff;background-color:#856404;border-color:#856404}.list-group-item-danger{color:#721c24;background-color:#f5c6cb}a.list-group-item-danger,button.list-group-item-danger{color:#721c24}a.list-group-item-danger:focus,a.list-group-item-danger:hover,button.list-group-item-danger:focus,button.list-group-item-danger:hover{color:#721c24;background-color:#f1b0b7}a.list-group-item-danger.active,button.list-group-item-danger.active{color:#fff;background-color:#721c24;border-color:#721c24}.list-group-item-light{color:#818182;background-color:#fdfdfe}a.list-group-item-light,button.list-group-item-light{color:#818182}a.list-group-item-light:focus,a.list-group-item-light:hover,button.list-group-item-light:focus,button.list-group-item-light:hover{color:#818182;background-color:#ececf6}a.list-group-item-light.active,button.list-group-item-light.active{color:#fff;background-color:#818182;border-color:#818182}.list-group-item-dark{color:#1b1e21;background-color:#c6c8ca}a.list-group-item-dark,button.list-group-item-dark{color:#1b1e21}a.list-group-item-dark:focus,a.list-group-item-dark:hover,button.list-group-item-dark:focus,button.list-group-item-dark:hover{color:#1b1e21;background-color:#b9bbbe}a.list-group-item-dark.active,button.list-group-item-dark.active{color:#fff;background-color:#1b1e21;border-color:#1b1e21}.close{float:right;font-size:1.5rem;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;opacity:.5}.close:focus,.close:hover{color:#000;text-decoration:none;opacity:.75}button.close{padding:0;background:0 0;border:0;-webkit-appearance:none}.modal-open{overflow:hidden}.modal{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1050;display:none;overflow:hidden;outline:0}.modal.fade .modal-dialog{transition:-webkit-transform .3s ease-out;transition:transform .3s ease-out;transition:transform .3s ease-out,-webkit-transform .3s ease-out;-webkit-transform:translate(0,-25%);transform:translate(0,-25%)}.modal.show .modal-dialog{-webkit-transform:translate(0,0);transform:translate(0,0)}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal-dialog{position:relative;width:auto;margin:10px}.modal-content{position:relative;display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.2);border-radius:.3rem;outline:0}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{opacity:0}.modal-backdrop.show{opacity:.5}.modal-header{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-ms-flex-pack:justify;justify-content:space-between;padding:15px;border-bottom:1px solid #e9ecef}.modal-title{margin-bottom:0;line-height:1.5}.modal-body{position:relative;-ms-flex:1 1 auto;flex:1 1 auto;padding:15px}.modal-footer{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-ms-flex-pack:end;justify-content:flex-end;padding:15px;border-top:1px solid #e9ecef}.modal-footer>:not(:first-child){margin-left:.25rem}.modal-footer>:not(:last-child){margin-right:.25rem}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:576px){.modal-dialog{max-width:500px;margin:30px auto}.modal-sm{max-width:300px}}@media (min-width:992px){.modal-lg{max-width:800px}}.tooltip{position:absolute;z-index:1070;display:block;margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;white-space:normal;line-break:auto;font-size:.875rem;word-wrap:break-word;opacity:0}.tooltip.show{opacity:.9}.tooltip .arrow{position:absolute;display:block;width:5px;height:5px}.tooltip.bs-tooltip-auto[x-placement^=top],.tooltip.bs-tooltip-top{padding:5px 0}.tooltip.bs-tooltip-auto[x-placement^=top] .arrow,.tooltip.bs-tooltip-top .arrow{bottom:0}.tooltip.bs-tooltip-auto[x-placement^=top] .arrow::before,.tooltip.bs-tooltip-top .arrow::before{margin-left:-3px;content:"";border-width:5px 5px 0;border-top-color:#000}.tooltip.bs-tooltip-auto[x-placement^=right],.tooltip.bs-tooltip-right{padding:0 5px}.tooltip.bs-tooltip-auto[x-placement^=right] .arrow,.tooltip.bs-tooltip-right .arrow{left:0}.tooltip.bs-tooltip-auto[x-placement^=right] .arrow::before,.tooltip.bs-tooltip-right .arrow::before{margin-top:-3px;content:"";border-width:5px 5px 5px 0;border-right-color:#000}.tooltip.bs-tooltip-auto[x-placement^=bottom],.tooltip.bs-tooltip-bottom{padding:5px 0}.tooltip.bs-tooltip-auto[x-placement^=bottom] .arrow,.tooltip.bs-tooltip-bottom .arrow{top:0}.tooltip.bs-tooltip-auto[x-placement^=bottom] .arrow::before,.tooltip.bs-tooltip-bottom .arrow::before{margin-left:-3px;content:"";border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bs-tooltip-auto[x-placement^=left],.tooltip.bs-tooltip-left{padding:0 5px}.tooltip.bs-tooltip-auto[x-placement^=left] .arrow,.tooltip.bs-tooltip-left .arrow{right:0}.tooltip.bs-tooltip-auto[x-placement^=left] .arrow::before,.tooltip.bs-tooltip-left .arrow::before{right:0;margin-top:-3px;content:"";border-width:5px 0 5px 5px;border-left-color:#000}.tooltip .arrow::before{position:absolute;border-color:transparent;border-style:solid}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;background-color:#000;border-radius:.25rem}.popover{position:absolute;top:0;left:0;z-index:1060;display:block;max-width:276px;padding:1px;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;white-space:normal;line-break:auto;font-size:.875rem;word-wrap:break-word;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.2);border-radius:.3rem}.popover .arrow{position:absolute;display:block;width:10px;height:5px}.popover .arrow::after,.popover .arrow::before{position:absolute;display:block;border-color:transparent;border-style:solid}.popover .arrow::before{content:"";border-width:11px}.popover .arrow::after{content:"";border-width:11px}.popover.bs-popover-auto[x-placement^=top],.popover.bs-popover-top{margin-bottom:10px}.popover.bs-popover-auto[x-placement^=top] .arrow,.popover.bs-popover-top .arrow{bottom:0}.popover.bs-popover-auto[x-placement^=top] .arrow::after,.popover.bs-popover-auto[x-placement^=top] .arrow::before,.popover.bs-popover-top .arrow::after,.popover.bs-popover-top .arrow::before{border-bottom-width:0}.popover.bs-popover-auto[x-placement^=top] .arrow::before,.popover.bs-popover-top .arrow::before{bottom:-11px;margin-left:-6px;border-top-color:rgba(0,0,0,.25)}.popover.bs-popover-auto[x-placement^=top] .arrow::after,.popover.bs-popover-top .arrow::after{bottom:-10px;margin-left:-6px;border-top-color:#fff}.popover.bs-popover-auto[x-placement^=right],.popover.bs-popover-right{margin-left:10px}.popover.bs-popover-auto[x-placement^=right] .arrow,.popover.bs-popover-right .arrow{left:0}.popover.bs-popover-auto[x-placement^=right] .arrow::after,.popover.bs-popover-auto[x-placement^=right] .arrow::before,.popover.bs-popover-right .arrow::after,.popover.bs-popover-right .arrow::before{margin-top:-8px;border-left-width:0}.popover.bs-popover-auto[x-placement^=right] .arrow::before,.popover.bs-popover-right .arrow::before{left:-11px;border-right-color:rgba(0,0,0,.25)}.popover.bs-popover-auto[x-placement^=right] .arrow::after,.popover.bs-popover-right .arrow::after{left:-10px;border-right-color:#fff}.popover.bs-popover-auto[x-placement^=bottom],.popover.bs-popover-bottom{margin-top:10px}.popover.bs-popover-auto[x-placement^=bottom] .arrow,.popover.bs-popover-bottom .arrow{top:0}.popover.bs-popover-auto[x-placement^=bottom] .arrow::after,.popover.bs-popover-auto[x-placement^=bottom] .arrow::before,.popover.bs-popover-bottom .arrow::after,.popover.bs-popover-bottom .arrow::before{margin-left:-7px;border-top-width:0}.popover.bs-popover-auto[x-placement^=bottom] .arrow::before,.popover.bs-popover-bottom .arrow::before{top:-11px;border-bottom-color:rgba(0,0,0,.25)}.popover.bs-popover-auto[x-placement^=bottom] .arrow::after,.popover.bs-popover-bottom .arrow::after{top:-10px;border-bottom-color:#fff}.popover.bs-popover-auto[x-placement^=bottom] .popover-header::before,.popover.bs-popover-bottom .popover-header::before{position:absolute;top:0;left:50%;display:block;width:20px;margin-left:-10px;content:"";border-bottom:1px solid #f7f7f7}.popover.bs-popover-auto[x-placement^=left],.popover.bs-popover-left{margin-right:10px}.popover.bs-popover-auto[x-placement^=left] .arrow,.popover.bs-popover-left .arrow{right:0}.popover.bs-popover-auto[x-placement^=left] .arrow::after,.popover.bs-popover-auto[x-placement^=left] .arrow::before,.popover.bs-popover-left .arrow::after,.popover.bs-popover-left .arrow::before{margin-top:-8px;border-right-width:0}.popover.bs-popover-auto[x-placement^=left] .arrow::before,.popover.bs-popover-left .arrow::before{right:-11px;border-left-color:rgba(0,0,0,.25)}.popover.bs-popover-auto[x-placement^=left] .arrow::after,.popover.bs-popover-left .arrow::after{right:-10px;border-left-color:#fff}.popover-header{padding:8px 14px;margin-bottom:0;font-size:1rem;color:inherit;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-top-left-radius:calc(.3rem - 1px);border-top-right-radius:calc(.3rem - 1px)}.popover-header:empty{display:none}.popover-body{padding:9px 14px;color:#212529}.carousel{position:relative}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-item{position:relative;display:none;-ms-flex-align:center;align-items:center;width:100%;transition:-webkit-transform .6s ease;transition:transform .6s ease;transition:transform .6s ease,-webkit-transform .6s ease;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-perspective:1000px;perspective:1000px}.carousel-item-next,.carousel-item-prev,.carousel-item.active{display:block}.carousel-item-next,.carousel-item-prev{position:absolute;top:0}.carousel-item-next.carousel-item-left,.carousel-item-prev.carousel-item-right{-webkit-transform:translateX(0);transform:translateX(0)}@supports ((-webkit-transform-style:preserve-3d) or (transform-style:preserve-3d)){.carousel-item-next.carousel-item-left,.carousel-item-prev.carousel-item-right{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}.active.carousel-item-right,.carousel-item-next{-webkit-transform:translateX(100%);transform:translateX(100%)}@supports ((-webkit-transform-style:preserve-3d) or (transform-style:preserve-3d)){.active.carousel-item-right,.carousel-item-next{-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}}.active.carousel-item-left,.carousel-item-prev{-webkit-transform:translateX(-100%);transform:translateX(-100%)}@supports ((-webkit-transform-style:preserve-3d) or (transform-style:preserve-3d)){.active.carousel-item-left,.carousel-item-prev{-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}}.carousel-control-next,.carousel-control-prev{position:absolute;top:0;bottom:0;display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center;width:15%;color:#fff;text-align:center;opacity:.5}.carousel-control-next:focus,.carousel-control-next:hover,.carousel-control-prev:focus,.carousel-control-prev:hover{color:#fff;text-decoration:none;outline:0;opacity:.9}.carousel-control-prev{left:0}.carousel-control-next{right:0}.carousel-control-next-icon,.carousel-control-prev-icon{display:inline-block;width:20px;height:20px;background:transparent no-repeat center center;background-size:100% 100%}.carousel-control-prev-icon{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 8 8'%3E%3Cpath d='M4 0l-4 4 4 4 1.5-1.5-2.5-2.5 2.5-2.5-1.5-1.5z'/%3E%3C/svg%3E")}.carousel-control-next-icon{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 8 8'%3E%3Cpath d='M1.5 0l-1.5 1.5 2.5 2.5-2.5 2.5 1.5 1.5 4-4-4-4z'/%3E%3C/svg%3E")}.carousel-indicators{position:absolute;right:0;bottom:10px;left:0;z-index:15;display:-ms-flexbox;display:flex;-ms-flex-pack:center;justify-content:center;padding-left:0;margin-right:15%;margin-left:15%;list-style:none}.carousel-indicators li{position:relative;-ms-flex:0 1 auto;flex:0 1 auto;width:30px;height:3px;margin-right:3px;margin-left:3px;text-indent:-999px;background-color:rgba(255,255,255,.5)}.carousel-indicators li::before{position:absolute;top:-10px;left:0;display:inline-block;width:100%;height:10px;content:""}.carousel-indicators li::after{position:absolute;bottom:-10px;left:0;display:inline-block;width:100%;height:10px;content:""}.carousel-indicators .active{background-color:#fff}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center}.align-baseline{vertical-align:baseline!important}.align-top{vertical-align:top!important}.align-middle{vertical-align:middle!important}.align-bottom{vertical-align:bottom!important}.align-text-bottom{vertical-align:text-bottom!important}.align-text-top{vertical-align:text-top!important}.bg-primary{background-color:#007bff!important}a.bg-primary:focus,a.bg-primary:hover{background-color:#0062cc!important}.bg-secondary{background-color:#868e96!important}a.bg-secondary:focus,a.bg-secondary:hover{background-color:#6c757d!important}.bg-success{background-color:#28a745!important}a.bg-success:focus,a.bg-success:hover{background-color:#1e7e34!important}.bg-info{background-color:#17a2b8!important}a.bg-info:focus,a.bg-info:hover{background-color:#117a8b!important}.bg-warning{background-color:#ffc107!important}a.bg-warning:focus,a.bg-warning:hover{background-color:#d39e00!important}.bg-danger{background-color:#dc3545!important}a.bg-danger:focus,a.bg-danger:hover{background-color:#bd2130!important}.bg-light{background-color:#f8f9fa!important}a.bg-light:focus,a.bg-light:hover{background-color:#dae0e5!important}.bg-dark{background-color:#343a40!important}a.bg-dark:focus,a.bg-dark:hover{background-color:#1d2124!important}.bg-white{background-color:#fff!important}.bg-transparent{background-color:transparent!important}.border{border:1px solid #e9ecef!important}.border-0{border:0!important}.border-top-0{border-top:0!important}.border-right-0{border-right:0!important}.border-bottom-0{border-bottom:0!important}.border-left-0{border-left:0!important}.border-primary{border-color:#007bff!important}.border-secondary{border-color:#868e96!important}.border-success{border-color:#28a745!important}.border-info{border-color:#17a2b8!important}.border-warning{border-color:#ffc107!important}.border-danger{border-color:#dc3545!important}.border-light{border-color:#f8f9fa!important}.border-dark{border-color:#343a40!important}.border-white{border-color:#fff!important}.rounded{border-radius:.25rem!important}.rounded-top{border-top-left-radius:.25rem!important;border-top-right-radius:.25rem!important}.rounded-right{border-top-right-radius:.25rem!important;border-bottom-right-radius:.25rem!important}.rounded-bottom{border-bottom-right-radius:.25rem!important;border-bottom-left-radius:.25rem!important}.rounded-left{border-top-left-radius:.25rem!important;border-bottom-left-radius:.25rem!important}.rounded-circle{border-radius:50%}.rounded-0{border-radius:0}.clearfix::after{display:block;clear:both;content:""}.d-none{display:none!important}.d-inline{display:inline!important}.d-inline-block{display:inline-block!important}.d-block{display:block!important}.d-table{display:table!important}.d-table-cell{display:table-cell!important}.d-flex{display:-ms-flexbox!important;display:flex!important}.d-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}@media (min-width:576px){.d-sm-none{display:none!important}.d-sm-inline{display:inline!important}.d-sm-inline-block{display:inline-block!important}.d-sm-block{display:block!important}.d-sm-table{display:table!important}.d-sm-table-cell{display:table-cell!important}.d-sm-flex{display:-ms-flexbox!important;display:flex!important}.d-sm-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media (min-width:768px){.d-md-none{display:none!important}.d-md-inline{display:inline!important}.d-md-inline-block{display:inline-block!important}.d-md-block{display:block!important}.d-md-table{display:table!important}.d-md-table-cell{display:table-cell!important}.d-md-flex{display:-ms-flexbox!important;display:flex!important}.d-md-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media (min-width:992px){.d-lg-none{display:none!important}.d-lg-inline{display:inline!important}.d-lg-inline-block{display:inline-block!important}.d-lg-block{display:block!important}.d-lg-table{display:table!important}.d-lg-table-cell{display:table-cell!important}.d-lg-flex{display:-ms-flexbox!important;display:flex!important}.d-lg-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media (min-width:1200px){.d-xl-none{display:none!important}.d-xl-inline{display:inline!important}.d-xl-inline-block{display:inline-block!important}.d-xl-block{display:block!important}.d-xl-table{display:table!important}.d-xl-table-cell{display:table-cell!important}.d-xl-flex{display:-ms-flexbox!important;display:flex!important}.d-xl-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}.d-print-block{display:none!important}@media print{.d-print-block{display:block!important}}.d-print-inline{display:none!important}@media print{.d-print-inline{display:inline!important}}.d-print-inline-block{display:none!important}@media print{.d-print-inline-block{display:inline-block!important}}@media print{.d-print-none{display:none!important}}.embed-responsive{position:relative;display:block;width:100%;padding:0;overflow:hidden}.embed-responsive::before{display:block;content:""}.embed-responsive .embed-responsive-item,.embed-responsive embed,.embed-responsive iframe,.embed-responsive object,.embed-responsive video{position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;border:0}.embed-responsive-21by9::before{padding-top:42.857143%}.embed-responsive-16by9::before{padding-top:56.25%}.embed-responsive-4by3::before{padding-top:75%}.embed-responsive-1by1::before{padding-top:100%}.flex-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.justify-content-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-center{-ms-flex-align:center!important;align-items:center!important}.align-items-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}@media (min-width:576px){.flex-sm-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-sm-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-sm-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-sm-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-sm-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-sm-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-sm-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.justify-content-sm-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-sm-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-sm-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-sm-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-sm-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-sm-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-sm-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-sm-center{-ms-flex-align:center!important;align-items:center!important}.align-items-sm-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-sm-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-sm-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-sm-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-sm-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-sm-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-sm-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-sm-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-sm-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-sm-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-sm-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-sm-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-sm-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-sm-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}}@media (min-width:768px){.flex-md-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-md-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-md-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-md-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-md-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-md-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-md-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.justify-content-md-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-md-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-md-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-md-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-md-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-md-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-md-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-md-center{-ms-flex-align:center!important;align-items:center!important}.align-items-md-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-md-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-md-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-md-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-md-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-md-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-md-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-md-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-md-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-md-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-md-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-md-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-md-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-md-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}}@media (min-width:992px){.flex-lg-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-lg-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-lg-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-lg-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-lg-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-lg-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-lg-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.justify-content-lg-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-lg-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-lg-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-lg-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-lg-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-lg-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-lg-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-lg-center{-ms-flex-align:center!important;align-items:center!important}.align-items-lg-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-lg-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-lg-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-lg-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-lg-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-lg-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-lg-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-lg-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-lg-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-lg-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-lg-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-lg-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-lg-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-lg-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}}@media (min-width:1200px){.flex-xl-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-xl-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-xl-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-xl-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-xl-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-xl-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-xl-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.justify-content-xl-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-xl-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-xl-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-xl-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-xl-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-xl-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-xl-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-xl-center{-ms-flex-align:center!important;align-items:center!important}.align-items-xl-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-xl-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-xl-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-xl-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-xl-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-xl-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-xl-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-xl-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-xl-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-xl-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-xl-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-xl-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-xl-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-xl-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}}.float-left{float:left!important}.float-right{float:right!important}.float-none{float:none!important}@media (min-width:576px){.float-sm-left{float:left!important}.float-sm-right{float:right!important}.float-sm-none{float:none!important}}@media (min-width:768px){.float-md-left{float:left!important}.float-md-right{float:right!important}.float-md-none{float:none!important}}@media (min-width:992px){.float-lg-left{float:left!important}.float-lg-right{float:right!important}.float-lg-none{float:none!important}}@media (min-width:1200px){.float-xl-left{float:left!important}.float-xl-right{float:right!important}.float-xl-none{float:none!important}}.fixed-top{position:fixed;top:0;right:0;left:0;z-index:1030}.fixed-bottom{position:fixed;right:0;bottom:0;left:0;z-index:1030}@supports ((position:-webkit-sticky) or (position:sticky)){.sticky-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}}.sr-only{position:absolute;width:1px;height:1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;-webkit-clip-path:inset(50%);clip-path:inset(50%);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;overflow:visible;clip:auto;white-space:normal;-webkit-clip-path:none;clip-path:none}.w-25{width:25%!important}.w-50{width:50%!important}.w-75{width:75%!important}.w-100{width:100%!important}.h-25{height:25%!important}.h-50{height:50%!important}.h-75{height:75%!important}.h-100{height:100%!important}.mw-100{max-width:100%!important}.mh-100{max-height:100%!important}.m-0{margin:0!important}.mt-0{margin-top:0!important}.mr-0{margin-right:0!important}.mb-0{margin-bottom:0!important}.ml-0{margin-left:0!important}.mx-0{margin-right:0!important;margin-left:0!important}.my-0{margin-top:0!important;margin-bottom:0!important}.m-1{margin:.25rem!important}.mt-1{margin-top:.25rem!important}.mr-1{margin-right:.25rem!important}.mb-1{margin-bottom:.25rem!important}.ml-1{margin-left:.25rem!important}.mx-1{margin-right:.25rem!important;margin-left:.25rem!important}.my-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.m-2{margin:.5rem!important}.mt-2{margin-top:.5rem!important}.mr-2{margin-right:.5rem!important}.mb-2{margin-bottom:.5rem!important}.ml-2{margin-left:.5rem!important}.mx-2{margin-right:.5rem!important;margin-left:.5rem!important}.my-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.m-3{margin:1rem!important}.mt-3{margin-top:1rem!important}.mr-3{margin-right:1rem!important}.mb-3{margin-bottom:1rem!important}.ml-3{margin-left:1rem!important}.mx-3{margin-right:1rem!important;margin-left:1rem!important}.my-3{margin-top:1rem!important;margin-bottom:1rem!important}.m-4{margin:1.5rem!important}.mt-4{margin-top:1.5rem!important}.mr-4{margin-right:1.5rem!important}.mb-4{margin-bottom:1.5rem!important}.ml-4{margin-left:1.5rem!important}.mx-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.my-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.m-5{margin:3rem!important}.mt-5{margin-top:3rem!important}.mr-5{margin-right:3rem!important}.mb-5{margin-bottom:3rem!important}.ml-5{margin-left:3rem!important}.mx-5{margin-right:3rem!important;margin-left:3rem!important}.my-5{margin-top:3rem!important;margin-bottom:3rem!important}.p-0{padding:0!important}.pt-0{padding-top:0!important}.pr-0{padding-right:0!important}.pb-0{padding-bottom:0!important}.pl-0{padding-left:0!important}.px-0{padding-right:0!important;padding-left:0!important}.py-0{padding-top:0!important;padding-bottom:0!important}.p-1{padding:.25rem!important}.pt-1{padding-top:.25rem!important}.pr-1{padding-right:.25rem!important}.pb-1{padding-bottom:.25rem!important}.pl-1{padding-left:.25rem!important}.px-1{padding-right:.25rem!important;padding-left:.25rem!important}.py-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.p-2{padding:.5rem!important}.pt-2{padding-top:.5rem!important}.pr-2{padding-right:.5rem!important}.pb-2{padding-bottom:.5rem!important}.pl-2{padding-left:.5rem!important}.px-2{padding-right:.5rem!important;padding-left:.5rem!important}.py-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.p-3{padding:1rem!important}.pt-3{padding-top:1rem!important}.pr-3{padding-right:1rem!important}.pb-3{padding-bottom:1rem!important}.pl-3{padding-left:1rem!important}.px-3{padding-right:1rem!important;padding-left:1rem!important}.py-3{padding-top:1rem!important;padding-bottom:1rem!important}.p-4{padding:1.5rem!important}.pt-4{padding-top:1.5rem!important}.pr-4{padding-right:1.5rem!important}.pb-4{padding-bottom:1.5rem!important}.pl-4{padding-left:1.5rem!important}.px-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.py-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.p-5{padding:3rem!important}.pt-5{padding-top:3rem!important}.pr-5{padding-right:3rem!important}.pb-5{padding-bottom:3rem!important}.pl-5{padding-left:3rem!important}.px-5{padding-right:3rem!important;padding-left:3rem!important}.py-5{padding-top:3rem!important;padding-bottom:3rem!important}.m-auto{margin:auto!important}.mt-auto{margin-top:auto!important}.mr-auto{margin-right:auto!important}.mb-auto{margin-bottom:auto!important}.ml-auto{margin-left:auto!important}.mx-auto{margin-right:auto!important;margin-left:auto!important}.my-auto{margin-top:auto!important;margin-bottom:auto!important}@media (min-width:576px){.m-sm-0{margin:0!important}.mt-sm-0{margin-top:0!important}.mr-sm-0{margin-right:0!important}.mb-sm-0{margin-bottom:0!important}.ml-sm-0{margin-left:0!important}.mx-sm-0{margin-right:0!important;margin-left:0!important}.my-sm-0{margin-top:0!important;margin-bottom:0!important}.m-sm-1{margin:.25rem!important}.mt-sm-1{margin-top:.25rem!important}.mr-sm-1{margin-right:.25rem!important}.mb-sm-1{margin-bottom:.25rem!important}.ml-sm-1{margin-left:.25rem!important}.mx-sm-1{margin-right:.25rem!important;margin-left:.25rem!important}.my-sm-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.m-sm-2{margin:.5rem!important}.mt-sm-2{margin-top:.5rem!important}.mr-sm-2{margin-right:.5rem!important}.mb-sm-2{margin-bottom:.5rem!important}.ml-sm-2{margin-left:.5rem!important}.mx-sm-2{margin-right:.5rem!important;margin-left:.5rem!important}.my-sm-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.m-sm-3{margin:1rem!important}.mt-sm-3{margin-top:1rem!important}.mr-sm-3{margin-right:1rem!important}.mb-sm-3{margin-bottom:1rem!important}.ml-sm-3{margin-left:1rem!important}.mx-sm-3{margin-right:1rem!important;margin-left:1rem!important}.my-sm-3{margin-top:1rem!important;margin-bottom:1rem!important}.m-sm-4{margin:1.5rem!important}.mt-sm-4{margin-top:1.5rem!important}.mr-sm-4{margin-right:1.5rem!important}.mb-sm-4{margin-bottom:1.5rem!important}.ml-sm-4{margin-left:1.5rem!important}.mx-sm-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.my-sm-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.m-sm-5{margin:3rem!important}.mt-sm-5{margin-top:3rem!important}.mr-sm-5{margin-right:3rem!important}.mb-sm-5{margin-bottom:3rem!important}.ml-sm-5{margin-left:3rem!important}.mx-sm-5{margin-right:3rem!important;margin-left:3rem!important}.my-sm-5{margin-top:3rem!important;margin-bottom:3rem!important}.p-sm-0{padding:0!important}.pt-sm-0{padding-top:0!important}.pr-sm-0{padding-right:0!important}.pb-sm-0{padding-bottom:0!important}.pl-sm-0{padding-left:0!important}.px-sm-0{padding-right:0!important;padding-left:0!important}.py-sm-0{padding-top:0!important;padding-bottom:0!important}.p-sm-1{padding:.25rem!important}.pt-sm-1{padding-top:.25rem!important}.pr-sm-1{padding-right:.25rem!important}.pb-sm-1{padding-bottom:.25rem!important}.pl-sm-1{padding-left:.25rem!important}.px-sm-1{padding-right:.25rem!important;padding-left:.25rem!important}.py-sm-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.p-sm-2{padding:.5rem!important}.pt-sm-2{padding-top:.5rem!important}.pr-sm-2{padding-right:.5rem!important}.pb-sm-2{padding-bottom:.5rem!important}.pl-sm-2{padding-left:.5rem!important}.px-sm-2{padding-right:.5rem!important;padding-left:.5rem!important}.py-sm-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.p-sm-3{padding:1rem!important}.pt-sm-3{padding-top:1rem!important}.pr-sm-3{padding-right:1rem!important}.pb-sm-3{padding-bottom:1rem!important}.pl-sm-3{padding-left:1rem!important}.px-sm-3{padding-right:1rem!important;padding-left:1rem!important}.py-sm-3{padding-top:1rem!important;padding-bottom:1rem!important}.p-sm-4{padding:1.5rem!important}.pt-sm-4{padding-top:1.5rem!important}.pr-sm-4{padding-right:1.5rem!important}.pb-sm-4{padding-bottom:1.5rem!important}.pl-sm-4{padding-left:1.5rem!important}.px-sm-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.py-sm-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.p-sm-5{padding:3rem!important}.pt-sm-5{padding-top:3rem!important}.pr-sm-5{padding-right:3rem!important}.pb-sm-5{padding-bottom:3rem!important}.pl-sm-5{padding-left:3rem!important}.px-sm-5{padding-right:3rem!important;padding-left:3rem!important}.py-sm-5{padding-top:3rem!important;padding-bottom:3rem!important}.m-sm-auto{margin:auto!important}.mt-sm-auto{margin-top:auto!important}.mr-sm-auto{margin-right:auto!important}.mb-sm-auto{margin-bottom:auto!important}.ml-sm-auto{margin-left:auto!important}.mx-sm-auto{margin-right:auto!important;margin-left:auto!important}.my-sm-auto{margin-top:auto!important;margin-bottom:auto!important}}@media (min-width:768px){.m-md-0{margin:0!important}.mt-md-0{margin-top:0!important}.mr-md-0{margin-right:0!important}.mb-md-0{margin-bottom:0!important}.ml-md-0{margin-left:0!important}.mx-md-0{margin-right:0!important;margin-left:0!important}.my-md-0{margin-top:0!important;margin-bottom:0!important}.m-md-1{margin:.25rem!important}.mt-md-1{margin-top:.25rem!important}.mr-md-1{margin-right:.25rem!important}.mb-md-1{margin-bottom:.25rem!important}.ml-md-1{margin-left:.25rem!important}.mx-md-1{margin-right:.25rem!important;margin-left:.25rem!important}.my-md-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.m-md-2{margin:.5rem!important}.mt-md-2{margin-top:.5rem!important}.mr-md-2{margin-right:.5rem!important}.mb-md-2{margin-bottom:.5rem!important}.ml-md-2{margin-left:.5rem!important}.mx-md-2{margin-right:.5rem!important;margin-left:.5rem!important}.my-md-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.m-md-3{margin:1rem!important}.mt-md-3{margin-top:1rem!important}.mr-md-3{margin-right:1rem!important}.mb-md-3{margin-bottom:1rem!important}.ml-md-3{margin-left:1rem!important}.mx-md-3{margin-right:1rem!important;margin-left:1rem!important}.my-md-3{margin-top:1rem!important;margin-bottom:1rem!important}.m-md-4{margin:1.5rem!important}.mt-md-4{margin-top:1.5rem!important}.mr-md-4{margin-right:1.5rem!important}.mb-md-4{margin-bottom:1.5rem!important}.ml-md-4{margin-left:1.5rem!important}.mx-md-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.my-md-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.m-md-5{margin:3rem!important}.mt-md-5{margin-top:3rem!important}.mr-md-5{margin-right:3rem!important}.mb-md-5{margin-bottom:3rem!important}.ml-md-5{margin-left:3rem!important}.mx-md-5{margin-right:3rem!important;margin-left:3rem!important}.my-md-5{margin-top:3rem!important;margin-bottom:3rem!important}.p-md-0{padding:0!important}.pt-md-0{padding-top:0!important}.pr-md-0{padding-right:0!important}.pb-md-0{padding-bottom:0!important}.pl-md-0{padding-left:0!important}.px-md-0{padding-right:0!important;padding-left:0!important}.py-md-0{padding-top:0!important;padding-bottom:0!important}.p-md-1{padding:.25rem!important}.pt-md-1{padding-top:.25rem!important}.pr-md-1{padding-right:.25rem!important}.pb-md-1{padding-bottom:.25rem!important}.pl-md-1{padding-left:.25rem!important}.px-md-1{padding-right:.25rem!important;padding-left:.25rem!important}.py-md-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.p-md-2{padding:.5rem!important}.pt-md-2{padding-top:.5rem!important}.pr-md-2{padding-right:.5rem!important}.pb-md-2{padding-bottom:.5rem!important}.pl-md-2{padding-left:.5rem!important}.px-md-2{padding-right:.5rem!important;padding-left:.5rem!important}.py-md-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.p-md-3{padding:1rem!important}.pt-md-3{padding-top:1rem!important}.pr-md-3{padding-right:1rem!important}.pb-md-3{padding-bottom:1rem!important}.pl-md-3{padding-left:1rem!important}.px-md-3{padding-right:1rem!important;padding-left:1rem!important}.py-md-3{padding-top:1rem!important;padding-bottom:1rem!important}.p-md-4{padding:1.5rem!important}.pt-md-4{padding-top:1.5rem!important}.pr-md-4{padding-right:1.5rem!important}.pb-md-4{padding-bottom:1.5rem!important}.pl-md-4{padding-left:1.5rem!important}.px-md-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.py-md-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.p-md-5{padding:3rem!important}.pt-md-5{padding-top:3rem!important}.pr-md-5{padding-right:3rem!important}.pb-md-5{padding-bottom:3rem!important}.pl-md-5{padding-left:3rem!important}.px-md-5{padding-right:3rem!important;padding-left:3rem!important}.py-md-5{padding-top:3rem!important;padding-bottom:3rem!important}.m-md-auto{margin:auto!important}.mt-md-auto{margin-top:auto!important}.mr-md-auto{margin-right:auto!important}.mb-md-auto{margin-bottom:auto!important}.ml-md-auto{margin-left:auto!important}.mx-md-auto{margin-right:auto!important;margin-left:auto!important}.my-md-auto{margin-top:auto!important;margin-bottom:auto!important}}@media (min-width:992px){.m-lg-0{margin:0!important}.mt-lg-0{margin-top:0!important}.mr-lg-0{margin-right:0!important}.mb-lg-0{margin-bottom:0!important}.ml-lg-0{margin-left:0!important}.mx-lg-0{margin-right:0!important;margin-left:0!important}.my-lg-0{margin-top:0!important;margin-bottom:0!important}.m-lg-1{margin:.25rem!important}.mt-lg-1{margin-top:.25rem!important}.mr-lg-1{margin-right:.25rem!important}.mb-lg-1{margin-bottom:.25rem!important}.ml-lg-1{margin-left:.25rem!important}.mx-lg-1{margin-right:.25rem!important;margin-left:.25rem!important}.my-lg-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.m-lg-2{margin:.5rem!important}.mt-lg-2{margin-top:.5rem!important}.mr-lg-2{margin-right:.5rem!important}.mb-lg-2{margin-bottom:.5rem!important}.ml-lg-2{margin-left:.5rem!important}.mx-lg-2{margin-right:.5rem!important;margin-left:.5rem!important}.my-lg-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.m-lg-3{margin:1rem!important}.mt-lg-3{margin-top:1rem!important}.mr-lg-3{margin-right:1rem!important}.mb-lg-3{margin-bottom:1rem!important}.ml-lg-3{margin-left:1rem!important}.mx-lg-3{margin-right:1rem!important;margin-left:1rem!important}.my-lg-3{margin-top:1rem!important;margin-bottom:1rem!important}.m-lg-4{margin:1.5rem!important}.mt-lg-4{margin-top:1.5rem!important}.mr-lg-4{margin-right:1.5rem!important}.mb-lg-4{margin-bottom:1.5rem!important}.ml-lg-4{margin-left:1.5rem!important}.mx-lg-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.my-lg-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.m-lg-5{margin:3rem!important}.mt-lg-5{margin-top:3rem!important}.mr-lg-5{margin-right:3rem!important}.mb-lg-5{margin-bottom:3rem!important}.ml-lg-5{margin-left:3rem!important}.mx-lg-5{margin-right:3rem!important;margin-left:3rem!important}.my-lg-5{margin-top:3rem!important;margin-bottom:3rem!important}.p-lg-0{padding:0!important}.pt-lg-0{padding-top:0!important}.pr-lg-0{padding-right:0!important}.pb-lg-0{padding-bottom:0!important}.pl-lg-0{padding-left:0!important}.px-lg-0{padding-right:0!important;padding-left:0!important}.py-lg-0{padding-top:0!important;padding-bottom:0!important}.p-lg-1{padding:.25rem!important}.pt-lg-1{padding-top:.25rem!important}.pr-lg-1{padding-right:.25rem!important}.pb-lg-1{padding-bottom:.25rem!important}.pl-lg-1{padding-left:.25rem!important}.px-lg-1{padding-right:.25rem!important;padding-left:.25rem!important}.py-lg-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.p-lg-2{padding:.5rem!important}.pt-lg-2{padding-top:.5rem!important}.pr-lg-2{padding-right:.5rem!important}.pb-lg-2{padding-bottom:.5rem!important}.pl-lg-2{padding-left:.5rem!important}.px-lg-2{padding-right:.5rem!important;padding-left:.5rem!important}.py-lg-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.p-lg-3{padding:1rem!important}.pt-lg-3{padding-top:1rem!important}.pr-lg-3{padding-right:1rem!important}.pb-lg-3{padding-bottom:1rem!important}.pl-lg-3{padding-left:1rem!important}.px-lg-3{padding-right:1rem!important;padding-left:1rem!important}.py-lg-3{padding-top:1rem!important;padding-bottom:1rem!important}.p-lg-4{padding:1.5rem!important}.pt-lg-4{padding-top:1.5rem!important}.pr-lg-4{padding-right:1.5rem!important}.pb-lg-4{padding-bottom:1.5rem!important}.pl-lg-4{padding-left:1.5rem!important}.px-lg-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.py-lg-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.p-lg-5{padding:3rem!important}.pt-lg-5{padding-top:3rem!important}.pr-lg-5{padding-right:3rem!important}.pb-lg-5{padding-bottom:3rem!important}.pl-lg-5{padding-left:3rem!important}.px-lg-5{padding-right:3rem!important;padding-left:3rem!important}.py-lg-5{padding-top:3rem!important;padding-bottom:3rem!important}.m-lg-auto{margin:auto!important}.mt-lg-auto{margin-top:auto!important}.mr-lg-auto{margin-right:auto!important}.mb-lg-auto{margin-bottom:auto!important}.ml-lg-auto{margin-left:auto!important}.mx-lg-auto{margin-right:auto!important;margin-left:auto!important}.my-lg-auto{margin-top:auto!important;margin-bottom:auto!important}}@media (min-width:1200px){.m-xl-0{margin:0!important}.mt-xl-0{margin-top:0!important}.mr-xl-0{margin-right:0!important}.mb-xl-0{margin-bottom:0!important}.ml-xl-0{margin-left:0!important}.mx-xl-0{margin-right:0!important;margin-left:0!important}.my-xl-0{margin-top:0!important;margin-bottom:0!important}.m-xl-1{margin:.25rem!important}.mt-xl-1{margin-top:.25rem!important}.mr-xl-1{margin-right:.25rem!important}.mb-xl-1{margin-bottom:.25rem!important}.ml-xl-1{margin-left:.25rem!important}.mx-xl-1{margin-right:.25rem!important;margin-left:.25rem!important}.my-xl-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.m-xl-2{margin:.5rem!important}.mt-xl-2{margin-top:.5rem!important}.mr-xl-2{margin-right:.5rem!important}.mb-xl-2{margin-bottom:.5rem!important}.ml-xl-2{margin-left:.5rem!important}.mx-xl-2{margin-right:.5rem!important;margin-left:.5rem!important}.my-xl-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.m-xl-3{margin:1rem!important}.mt-xl-3{margin-top:1rem!important}.mr-xl-3{margin-right:1rem!important}.mb-xl-3{margin-bottom:1rem!important}.ml-xl-3{margin-left:1rem!important}.mx-xl-3{margin-right:1rem!important;margin-left:1rem!important}.my-xl-3{margin-top:1rem!important;margin-bottom:1rem!important}.m-xl-4{margin:1.5rem!important}.mt-xl-4{margin-top:1.5rem!important}.mr-xl-4{margin-right:1.5rem!important}.mb-xl-4{margin-bottom:1.5rem!important}.ml-xl-4{margin-left:1.5rem!important}.mx-xl-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.my-xl-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.m-xl-5{margin:3rem!important}.mt-xl-5{margin-top:3rem!important}.mr-xl-5{margin-right:3rem!important}.mb-xl-5{margin-bottom:3rem!important}.ml-xl-5{margin-left:3rem!important}.mx-xl-5{margin-right:3rem!important;margin-left:3rem!important}.my-xl-5{margin-top:3rem!important;margin-bottom:3rem!important}.p-xl-0{padding:0!important}.pt-xl-0{padding-top:0!important}.pr-xl-0{padding-right:0!important}.pb-xl-0{padding-bottom:0!important}.pl-xl-0{padding-left:0!important}.px-xl-0{padding-right:0!important;padding-left:0!important}.py-xl-0{padding-top:0!important;padding-bottom:0!important}.p-xl-1{padding:.25rem!important}.pt-xl-1{padding-top:.25rem!important}.pr-xl-1{padding-right:.25rem!important}.pb-xl-1{padding-bottom:.25rem!important}.pl-xl-1{padding-left:.25rem!important}.px-xl-1{padding-right:.25rem!important;padding-left:.25rem!important}.py-xl-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.p-xl-2{padding:.5rem!important}.pt-xl-2{padding-top:.5rem!important}.pr-xl-2{padding-right:.5rem!important}.pb-xl-2{padding-bottom:.5rem!important}.pl-xl-2{padding-left:.5rem!important}.px-xl-2{padding-right:.5rem!important;padding-left:.5rem!important}.py-xl-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.p-xl-3{padding:1rem!important}.pt-xl-3{padding-top:1rem!important}.pr-xl-3{padding-right:1rem!important}.pb-xl-3{padding-bottom:1rem!important}.pl-xl-3{padding-left:1rem!important}.px-xl-3{padding-right:1rem!important;padding-left:1rem!important}.py-xl-3{padding-top:1rem!important;padding-bottom:1rem!important}.p-xl-4{padding:1.5rem!important}.pt-xl-4{padding-top:1.5rem!important}.pr-xl-4{padding-right:1.5rem!important}.pb-xl-4{padding-bottom:1.5rem!important}.pl-xl-4{padding-left:1.5rem!important}.px-xl-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.py-xl-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.p-xl-5{padding:3rem!important}.pt-xl-5{padding-top:3rem!important}.pr-xl-5{padding-right:3rem!important}.pb-xl-5{padding-bottom:3rem!important}.pl-xl-5{padding-left:3rem!important}.px-xl-5{padding-right:3rem!important;padding-left:3rem!important}.py-xl-5{padding-top:3rem!important;padding-bottom:3rem!important}.m-xl-auto{margin:auto!important}.mt-xl-auto{margin-top:auto!important}.mr-xl-auto{margin-right:auto!important}.mb-xl-auto{margin-bottom:auto!important}.ml-xl-auto{margin-left:auto!important}.mx-xl-auto{margin-right:auto!important;margin-left:auto!important}.my-xl-auto{margin-top:auto!important;margin-bottom:auto!important}}.text-justify{text-align:justify!important}.text-nowrap{white-space:nowrap!important}.text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.text-left{text-align:left!important}.text-right{text-align:right!important}.text-center{text-align:center!important}@media (min-width:576px){.text-sm-left{text-align:left!important}.text-sm-right{text-align:right!important}.text-sm-center{text-align:center!important}}@media (min-width:768px){.text-md-left{text-align:left!important}.text-md-right{text-align:right!important}.text-md-center{text-align:center!important}}@media (min-width:992px){.text-lg-left{text-align:left!important}.text-lg-right{text-align:right!important}.text-lg-center{text-align:center!important}}@media (min-width:1200px){.text-xl-left{text-align:left!important}.text-xl-right{text-align:right!important}.text-xl-center{text-align:center!important}}.text-lowercase{text-transform:lowercase!important}.text-uppercase{text-transform:uppercase!important}.text-capitalize{text-transform:capitalize!important}.font-weight-normal{font-weight:400}.font-weight-bold{font-weight:700}.font-italic{font-style:italic}.text-white{color:#fff!important}.text-primary{color:#007bff!important}a.text-primary:focus,a.text-primary:hover{color:#0062cc!important}.text-secondary{color:#868e96!important}a.text-secondary:focus,a.text-secondary:hover{color:#6c757d!important}.text-success{color:#28a745!important}a.text-success:focus,a.text-success:hover{color:#1e7e34!important}.text-info{color:#17a2b8!important}a.text-info:focus,a.text-info:hover{color:#117a8b!important}.text-warning{color:#ffc107!important}a.text-warning:focus,a.text-warning:hover{color:#d39e00!important}.text-danger{color:#dc3545!important}a.text-danger:focus,a.text-danger:hover{color:#bd2130!important}.text-light{color:#f8f9fa!important}a.text-light:focus,a.text-light:hover{color:#dae0e5!important}.text-dark{color:#343a40!important}a.text-dark:focus,a.text-dark:hover{color:#1d2124!important}.text-muted{color:#868e96!important}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.visible{visibility:visible!important}.invisible{visibility:hidden!important} -/*# sourceMappingURL=bootstrap.min.css.map */ diff --git a/web/templates/boilerplate/assets/css/now-ui-dashboard.css b/web/templates/boilerplate/assets/css/now-ui-dashboard.css deleted file mode 100644 index 7faac47..0000000 --- a/web/templates/boilerplate/assets/css/now-ui-dashboard.css +++ /dev/null @@ -1,3570 +0,0 @@ -/*! - - ========================================================= - * Now UI Dashboard - v1.0.1 - ========================================================= - - * Product Page: http://www.creative-tim.com/product/now-ui-dashboard - * Copyright 2017 Creative Tim (http://www.creative-tim.com) - * Licensed under MIT (https://github.com/creativetimofficial/now-ui-dashboard/blob/master/LICENSE.md) - - - * Designed by www.invisionapp.com Coded by www.creative-tim.com - - ========================================================= - - * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - - */ -/* brand Colors */ -/* light colors */ -/*! -Animate.css - http://daneden.me/animate -Licensed under the MIT license - http://opensource.org/licenses/MIT - -Copyright (c) 2015 Daniel Eden -*/ -.animated { - -webkit-animation-duration: 1s; - animation-duration: 1s; - -webkit-animation-fill-mode: both; - animation-fill-mode: both; } - -.animated.infinite { - -webkit-animation-iteration-count: infinite; - animation-iteration-count: infinite; } - -.animated.hinge { - -webkit-animation-duration: 2s; - animation-duration: 2s; } - -.animated.bounceIn, -.animated.bounceOut { - -webkit-animation-duration: .75s; - animation-duration: .75s; } - -.animated.flipOutX, -.animated.flipOutY { - -webkit-animation-duration: .75s; - animation-duration: .75s; } - -@-webkit-keyframes shake { - from, to { - -webkit-transform: translate3d(0, 0, 0); - transform: translate3d(0, 0, 0); } - 10%, 30%, 50%, 70%, 90% { - -webkit-transform: translate3d(-10px, 0, 0); - transform: translate3d(-10px, 0, 0); } - 20%, 40%, 60%, 80% { - -webkit-transform: translate3d(10px, 0, 0); - transform: translate3d(10px, 0, 0); } } - -@keyframes shake { - from, to { - -webkit-transform: translate3d(0, 0, 0); - transform: translate3d(0, 0, 0); } - 10%, 30%, 50%, 70%, 90% { - -webkit-transform: translate3d(-10px, 0, 0); - transform: translate3d(-10px, 0, 0); } - 20%, 40%, 60%, 80% { - -webkit-transform: translate3d(10px, 0, 0); - transform: translate3d(10px, 0, 0); } } - -.shake { - -webkit-animation-name: shake; - animation-name: shake; } - -@-webkit-keyframes fadeInDown { - from { - opacity: 0; - -webkit-transform: translate3d(0, -100%, 0); - transform: translate3d(0, -100%, 0); } - to { - opacity: 1; - -webkit-transform: none; - transform: none; } } - -@keyframes fadeInDown { - from { - opacity: 0; - -webkit-transform: translate3d(0, -100%, 0); - transform: translate3d(0, -100%, 0); } - to { - opacity: 1; - -webkit-transform: none; - transform: none; } } - -.fadeInDown { - -webkit-animation-name: fadeInDown; - animation-name: fadeInDown; } - -@-webkit-keyframes fadeOut { - from { - opacity: 1; } - to { - opacity: 0; } } - -@keyframes fadeOut { - from { - opacity: 1; } - to { - opacity: 0; } } - -.fadeOut { - -webkit-animation-name: fadeOut; - animation-name: fadeOut; } - -@-webkit-keyframes fadeOutDown { - from { - opacity: 1; } - to { - opacity: 0; - -webkit-transform: translate3d(0, 100%, 0); - transform: translate3d(0, 100%, 0); } } - -@keyframes fadeOutDown { - from { - opacity: 1; } - to { - opacity: 0; - -webkit-transform: translate3d(0, 100%, 0); - transform: translate3d(0, 100%, 0); } } - -.fadeOutDown { - -webkit-animation-name: fadeOutDown; - animation-name: fadeOutDown; } - -@-webkit-keyframes fadeOutUp { - from { - opacity: 1; } - to { - opacity: 0; - -webkit-transform: translate3d(0, -100%, 0); - transform: translate3d(0, -100%, 0); } } - -@keyframes fadeOutUp { - from { - opacity: 1; } - to { - opacity: 0; - -webkit-transform: translate3d(0, -100%, 0); - transform: translate3d(0, -100%, 0); } } - -.fadeOutUp { - -webkit-animation-name: fadeOutUp; - animation-name: fadeOutUp; } - -/* perfect-scrollbar v0.6.13 */ -.ps-container { - -ms-touch-action: auto; - touch-action: auto; - overflow: hidden !important; - -ms-overflow-style: none; } - -@supports (-ms-overflow-style: none) { - .ps-container { - overflow: auto !important; } } - -@media screen and (-ms-high-contrast: active), (-ms-high-contrast: none) { - .ps-container { - overflow: auto !important; } } - -.ps-container.ps-active-x > .ps-scrollbar-x-rail, -.ps-container.ps-active-y > .ps-scrollbar-y-rail { - display: block; - background-color: transparent; } - -.ps-container.ps-in-scrolling.ps-x > .ps-scrollbar-x-rail { - background-color: #eee; - opacity: 0.9; } - -.ps-container.ps-in-scrolling.ps-x > .ps-scrollbar-x-rail > .ps-scrollbar-x { - background-color: #999; - height: 11px; } - -.ps-container.ps-in-scrolling.ps-y > .ps-scrollbar-y-rail { - background-color: #eee; - opacity: 0.9; } - -.ps-container.ps-in-scrolling.ps-y > .ps-scrollbar-y-rail > .ps-scrollbar-y { - background-color: #999; - width: 11px; } - -.ps-container > .ps-scrollbar-x-rail { - display: none; - position: absolute; - /* please don't change 'position' */ - opacity: 0; - -webkit-transition: background-color .2s linear, opacity .2s linear; - transition: background-color .2s linear, opacity .2s linear; - bottom: 0px; - /* there must be 'bottom' for ps-scrollbar-x-rail */ - height: 15px; } - -.ps-container > .ps-scrollbar-x-rail > .ps-scrollbar-x { - position: absolute; - /* please don't change 'position' */ - background-color: #aaa; - border-radius: 6px; - -webkit-transition: background-color .2s linear, height .2s linear, width .2s ease-in-out, -webkit-border-radius .2s ease-in-out; - -webkit-transition: background-color .2s linear, height .2s linear, width .2s ease-in-out, border-radius .2s ease-in-out; - transition: background-color .2s linear, height .2s linear, width .2s ease-in-out, border-radius .2s ease-in-out; - bottom: 2px; - /* there must be 'bottom' for ps-scrollbar-x */ - height: 6px; } - -.ps-container > .ps-scrollbar-x-rail:hover > .ps-scrollbar-x, .ps-container > .ps-scrollbar-x-rail:active > .ps-scrollbar-x { - height: 11px; } - -.ps-container > .ps-scrollbar-y-rail { - display: none; - position: absolute; - /* please don't change 'position' */ - opacity: 0; - -webkit-transition: background-color .2s linear, opacity .2s linear; - transition: background-color .2s linear, opacity .2s linear; - right: 0; - /* there must be 'right' for ps-scrollbar-y-rail */ - width: 15px; } - -.ps-container > .ps-scrollbar-y-rail > .ps-scrollbar-y { - position: absolute; - /* please don't change 'position' */ - background-color: #aaa; - border-radius: 6px; - -webkit-transition: background-color .2s linear, height .2s linear, width .2s ease-in-out, -webkit-border-radius .2s ease-in-out; - -webkit-transition: background-color .2s linear, height .2s linear, width .2s ease-in-out, border-radius .2s ease-in-out; - transition: background-color .2s linear, height .2s linear, width .2s ease-in-out, border-radius .2s ease-in-out; - right: 2px; - /* there must be 'right' for ps-scrollbar-y */ - width: 6px; } - -.ps-container > .ps-scrollbar-y-rail:hover > .ps-scrollbar-y, .ps-container > .ps-scrollbar-y-rail:active > .ps-scrollbar-y { - width: 11px; } - -.ps-container:hover.ps-in-scrolling.ps-x > .ps-scrollbar-x-rail { - background-color: #eee; - opacity: 0.9; } - -.ps-container:hover.ps-in-scrolling.ps-x > .ps-scrollbar-x-rail > .ps-scrollbar-x { - background-color: #999; - height: 11px; } - -.ps-container:hover.ps-in-scrolling.ps-y > .ps-scrollbar-y-rail { - background-color: #eee; - opacity: 0.9; } - -.ps-container:hover.ps-in-scrolling.ps-y > .ps-scrollbar-y-rail > .ps-scrollbar-y { - background-color: #999; - width: 11px; } - -.ps-container:hover > .ps-scrollbar-x-rail, -.ps-container:hover > .ps-scrollbar-y-rail { - opacity: 0.6; } - -.ps-container:hover > .ps-scrollbar-x-rail:hover { - background-color: #eee; - opacity: 0.9; } - -.ps-container:hover > .ps-scrollbar-x-rail:hover > .ps-scrollbar-x { - background-color: #999; } - -.ps-container:hover > .ps-scrollbar-y-rail:hover { - background-color: #eee; - opacity: 0.9; } - -.ps-container:hover > .ps-scrollbar-y-rail:hover > .ps-scrollbar-y { - background-color: #999; } - -.btn, -.navbar .navbar-nav > a.btn { - border-width: 2px; - font-weight: 400; - font-size: 0.8571em; - line-height: 1.35em; - margin: 5px 1px; - border: none; - margin: 10px 1px; - border-radius: 0.1875rem; - padding: 11px 22px; - cursor: pointer; - background-color: #888; - color: #FFFFFF; } - .btn:hover, .btn:focus, .btn:active, .btn.active, .btn:active:focus, .btn:active:hover, .btn.active:focus, .btn.active:hover, - .show > .btn.dropdown-toggle, - .show > .btn.dropdown-toggle:focus, - .show > .btn.dropdown-toggle:hover, - .navbar .navbar-nav > a.btn:hover, - .navbar .navbar-nav > a.btn:focus, - .navbar .navbar-nav > a.btn:active, - .navbar .navbar-nav > a.btn.active, - .navbar .navbar-nav > a.btn:active:focus, - .navbar .navbar-nav > a.btn:active:hover, - .navbar .navbar-nav > a.btn.active:focus, - .navbar .navbar-nav > a.btn.active:hover, - .show > - .navbar .navbar-nav > a.btn.dropdown-toggle, - .show > - .navbar .navbar-nav > a.btn.dropdown-toggle:focus, - .show > - .navbar .navbar-nav > a.btn.dropdown-toggle:hover { - background-color: #979797; - color: #FFFFFF; - -webkit-box-shadow: none; - box-shadow: none; } - .btn:not([data-action]):hover, - .navbar .navbar-nav > a.btn:not([data-action]):hover { - -webkit-box-shadow: 0 3px 8px 0 rgba(0, 0, 0, 0.17); - box-shadow: 0 3px 8px 0 rgba(0, 0, 0, 0.17); } - .btn.disabled, .btn.disabled:hover, .btn.disabled:focus, .btn.disabled.focus, .btn.disabled:active, .btn.disabled.active, .btn:disabled, .btn:disabled:hover, .btn:disabled:focus, .btn:disabled.focus, .btn:disabled:active, .btn:disabled.active, .btn[disabled], .btn[disabled]:hover, .btn[disabled]:focus, .btn[disabled].focus, .btn[disabled]:active, .btn[disabled].active, - fieldset[disabled] .btn, - fieldset[disabled] .btn:hover, - fieldset[disabled] .btn:focus, - fieldset[disabled] .btn.focus, - fieldset[disabled] .btn:active, - fieldset[disabled] .btn.active, - .navbar .navbar-nav > a.btn.disabled, - .navbar .navbar-nav > a.btn.disabled:hover, - .navbar .navbar-nav > a.btn.disabled:focus, - .navbar .navbar-nav > a.btn.disabled.focus, - .navbar .navbar-nav > a.btn.disabled:active, - .navbar .navbar-nav > a.btn.disabled.active, - .navbar .navbar-nav > a.btn:disabled, - .navbar .navbar-nav > a.btn:disabled:hover, - .navbar .navbar-nav > a.btn:disabled:focus, - .navbar .navbar-nav > a.btn:disabled.focus, - .navbar .navbar-nav > a.btn:disabled:active, - .navbar .navbar-nav > a.btn:disabled.active, - .navbar .navbar-nav > a.btn[disabled], - .navbar .navbar-nav > a.btn[disabled]:hover, - .navbar .navbar-nav > a.btn[disabled]:focus, - .navbar .navbar-nav > a.btn[disabled].focus, - .navbar .navbar-nav > a.btn[disabled]:active, - .navbar .navbar-nav > a.btn[disabled].active, - fieldset[disabled] - .navbar .navbar-nav > a.btn, - fieldset[disabled] - .navbar .navbar-nav > a.btn:hover, - fieldset[disabled] - .navbar .navbar-nav > a.btn:focus, - fieldset[disabled] - .navbar .navbar-nav > a.btn.focus, - fieldset[disabled] - .navbar .navbar-nav > a.btn:active, - fieldset[disabled] - .navbar .navbar-nav > a.btn.active { - background-color: #888; - border-color: #888; } - .btn.btn-simple, - .navbar .navbar-nav > a.btn.btn-simple { - color: #888; - border-color: #888; } - .btn.btn-simple:hover, .btn.btn-simple:focus, .btn.btn-simple:active, - .navbar .navbar-nav > a.btn.btn-simple:hover, - .navbar .navbar-nav > a.btn.btn-simple:focus, - .navbar .navbar-nav > a.btn.btn-simple:active { - background-color: transparent; - color: #979797; - border-color: #979797; - -webkit-box-shadow: none; - box-shadow: none; } - .btn.btn-link, - .navbar .navbar-nav > a.btn.btn-link { - color: #888; } - .btn.btn-link:hover, .btn.btn-link:focus, .btn.btn-link:active, - .navbar .navbar-nav > a.btn.btn-link:hover, - .navbar .navbar-nav > a.btn.btn-link:focus, - .navbar .navbar-nav > a.btn.btn-link:active { - background-color: transparent; - color: #979797; - text-decoration: none; - -webkit-box-shadow: none; - box-shadow: none; } - .btn:hover, .btn:focus, - .navbar .navbar-nav > a.btn:hover, - .navbar .navbar-nav > a.btn:focus { - opacity: 1; - filter: alpha(opacity=100); - outline: 0 !important; } - .btn:active, .btn.active, - .open > .btn.dropdown-toggle, - .navbar .navbar-nav > a.btn:active, - .navbar .navbar-nav > a.btn.active, - .open > - .navbar .navbar-nav > a.btn.dropdown-toggle { - -webkit-box-shadow: none; - box-shadow: none; - outline: 0 !important; } - .btn .badge, - .navbar .navbar-nav > a.btn .badge { - margin: 0; } - .btn.btn-icon, - .navbar .navbar-nav > a.btn.btn-icon { - height: 2.375rem; - min-width: 2.375rem; - width: 2.375rem; - padding: 0; - font-size: 0.9375rem; - overflow: hidden; - position: relative; - line-height: normal; } - .btn.btn-icon.btn-simple, - .navbar .navbar-nav > a.btn.btn-icon.btn-simple { - padding: 0; } - .btn.btn-icon.btn-sm, - .navbar .navbar-nav > a.btn.btn-icon.btn-sm { - height: 1.875rem; - min-width: 1.875rem; - width: 1.875rem; } - .btn.btn-icon.btn-sm i.fa, - .btn.btn-icon.btn-sm i.now-ui-icons, - .navbar .navbar-nav > a.btn.btn-icon.btn-sm i.fa, - .navbar .navbar-nav > a.btn.btn-icon.btn-sm i.now-ui-icons { - font-size: 0.6875rem; } - .btn.btn-icon.btn-lg, - .navbar .navbar-nav > a.btn.btn-icon.btn-lg { - height: 3.6rem; - min-width: 3.6rem; - width: 3.6rem; } - .btn.btn-icon.btn-lg i.now-ui-icons, - .btn.btn-icon.btn-lg i.fa, - .navbar .navbar-nav > a.btn.btn-icon.btn-lg i.now-ui-icons, - .navbar .navbar-nav > a.btn.btn-icon.btn-lg i.fa { - font-size: 1.325rem; } - .btn.btn-icon:not(.btn-footer) i.now-ui-icons, - .btn.btn-icon:not(.btn-footer) i.fa, - .navbar .navbar-nav > a.btn.btn-icon:not(.btn-footer) i.now-ui-icons, - .navbar .navbar-nav > a.btn.btn-icon:not(.btn-footer) i.fa { - position: absolute; - top: 50%; - left: 50%; - -webkit-transform: translate(-12px, -12px); - transform: translate(-12px, -12px); - line-height: 1.5626rem; - width: 24px; } - .btn:not(.btn-icon) .now-ui-icons, - .navbar .navbar-nav > a.btn:not(.btn-icon) .now-ui-icons { - position: relative; - top: 1px; } - -.btn-primary { - background-color: #f96332; - color: #FFFFFF; } - .btn-primary:hover, .btn-primary:focus, .btn-primary:active, .btn-primary.active, .btn-primary:active:focus, .btn-primary:active:hover, .btn-primary.active:focus, .btn-primary.active:hover, - .show > .btn-primary.dropdown-toggle, - .show > .btn-primary.dropdown-toggle:focus, - .show > .btn-primary.dropdown-toggle:hover { - background-color: #fa7a50; - color: #FFFFFF; - -webkit-box-shadow: none; - box-shadow: none; } - .btn-primary:not([data-action]):hover { - -webkit-box-shadow: 0 3px 8px 0 rgba(0, 0, 0, 0.17); - box-shadow: 0 3px 8px 0 rgba(0, 0, 0, 0.17); } - .btn-primary.disabled, .btn-primary.disabled:hover, .btn-primary.disabled:focus, .btn-primary.disabled.focus, .btn-primary.disabled:active, .btn-primary.disabled.active, .btn-primary:disabled, .btn-primary:disabled:hover, .btn-primary:disabled:focus, .btn-primary:disabled.focus, .btn-primary:disabled:active, .btn-primary:disabled.active, .btn-primary[disabled], .btn-primary[disabled]:hover, .btn-primary[disabled]:focus, .btn-primary[disabled].focus, .btn-primary[disabled]:active, .btn-primary[disabled].active, - fieldset[disabled] .btn-primary, - fieldset[disabled] .btn-primary:hover, - fieldset[disabled] .btn-primary:focus, - fieldset[disabled] .btn-primary.focus, - fieldset[disabled] .btn-primary:active, - fieldset[disabled] .btn-primary.active { - background-color: #f96332; - border-color: #f96332; } - .btn-primary.btn-simple { - color: #f96332; - border-color: #f96332; } - .btn-primary.btn-simple:hover, .btn-primary.btn-simple:focus, .btn-primary.btn-simple:active { - background-color: transparent; - color: #fa7a50; - border-color: #fa7a50; - -webkit-box-shadow: none; - box-shadow: none; } - .btn-primary.btn-link { - color: #f96332; } - .btn-primary.btn-link:hover, .btn-primary.btn-link:focus, .btn-primary.btn-link:active { - background-color: transparent; - color: #fa7a50; - text-decoration: none; - -webkit-box-shadow: none; - box-shadow: none; } - -.btn-success { - background-color: #18ce0f; - color: #FFFFFF; } - .btn-success:hover, .btn-success:focus, .btn-success:active, .btn-success.active, .btn-success:active:focus, .btn-success:active:hover, .btn-success.active:focus, .btn-success.active:hover, - .show > .btn-success.dropdown-toggle, - .show > .btn-success.dropdown-toggle:focus, - .show > .btn-success.dropdown-toggle:hover { - background-color: #1beb11; - color: #FFFFFF; - -webkit-box-shadow: none; - box-shadow: none; } - .btn-success:not([data-action]):hover { - -webkit-box-shadow: 0 3px 8px 0 rgba(0, 0, 0, 0.17); - box-shadow: 0 3px 8px 0 rgba(0, 0, 0, 0.17); } - .btn-success.disabled, .btn-success.disabled:hover, .btn-success.disabled:focus, .btn-success.disabled.focus, .btn-success.disabled:active, .btn-success.disabled.active, .btn-success:disabled, .btn-success:disabled:hover, .btn-success:disabled:focus, .btn-success:disabled.focus, .btn-success:disabled:active, .btn-success:disabled.active, .btn-success[disabled], .btn-success[disabled]:hover, .btn-success[disabled]:focus, .btn-success[disabled].focus, .btn-success[disabled]:active, .btn-success[disabled].active, - fieldset[disabled] .btn-success, - fieldset[disabled] .btn-success:hover, - fieldset[disabled] .btn-success:focus, - fieldset[disabled] .btn-success.focus, - fieldset[disabled] .btn-success:active, - fieldset[disabled] .btn-success.active { - background-color: #18ce0f; - border-color: #18ce0f; } - .btn-success.btn-simple { - color: #18ce0f; - border-color: #18ce0f; } - .btn-success.btn-simple:hover, .btn-success.btn-simple:focus, .btn-success.btn-simple:active { - background-color: transparent; - color: #1beb11; - border-color: #1beb11; - -webkit-box-shadow: none; - box-shadow: none; } - .btn-success.btn-link { - color: #18ce0f; } - .btn-success.btn-link:hover, .btn-success.btn-link:focus, .btn-success.btn-link:active { - background-color: transparent; - color: #1beb11; - text-decoration: none; - -webkit-box-shadow: none; - box-shadow: none; } - -.btn-info { - background-color: #2CA8FF; - color: #FFFFFF; } - .btn-info:hover, .btn-info:focus, .btn-info:active, .btn-info.active, .btn-info:active:focus, .btn-info:active:hover, .btn-info.active:focus, .btn-info.active:hover, - .show > .btn-info.dropdown-toggle, - .show > .btn-info.dropdown-toggle:focus, - .show > .btn-info.dropdown-toggle:hover { - background-color: #4bb5ff; - color: #FFFFFF; - -webkit-box-shadow: none; - box-shadow: none; } - .btn-info:not([data-action]):hover { - -webkit-box-shadow: 0 3px 8px 0 rgba(0, 0, 0, 0.17); - box-shadow: 0 3px 8px 0 rgba(0, 0, 0, 0.17); } - .btn-info.disabled, .btn-info.disabled:hover, .btn-info.disabled:focus, .btn-info.disabled.focus, .btn-info.disabled:active, .btn-info.disabled.active, .btn-info:disabled, .btn-info:disabled:hover, .btn-info:disabled:focus, .btn-info:disabled.focus, .btn-info:disabled:active, .btn-info:disabled.active, .btn-info[disabled], .btn-info[disabled]:hover, .btn-info[disabled]:focus, .btn-info[disabled].focus, .btn-info[disabled]:active, .btn-info[disabled].active, - fieldset[disabled] .btn-info, - fieldset[disabled] .btn-info:hover, - fieldset[disabled] .btn-info:focus, - fieldset[disabled] .btn-info.focus, - fieldset[disabled] .btn-info:active, - fieldset[disabled] .btn-info.active { - background-color: #2CA8FF; - border-color: #2CA8FF; } - .btn-info.btn-simple { - color: #2CA8FF; - border-color: #2CA8FF; } - .btn-info.btn-simple:hover, .btn-info.btn-simple:focus, .btn-info.btn-simple:active { - background-color: transparent; - color: #4bb5ff; - border-color: #4bb5ff; - -webkit-box-shadow: none; - box-shadow: none; } - .btn-info.btn-link { - color: #2CA8FF; } - .btn-info.btn-link:hover, .btn-info.btn-link:focus, .btn-info.btn-link:active { - background-color: transparent; - color: #4bb5ff; - text-decoration: none; - -webkit-box-shadow: none; - box-shadow: none; } - -.btn-warning { - background-color: #FFB236; - color: #FFFFFF; } - .btn-warning:hover, .btn-warning:focus, .btn-warning:active, .btn-warning.active, .btn-warning:active:focus, .btn-warning:active:hover, .btn-warning.active:focus, .btn-warning.active:hover, - .show > .btn-warning.dropdown-toggle, - .show > .btn-warning.dropdown-toggle:focus, - .show > .btn-warning.dropdown-toggle:hover { - background-color: #ffbe55; - color: #FFFFFF; - -webkit-box-shadow: none; - box-shadow: none; } - .btn-warning:not([data-action]):hover { - -webkit-box-shadow: 0 3px 8px 0 rgba(0, 0, 0, 0.17); - box-shadow: 0 3px 8px 0 rgba(0, 0, 0, 0.17); } - .btn-warning.disabled, .btn-warning.disabled:hover, .btn-warning.disabled:focus, .btn-warning.disabled.focus, .btn-warning.disabled:active, .btn-warning.disabled.active, .btn-warning:disabled, .btn-warning:disabled:hover, .btn-warning:disabled:focus, .btn-warning:disabled.focus, .btn-warning:disabled:active, .btn-warning:disabled.active, .btn-warning[disabled], .btn-warning[disabled]:hover, .btn-warning[disabled]:focus, .btn-warning[disabled].focus, .btn-warning[disabled]:active, .btn-warning[disabled].active, - fieldset[disabled] .btn-warning, - fieldset[disabled] .btn-warning:hover, - fieldset[disabled] .btn-warning:focus, - fieldset[disabled] .btn-warning.focus, - fieldset[disabled] .btn-warning:active, - fieldset[disabled] .btn-warning.active { - background-color: #FFB236; - border-color: #FFB236; } - .btn-warning.btn-simple { - color: #FFB236; - border-color: #FFB236; } - .btn-warning.btn-simple:hover, .btn-warning.btn-simple:focus, .btn-warning.btn-simple:active { - background-color: transparent; - color: #ffbe55; - border-color: #ffbe55; - -webkit-box-shadow: none; - box-shadow: none; } - .btn-warning.btn-link { - color: #FFB236; } - .btn-warning.btn-link:hover, .btn-warning.btn-link:focus, .btn-warning.btn-link:active { - background-color: transparent; - color: #ffbe55; - text-decoration: none; - -webkit-box-shadow: none; - box-shadow: none; } - -.btn-danger { - background-color: #FF3636; - color: #FFFFFF; } - .btn-danger:hover, .btn-danger:focus, .btn-danger:active, .btn-danger.active, .btn-danger:active:focus, .btn-danger:active:hover, .btn-danger.active:focus, .btn-danger.active:hover, - .show > .btn-danger.dropdown-toggle, - .show > .btn-danger.dropdown-toggle:focus, - .show > .btn-danger.dropdown-toggle:hover { - background-color: #ff5555; - color: #FFFFFF; - -webkit-box-shadow: none; - box-shadow: none; } - .btn-danger:not([data-action]):hover { - -webkit-box-shadow: 0 3px 8px 0 rgba(0, 0, 0, 0.17); - box-shadow: 0 3px 8px 0 rgba(0, 0, 0, 0.17); } - .btn-danger.disabled, .btn-danger.disabled:hover, .btn-danger.disabled:focus, .btn-danger.disabled.focus, .btn-danger.disabled:active, .btn-danger.disabled.active, .btn-danger:disabled, .btn-danger:disabled:hover, .btn-danger:disabled:focus, .btn-danger:disabled.focus, .btn-danger:disabled:active, .btn-danger:disabled.active, .btn-danger[disabled], .btn-danger[disabled]:hover, .btn-danger[disabled]:focus, .btn-danger[disabled].focus, .btn-danger[disabled]:active, .btn-danger[disabled].active, - fieldset[disabled] .btn-danger, - fieldset[disabled] .btn-danger:hover, - fieldset[disabled] .btn-danger:focus, - fieldset[disabled] .btn-danger.focus, - fieldset[disabled] .btn-danger:active, - fieldset[disabled] .btn-danger.active { - background-color: #FF3636; - border-color: #FF3636; } - .btn-danger.btn-simple { - color: #FF3636; - border-color: #FF3636; } - .btn-danger.btn-simple:hover, .btn-danger.btn-simple:focus, .btn-danger.btn-simple:active { - background-color: transparent; - color: #ff5555; - border-color: #ff5555; - -webkit-box-shadow: none; - box-shadow: none; } - .btn-danger.btn-link { - color: #FF3636; } - .btn-danger.btn-link:hover, .btn-danger.btn-link:focus, .btn-danger.btn-link:active { - background-color: transparent; - color: #ff5555; - text-decoration: none; - -webkit-box-shadow: none; - box-shadow: none; } - -.btn-neutral { - background-color: #FFFFFF; - color: #f96332; } - .btn-neutral:hover, .btn-neutral:focus, .btn-neutral:active, .btn-neutral.active, .btn-neutral:active:focus, .btn-neutral:active:hover, .btn-neutral.active:focus, .btn-neutral.active:hover, - .show > .btn-neutral.dropdown-toggle, - .show > .btn-neutral.dropdown-toggle:focus, - .show > .btn-neutral.dropdown-toggle:hover { - background-color: #FFFFFF; - color: #FFFFFF; - -webkit-box-shadow: none; - box-shadow: none; } - .btn-neutral:not([data-action]):hover { - -webkit-box-shadow: 0 3px 8px 0 rgba(0, 0, 0, 0.17); - box-shadow: 0 3px 8px 0 rgba(0, 0, 0, 0.17); } - .btn-neutral.disabled, .btn-neutral.disabled:hover, .btn-neutral.disabled:focus, .btn-neutral.disabled.focus, .btn-neutral.disabled:active, .btn-neutral.disabled.active, .btn-neutral:disabled, .btn-neutral:disabled:hover, .btn-neutral:disabled:focus, .btn-neutral:disabled.focus, .btn-neutral:disabled:active, .btn-neutral:disabled.active, .btn-neutral[disabled], .btn-neutral[disabled]:hover, .btn-neutral[disabled]:focus, .btn-neutral[disabled].focus, .btn-neutral[disabled]:active, .btn-neutral[disabled].active, - fieldset[disabled] .btn-neutral, - fieldset[disabled] .btn-neutral:hover, - fieldset[disabled] .btn-neutral:focus, - fieldset[disabled] .btn-neutral.focus, - fieldset[disabled] .btn-neutral:active, - fieldset[disabled] .btn-neutral.active { - background-color: #FFFFFF; - border-color: #FFFFFF; } - .btn-neutral.btn-danger { - color: #FF3636; } - .btn-neutral.btn-danger:hover, .btn-neutral.btn-danger:focus, .btn-neutral.btn-danger:active, .btn-neutral.btn-danger:active:focus { - color: #ff5555; } - .btn-neutral.btn-info { - color: #2CA8FF; } - .btn-neutral.btn-info:hover, .btn-neutral.btn-info:focus, .btn-neutral.btn-info:active, .btn-neutral.btn-info:active:focus { - color: #4bb5ff; } - .btn-neutral.btn-warning { - color: #FFB236; } - .btn-neutral.btn-warning:hover, .btn-neutral.btn-warning:focus, .btn-neutral.btn-warning:active, .btn-neutral.btn-warning:active:focus { - color: #ffbe55; } - .btn-neutral.btn-success { - color: #18ce0f; } - .btn-neutral.btn-success:hover, .btn-neutral.btn-success:focus, .btn-neutral.btn-success:active, .btn-neutral.btn-success:active:focus { - color: #1beb11; } - .btn-neutral.btn-default { - color: #888; } - .btn-neutral.btn-default:hover, .btn-neutral.btn-default:focus, .btn-neutral.btn-default:active, .btn-neutral.btn-default:active:focus { - color: #979797; } - .btn-neutral.active, .btn-neutral:active, .btn-neutral:active:focus, .btn-neutral:active:hover, .btn-neutral.active:focus, .btn-neutral.active:hover, - .show > .btn-neutral.dropdown-toggle, - .show > .btn-neutral.dropdown-toggle:focus, - .show > .btn-neutral.dropdown-toggle:hover { - background-color: #FFFFFF; - color: #fa7a50; - -webkit-box-shadow: none; - box-shadow: none; } - .btn-neutral:hover, .btn-neutral:focus { - color: #fa7a50; } - .btn-neutral:hover:not(.nav-link), .btn-neutral:focus:not(.nav-link) { - -webkit-box-shadow: none; - box-shadow: none; } - .btn-neutral.btn-simple { - color: #FFFFFF; - border-color: #FFFFFF; } - .btn-neutral.btn-simple:hover, .btn-neutral.btn-simple:focus, .btn-neutral.btn-simple:active { - background-color: transparent; - color: #FFFFFF; - border-color: #FFFFFF; - -webkit-box-shadow: none; - box-shadow: none; } - .btn-neutral.btn-link { - color: #FFFFFF; } - .btn-neutral.btn-link:hover, .btn-neutral.btn-link:focus, .btn-neutral.btn-link:active { - background-color: transparent; - color: #FFFFFF; - text-decoration: none; - -webkit-box-shadow: none; - box-shadow: none; } - -.btn:disabled, .btn[disabled], .btn.disabled { - opacity: 0.5; - filter: alpha(opacity=50); - pointer-events: none; } - -.btn-simple { - border: 1px solid; - border-color: #888; - padding: 10px 22px; - background-color: transparent; } - -.btn-simple.disabled, .btn-simple.disabled:hover, .btn-simple.disabled:focus, .btn-simple.disabled.focus, .btn-simple.disabled:active, .btn-simple.disabled.active, .btn-simple:disabled, .btn-simple:disabled:hover, .btn-simple:disabled:focus, .btn-simple:disabled.focus, .btn-simple:disabled:active, .btn-simple:disabled.active, .btn-simple[disabled], .btn-simple[disabled]:hover, .btn-simple[disabled]:focus, .btn-simple[disabled].focus, .btn-simple[disabled]:active, .btn-simple[disabled].active, -fieldset[disabled] .btn-simple, -fieldset[disabled] .btn-simple:hover, -fieldset[disabled] .btn-simple:focus, -fieldset[disabled] .btn-simple.focus, -fieldset[disabled] .btn-simple:active, -fieldset[disabled] .btn-simple.active, -.btn-link.disabled, -.btn-link.disabled:hover, -.btn-link.disabled:focus, -.btn-link.disabled.focus, -.btn-link.disabled:active, -.btn-link.disabled.active, -.btn-link:disabled, -.btn-link:disabled:hover, -.btn-link:disabled:focus, -.btn-link:disabled.focus, -.btn-link:disabled:active, -.btn-link:disabled.active, -.btn-link[disabled], -.btn-link[disabled]:hover, -.btn-link[disabled]:focus, -.btn-link[disabled].focus, -.btn-link[disabled]:active, -.btn-link[disabled].active, -fieldset[disabled] -.btn-link, -fieldset[disabled] -.btn-link:hover, -fieldset[disabled] -.btn-link:focus, -fieldset[disabled] -.btn-link.focus, -fieldset[disabled] -.btn-link:active, -fieldset[disabled] -.btn-link.active { - background-color: transparent; } - -.btn-link { - border: 0; - padding: 0.5rem 0.7rem; - background-color: transparent; } - -.btn-lg { - font-size: 1em; - border-radius: 0.25rem; - padding: 15px 48px; } - .btn-lg.btn-simple { - padding: 14px 47px; } - -.btn-sm { - font-size: 14px; - border-radius: 0.1875rem; - padding: 5px 15px; } - .btn-sm.btn-simple { - padding: 4px 14px; } - -.btn-wd { - min-width: 140px; } - -.btn-group.select { - width: 100%; } - -.btn-group.select .btn { - text-align: left; } - -.btn-group.select .caret { - position: absolute; - top: 50%; - margin-top: -1px; - right: 8px; } - -.btn-round { - border-width: 1px; - border-radius: 30px; - padding-right: 23px; - padding-left: 23px; } - .btn-round.btn-simple { - padding: 10px 22px; } - -.no-caret.dropdown-toggle::after { - display: none; } - -.form-control::-moz-placeholder { - color: #DDDDDD; - opacity: 1; - filter: alpha(opacity=100); } - -.form-control:-moz-placeholder { - color: #DDDDDD; - opacity: 1; - filter: alpha(opacity=100); } - -.form-control::-webkit-input-placeholder { - color: #DDDDDD; - opacity: 1; - filter: alpha(opacity=100); } - -.form-control:-ms-input-placeholder { - color: #DDDDDD; - opacity: 1; - filter: alpha(opacity=100); } - -.form-control { - background-color: transparent; - border: 1px solid #E3E3E3; - border-radius: 30px; - color: #2c2c2c; - line-height: normal; - font-size: 0.8571em; - -webkit-transition: color 0.3s ease-in-out, border-color 0.3s ease-in-out, background-color 0.3s ease-in-out; - transition: color 0.3s ease-in-out, border-color 0.3s ease-in-out, background-color 0.3s ease-in-out; - -webkit-box-shadow: none; - box-shadow: none; } - .form-control:focus { - border: 1px solid #f96332; - -webkit-box-shadow: none; - box-shadow: none; - outline: 0 !important; - color: #2c2c2c; } - .form-control:focus + .input-group-addon, - .form-control:focus ~ .input-group-addon { - border: 1px solid #f96332; - border-left: none; - background-color: transparent; } - .has-success .form-control, - .has-error .form-control, - .has-success .form-control:focus, - .has-error .form-control:focus { - -webkit-box-shadow: none; - box-shadow: none; } - .has-danger .form-control.form-control-success, .has-danger .form-control.form-control-danger, - .has-success .form-control.form-control-success, - .has-success .form-control.form-control-danger { - background-image: none; } - .form-control + .form-control-feedback { - border-radius: 0.25rem; - font-size: 14px; - margin-top: -7px; - position: absolute; - right: 10px; - top: 50%; - vertical-align: middle; } - .open .form-control { - border-radius: 0.25rem 0.25rem 0 0; - border-bottom-color: transparent; } - .form-control + .input-group-addon { - background-color: #FFFFFF; } - -.has-success .input-group-addon, -.has-success .form-control { - border-color: #E3E3E3; } - -.has-success .form-control:focus, -.has-success.input-group-focus .input-group-addon { - border-color: #1be611; } - -.has-danger .form-control, -.has-danger .input-group-addon, -.has-danger.input-group-focus .input-group-addon { - border-color: #ffcfcf; - color: #FF3636; - background-color: rgba(222, 222, 222, 0.1); } - .has-danger .form-control:focus, - .has-danger .input-group-addon:focus, - .has-danger.input-group-focus .input-group-addon:focus { - background-color: #FFFFFF; } - -.has-success:after, -.has-danger:after { - font-family: 'Nucleo Outline'; - content: "\ea22"; - display: inline-block; - position: absolute; - right: 20px; - bottom: 10px; - color: #18ce0f; - font-size: 11px; } - -.has-success.form-control-lg:after, -.has-danger.form-control-lg:after { - font-size: 13px; - top: 24px; } - -.has-success.has-label:after, -.has-danger.has-label:after { - top: 35px; } - -.has-success .form-control + label, -.has-success.form-check .form-check-label label, .has-success.form-check:after, -.has-danger .form-control + label, -.has-danger.form-check .form-check-label label, -.has-danger.form-check:after { - display: none !important; } - -.has-success.form-check .form-check-label, -.has-danger.form-check .form-check-label { - color: #18ce0f; } - -.has-danger:after { - content: "\ea53"; - color: #FF3636; } - -.has-danger.form-check .form-check-label { - color: #FF3636; } - -.form-group.no-border.form-control-lg .input-group-addon, -.input-group.no-border.form-control-lg .input-group-addon { - padding: 15px 0 15px 19px; } - -.form-group.no-border.form-control-lg .form-control, -.input-group.no-border.form-control-lg .form-control { - padding: 15px 19px; } - .form-group.no-border.form-control-lg .form-control + .input-group-addon, - .input-group.no-border.form-control-lg .form-control + .input-group-addon { - padding: 15px 19px 15px 0; } - -.form-group.form-control-lg .form-control, -.input-group.form-control-lg .form-control { - padding: 14px 18px; } - .form-group.form-control-lg .form-control + .input-group-addon, - .input-group.form-control-lg .form-control + .input-group-addon { - padding: 14px 18px 14px 0; } - -.form-group.form-control-lg .input-group-addon, -.input-group.form-control-lg .input-group-addon { - padding: 14px 0 15px 18px; } - .form-group.form-control-lg .input-group-addon + .form-control, - .input-group.form-control-lg .input-group-addon + .form-control { - padding: 15px 18px 15px 16px; } - -.form-group.no-border .form-control, -.input-group.no-border .form-control { - padding: 11px 19px; } - .form-group.no-border .form-control + .input-group-addon, - .input-group.no-border .form-control + .input-group-addon { - padding: 11px 19px 11px 0; } - -.form-group.no-border .input-group-addon, -.input-group.no-border .input-group-addon { - padding: 11px 0 11px 19px; } - -.form-group .form-control, -.input-group .form-control { - padding: 10px 18px 10px 18px; } - .form-group .form-control + .input-group-addon, - .input-group .form-control + .input-group-addon { - padding: 10px 18px 10px 0; } - -.form-group .input-group-addon, -.input-group .input-group-addon { - padding: 10px 0 10px 18px; } - .form-group .input-group-addon + .form-control, - .form-group .input-group-addon ~ .form-control, - .input-group .input-group-addon + .form-control, - .input-group .input-group-addon ~ .form-control { - padding: 10px 19px 11px 16px; } - -.form-group.no-border .form-control, -.form-group.no-border .form-control + .input-group-addon, -.input-group.no-border .form-control, -.input-group.no-border .form-control + .input-group-addon { - background-color: rgba(222, 222, 222, 0.3); - border: medium none; } - .form-group.no-border .form-control:focus, .form-group.no-border .form-control:active, .form-group.no-border .form-control:active, - .form-group.no-border .form-control + .input-group-addon:focus, - .form-group.no-border .form-control + .input-group-addon:active, - .form-group.no-border .form-control + .input-group-addon:active, - .input-group.no-border .form-control:focus, - .input-group.no-border .form-control:active, - .input-group.no-border .form-control:active, - .input-group.no-border .form-control + .input-group-addon:focus, - .input-group.no-border .form-control + .input-group-addon:active, - .input-group.no-border .form-control + .input-group-addon:active { - border: medium none; - background-color: rgba(222, 222, 222, 0.5); } - -.form-group.no-border .form-control:focus + .input-group-addon, -.input-group.no-border .form-control:focus + .input-group-addon { - background-color: rgba(222, 222, 222, 0.5); } - -.form-group.no-border .input-group-addon, -.input-group.no-border .input-group-addon { - background-color: rgba(222, 222, 222, 0.3); - border: none; } - -.has-error .form-control-feedback, .has-error .control-label { - color: #FF3636; } - -.has-success .form-control-feedback, .has-success .control-label { - color: #18ce0f; } - -.input-group-addon { - background-color: #FFFFFF; - border: 1px solid #E3E3E3; - border-radius: 30px; - color: #555555; - padding: -0.5rem 0 -0.5rem -0.3rem; - -webkit-transition: color 0.3s ease-in-out, border-color 0.3s ease-in-out, background-color 0.3s ease-in-out; - transition: color 0.3s ease-in-out, border-color 0.3s ease-in-out, background-color 0.3s ease-in-out; } - .has-danger.input-group-focus .input-group-addon { - background-color: #FFFFFF; } - .has-success .input-group-addon { - background-color: #FFFFFF; } - .has-danger .form-control:focus + .input-group-addon { - color: #FF3636; } - .has-success .form-control:focus + .input-group-addon { - color: #18ce0f; } - .input-group-addon + .form-control, - .input-group-addon ~ .form-control { - padding: -0.5rem 0.7rem; - padding-left: 18px; } - .input-group-addon i { - width: 17px; } - -.input-group-focus .input-group-addon { - background-color: #FFFFFF; - border-color: #f96332; } - -.input-group-focus.no-border .input-group-addon { - background-color: rgba(222, 222, 222, 0.5); } - -.input-group, -.form-group { - margin-bottom: 10px; - position: relative; } - .input-group .form-control-static, - .form-group .form-control-static { - margin-top: 9px; } - -.input-group[disabled] .input-group-addon { - background-color: #E3E3E3; } - -.input-group .form-control:not(:first-child):not(:last-child), .input-group-addon:not(:first-child):not(:last-child), .input-group-btn:not(:first-child):not(:last-child) { - border-radius: 30px; - border-top-left-radius: 0; - border-bottom-left-radius: 0; - border-left: 0 none; } - -.input-group .form-control:first-child, -.input-group-addon:first-child, -.input-group-btn:first-child > .dropdown-toggle, -.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle) { - border-right: 0 none; } - -.input-group .form-control:last-child, -.input-group-addon:last-child, -.input-group-btn:last-child > .dropdown-toggle, -.input-group-btn:first-child > .btn:not(:first-child) { - border-left: 0 none; } - -.form-control[disabled], .form-control[readonly], fieldset[disabled] .form-control { - background-color: #E3E3E3; - color: #888; - cursor: not-allowed; } - -.input-group-btn .btn { - border-width: 1px; - padding: 11px 0.7rem; } - -.input-group-btn .btn-default:not(.btn-fill) { - border-color: #DDDDDD; } - -.input-group-btn:last-child > .btn { - margin-left: 0; } - -textarea.form-control { - max-width: 100%; - max-height: 80px; - padding: 10px 10px 0 0; - resize: none; - border: none; - border-bottom: 1px solid #E3E3E3; - border-radius: 0; - line-height: 2; } - textarea.form-control:focus, textarea.form-control:active { - border-left: none; - border-top: none; - border-right: none; } - -.has-success.form-group .form-control, -.has-success.form-group.no-border .form-control, -.has-danger.form-group .form-control, -.has-danger.form-group.no-border .form-control { - padding-right: 40px; } - -.form.form-newsletter .form-group { - float: left; - width: 78%; - margin-right: 2%; - margin-top: 9px; } - -.input-group .input-group-btn { - padding: 0 12px; } - -.form-group input[type=file] { - opacity: 0; - position: absolute; - top: 0; - right: 0; - bottom: 0; - left: 0; - width: 100%; - height: 100%; - z-index: 100; } - -.form-text { - font-size: 0.8571em; } - -.form-control-lg { - padding: 0; - font-size: inherit; - line-height: 0; - border-radius: 0; } - -.form-horizontal .col-form-label, -.form-horizontal .label-on-right { - padding: 10px 5px 0 15px; - text-align: right; - max-width: 180px; } - -.form-horizontal .checkbox-radios { - margin-bottom: 15px; } - .form-horizontal .checkbox-radios .form-check:first-child { - margin-top: 8px; } - -.form-horizontal .label-on-right { - text-align: left; - padding: 10px 15px 0 5px; } - -.form-horizontal .form-check-inline { - margin-top: 6px; } - -button, -input, -optgroup, -select, -textarea { - font-family: "Montserrat", "Helvetica Neue", Arial, sans-serif; } - -h1, h2, h3, h4, h5, h6 { - font-weight: 400; } - -a { - color: #f96332; } - a:hover, a:focus { - color: #f96332; } - -h1, .h1 { - font-size: 3.5em; - line-height: 1.15; - margin-bottom: 30px; } - h1 small, .h1 small { - font-weight: 700; - text-transform: uppercase; - opacity: .8; } - -h2, .h2 { - font-size: 2.5em; - margin-bottom: 30px; } - -h3, .h3 { - font-size: 2em; - margin-bottom: 30px; - line-height: 1.4em; } - -h4, .h4 { - font-size: 1.714em; - line-height: 1.45em; - margin-top: 30px; - margin-bottom: 15px; } - h4 + .category, - h4.title + .category, .h4 + .category, - .h4.title + .category { - margin-top: -10px; } - -h5, .h5 { - font-size: 1.57em; - line-height: 1.4em; - margin-bottom: 15px; } - -h6, .h6 { - font-size: 1em; - font-weight: 700; - text-transform: uppercase; } - -p.description { - font-size: 1.14em; } - -.title { - font-weight: 700; } - .title.title-up { - text-transform: uppercase; } - .title.title-up a { - color: #2c2c2c; - text-decoration: none; } - .title + .category { - margin-top: -10px; } - -.description, -.card-description, -.footer-big p, -.card .footer .stats { - color: #9A9A9A; - font-weight: 300; } - -.category, -.card-category { - text-transform: capitalize; - font-weight: 400; - color: #9A9A9A; - font-size: 0.7142em; } - -.card-category { - font-size: 1em; } - -.text-primary, -a.text-primary:focus, a.text-primary:hover { - color: #f96332 !important; } - -.text-info, -a.text-info:focus, a.text-info:hover { - color: #2CA8FF !important; } - -.text-success, -a.text-success:focus, a.text-success:hover { - color: #18ce0f !important; } - -.text-warning, -a.text-warning:focus, a.text-warning:hover { - color: #FFB236 !important; } - -.text-danger, -a.text-danger:focus, a.text-danger:hover { - color: #FF3636 !important; } - -.text-gray, -a.text-gray:focus, a.text-gray:hover { - color: #E3E3E3 !important; } - -.blockquote { - border-left: none; - border: 1px solid #888; - padding: 20px; - font-size: 1.1em; - line-height: 1.8; } - .blockquote small { - color: #888; - font-size: 0.8571em; - text-transform: uppercase; } - .blockquote.blockquote-primary { - border-color: #f96332; - color: #f96332; } - .blockquote.blockquote-primary small { - color: #f96332; } - .blockquote.blockquote-danger { - border-color: #FF3636; - color: #FF3636; } - .blockquote.blockquote-danger small { - color: #FF3636; } - .blockquote.blockquote-white { - border-color: rgba(255, 255, 255, 0.8); - color: #FFFFFF; } - .blockquote.blockquote-white small { - color: rgba(255, 255, 255, 0.8); } - -body { - color: #2c2c2c; - font-size: 14px; - font-family: "Montserrat", "Helvetica Neue", Arial, sans-serif; - -moz-osx-font-smoothing: grayscale; - -webkit-font-smoothing: antialiased; } - -.main { - position: relative; - background: #FFFFFF; } - -/* Animations */ -.nav-pills .nav-link, -.navbar, -.nav-tabs .nav-link, -.sidebar .nav a, -.sidebar .nav a i, -.navbar-collapse .navbar-nav .nav-link, -.animation-transition-general, -.sidebar .navbar-minimize, -.off-canvas-sidebar .navbar-minimize, -.sidebar .nav p, -.off-canvas-sidebar .nav p, -.sidebar .logo a.logo-mini, -.sidebar .logo a.logo-normal, -.off-canvas-sidebar .logo a.logo-mini, -.off-canvas-sidebar .logo a.logo-normal, -.tag, -.tag [data-role="remove"], -.animation-transition-general, -.sidebar .navbar-minimize, -.off-canvas-sidebar .navbar-minimize, -.sidebar .nav p, -.off-canvas-sidebar .nav p, -.sidebar .logo a.logo-mini, -.sidebar .logo a.logo-normal, -.off-canvas-sidebar .logo a.logo-mini, -.off-canvas-sidebar .logo a.logo-normal { - -webkit-transition: all 300ms ease 0s; - transition: all 300ms ease 0s; } - -.dropdown-toggle:after, -.bootstrap-switch-label:before, -.caret { - -webkit-transition: all 150ms ease 0s; - transition: all 150ms ease 0s; } - -.dropdown-toggle[aria-expanded="true"]:after, -a[data-toggle="collapse"][aria-expanded="true"] .caret, -.card-collapse .card a[data-toggle="collapse"][aria-expanded="true"] i, -.card-collapse .card a[data-toggle="collapse"].expanded i { - filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=2); - -webkit-transform: rotate(180deg); - transform: rotate(180deg); } - -.button-bar { - display: block; - position: relative; - width: 22px; - height: 1px; - border-radius: 1px; - background: #FFFFFF; } - .button-bar + .button-bar { - margin-top: 7px; } - .button-bar:nth-child(2) { - width: 17px; } - -.caret { - display: inline-block; - width: 0; - height: 0; - margin-left: 2px; - vertical-align: middle; - border-top: 4px dashed; - border-top: 4px solid\9; - border-right: 4px solid transparent; - border-left: 4px solid transparent; } - -.form-check { - margin-top: .5rem; } - -.form-check .form-check-label { - display: inline-block; - position: relative; - cursor: pointer; - padding-left: 35px; - line-height: 26px; - margin-bottom: 0; - -webkit-transition: color 0.3s linear; - transition: color 0.3s linear; } - -.radio .form-check-sign { - padding-left: 28px; } - -.form-check .form-check-sign::before, -.form-check .form-check-sign::after { - content: " "; - display: inline-block; - position: absolute; - width: 26px; - height: 26px; - left: 0; - cursor: pointer; - border-radius: 3px; - top: 0; - background-color: transparent; - border: 1px solid #E3E3E3; - -webkit-transition: opacity 0.3s linear; - transition: opacity 0.3s linear; } - -.form-check .form-check-sign::after { - font-family: 'Nucleo Outline'; - content: "\ea22"; - top: 0px; - text-align: center; - font-size: 14px; - opacity: 0; - color: #555555; - border: 0; - background-color: inherit; } - -.form-check.disabled .form-check-label, -.form-check.disabled .form-check-label { - color: #9A9A9A; - opacity: .5; - cursor: not-allowed; } - -.form-check input[type="checkbox"], -.radio input[type="radio"] { - opacity: 0; - position: absolute; - visibility: hidden; } - -.form-check input[type="checkbox"]:checked + .form-check-sign::after { - opacity: 1; } - -.form-control input[type="checkbox"]:disabled + .form-check-sign::before, -.checkbox input[type="checkbox"]:disabled + .form-check-sign::after { - cursor: not-allowed; } - -.form-check input[type="checkbox"]:disabled + .form-check-sign, -.form-check input[type="radio"]:disabled + .form-check-sign { - pointer-events: none; } - -.form-check-radio .form-check-sign::before, -.form-check-radio .form-check-sign::after { - content: " "; - width: 20px; - height: 20px; - border-radius: 50%; - border: 1px solid #E3E3E3; - display: inline-block; - position: absolute; - left: 3px; - top: 3px; - padding: 1px; - -webkit-transition: opacity 0.3s linear; - transition: opacity 0.3s linear; } - -.form-check-radio input[type="radio"] + .form-check-sign:after, -.form-check-radio input[type="radio"] { - opacity: 0; } - -.form-check-radio input[type="radio"]:checked + .form-check-sign::after { - width: 4px; - height: 4px; - background-color: #555555; - border-color: #555555; - top: 11px; - left: 11px; - opacity: 1; } - -.form-check-radio input[type="radio"]:checked + .form-check-sign::after { - opacity: 1; } - -.form-check-radio input[type="radio"]:disabled + .form-check-sign { - color: #9A9A9A; } - -.form-check-radio input[type="radio"]:disabled + .form-check-sign::before, -.form-check-radio input[type="radio"]:disabled + .form-check-sign::after { - color: #9A9A9A; } - -.navbar { - padding-top: 0.625rem; - padding-bottom: 0.625rem; - min-height: 53px; - margin-bottom: 20px; - -webkit-box-shadow: 0px 0px 20px 0px rgba(0, 0, 0, 0.15); - box-shadow: 0px 0px 20px 0px rgba(0, 0, 0, 0.15); } - .navbar a { - vertical-align: middle; } - .navbar a:not(.btn):not(.dropdown-item) { - color: #FFFFFF; } - .navbar a.dropdown-item { - color: #888; } - .navbar.bg-white .input-group .form-control, - .navbar.bg-white .input-group.no-border .form-control { - color: #888; } - .navbar.bg-white .input-group .form-control::-moz-placeholder, - .navbar.bg-white .input-group.no-border .form-control::-moz-placeholder { - color: #888; } - .navbar.bg-white .input-group .form-control:-ms-input-placeholder, - .navbar.bg-white .input-group.no-border .form-control:-ms-input-placeholder { - color: #888; } - .navbar.bg-white .input-group .form-control::-webkit-input-placeholder, - .navbar.bg-white .input-group.no-border .form-control::-webkit-input-placeholder { - color: #888; } - .navbar.bg-white .input-group-addon i { - color: #888; - opacity: .5; } - .navbar .form-group, - .navbar .input-group { - margin: 0; - margin-left: -3px; - margin-right: 5px; } - .navbar .form-group .form-group-addon, - .navbar .form-group .input-group-addon, - .navbar .input-group .form-group-addon, - .navbar .input-group .input-group-addon { - color: #FFFFFF; } - .navbar .form-group.no-border .form-control, - .navbar .input-group.no-border .form-control { - color: #FFFFFF; } - .navbar .form-group.no-border .form-control::-moz-placeholder, - .navbar .input-group.no-border .form-control::-moz-placeholder { - color: #FFFFFF; } - .navbar .form-group.no-border .form-control:-ms-input-placeholder, - .navbar .input-group.no-border .form-control:-ms-input-placeholder { - color: #FFFFFF; } - .navbar .form-group.no-border .form-control::-webkit-input-placeholder, - .navbar .input-group.no-border .form-control::-webkit-input-placeholder { - color: #FFFFFF; } - .navbar p { - display: inline-block; - margin: 0; - line-height: 1.8em; - font-size: 1em; - font-weight: 400; } - .navbar.navbar-absolute { - position: absolute; - width: 100%; - padding-top: 10px; - z-index: 1029; } - .documentation .navbar.fixed-top { - left: 0; - width: initial; } - .navbar .navbar-wrapper { - display: -webkit-inline-box; - display: -ms-inline-flexbox; - display: inline-flex; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; } - .navbar .navbar-wrapper .navbar-minimize { - padding-right: 10px; } - .navbar .navbar-wrapper .navbar-minimize .btn { - margin: 0; } - .navbar .navbar-wrapper .navbar-toggle .navbar-toggler { - padding-left: 0; } - .navbar .navbar-wrapper .navbar-toggle:hover .navbar-toggler-bar.bar2 { - width: 22px; } - .navbar .navbar-nav.navbar-logo { - position: absolute; - left: 0; - right: 0; - margin: 0 auto; - width: 49px; - top: -4px; } - .navbar .navbar-nav .nav-link.btn { - padding: 11px 22px; } - .navbar .navbar-nav .nav-link.btn.btn-lg { - padding: 15px 48px; } - .navbar .navbar-nav .nav-link.btn.btn-sm { - padding: 5px 15px; } - .navbar .navbar-nav .nav-link { - text-transform: uppercase; - font-size: 0.7142em; - padding: 0.5rem 0.7rem; - line-height: 1.625rem; - margin-right: 3px; } - .navbar .navbar-nav .nav-link i.fa + p, - .navbar .navbar-nav .nav-link i.now-ui-icons + p { - margin-left: 3px; } - .navbar .navbar-nav .nav-link i.fa, - .navbar .navbar-nav .nav-link i.now-ui-icons { - font-size: 18px; - position: relative; - top: 3px; - text-align: center; - width: 21px; } - .navbar .navbar-nav .nav-link i.now-ui-icons { - top: 4px; - font-size: 16px; } - .navbar .navbar-nav .nav-link.profile-photo .profile-photo-small { - width: 27px; - height: 27px; } - .navbar .navbar-nav .nav-link.disabled { - opacity: .5; - color: #FFFFFF; } - .navbar .navbar-nav .nav-item.active .nav-link:not(.btn), - .navbar .navbar-nav .nav-item .nav-link:not(.btn):focus, - .navbar .navbar-nav .nav-item .nav-link:not(.btn):hover, - .navbar .navbar-nav .nav-item .nav-link:not(.btn):active { - background-color: rgba(255, 255, 255, 0.2); - border-radius: 0.1875rem; - color: #FFFFFF; } - .navbar .logo-container { - width: 27px; - height: 27px; - overflow: hidden; - margin: 0 auto; - border-radius: 50%; - border: 1px solid transparent; } - .navbar .navbar-brand { - text-transform: uppercase; - font-size: 0.8571em; - padding-top: 0.5rem; - padding-bottom: 0.5rem; - line-height: 1.625rem; } - .navbar .navbar-toggler { - width: 37px; - height: 27px; - vertical-align: middle; - outline: 0; - cursor: pointer; } - .navbar .navbar-toggler .navbar-toggler-bar.navbar-kebab { - width: 3px; - height: 3px; - border-radius: 50%; - margin: 0 auto; } - .navbar .button-dropdown .navbar-toggler-bar:nth-child(2) { - width: 17px; } - .navbar.navbar-transparent { - background-color: transparent !important; - -webkit-box-shadow: none; - box-shadow: none; - color: #FFFFFF; } - .navbar.bg-white:not(.navbar-transparent) a:not(.dropdown-item):not(.btn) { - color: #888; } - .navbar.bg-white:not(.navbar-transparent) a:not(.dropdown-item):not(.btn).disabled { - opacity: .5; - color: #888; } - .navbar.bg-white:not(.navbar-transparent) .button-bar { - background: #888; } - .navbar.bg-white:not(.navbar-transparent) .nav-item.active .nav-link:not(.btn), - .navbar.bg-white:not(.navbar-transparent) .nav-item .nav-link:not(.btn):focus, - .navbar.bg-white:not(.navbar-transparent) .nav-item .nav-link:not(.btn):hover, - .navbar.bg-white:not(.navbar-transparent) .nav-item .nav-link:not(.btn):active { - background-color: rgba(222, 222, 222, 0.8); - color: #888; } - .navbar.bg-white:not(.navbar-transparent) .logo-container { - border: 1px solid #888; } - -.bg-default { - background-color: #888 !important; } - -.bg-primary { - background-color: #f96332 !important; } - -.bg-info { - background-color: #2CA8FF !important; } - -.bg-success { - background-color: #18ce0f !important; } - -.bg-danger { - background-color: #FF3636 !important; } - -.bg-warning { - background-color: #FFB236 !important; } - -.bg-white { - background-color: #FFFFFF !important; } - -.page-header { - min-height: 100vh; - max-height: 999px; - padding: 0; - color: #FFFFFF; - position: relative; } - .page-header .page-header-image { - position: absolute; - background-size: cover; - background-position: center center; - width: 100%; - height: 100%; - z-index: -1; } - .page-header .content-center { - position: absolute; - top: 50%; - left: 50%; - z-index: 2; - -webkit-transform: translate(-50%, -50%); - transform: translate(-50%, -50%); - text-align: center; - color: #FFFFFF; - padding: 0 15px; - width: 100%; - max-width: 880px; } - .page-header footer { - position: absolute; - bottom: 0; - width: 100%; } - .page-header .container { - height: 100%; - z-index: 1; } - .page-header .category, - .page-header .description { - color: rgba(255, 255, 255, 0.8); } - .page-header.page-header-small { - min-height: 60vh; - max-height: 440px; } - .page-header.page-header-mini { - min-height: 40vh; - max-height: 340px; } - .page-header .title { - margin-bottom: 15px; } - .page-header .title + h4 { - margin-top: 10px; } - .page-header:after, .page-header:before { - position: absolute; - z-index: 0; - width: 100%; - height: 100%; - display: block; - left: 0; - top: 0; - content: ""; } - .page-header:before { - background-color: rgba(0, 0, 0, 0.3); } - .page-header[filter-color="orange"] { - background: rgba(44, 44, 44, 0.2); - /* For browsers that do not support gradients */ - /* For Safari 5.1 to 6.0 */ - /* For Opera 11.1 to 12.0 */ - /* For Firefox 3.6 to 15 */ - background: -webkit-gradient(linear, left bottom, left top, from(rgba(44, 44, 44, 0.2)), to(rgba(224, 23, 3, 0.6))); - background: linear-gradient(0deg, rgba(44, 44, 44, 0.2), rgba(224, 23, 3, 0.6)); - /* Standard syntax */ } - -.dropdown-menu { - border: 0; - -webkit-box-shadow: 0px 10px 50px 0px rgba(0, 0, 0, 0.2); - box-shadow: 0px 10px 50px 0px rgba(0, 0, 0, 0.2); - border-radius: 0.125rem; - -webkit-transition: all 150ms linear; - transition: all 150ms linear; - font-size: 14px; } - .dropdown-menu.dropdown-menu-right:before { - left: auto; - right: 10px; } - .dropdown-menu i { - margin-right: 5px; - position: relative; - top: 1px; } - .dropdown-menu .now-ui-icons { - margin-right: 10px; - position: relative; - top: 4px; - font-size: 18px; - margin-top: -5px; - opacity: .5; } - .dropdown-menu .dropdown-item.active, .dropdown-menu .dropdown-item:active { - color: inherit; } - .dropup .dropdown-menu:before { - display: none; } - .dropup .dropdown-menu:after { - display: inline-block; - position: absolute; - width: 0; - height: 0; - vertical-align: middle; - content: ""; - top: auto; - bottom: -5px; - right: auto; - left: 10px; - color: #FFFFFF; - border-top: .4em solid; - border-right: .4em solid transparent; - border-left: .4em solid transparent; } - .dropup .dropdown-menu.dropdown-menu-right:after { - right: 10px; - left: auto; } - .dropdown-menu:before { - display: inline-block; - position: absolute; - width: 0; - height: 0; - vertical-align: middle; - content: ""; - top: -5px; - left: 10px; - right: auto; - color: #FFFFFF; - border-bottom: .4em solid; - border-right: .4em solid transparent; - border-left: .4em solid transparent; } - .dropdown-menu.dropdown-menu-right { - right: 0 !important; - left: auto !important; } - .dropdown-menu .dropdown-item, - .bootstrap-select .dropdown-menu.inner li a { - font-size: 0.8571em; - padding-top: .6rem; - padding-bottom: .6rem; - margin-top: 5px; - -webkit-transition: all 150ms linear; - transition: all 150ms linear; } - .dropdown-menu .dropdown-item:hover, .dropdown-menu .dropdown-item:focus, - .bootstrap-select .dropdown-menu.inner li a:hover, - .bootstrap-select .dropdown-menu.inner li a:focus { - background-color: rgba(222, 222, 222, 0.3); } - .dropdown-menu .dropdown-item.disabled, .dropdown-menu .dropdown-item:disabled, - .bootstrap-select .dropdown-menu.inner li a.disabled, - .bootstrap-select .dropdown-menu.inner li a:disabled { - color: rgba(182, 182, 182, 0.6); } - .dropdown-menu .dropdown-item.disabled:hover, .dropdown-menu .dropdown-item.disabled:focus, .dropdown-menu .dropdown-item:disabled:hover, .dropdown-menu .dropdown-item:disabled:focus, - .bootstrap-select .dropdown-menu.inner li a.disabled:hover, - .bootstrap-select .dropdown-menu.inner li a.disabled:focus, - .bootstrap-select .dropdown-menu.inner li a:disabled:hover, - .bootstrap-select .dropdown-menu.inner li a:disabled:focus { - background-color: transparent; } - .dropdown-menu .dropdown-divider { - background-color: rgba(222, 222, 222, 0.5); } - .dropdown-menu .dropdown-header:not([href]):not([tabindex]) { - color: rgba(182, 182, 182, 0.6); - font-size: 0.7142em; - text-transform: uppercase; - font-weight: 700; } - .dropdown-menu.dropdown-primary { - background-color: #f95823; } - .dropdown-menu.dropdown-primary:before { - color: #f95823; } - .dropdown-menu.dropdown-primary .dropdown-header:not([href]):not([tabindex]) { - color: rgba(255, 255, 255, 0.8); } - .dropdown-menu.dropdown-primary .dropdown-item { - color: #FFFFFF; } - .dropdown-menu.dropdown-primary .dropdown-item:hover, .dropdown-menu.dropdown-primary .dropdown-item:focus { - background-color: rgba(255, 255, 255, 0.2); } - .dropdown-menu.dropdown-primary .dropdown-divider { - background-color: rgba(255, 255, 255, 0.2); } - .dropdown-menu.dropdown-info { - background-color: #1da2ff; } - .dropdown-menu.dropdown-info:before { - color: #1da2ff; } - .dropdown-menu.dropdown-info .dropdown-header:not([href]):not([tabindex]) { - color: rgba(255, 255, 255, 0.8); } - .dropdown-menu.dropdown-info .dropdown-item { - color: #FFFFFF; } - .dropdown-menu.dropdown-info .dropdown-item:hover, .dropdown-menu.dropdown-info .dropdown-item:focus { - background-color: rgba(255, 255, 255, 0.2); } - .dropdown-menu.dropdown-info .dropdown-divider { - background-color: rgba(255, 255, 255, 0.2); } - .dropdown-menu.dropdown-danger { - background-color: #ff2727; } - .dropdown-menu.dropdown-danger:before { - color: #ff2727; } - .dropdown-menu.dropdown-danger .dropdown-header:not([href]):not([tabindex]) { - color: rgba(255, 255, 255, 0.8); } - .dropdown-menu.dropdown-danger .dropdown-item { - color: #FFFFFF; } - .dropdown-menu.dropdown-danger .dropdown-item:hover, .dropdown-menu.dropdown-danger .dropdown-item:focus { - background-color: rgba(255, 255, 255, 0.2); } - .dropdown-menu.dropdown-danger .dropdown-divider { - background-color: rgba(255, 255, 255, 0.2); } - .dropdown-menu.dropdown-success { - background-color: #16c00e; } - .dropdown-menu.dropdown-success:before { - color: #16c00e; } - .dropdown-menu.dropdown-success .dropdown-header:not([href]):not([tabindex]) { - color: rgba(255, 255, 255, 0.8); } - .dropdown-menu.dropdown-success .dropdown-item { - color: #FFFFFF; } - .dropdown-menu.dropdown-success .dropdown-item:hover, .dropdown-menu.dropdown-success .dropdown-item:focus { - background-color: rgba(255, 255, 255, 0.2); } - .dropdown-menu.dropdown-success .dropdown-divider { - background-color: rgba(255, 255, 255, 0.2); } - .dropdown-menu.dropdown-warning { - background-color: #ffac27; } - .dropdown-menu.dropdown-warning:before { - color: #ffac27; } - .dropdown-menu.dropdown-warning .dropdown-header:not([href]):not([tabindex]) { - color: rgba(255, 255, 255, 0.8); } - .dropdown-menu.dropdown-warning .dropdown-item { - color: #FFFFFF; } - .dropdown-menu.dropdown-warning .dropdown-item:hover, .dropdown-menu.dropdown-warning .dropdown-item:focus { - background-color: rgba(255, 255, 255, 0.2); } - .dropdown-menu.dropdown-warning .dropdown-divider { - background-color: rgba(255, 255, 255, 0.2); } - .dropdown .dropdown-menu, - .dropup:not(.bootstrap-select) .dropdown-menu, - .bootstrap-select .dropdown-menu:not(.inner), .dropdown-menu.bootstrap-datetimepicker-widget.top, .dropdown-menu.bootstrap-datetimepicker-widget.bottom { - -webkit-transform: translate3d(0, -20px, 0) !important; - transform: translate3d(0, -20px, 0) !important; - visibility: hidden; - display: block; - opacity: 0; - filter: alpha(opacity=0); - top: 100% !important; } - .dropdown-menu.bootstrap-datetimepicker-widget.top, .dropdown-menu.bootstrap-datetimepicker-widget.bottom { - -webkit-transform: translate3d(0, -20px, 0) !important; - transform: translate3d(0, -20px, 0) !important; } - .bootstrap-select.dropup .dropdown-menu:not(.inner) { - -webkit-transform: translate3d(0, 25px, 0) !important; - transform: translate3d(0, 25px, 0) !important; } - .dropup:not(.bootstrap-select) .dropdown-menu { - -webkit-transform: translate3d(0, 20px, 0) !important; - transform: translate3d(0, 20px, 0) !important; - top: auto !important; - bottom: 100%; } - .dropdown.show .dropdown-menu, - .bootstrap-select.show .dropdown-menu:not(.inner), .dropdown-menu.bootstrap-datetimepicker-widget.top.open, .dropdown-menu.bootstrap-datetimepicker-widget.bottom.open, - .dropup.show:not(.bootstrap-select) .dropdown-menu, - .navbar .dropdown.show .dropdown-menu { - opacity: 1; - filter: alpha(opacity=100); - visibility: visible; - -webkit-transform: translate3d(0, 1px, 0) !important; - transform: translate3d(0, 1px, 0) !important; } - .dropdown-menu.bootstrap-datetimepicker-widget.top.open, .dropdown-menu.bootstrap-datetimepicker-widget.bottom.open { - -webkit-transform: translate3d(0, 0px, 0) !important; - transform: translate3d(0, 0px, 0) !important; } - .dropup.show:not(.bootstrap-select) .dropdown-menu { - -webkit-transform: translate3d(0, -2px, 0) !important; - transform: translate3d(0, -2px, 0) !important; } - -.button-dropdown { - padding-right: 0.7rem; - cursor: pointer; } - .button-dropdown .dropdown-toggle { - padding-top: 0.5rem; - padding-bottom: 0.5rem; - display: block; } - .button-dropdown .dropdown-toggle:after { - display: none; } - -.alert { - border: 0; - border-radius: 0.1875rem; - color: #FFFFFF; - padding-top: .9rem; - padding-bottom: .9rem; - position: relative; } - .alert.alert-success { - background-color: #1be611; } - .alert.alert-danger { - background-color: #ff5050; } - .alert.alert-warning { - background-color: #ffbc50; } - .alert.alert-info { - background-color: #46b3ff; } - .alert.alert-primary { - background-color: #fa764b; } - .alert i.fa, - .alert i.now-ui-icons { - font-size: 20px; } - .alert .close { - color: #FFFFFF; - opacity: .9; - text-shadow: none; - line-height: 0; - outline: 0; } - .alert span[data-notify="icon"] { - font-size: 22px; - display: block; - left: 19px; - position: absolute; - top: 50%; - margin-top: -11px; } - .alert button.close { - position: absolute; - right: 10px; - top: 50%; - margin-top: -13px; - width: 25px; - height: 25px; - padding: 3px; } - .alert .close ~ span { - display: block; - max-width: 89%; } - .alert.alert-with-icon { - padding-left: 65px; } - -img { - max-width: 100%; - border-radius: 0.1875rem; } - -.img-raised { - -webkit-box-shadow: 0px 10px 25px 0px rgba(0, 0, 0, 0.3); - box-shadow: 0px 10px 25px 0px rgba(0, 0, 0, 0.3); } - -/* -------------------------------- - -Nucleo Outline Web Font - nucleoapp.com/ -License - nucleoapp.com/license/ -Created using IcoMoon - icomoon.io - --------------------------------- */ -@font-face { - font-family: 'Nucleo Outline'; - src: url("../fonts/nucleo-outline.eot"); - src: url("../fonts/nucleo-outline.eot") format("embedded-opentype"), url("../fonts/nucleo-outline.woff2") format("woff2"), url("../fonts/nucleo-outline.woff") format("woff"), url("../fonts/nucleo-outline.ttf") format("truetype"), url("../fonts/nucleo-outline.svg") format("svg"); - font-weight: normal; - font-style: normal; } - -/*------------------------ - base class definition --------------------------*/ -.now-ui-icons { - display: inline-block; - font: normal normal normal 14px/1 'Nucleo Outline'; - font-size: inherit; - speak: none; - text-transform: none; - /* Better Font Rendering */ - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; } - -/*------------------------ - change icon size --------------------------*/ -/*---------------------------------- - add a square/circle background ------------------------------------*/ -.now-ui-icons.circle { - padding: 0.33333333em; - vertical-align: -16%; - background-color: #eee; } - -.now-ui-icons.circle { - border-radius: 50%; } - -/*------------------------ - list icons --------------------------*/ -.nc-icon-ul { - padding-left: 0; - margin-left: 2.14285714em; - list-style-type: none; } - -.nc-icon-ul > li { - position: relative; } - -.nc-icon-ul > li > .now-ui-icons { - position: absolute; - left: -1.57142857em; - top: 0.14285714em; - text-align: center; } - -.nc-icon-ul > li > .now-ui-icons.circle { - top: -0.19047619em; - left: -1.9047619em; } - -/*------------------------ - spinning icons --------------------------*/ -.now-ui-icons.spin { - -webkit-animation: nc-icon-spin 2s infinite linear; - animation: nc-icon-spin 2s infinite linear; } - -@-webkit-keyframes nc-icon-spin { - 0% { - -webkit-transform: rotate(0deg); } - 100% { - -webkit-transform: rotate(360deg); } } - -@keyframes nc-icon-spin { - 0% { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); } - 100% { - -webkit-transform: rotate(360deg); - transform: rotate(360deg); } } - -/*------------------------ - rotated/flipped icons --------------------------*/ -/*------------------------ - font icons --------------------------*/ -.now-ui-icons.ui-1_check:before { - content: "\ea22"; } - -.now-ui-icons.ui-1_email-85:before { - content: "\ea2a"; } - -.now-ui-icons.arrows-1_cloud-download-93:before { - content: "\ea21"; } - -.now-ui-icons.arrows-1_cloud-upload-94:before { - content: "\ea24"; } - -.now-ui-icons.arrows-1_minimal-down:before { - content: "\ea39"; } - -.now-ui-icons.arrows-1_minimal-left:before { - content: "\ea3a"; } - -.now-ui-icons.arrows-1_minimal-right:before { - content: "\ea3b"; } - -.now-ui-icons.arrows-1_minimal-up:before { - content: "\ea3c"; } - -.now-ui-icons.arrows-1_refresh-69:before { - content: "\ea44"; } - -.now-ui-icons.arrows-1_share-66:before { - content: "\ea4c"; } - -.now-ui-icons.business_badge:before { - content: "\ea09"; } - -.now-ui-icons.business_bank:before { - content: "\ea0a"; } - -.now-ui-icons.business_briefcase-24:before { - content: "\ea13"; } - -.now-ui-icons.business_bulb-63:before { - content: "\ea15"; } - -.now-ui-icons.business_chart-bar-32:before { - content: "\ea1e"; } - -.now-ui-icons.business_chart-pie-36:before { - content: "\ea1f"; } - -.now-ui-icons.business_globe:before { - content: "\ea2f"; } - -.now-ui-icons.business_money-coins:before { - content: "\ea40"; } - -.now-ui-icons.clothes_tie-bow:before { - content: "\ea5b"; } - -.now-ui-icons.design_vector:before { - content: "\ea61"; } - -.now-ui-icons.design_app:before { - content: "\ea08"; } - -.now-ui-icons.design_bullet-list-67:before { - content: "\ea14"; } - -.now-ui-icons.design_image:before { - content: "\ea33"; } - -.now-ui-icons.design_palette:before { - content: "\ea41"; } - -.now-ui-icons.design_scissors:before { - content: "\ea4a"; } - -.now-ui-icons.design-2_html5:before { - content: "\ea32"; } - -.now-ui-icons.design-2_ruler-pencil:before { - content: "\ea48"; } - -.now-ui-icons.emoticons_satisfied:before { - content: "\ea49"; } - -.now-ui-icons.files_box:before { - content: "\ea12"; } - -.now-ui-icons.files_paper:before { - content: "\ea43"; } - -.now-ui-icons.files_single-copy-04:before { - content: "\ea52"; } - -.now-ui-icons.health_ambulance:before { - content: "\ea07"; } - -.now-ui-icons.loader_gear:before { - content: "\ea4e"; } - -.now-ui-icons.loader_refresh:before { - content: "\ea44"; } - -.now-ui-icons.location_bookmark:before { - content: "\ea10"; } - -.now-ui-icons.location_compass-05:before { - content: "\ea25"; } - -.now-ui-icons.location_map-big:before { - content: "\ea3d"; } - -.now-ui-icons.location_pin:before { - content: "\ea47"; } - -.now-ui-icons.location_world:before { - content: "\ea63"; } - -.now-ui-icons.media-1_album:before { - content: "\ea02"; } - -.now-ui-icons.media-1_button-pause:before { - content: "\ea16"; } - -.now-ui-icons.media-1_button-play:before { - content: "\ea18"; } - -.now-ui-icons.media-1_button-power:before { - content: "\ea19"; } - -.now-ui-icons.media-1_camera-compact:before { - content: "\ea1c"; } - -.now-ui-icons.media-2_note-03:before { - content: "\ea3f"; } - -.now-ui-icons.media-2_sound-wave:before { - content: "\ea57"; } - -.now-ui-icons.objects_diamond:before { - content: "\ea29"; } - -.now-ui-icons.objects_globe:before { - content: "\ea2f"; } - -.now-ui-icons.objects_key-25:before { - content: "\ea38"; } - -.now-ui-icons.objects_planet:before { - content: "\ea46"; } - -.now-ui-icons.objects_spaceship:before { - content: "\ea55"; } - -.now-ui-icons.objects_support-17:before { - content: "\ea56"; } - -.now-ui-icons.objects_umbrella-13:before { - content: "\ea5f"; } - -.now-ui-icons.education_agenda-bookmark:before { - content: "\ea01"; } - -.now-ui-icons.education_atom:before { - content: "\ea0c"; } - -.now-ui-icons.education_glasses:before { - content: "\ea2d"; } - -.now-ui-icons.education_hat:before { - content: "\ea30"; } - -.now-ui-icons.education_paper:before { - content: "\ea42"; } - -.now-ui-icons.shopping_bag-16:before { - content: "\ea0d"; } - -.now-ui-icons.shopping_basket:before { - content: "\ea0b"; } - -.now-ui-icons.shopping_box:before { - content: "\ea11"; } - -.now-ui-icons.shopping_cart-simple:before { - content: "\ea1d"; } - -.now-ui-icons.shopping_credit-card:before { - content: "\ea28"; } - -.now-ui-icons.shopping_delivery-fast:before { - content: "\ea27"; } - -.now-ui-icons.shopping_shop:before { - content: "\ea50"; } - -.now-ui-icons.shopping_tag-content:before { - content: "\ea59"; } - -.now-ui-icons.sport_trophy:before { - content: "\ea5d"; } - -.now-ui-icons.sport_user-run:before { - content: "\ea60"; } - -.now-ui-icons.tech_controller-modern:before { - content: "\ea26"; } - -.now-ui-icons.tech_headphones:before { - content: "\ea31"; } - -.now-ui-icons.tech_laptop:before { - content: "\ea36"; } - -.now-ui-icons.tech_mobile:before { - content: "\ea3e"; } - -.now-ui-icons.tech_tablet:before { - content: "\ea58"; } - -.now-ui-icons.tech_tv:before { - content: "\ea5e"; } - -.now-ui-icons.tech_watch-time:before { - content: "\ea62"; } - -.now-ui-icons.text_align-center:before { - content: "\ea05"; } - -.now-ui-icons.text_align-left:before { - content: "\ea06"; } - -.now-ui-icons.text_bold:before { - content: "\ea0e"; } - -.now-ui-icons.text_caps-small:before { - content: "\ea1b"; } - -.now-ui-icons.gestures_tap-01:before { - content: "\ea5a"; } - -.now-ui-icons.transportation_air-baloon:before { - content: "\ea03"; } - -.now-ui-icons.transportation_bus-front-12:before { - content: "\ea17"; } - -.now-ui-icons.travel_info:before { - content: "\ea04"; } - -.now-ui-icons.travel_istanbul:before { - content: "\ea34"; } - -.now-ui-icons.ui-1_bell-53:before { - content: "\ea0f"; } - -.now-ui-icons.ui-1_calendar-60:before { - content: "\ea1a"; } - -.now-ui-icons.ui-1_lock-circle-open:before { - content: "\ea35"; } - -.now-ui-icons.ui-1_send:before { - content: "\ea4d"; } - -.now-ui-icons.ui-1_settings-gear-63:before { - content: "\ea4e"; } - -.now-ui-icons.ui-1_simple-add:before { - content: "\ea4f"; } - -.now-ui-icons.ui-1_simple-delete:before { - content: "\ea54"; } - -.now-ui-icons.ui-1_simple-remove:before { - content: "\ea53"; } - -.now-ui-icons.ui-1_zoom-bold:before { - content: "\ea64"; } - -.now-ui-icons.ui-2_chat-round:before { - content: "\ea20"; } - -.now-ui-icons.ui-2_favourite-28:before { - content: "\ea2b"; } - -.now-ui-icons.ui-2_like:before { - content: "\ea37"; } - -.now-ui-icons.ui-2_settings-90:before { - content: "\ea4b"; } - -.now-ui-icons.ui-2_time-alarm:before { - content: "\ea5c"; } - -.now-ui-icons.users_circle-08:before { - content: "\ea23"; } - -.now-ui-icons.users_single-02:before { - content: "\ea51"; } - -.all-icons .font-icon-detail { - text-align: center; - padding: 45px 0px 30px; - border: 1px solid #e5e5e5; - border-radius: 0.1875rem; - margin: 15px 0; - min-height: 168px; } - -.all-icons [class*="now-ui-icons"] { - font-size: 32px; } - -.all-icons .font-icon-detail p { - margin: 25px auto 0; - width: 100%; - text-align: center; - display: block; - color: #B8B8B8; - padding: 0 10px; - font-size: 0.7142em; } - -.table .img-wrapper { - width: 40px; - height: 40px; - border-radius: 50%; - overflow: hidden; - margin: 0 auto; } - -.table .img-row { - max-width: 60px; - width: 60px; } - -.table .form-check { - margin: 0; } - .table .form-check label .form-check-sign::before, - .table .form-check label .form-check-sign::after { - top: -17px; - left: 4px; } - -.table .btn { - margin: 0; } - -.table small, .table .small { - font-weight: 300; } - -.card-tasks .card-body .table { - margin-bottom: 0; } - .card-tasks .card-body .table > thead > tr > th, - .card-tasks .card-body .table > tbody > tr > th, - .card-tasks .card-body .table > tfoot > tr > th, - .card-tasks .card-body .table > thead > tr > td, - .card-tasks .card-body .table > tbody > tr > td, - .card-tasks .card-body .table > tfoot > tr > td { - padding-top: 0; - padding-bottom: 0; } - -.table > thead > tr > th { - border-bottom-width: 1px; - font-size: 1.45em; - font-weight: 300; - border: 0; } - -.table .radio, -.table .checkbox { - margin-top: 0; - margin-bottom: 0; - padding: 0; - width: 15px; } - .table .radio .icons, - .table .checkbox .icons { - position: relative; } - .table .radio label:after, .table .radio label:before, - .table .checkbox label:after, - .table .checkbox label:before { - top: -17px; - left: -3px; } - -.table > thead > tr > th, -.table > tbody > tr > th, -.table > tfoot > tr > th, -.table > thead > tr > td, -.table > tbody > tr > td, -.table > tfoot > tr > td { - padding: 12px 7px; - vertical-align: middle; } - -.table .th-description { - max-width: 150px; } - -.table .td-price { - font-size: 26px; - font-weight: 300; - margin-top: 5px; - position: relative; - top: 4px; - text-align: right; } - -.table .td-total { - font-weight: 700; - font-size: 1.57em; - padding-top: 20px; - text-align: right; } - -.table .td-actions .btn { - margin: 0px; } - -.table > tbody > tr { - position: relative; } - -.table-shopping > thead > tr > th { - font-size: 1em; - text-transform: uppercase; } - -.table-shopping > tbody > tr > td { - font-size: 1em; } - .table-shopping > tbody > tr > td b { - display: block; - margin-bottom: 5px; } - -.table-shopping .td-name { - font-weight: 400; - font-size: 1.5em; } - .table-shopping .td-name small { - color: #9A9A9A; - font-size: 0.75em; - font-weight: 300; } - -.table-shopping .td-number { - font-weight: 300; - font-size: 1.714em; } - -.table-shopping .td-name { - min-width: 200px; } - -.table-shopping .td-number { - text-align: right; - min-width: 145px; } - .table-shopping .td-number small { - margin-right: 3px; } - -.table-shopping .img-container { - width: 120px; - max-height: 160px; - overflow: hidden; - display: block; } - .table-shopping .img-container img { - width: 100%; } - -#tables .table-responsive { - margin-bottom: 30px; } - -.wrapper { - position: relative; - top: 0; - height: 100vh; } - .wrapper.wrapper-full-page { - min-height: 100vh; - height: auto; } - -.sidebar, -.off-canvas-sidebar { - position: fixed; - top: 0; - height: 100%; - bottom: 0; - width: 260px; - left: 0; - z-index: 1030; } - .sidebar .sidebar-wrapper, - .off-canvas-sidebar .sidebar-wrapper { - position: relative; - height: calc(100vh - 75px); - overflow: auto; - width: 260px; - z-index: 4; - padding-bottom: 100px; } - .sidebar .sidebar-wrapper .dropdown .dropdown-backdrop, - .off-canvas-sidebar .sidebar-wrapper .dropdown .dropdown-backdrop { - display: none !important; } - .sidebar .sidebar-wrapper .navbar-form, - .off-canvas-sidebar .sidebar-wrapper .navbar-form { - border: none; } - .sidebar .navbar-minimize, - .off-canvas-sidebar .navbar-minimize { - position: absolute; - right: 20px; - top: 2px; - opacity: 1; } - .sidebar .logo-tim, - .off-canvas-sidebar .logo-tim { - border-radius: 50%; - border: 1px solid #333; - display: block; - height: 61px; - width: 61px; - float: left; - overflow: hidden; } - .sidebar .logo-tim img, - .off-canvas-sidebar .logo-tim img { - width: 60px; - height: 60px; } - .sidebar .nav, - .off-canvas-sidebar .nav { - margin-top: 20px; - display: block; } - .sidebar .nav .caret, - .off-canvas-sidebar .nav .caret { - top: 14px; - position: absolute; - right: 10px; } - .sidebar .nav li > a + div .nav li > a, - .off-canvas-sidebar .nav li > a + div .nav li > a { - margin-top: 7px; } - .sidebar .nav li > a, - .off-canvas-sidebar .nav li > a { - margin: 10px 15px 0; - border-radius: 30px; - color: #FFFFFF; - display: block; - text-decoration: none; - position: relative; - text-transform: uppercase; - cursor: pointer; - font-size: 0.7142em; - padding: 10px 8px; - line-height: 1.625rem; } - .sidebar .nav li:first-child > a, - .off-canvas-sidebar .nav li:first-child > a { - margin: 0 15px; } - .sidebar .nav li:hover:not(.active) > a, - .sidebar .nav li:focus:not(.active) > a, - .off-canvas-sidebar .nav li:hover:not(.active) > a, - .off-canvas-sidebar .nav li:focus:not(.active) > a { - background-color: rgba(255, 255, 255, 0.1); } - .sidebar .nav li:hover:not(.active) > a i, - .sidebar .nav li:focus:not(.active) > a i, - .off-canvas-sidebar .nav li:hover:not(.active) > a i, - .off-canvas-sidebar .nav li:focus:not(.active) > a i { - color: #FFFFFF; } - .sidebar .nav li.active > a, - .off-canvas-sidebar .nav li.active > a { - background-color: #FFFFFF; - -webkit-box-shadow: 0 1px 15px 1px rgba(39, 39, 39, 0.1); - box-shadow: 0 1px 15px 1px rgba(39, 39, 39, 0.1); } - .sidebar .nav p, - .off-canvas-sidebar .nav p { - margin: 0; - line-height: 30px; - position: relative; - display: block; - height: auto; - white-space: nowrap; } - .sidebar .nav i, - .off-canvas-sidebar .nav i { - font-size: 20px; - float: left; - margin-right: 12px; - line-height: 30px; - width: 34px; - text-align: center; - color: rgba(255, 255, 255, 0.5); - position: relative; } - .sidebar .sidebar-background, - .off-canvas-sidebar .sidebar-background { - position: absolute; - z-index: 1; - height: 100%; - width: 100%; - display: block; - top: 0; - left: 0; - background-size: cover; - background-position: center center; } - .sidebar .sidebar-background:after, - .off-canvas-sidebar .sidebar-background:after { - position: absolute; - z-index: 3; - width: 100%; - height: 100%; - content: ""; - display: block; - background: #FFFFFF; - opacity: 1; } - .sidebar .logo, - .off-canvas-sidebar .logo { - position: relative; - padding: 0.5rem 0.7rem; - z-index: 4; } - .sidebar .logo a.logo-mini, - .off-canvas-sidebar .logo a.logo-mini { - opacity: 1; - float: left; - width: 34px; - text-align: center; - margin-left: 10px; - margin-right: 12px; } - .sidebar .logo a.logo-normal, - .off-canvas-sidebar .logo a.logo-normal { - display: block; - opacity: 1; - -webkit-transform: translate3d(0px, 0, 0); - transform: translate3d(0px, 0, 0); } - .sidebar .logo:after, - .off-canvas-sidebar .logo:after { - content: ''; - position: absolute; - bottom: 0; - right: 15px; - height: 1px; - width: calc(100% - 30px); - background-color: rgba(255, 255, 255, 0.5); } - .sidebar .logo p, - .off-canvas-sidebar .logo p { - float: left; - font-size: 20px; - margin: 10px 10px; - color: #FFFFFF; - line-height: 20px; - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; } - .sidebar .logo .simple-text, - .off-canvas-sidebar .logo .simple-text { - text-transform: uppercase; - padding: 0.5rem 0; - display: block; - white-space: nowrap; - font-size: 1em; - color: #FFFFFF; - text-decoration: none; - font-weight: 400; - line-height: 30px; - overflow: hidden; } - .sidebar .logo-tim, - .off-canvas-sidebar .logo-tim { - border-radius: 50%; - border: 1px solid #333; - display: block; - height: 61px; - width: 61px; - float: left; - overflow: hidden; } - .sidebar .logo-tim img, - .off-canvas-sidebar .logo-tim img { - width: 60px; - height: 60px; } - .sidebar:before, .sidebar:after, - .off-canvas-sidebar:before, - .off-canvas-sidebar:after { - display: block; - content: ""; - opacity: 1; - position: absolute; - width: 100%; - height: 100%; - top: 0; - left: 0; } - .sidebar:after, - .off-canvas-sidebar:after { - background: #888; - background: -webkit-gradient(linear, left top, left bottom, from(#888), color-stop(80%, #000)); - background: linear-gradient(#888 0%, #000 80%); - z-index: 3; } - .sidebar[data-color="blue"]:after, - .off-canvas-sidebar[data-color="blue"]:after { - background: #2CA8FF; } - .sidebar[data-color="blue"] .nav li.active > a, - .off-canvas-sidebar[data-color="blue"] .nav li.active > a { - color: #2CA8FF; } - .sidebar[data-color="blue"] .nav li.active > a i, - .off-canvas-sidebar[data-color="blue"] .nav li.active > a i { - color: #2CA8FF; } - .sidebar[data-color="green"]:after, - .off-canvas-sidebar[data-color="green"]:after { - background: #18ce0f; } - .sidebar[data-color="green"] .nav li.active > a, - .off-canvas-sidebar[data-color="green"] .nav li.active > a { - color: #18ce0f; } - .sidebar[data-color="green"] .nav li.active > a i, - .off-canvas-sidebar[data-color="green"] .nav li.active > a i { - color: #18ce0f; } - .sidebar[data-color="orange"]:after, - .off-canvas-sidebar[data-color="orange"]:after { - background: #f96332; } - .sidebar[data-color="orange"] .nav li.active > a, - .off-canvas-sidebar[data-color="orange"] .nav li.active > a { - color: #f96332; } - .sidebar[data-color="orange"] .nav li.active > a i, - .off-canvas-sidebar[data-color="orange"] .nav li.active > a i { - color: #f96332; } - .sidebar[data-color="red"]:after, - .off-canvas-sidebar[data-color="red"]:after { - background: #FF3636; } - .sidebar[data-color="red"] .nav li.active > a, - .off-canvas-sidebar[data-color="red"] .nav li.active > a { - color: #FF3636; } - .sidebar[data-color="red"] .nav li.active > a i, - .off-canvas-sidebar[data-color="red"] .nav li.active > a i { - color: #FF3636; } - .sidebar[data-color="yellow"]:after, - .off-canvas-sidebar[data-color="yellow"]:after { - background: #FFB236; } - .sidebar[data-color="yellow"] .nav li.active > a, - .off-canvas-sidebar[data-color="yellow"] .nav li.active > a { - color: #FFB236; } - .sidebar[data-color="yellow"] .nav li.active > a i, - .off-canvas-sidebar[data-color="yellow"] .nav li.active > a i { - color: #FFB236; } - -.visible-on-sidebar-regular { - display: inline-block !important; } - -.visible-on-sidebar-mini { - display: none !important; } - -.off-canvas-sidebar .nav > li > a, -.off-canvas-sidebar .nav > li > a:hover { - color: #FFFFFF; } - -.off-canvas-sidebar .nav > li > a:focus { - background: rgba(200, 200, 200, 0.2); } - -.main-panel { - position: relative; - float: right; - width: calc(100% - 260px); - background-color: #E3E3E3; - background-color: #ebecf1; - -webkit-transition: all 0.5s cubic-bezier(0.685, 0.0473, 0.346, 1); - transition: all 0.5s cubic-bezier(0.685, 0.0473, 0.346, 1); } - .main-panel > .content { - padding: 0 30px 30px; - min-height: calc(100vh - 123px); - margin-top: -30px; } - .main-panel > .navbar { - margin-bottom: 0; } - .main-panel .header { - margin-bottom: 50px; } - -.perfect-scrollbar-on .sidebar, -.perfect-scrollbar-on .main-panel { - height: 100%; - max-height: 100%; } - -@media (min-width: 991px) { - .sidebar { - display: block; - -webkit-box-shadow: 0px 2px 22px 0 rgba(0, 0, 0, 0.2), 0px 2px 30px 0 rgba(0, 0, 0, 0.35); - box-shadow: 0px 2px 22px 0 rgba(0, 0, 0, 0.2), 0px 2px 30px 0 rgba(0, 0, 0, 0.35); } } - -.panel-header { - height: 260px; - padding-top: 80px; - padding-bottom: 45px; - background: #141E30; - /* fallback for old browsers */ - background: -webkit-gradient(linear, left top, right top, from(#0c2646), color-stop(60%, #204065), to(#2a5788)); - background: linear-gradient(to right, #0c2646 0%, #204065 60%, #2a5788 100%); - position: relative; - overflow: hidden; } - .panel-header .header .title { - color: #FFFFFF; } - .panel-header .header .category { - max-width: 600px; - color: rgba(255, 255, 255, 0.5); - margin: 0 auto; - font-size: 13px; } - .panel-header .header .category a { - color: #FFFFFF; } - -.panel-header-sm { - height: 135px; } - -.panel-header-lg { - height: 380px; } - -.card { - border: 0; - border-radius: 0.1875rem; - display: inline-block; - position: relative; - width: 100%; - margin-bottom: 20px; - -webkit-box-shadow: 0 1px 15px 1px rgba(39, 39, 39, 0.1); - box-shadow: 0 1px 15px 1px rgba(39, 39, 39, 0.1); } - .card .card-body { - padding: 15px 15px 10px 15px; } - .card .card-body.table-full-width { - padding-left: 0; - padding-right: 0; } - .card .card-header { - padding: 15px 15px 0; - border: 0; } - .card .card-header:not([data-background-color]) { - background-color: transparent; } - .card .card-header .card-title { - margin-top: 10px; } - .card .map { - height: 500px; - border-radius: 0.1875rem; } - .card .map.map-big { - height: 400px; } - .card[data-background-color="orange"] { - background-color: #f96332; } - .card[data-background-color="orange"] .card-header { - background-color: #f96332; } - .card[data-background-color="orange"] .card-footer .stats { - color: #FFFFFF; } - .card[data-background-color="red"] { - background-color: #FF3636; } - .card[data-background-color="yellow"] { - background-color: #FFB236; } - .card[data-background-color="blue"] { - background-color: #2CA8FF; } - .card[data-background-color="green"] { - background-color: #18ce0f; } - .card .image { - overflow: hidden; - height: 200px; - position: relative; } - .card .avatar { - width: 30px; - height: 30px; - overflow: hidden; - border-radius: 50%; - margin-bottom: 15px; } - .card label { - font-size: 0.8571em; - margin-bottom: 5px; - color: #9A9A9A; } - .card .card-footer { - background-color: transparent; - border: 0; } - .card .card-footer .stats i { - margin-right: 5px; - position: relative; - top: 2px; } - .card .card-footer .btn { - margin: 0; } - -.card-user .image { - height: 120px; } - -.card-user .author { - text-align: center; - text-transform: none; - margin-top: -77px; } - .card-user .author a + p.description { - margin-top: -7px; } - -.card-user .avatar { - width: 124px; - height: 124px; - border: 1px solid #FFFFFF; - position: relative; } - -.card-user .card-body { - min-height: 240px; } - -.card-user hr { - margin: 5px 15px; } - -.card-user .button-container { - margin-bottom: 6px; - text-align: center; } - -.card-plain { - background: transparent; - -webkit-box-shadow: none; - box-shadow: none; } - .card-plain .card-header, - .card-plain .card-footer { - margin-left: 0; - margin-right: 0; - background-color: transparent; } - .card-plain:not(.card-subcategories).card-body { - padding-left: 0; - padding-right: 0; } - -.card-chart .card-header .card-title { - margin-top: 10px; - margin-bottom: 0; } - -.card-chart .card-header .card-category { - margin-bottom: 5px; } - -.card-chart .table { - margin-bottom: 0; } - .card-chart .table td { - border-top: none; - border-bottom: 1px solid #e9ecef; } - -.card-chart .card-progress { - margin-top: 30px; } - -.card-chart .chart-area { - height: 190px; - width: calc(100% + 30px); - margin-left: -15px; - margin-right: -15px; } - -.card-chart .card-footer { - margin-top: 15px; } - .card-chart .card-footer .stats { - color: #9A9A9A; } - -.card-chart .dropdown { - position: absolute; - right: 20px; - top: 20px; } - .card-chart .dropdown .btn { - margin: 0; } - -.footer { - padding: 24px 0; } - .footer.footer-default { - background-color: #f2f2f2; } - .footer nav { - display: inline-block; - float: left; - padding-left: 7px; } - .footer ul { - margin-bottom: 0; - padding: 0; - list-style: none; } - .footer ul li { - display: inline-block; } - .footer ul li a { - color: inherit; - padding: 0.5rem; - font-size: 0.8571em; - text-transform: uppercase; - text-decoration: none; } - .footer ul li a:hover { - text-decoration: none; } - .footer .copyright { - font-size: 0.8571em; - line-height: 1.8; } - .footer:after { - display: table; - clear: both; - content: " "; } - -.fixed-plugin { - position: fixed; - right: 0; - width: 64px; - background: rgba(0, 0, 0, 0.3); - z-index: 1031; - border-radius: 8px 0 0 8px; - text-align: center; - top: 120px; } - .fixed-plugin li > a, - .fixed-plugin .badge { - transition: all .34s; - -webkit-transition: all .34s; - -moz-transition: all .34s; } - .fixed-plugin .fa-cog { - color: #FFFFFF; - padding: 10px; - border-radius: 0 0 6px 6px; - width: auto; } - .fixed-plugin .dropdown-menu { - right: 80px; - left: auto !important; - top: -52px !important; - width: 290px; - border-radius: 0.1875rem; - padding: 0 10px; } - .fixed-plugin .dropdown .dropdown-menu .now-ui-icons { - top: 5px; } - .fixed-plugin .dropdown-menu:after, - .fixed-plugin .dropdown-menu:before { - right: 10px; - margin-left: auto; - left: auto; } - .fixed-plugin .fa-circle-thin { - color: #FFFFFF; } - .fixed-plugin .active .fa-circle-thin { - color: #00bbff; } - .fixed-plugin .dropdown-menu > .active > a, - .fixed-plugin .dropdown-menu > .active > a:hover, - .fixed-plugin .dropdown-menu > .active > a:focus { - color: #777777; - text-align: center; } - .fixed-plugin img { - border-radius: 0; - width: 100%; - height: 100px; - margin: 0 auto; } - .fixed-plugin .dropdown-menu li > a:hover, - .fixed-plugin .dropdown-menu li > a:focus { - -webkit-box-shadow: none; - box-shadow: none; } - .fixed-plugin .badge { - border: 3px solid #FFFFFF; - border-radius: 50%; - cursor: pointer; - display: inline-block; - height: 23px; - margin-right: 5px; - position: relative; - width: 23px; } - .fixed-plugin .badge.active, - .fixed-plugin .badge:hover { - border-color: #00bbff; } - .fixed-plugin .badge-blue { - background-color: #2CA8FF; } - .fixed-plugin .badge-green { - background-color: #18ce0f; } - .fixed-plugin .badge-orange { - background-color: #f96332; } - .fixed-plugin .badge-yellow { - background-color: #FFB236; } - .fixed-plugin .badge-red { - background-color: #FF3636; } - .fixed-plugin h5 { - font-size: 14px; - margin: 10px; } - .fixed-plugin .dropdown-menu li { - display: block; - padding: 18px 2px; - width: 25%; - float: left; } - .fixed-plugin li.adjustments-line, - .fixed-plugin li.header-title, - .fixed-plugin li.button-container { - width: 100%; - height: 50px; - min-height: inherit; } - .fixed-plugin li.button-container { - height: auto; } - .fixed-plugin li.button-container div { - margin-bottom: 5px; } - .fixed-plugin #sharrreTitle { - text-align: center; - padding: 10px 0; - height: 50px; } - .fixed-plugin li.header-title { - height: 30px; - line-height: 25px; - font-size: 12px; - font-weight: 600; - text-align: center; - text-transform: uppercase; } - .fixed-plugin .adjustments-line p { - float: left; - display: inline-block; - margin-bottom: 0; - font-size: 1em; - color: #3C4858; } - .fixed-plugin .adjustments-line a { - color: transparent; } - .fixed-plugin .adjustments-line a .badge-colors { - position: relative; - top: -2px; } - .fixed-plugin .adjustments-line a a:hover, - .fixed-plugin .adjustments-line a a:focus { - color: transparent; } - .fixed-plugin .adjustments-line .togglebutton { - text-align: center; } - .fixed-plugin .adjustments-line .togglebutton .label-switch { - position: relative; - left: -10px; - font-size: 0.7142em; - color: #888; } - .fixed-plugin .adjustments-line .togglebutton .label-switch.label-right { - left: 10px; } - .fixed-plugin .adjustments-line .togglebutton .toggle { - margin-right: 0; } - .fixed-plugin .adjustments-line .dropdown-menu > li.adjustments-line > a { - padding-right: 0; - padding-left: 0; - border-bottom: 1px solid #ddd; - border-radius: 0; - margin: 0; } - .fixed-plugin .dropdown-menu > li > a.img-holder { - font-size: 16px; - text-align: center; - border-radius: 10px; - background-color: #FFF; - border: 3px solid #FFF; - padding-left: 0; - padding-right: 0; - opacity: 1; - cursor: pointer; - display: block; - max-height: 100px; - overflow: hidden; - padding: 0; } - .fixed-plugin .dropdown-menu > li > a.img-holder img { - margin-top: auto; } - .fixed-plugin .dropdown-menu > li a.switch-trigger:hover, - .fixed-plugin .dropdown-menu > li > a.switch-trigger:focus { - background-color: transparent; } - .fixed-plugin .dropdown-menu > li:hover > a.img-holder, .fixed-plugin .dropdown-menu > li:focus > a.img-holder { - border-color: rgba(0, 187, 255, 0.53); } - .fixed-plugin .dropdown-menu > .active > a.img-holder, - .fixed-plugin .dropdown-menu > .active > a.img-holder { - border-color: #00bbff; - background-color: #FFFFFF; } - .fixed-plugin .btn-social { - width: 50%; - display: block; - width: 48%; - float: left; - font-weight: 600; } - .fixed-plugin .btn-social i { - margin-right: 5px; } - .fixed-plugin .btn-social:first-child { - margin-right: 2%; } - .fixed-plugin .dropdown .dropdown-menu { - -webkit-transform: translateY(-15%); - transform: translateY(-15%); - top: 27px; - opacity: 0; - -webkit-transform-origin: 0 0; - transform-origin: 0 0; } - .fixed-plugin .dropdown .dropdown-menu:before { - border-bottom: 0.4em solid transparent; - border-left: 0.4em solid rgba(0, 0, 0, 0.2); - border-top: 0.4em solid transparent; - right: -16px; - top: 46px; } - .fixed-plugin .dropdown .dropdown-menu:after { - border-bottom: 0.4em solid transparent; - border-left: .4em solid #FFFFFF; - border-top: 0.4em solid transparent; - right: -16px; } - .fixed-plugin .dropdown .dropdown-menu:before, .fixed-plugin .dropdown .dropdown-menu:after { - content: ""; - display: inline-block; - position: absolute; - top: 74px; - width: 16px; - transform: translateY(-50%); - -webkit-transform: translateY(-50%); - -moz-transform: translateY(-50%); } - .fixed-plugin .dropdown.show .dropdown-menu { - opacity: 1; - -webkit-transform: translateY(-13%); - transform: translateY(-13%); - -webkit-transform-origin: 0 0; - transform-origin: 0 0; } - .fixed-plugin .bootstrap-switch { - margin: 0; } - -@media screen and (max-width: 991px) { - .profile-photo .profile-photo-small { - margin-left: -2px; } - .button-dropdown { - display: none; } - #minimizeSidebar { - display: none; } - .navbar .container-fluid { - padding-right: 15px; - padding-left: 15px; } - .navbar .navbar-collapse .input-group { - margin: 0; - margin-top: 5px; } - .navbar .navbar-nav .nav-item:first-child { - margin-top: 10px; } - .navbar .navbar-nav .nav-item:not(:last-child) { - margin-bottom: 10px; } - .navbar .dropdown.show .dropdown-menu { - display: block; } - .navbar .dropdown .dropdown-menu { - display: none; } - .navbar .dropdown.show .dropdown-menu, - .navbar .dropdown .dropdown-menu { - background-color: transparent; - border: 0; - -webkit-transition: none; - transition: none; - -webkit-box-shadow: none; - box-shadow: none; - width: auto; - margin: 0px 1rem; - margin-top: 0px; } - .navbar .dropdown.show .dropdown-menu:before, - .navbar .dropdown .dropdown-menu:before { - display: none; } - .navbar .dropdown-menu .dropdown-item:focus, - .navbar .dropdown-menu .dropdown-item:hover { - color: #FFFFFF; } - .navbar.bg-white .dropdown-menu .dropdown-item:focus, - .navbar.bg-white .dropdown-menu .dropdown-item:hover { - color: #888; } - .navbar .navbar-toggler-bar { - display: block; - position: relative; - width: 22px; - height: 1px; - border-radius: 1px; - background: #FFFFFF; } - .navbar .navbar-toggler-bar + .navbar-toggler-bar { - margin-top: 7px; } - .navbar .navbar-toggler-bar + .navbar-toggler-bar.navbar-kebab { - margin-top: 3px; } - .navbar .navbar-toggler-bar.bar2 { - width: 17px; - -webkit-transition: width .2s linear; - transition: width .2s linear; } - .navbar.bg-white:not(.navbar-transparent) .navbar-toggler-bar { - background-color: #888; } - .navbar .toggled .navbar-toggler-bar { - width: 24px; } - .navbar .toggled .navbar-toggler-bar + .navbar-toggler-bar { - margin-top: 5px; } - .wrapper { - -webkit-transition: all 0.5s cubic-bezier(0.685, 0.0473, 0.346, 1); - transition: all 0.5s cubic-bezier(0.685, 0.0473, 0.346, 1); } - .nav-open .main-panel { - right: 0; - -webkit-transform: translate3d(260px, 0, 0); - transform: translate3d(260px, 0, 0); } - .nav-open .sidebar { - -webkit-transform: translate3d(0px, 0, 0); - transform: translate3d(0px, 0, 0); } - .nav-open body { - position: relative; - overflow-x: hidden; } - .nav-open .menu-on-right .main-panel { - -webkit-transform: translate3d(-260px, 0, 0); - transform: translate3d(-260px, 0, 0); } - .nav-open .menu-on-right .navbar-collapse, - .nav-open .menu-on-right .sidebar { - -webkit-transform: translate3d(0px, 0, 0); - transform: translate3d(0px, 0, 0); } - .nav-open .menu-on-right .navbar-translate { - -webkit-transform: translate3d(-300px, 0, 0); - transform: translate3d(-300px, 0, 0); } - .nav-open .menu-on-right #bodyClick { - right: 260px; - left: auto; } - .menu-on-right .sidebar { - left: auto; - right: 0; - -webkit-transform: translate3d(260px, 0, 0); - transform: translate3d(260px, 0, 0); } - .bar1, - .bar2, - .bar3 { - outline: 1px solid transparent; } - .bar1 { - top: 0px; - -webkit-animation: topbar-back 500ms linear 0s; - animation: topbar-back 500ms 0s; - -webkit-animation-fill-mode: forwards; - animation-fill-mode: forwards; } - .bar2 { - opacity: 1; } - .bar3 { - bottom: 0px; - -webkit-animation: bottombar-back 500ms linear 0s; - animation: bottombar-back 500ms 0s; - -webkit-animation-fill-mode: forwards; - animation-fill-mode: forwards; } - .toggled .bar1 { - top: 6px; - -webkit-animation: topbar-x 500ms linear 0s; - animation: topbar-x 500ms 0s; - -webkit-animation-fill-mode: forwards; - animation-fill-mode: forwards; } - .toggled .bar2 { - opacity: 0; } - .toggled .bar3 { - bottom: 6px; - -webkit-animation: bottombar-x 500ms linear 0s; - animation: bottombar-x 500ms 0s; - -webkit-animation-fill-mode: forwards; - animation-fill-mode: forwards; } - @keyframes topbar-x { - 0% { - top: 0px; - -webkit-transform: rotate(0deg); - transform: rotate(0deg); } - 45% { - top: 6px; - -webkit-transform: rotate(145deg); - transform: rotate(145deg); } - 75% { - -webkit-transform: rotate(130deg); - transform: rotate(130deg); } - 100% { - -webkit-transform: rotate(135deg); - transform: rotate(135deg); } } - @-webkit-keyframes topbar-x { - 0% { - top: 0px; - -webkit-transform: rotate(0deg); } - 45% { - top: 6px; - -webkit-transform: rotate(145deg); } - 75% { - -webkit-transform: rotate(130deg); } - 100% { - -webkit-transform: rotate(135deg); } } - @keyframes topbar-back { - 0% { - top: 6px; - -webkit-transform: rotate(135deg); - transform: rotate(135deg); } - 45% { - -webkit-transform: rotate(-10deg); - transform: rotate(-10deg); } - 75% { - -webkit-transform: rotate(5deg); - transform: rotate(5deg); } - 100% { - top: 0px; - -webkit-transform: rotate(0); - transform: rotate(0); } } - @-webkit-keyframes topbar-back { - 0% { - top: 6px; - -webkit-transform: rotate(135deg); } - 45% { - -webkit-transform: rotate(-10deg); } - 75% { - -webkit-transform: rotate(5deg); } - 100% { - top: 0px; - -webkit-transform: rotate(0); } } - @keyframes bottombar-x { - 0% { - bottom: 0px; - -webkit-transform: rotate(0deg); - transform: rotate(0deg); } - 45% { - bottom: 6px; - -webkit-transform: rotate(-145deg); - transform: rotate(-145deg); } - 75% { - -webkit-transform: rotate(-130deg); - transform: rotate(-130deg); } - 100% { - -webkit-transform: rotate(-135deg); - transform: rotate(-135deg); } } - @-webkit-keyframes bottombar-x { - 0% { - bottom: 0px; - -webkit-transform: rotate(0deg); } - 45% { - bottom: 6px; - -webkit-transform: rotate(-145deg); } - 75% { - -webkit-transform: rotate(-130deg); } - 100% { - -webkit-transform: rotate(-135deg); } } - @keyframes bottombar-back { - 0% { - bottom: 6px; - -webkit-transform: rotate(-135deg); - transform: rotate(-135deg); } - 45% { - -webkit-transform: rotate(10deg); - transform: rotate(10deg); } - 75% { - -webkit-transform: rotate(-5deg); - transform: rotate(-5deg); } - 100% { - bottom: 0px; - -webkit-transform: rotate(0); - transform: rotate(0); } } - @-webkit-keyframes bottombar-back { - 0% { - bottom: 6px; - -webkit-transform: rotate(-135deg); } - 45% { - -webkit-transform: rotate(10deg); } - 75% { - -webkit-transform: rotate(-5deg); } - 100% { - bottom: 0px; - -webkit-transform: rotate(0); } } - @-webkit-keyframes fadeIn { - 0% { - opacity: 0; } - 100% { - opacity: 1; } } - @keyframes fadeIn { - 0% { - opacity: 0; } - 100% { - opacity: 1; } } - #bodyClick { - height: 100%; - width: 100%; - position: fixed; - opacity: 1; - top: 0; - right: 0; - left: 260px; - content: ""; - z-index: 9999; - overflow-x: hidden; - background-color: transparent; - -webkit-transition: all 0.5s cubic-bezier(0.685, 0.0473, 0.346, 1); - transition: all 0.5s cubic-bezier(0.685, 0.0473, 0.346, 1); } - .footer .copyright { - text-align: right; } - .section-nucleo-icons .icons-container { - margin-top: 65px; } - .navbar-nav .nav-link i.fa, - .navbar-nav .nav-link i.now-ui-icons { - opacity: .5; } - .sidebar, - .bootstrap-navbar { - position: fixed; - display: block; - top: 0; - height: 100%; - width: 260px; - right: auto; - left: 0; - z-index: 1032; - visibility: visible; - overflow-y: visible; - padding: 0; - -webkit-transition: all 0.5s cubic-bezier(0.685, 0.0473, 0.346, 1); - transition: all 0.5s cubic-bezier(0.685, 0.0473, 0.346, 1); - -webkit-transform: translate3d(-260px, 0, 0); - transform: translate3d(-260px, 0, 0); } - .main-panel { - width: 100%; } } - -@media screen and (min-width: 992px) { - .navbar-collapse { - background: none !important; } - .navbar .navbar-toggle { - display: none; } - .navbar-nav .nav-link.profile-photo { - padding: 0; - margin: 7px 0.7rem; } - .section-nucleo-icons .icons-container { - margin: 0 0 0 auto; } - .dropdown-menu .dropdown-item { - color: inherit; } - .footer .copyright { - float: right; - padding-right: 15px; } } - -@media screen and (max-width: 768px) { - .nav-tabs { - display: inline-block; - width: 100%; - padding-left: 100px; - padding-right: 100px; - text-align: center; } - .nav-tabs .nav-item > .nav-link { - margin-bottom: 5px; } - .card-stats [class*="col-"] .statistics::after { - display: none; } - .main-panel .content { - padding-left: 15px; - padding-right: 15px; } - .footer nav { - display: block; - margin-bottom: 5px; - float: none; } - .landing-page .section-story-overview .image-container:nth-child(2) { - margin-left: 0; - margin-bottom: 30px; } } - -@media screen and (max-width: 576px) { - .navbar[class*='navbar-toggleable-'] .container { - margin-left: 0; - margin-right: 0; } - .card-contributions .card-stats { - -webkit-box-orient: vertical; - -webkit-box-direction: normal; - -ms-flex-direction: column; - flex-direction: column; } - .card-contributions .card-stats .bootstrap-switch { - margin-bottom: 15px; } - .footer .copyright { - text-align: center; } - .section-nucleo-icons .icons-container i { - font-size: 30px; } - .section-nucleo-icons .icons-container i:nth-child(6) { - font-size: 48px; } - .page-header .container h6.category-absolute { - width: 90%; } } - -/*# sourceMappingURL=now-ui-dashboard.css.map */ diff --git a/web/templates/boilerplate/assets/css/now-ui-dashboard.css.map b/web/templates/boilerplate/assets/css/now-ui-dashboard.css.map deleted file mode 100644 index ec11e86..0000000 --- a/web/templates/boilerplate/assets/css/now-ui-dashboard.css.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"sources":["now-ui-dashboard.scss","now-ui-dashboard/_variables.scss","now-ui-dashboard/plugins/_plugin-animate-bootstrap-notify.scss","now-ui-dashboard/plugins/_plugin-perfect-scrollbar.scss","now-ui-dashboard/_buttons.scss","now-ui-dashboard/mixins/_buttons.scss","now-ui-dashboard/mixins/_transparency.scss","now-ui-dashboard/mixins/_vendor-prefixes.scss","now-ui-dashboard/mixins/_inputs.scss","now-ui-dashboard/_inputs.scss","now-ui-dashboard/_typography.scss","now-ui-dashboard/_misc.scss","now-ui-dashboard/_checkboxes-radio.scss","now-ui-dashboard/_navbar.scss","now-ui-dashboard/_page-header.scss","now-ui-dashboard/mixins/_page-header.scss","now-ui-dashboard/_dropdown.scss","now-ui-dashboard/mixins/_dropdown.scss","now-ui-dashboard/_alerts.scss","now-ui-dashboard/_images.scss","now-ui-dashboard/_nucleo-outline.scss","now-ui-dashboard/_tables.scss","now-ui-dashboard/_sidebar-and-main-panel.scss","now-ui-dashboard/_cards.scss","now-ui-dashboard/cards/_card-chart.scss","now-ui-dashboard/_footers.scss","now-ui-dashboard/_fixed-plugin.scss","now-ui-dashboard/_responsive.scss"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AC6DH,mCAAmC;AAUnC,+BAA+B;ACrD/B;;;;;EAKE;AAEF;EACE,+BAA8B;EAC9B,uBAAsB;EACtB,kCAAiC;EACjC,0BAAyB,EAC1B;;AAED;EACE,4CAA2C;EAC3C,oCAAmC,EACpC;;AAED;EACE,+BAA8B;EAC9B,uBAAsB,EACvB;;AAED;;EAEE,iCAAgC;EAChC,yBAAwB,EACzB;;AAED;;EAEE,iCAAgC;EAChC,yBAAwB,EACzB;;AAED;EACE;IACE,wCAAuC;IACvC,gCAA+B,EAAA;EAGjC;IACE,4CAA2C;IAC3C,oCAAmC,EAAA;EAGrC;IACE,2CAA0C;IAC1C,mCAAkC,EAAA,EAAA;;AAItC;EACE;IACE,wCAAuC;IACvC,gCAA+B,EAAA;EAGjC;IACE,4CAA2C;IAC3C,oCAAmC,EAAA;EAGrC;IACE,2CAA0C;IAC1C,mCAAkC,EAAA,EAAA;;AAItC;EACE,8BAA6B;EAC7B,sBAAqB,EACtB;;AAID;EACE;IACE,WAAU;IACV,4CAA2C;IAC3C,oCAAmC,EAAA;EAGrC;IACE,WAAU;IACV,wBAAuB;IACvB,gBAAe,EAAA,EAAA;;AAInB;EACE;IACE,WAAU;IACV,4CAA2C;IAC3C,oCAAmC,EAAA;EAGrC;IACE,WAAU;IACV,wBAAuB;IACvB,gBAAe,EAAA,EAAA;;AAInB;EACE,mCAAkC;EAClC,2BAA0B,EAC3B;;AAGD;EACE;IACE,WAAU,EAAA;EAGZ;IACE,WAAU,EAAA,EAAA;;AAId;EACE;IACE,WAAU,EAAA;EAGZ;IACE,WAAU,EAAA,EAAA;;AAId;EACE,gCAA+B;EAC/B,wBAAuB,EACxB;;AAED;EACE;IACE,WAAU,EAAA;EAGZ;IACE,WAAU;IACV,2CAA0C;IAC1C,mCAAkC,EAAA,EAAA;;AAItC;EACE;IACE,WAAU,EAAA;EAGZ;IACE,WAAU;IACV,2CAA0C;IAC1C,mCAAkC,EAAA,EAAA;;AAItC;EACE,oCAAmC;EACnC,4BAA2B,EAC5B;;AAED;EACE;IACE,WAAU,EAAA;EAGZ;IACE,WAAU;IACV,4CAA2C;IAC3C,oCAAmC,EAAA,EAAA;;AAIvC;EACE;IACE,WAAU,EAAA;EAGZ;IACE,WAAU;IACV,4CAA2C;IAC3C,oCAAmC,EAAA,EAAA;;AAIvC;EACE,kCAAiC;EACjC,0BAAyB,EAC1B;;AClOD,+BAA+B;AAC/B;EACE,uBAAsB;EACtB,mBAAkB;EAClB,4BAA2B;EAC3B,yBAAwB,EAAI;;AACQ;EAClC;IACE,0BAAyB,EAAI,EAAA;;AACjC;EACE;IACE,0BAAyB,EAAI,EAAA;;AACjC;;EAEE,eAAc;EACd,8BAA6B,EAAI;;AACnC;EACE,uBAAsB;EACtB,aAAY,EAAI;;AAChB;EACE,uBAAsB;EACtB,aAAY,EAAI;;AACpB;EACE,uBAAsB;EACtB,aAAY,EAAI;;AAChB;EACE,uBAAsB;EACtB,YAAW,EAAI;;AACnB;EACE,cAAa;EACb,mBAAkB;EAClB,oCAAoC;EACpC,WAAU;EACV,oEAAmE;EAGnE,4DAA2D;EAC3D,YAAW;EACX,oDAAoD;EACpD,aAAY,EAAI;;AAChB;EACE,mBAAkB;EAClB,oCAAoC;EACpC,uBAAsB;EAGtB,mBAAkB;EAClB,iIAAgI;EAIhI,yHAAgH;EAAhH,iHAAgH;EAEhH,YAAW;EACX,+CAA+C;EAC/C,YAAW,EAAI;;AACjB;EACE,aAAY,EAAI;;AACpB;EACE,cAAa;EACb,mBAAkB;EAClB,oCAAoC;EACpC,WAAU;EACV,oEAAmE;EAGnE,4DAA2D;EAC3D,SAAQ;EACR,mDAAmD;EACnD,YAAW,EAAI;;AACf;EACE,mBAAkB;EAClB,oCAAoC;EACpC,uBAAsB;EAGtB,mBAAkB;EAClB,iIAAgI;EAIhI,yHAAgH;EAAhH,iHAAgH;EAEhH,WAAU;EACV,8CAA8C;EAC9C,WAAU,EAAI;;AAChB;EACE,YAAW,EAAI;;AACnB;EACE,uBAAsB;EACtB,aAAY,EAAI;;AAChB;EACE,uBAAsB;EACtB,aAAY,EAAI;;AACpB;EACE,uBAAsB;EACtB,aAAY,EAAI;;AAChB;EACE,uBAAsB;EACtB,YAAW,EAAI;;AACnB;;EAEE,aAAY,EAAI;;AAClB;EACE,uBAAsB;EACtB,aAAY,EAAI;;AAChB;EACE,uBAAsB,EAAI;;AAC9B;EACE,uBAAsB;EACtB,aAAY,EAAI;;AAChB;EACE,uBAAsB,EAAI;;AChHhC;;EAEI,kBHM4B;EGL5B,iBHoK+B;EGnK/B,oBH4JmC;EG3JnC,oBHyK+B;EGxK/B,gBAAe;EACf,aAAY;EACZ,iBAAe;EACf,yBH0HqC;EGzHrC,mBH2F+B;EG1F/B,gBAAe;ECTf,uBJ4C6B;EI6EzB,eJjH4B,EG0EnC;EChFG;;;;;;;;;;;;;;;;;;IAWI,0BJgCgD;II/BhD,eJN4B;IIO5B,yBAAgB;YAAhB,iBAAgB,EACnB;EAED;;IACI,oDAA0C;YAA1C,4CAA0C,EAC7C;EAMG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAMI,uBJYqB;IIXrB,mBJWqB,EIVxB;EA0FL;;IACI,YJjFyB;IIkFzB,mBJlFyB,EI4F5B;IARG;;;;MAGI,8BJ1F4B;MI2F5B,eJvF4C;MIwF5C,sBJxF4C;MIyF5C,yBAAgB;cAAhB,iBAAgB,EACnB;EAGL;;IACI,YJ/FyB,EIyG5B;IARG;;;;MAGI,8BJvG4B;MIwG5B,eJpG4C;MIqG5C,sBAAqB;MACrB,yBAAgB;cAAhB,iBAAgB,EACnB;EDtJT;;;IEGE,WFcwB;IEXxB,2BAAQ;IFYF,sBAAqB,EACxB;EAnBL;;;;;;IGCE,yBHsB+B;IGrBvB,iBHqBuB;IACxB,sBAAqB,EACzB;EAzBL;;IA4BM,UAAS,EACV;EA7BL;;IAiCQ,iBH8GgC;IG7GhC,oBH6GgC;IG5GhC,gBH4GgC;IG3GhC,WAAU;IACV,qBH2GiC;IG1GjC,iBAAgB;IAChB,mBAAkB;IAClB,oBAAmB,EAsCtB;IA9EL;;MA2CY,WAAU,EACb;IA5CT;;MA+CY,iBHmG4B;MGlG5B,oBHkG4B;MGjG5B,gBHiG4B,EG3F/B;MAvDT;;;;QAqDgB,qBH4FyB,EG3F5B;IAtDb;;MA0DY,eH0F0B;MGzF1B,kBHyF0B;MGxF1B,cHwF0B,EGlF7B;MAlET;;;;QAgEgB,oBHmFwB,EGlF3B;IAjEb;;;;MAsEY,mBAAkB;MAClB,SAAQ;MACR,UAAS;MACT,2CAAkC;cAAlC,mCAAkC;MAClC,uBAAsB;MACtB,YAAW,EACd;EA5ET;;IAiFQ,mBAAkB;IAClB,SAAQ,EACX;;AAKL;ECtFI,0BJgDgC;EIyE5B,eJjH4B,EG8EyC;ECpFzE;;;;IAWI,0BJoCgD;IInChD,eJN4B;IIO5B,yBAAgB;YAAhB,iBAAgB,EACnB;EAED;IACI,oDAA0C;YAA1C,4CAA0C,EAC7C;EAMG;;;;;;;IAMI,0BJgBwB;IIfxB,sBJewB,EId3B;EA0FL;IACI,eJ7E4B;II8E5B,sBJ9E4B,EIwF/B;IARG;MAGI,8BJ1F4B;MI2F5B,eJnF4C;MIoF5C,sBJpF4C;MIqF5C,yBAAgB;cAAhB,iBAAgB,EACnB;EAGL;IACI,eJ3F4B,EIqG/B;IARG;MAGI,8BJvG4B;MIwG5B,eJhG4C;MIiG5C,sBAAqB;MACrB,yBAAgB;cAAhB,iBAAgB,EACnB;;AD7DT;ECvFI,0BJqDgC;EIoE5B,eJjH4B,EG+EyC;ECrFzE;;;;IAWI,0BJyCgD;IIxChD,eJN4B;IIO5B,yBAAgB;YAAhB,iBAAgB,EACnB;EAED;IACI,oDAA0C;YAA1C,4CAA0C,EAC7C;EAMG;;;;;;;IAMI,0BJqBwB;IIpBxB,sBJoBwB,EInB3B;EA0FL;IACI,eJxE4B;IIyE5B,sBJzE4B,EImF/B;IARG;MAGI,8BJ1F4B;MI2F5B,eJ9E4C;MI+E5C,sBJ/E4C;MIgF5C,yBAAgB;cAAhB,iBAAgB,EACnB;EAGL;IACI,eJtF4B,EIgG/B;IARG;MAGI,8BJvG4B;MIwG5B,eJ3F4C;MI4F5C,sBAAqB;MACrB,yBAAgB;cAAhB,iBAAgB,EACnB;;AD5DT;ECxFI,0BJ0DgC;EI+D5B,eJjH4B,EGgFmC;ECtFnE;;;;IAWI,0BJ8C6C;II7C7C,eJN4B;IIO5B,yBAAgB;YAAhB,iBAAgB,EACnB;EAED;IACI,oDAA0C;YAA1C,4CAA0C,EAC7C;EAMG;;;;;;;IAMI,0BJ0BwB;IIzBxB,sBJyBwB,EIxB3B;EA0FL;IACI,eJnE4B;IIoE5B,sBJpE4B,EI8E/B;IARG;MAGI,8BJ1F4B;MI2F5B,eJzEyC;MI0EzC,sBJ1EyC;MI2EzC,yBAAgB;cAAhB,iBAAgB,EACnB;EAGL;IACI,eJjF4B,EI2F/B;IARG;MAGI,8BJvG4B;MIwG5B,eJtFyC;MIuFzC,sBAAqB;MACrB,yBAAgB;cAAhB,iBAAgB,EACnB;;AD3DT;ECzFI,0BJ+DgC;EI0D5B,eJjH4B,EGiFyC;ECvFzE;;;;IAWI,0BJmDgD;IIlDhD,eJN4B;IIO5B,yBAAgB;YAAhB,iBAAgB,EACnB;EAED;IACI,oDAA0C;YAA1C,4CAA0C,EAC7C;EAMG;;;;;;;IAMI,0BJ+BwB;II9BxB,sBJ8BwB,EI7B3B;EA0FL;IACI,eJ9D4B;II+D5B,sBJ/D4B,EIyE/B;IARG;MAGI,8BJ1F4B;MI2F5B,eJpE4C;MIqE5C,sBJrE4C;MIsE5C,yBAAgB;cAAhB,iBAAgB,EACnB;EAGL;IACI,eJ5E4B,EIsF/B;IARG;MAGI,8BJvG4B;MIwG5B,eJjF4C;MIkF5C,sBAAqB;MACrB,yBAAgB;cAAhB,iBAAgB,EACnB;;AD1DT;EC1FI,0BJoEgC;EIqD5B,eJjH4B,EGkFuC;ECxFvE;;;;IAWI,0BJwD+C;IIvD/C,eJN4B;IIO5B,yBAAgB;YAAhB,iBAAgB,EACnB;EAED;IACI,oDAA0C;YAA1C,4CAA0C,EAC7C;EAMG;;;;;;;IAMI,0BJoCwB;IInCxB,sBJmCwB,EIlC3B;EA0FL;IACI,eJzD4B;II0D5B,sBJ1D4B,EIoE/B;IARG;MAGI,8BJ1F4B;MI2F5B,eJ/D2C;MIgE3C,sBJhE2C;MIiE3C,yBAAgB;cAAhB,iBAAgB,EACnB;EAGL;IACI,eJvE4B,EIiF/B;IARG;MAGI,8BJvG4B;MIwG5B,eJ5E2C;MI6E3C,sBAAqB;MACrB,yBAAgB;cAAhB,iBAAgB,EACnB;;ADzDT;EC3FI,0BJQgC;EI+B5B,eJS4B,EG2C8B;ECzF9D;;;;IAWI,0BJL4B;IIM5B,eJN4B;IIO5B,yBAAgB;YAAhB,iBAAgB,EACnB;EAED;IACI,oDAA0C;YAA1C,4CAA0C,EAC7C;EAMG;;;;;;;IAMI,0BJxBwB;IIyBxB,sBJzBwB,EI0B3B;EAOD;IACI,eJ0BwB,EIlB3B;IANG;MAII,eJqBuC,EIpB1C;EAGL;IACI,eJKwB,EIG3B;IANG;MAII,eJAqC,EICxC;EAGL;IACI,eJDwB,EIS3B;IANG;MAII,eJNwC,EIO3C;EAGL;IACI,eJtBwB,EI8B3B;IANG;MAII,eJ3BwC,EI4B3C;EAGL;IACI,YJ1CqB,EIkDxB;IANG;MAII,eJ/CwC,EIgD3C;EAGL;;;;IASI,0BJjGwB;IIkGxB,eJzD4C;II0D5C,yBAAgB;YAAhB,iBAAgB,EACnB;EAED;IAEI,eJ/D4C,EIqE/C;IAJG;MACI,yBAAgB;cAAhB,iBAAgB,EACnB;EAQT;IACI,eJrH4B;IIsH5B,sBJtH4B,EIgI/B;IARG;MAGI,8BJ1F4B;MI2F5B,eJ5HwB;MI6HxB,sBJ7HwB;MI8HxB,yBAAgB;cAAhB,iBAAgB,EACnB;EAGL;IACI,eJnI4B,EI6I/B;IARG;MAGI,8BJvG4B;MIwG5B,eJzIwB;MI0IxB,sBAAqB;MACrB,yBAAgB;cAAhB,iBAAgB,EACnB;;ADvDT;EE5FE,aFgGyB;EE7FzB,0BAAQ;EF8FF,qBAAoB,EACvB;;AAEL;EACI,kBHyBqC;EGxBrC,mBH3D6B;EG4D7B,mBAAgE;EAChE,8BHhEoC,EGiEvC;;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAYY,8BH/E4B,EGgF/B;;AAIT;EACI,UH1H0B;EG2H1B,uBHzBgC;EG0BhC,8BHvFoC,EGwFvC;;AAED;ECuBG,eJM+B;EIL/B,uBJzBoC;EI0BpC,mBJ9CgC,EGuBlC;ECyBE;IACI,mBAAsD,EACzD;;AD1BJ;ECoBG,gBJKgC;EIJhC,yBJ1BsC;EI2BtC,kBJ3CgC,EGuBlC;ECsBE;IACI,kBAAsD,EACzD;;ADtBJ;EACI,iBAAgB,EACnB;;AACD;EACI,YAAW,EACd;;AACD;EACI,iBAAgB,EACnB;;AACD;EACI,mBAAkB;EAClB,SAAQ;EACR,iBAAgB;EAChB,WAAU,EACb;;AAED;EACI,kBHtJ4B;EGuJ5B,oBHpB+B;EGqB/B,oBHrD+B;EGsD/B,mBHtD+B,EG2DlC;EATD;IAOQ,mBAAiE,EACpE;;AAGL;EAEI,cAAa,EACd;;AIrKA;EACI,ePmB6B;EKtBlC,WEIuB;EFDvB,2BAAQ,EEEN;;AACD;EACI,ePe6B;EKtBlC,WEQuB;EFLvB,2BAAQ,EEMN;;AACD;EACI,ePW6B;EKtBlC,WEYuB;EFTvB,2BAAQ,EEUN;;AACD;EACI,ePO6B;EKtBlC,WEgBuB;EFbvB,2BAAQ,EEcN;;AClBJ;EACI,8BRwCoC;EQvCpC,0BRoBgC;EQnBhC,oBRqI+B;EQpI/B,eRagC;EQZhC,oBAAmB;EACnB,oBRwJmC;EM1JnC,6GAA4G;EAI5G,qGAAoG;EATtG,yBES0B;EFRlB,iBEQkB,EAmD3B;EA3DD;IAaQ,0BRmC4B;IMjDlC,yBEe8B;IFdtB,iBEcsB;IACxB,sBAAqB;IACrB,eRC4B,EQO/B;IAxBL;;MAoBY,0BR4BwB;MQ3BxB,kBAAiB;MACjB,8BRmB4B,EQlB/B;EAGL;;;;IF3BF,yBE+B8B;IF9BtB,iBE8BsB,EAC3B;EAED;;;IAIQ,uBAAsB,EACzB;EAtCT;IA0CQ,uBRwF+B;IQvF/B,gBRoH2B;IQnH3B,iBAAgB;IAChB,mBAAkB;IAClB,YAAW;IACX,SAAQ;IACR,uBAAsB,EACzB;EAED;IACI,mCAA4D;IAC5D,iCAAgC,EACnC;EAtDL;IAyDQ,0BRhD4B,EQiD/B;;AAGL;;EAEI,sBRzCgC,EQ0CnC;;AAED;;EAEI,sBAAyC,EAC5C;;AAED;;;EAGI,sBAAyC;EACzC,eRPgC;EQQhC,2CAAuC,EAK1C;EAVD;;;IAQQ,0BRvE4B,EQwE/B;;AAGL;;EAGQ,8BAA6B;EAC7B,iBAAgB;EAChB,sBAAqB;EACrB,mBAAkB;EAClB,YAAW;EACX,aAAY;EACZ,eRvC4B;EQwC5B,gBAAe,EAClB;;AAXL;;EAeY,gBAAe;EACf,UAAS,EACZ;;AAjBT;;EAsBY,UAAS,EACZ;;AAvBT;;;;;EA6BQ,yBAAwB,EAC3B;;AA9BL;;EAiCQ,eR/D4B,EQgE/B;;AAGL;EAEQ,iBAAgB;EAChB,eRvD4B,EQwD/B;;AAJL;EAOQ,eR3D4B,EQ4D/B;;AD3FD;;EAGQ,0BPwDwB,EOvD3B;;AAJL;;EAOQ,mBPoDwB,EO/C3B;EAZL;;IAUY,0BAAkE,EACrE;;AAIT;;EAGQ,mBAAsD,EAKzD;EARL;;IAMY,0BAA8E,EACjF;;AAPT;;EAWQ,0BAA0E,EAK7E;EAhBL;;IAcY,6BAA6F,EAChG;;AAQT;;EAGQ,mBPkBwB,EOb3B;EARL;;IAMY,0BAAkE,EACrE;;AAPT;;EAWQ,0BPUwB,EOT3B;;AAGL;;EAGQ,6BAAoG,EAKvG;EARL;;IAMY,0BAA8E,EACjF;;AAPT;;EAWQ,0BAA8E,EAMjF;EAjBL;;;;IAeY,6BAA2F,EAC9F;;AC4Bb;;;;EAIQ,2CRhH0C;EQiH1C,oBAAmB,EAOtB;EAZL;;;;;;;;;;IASY,oBAAmB;IACnB,2CRrHsC,EQsHzC;;AAXT;;EAiBgB,2CR5HkC,EQ6HrC;;AAlBb;;EAuBQ,2CRnI0C;EQoI1C,aAAY,EACf;;AAGL;EAEQ,eRhG4B,EQiG/B;;AAEL;EAEQ,eRpH4B,EQqH/B;;AAGL;EACI,0BRrKgC;EQsKhC,0BRzJgC;EQ0JhC,oBRxC+B;EQyC/B,eRvIgC;EQwIhC,mCAA6F;EF9K7F,6GAA4G;EAI5G,qGAAoG,EEqMvG;EAvBG;IACI,0BR/K4B,EQgL/B;EAED;IACI,0BRnL4B,EQoL/B;EACD;IACI,eR1H4B,EQ2H/B;EACD;IACI,eR5I4B,EQ6I/B;EArBL;;ID9KI,wBPuGgC;IQiG5B,mBAAkB,EACrB;EA3BL;IA8BQ,YAAW,EACd;;AAGL;EAEQ,0BRxM4B;EQyM5B,sBRlK4B,EQmK/B;;AAJL;EAQY,2CR5LsC,EQ6LzC;;AAIT;;EAEI,oBAAmB;EACnB,mBAAkB,EAKrB;EARD;;IAMQ,gBAAe,EAClB;;AAEL;EAEQ,0BRjN4B,EQkN/B;;AAGL;EACI,oBRpG+B;EQqG/B,0BAAyB;EACzB,6BAA4B;EAC5B,oBAAmB,EACtB;;AAED;;;;EAII,qBAAoB,EACvB;;AACD;;;;EAII,oBAAmB,EACtB;;AACD;EACI,0BRzOgC;EQ0OhC,YRpN6B;EQqN7B,oBAAmB,EACtB;;AAED;EACI,kBRhQ4B;EQiQ5B,qBRhKgC,EQiKnC;;AACD;EACI,sBRlPgC,EQmPnC;;AAED;EACI,eAAc,EACjB;;AACD;EACI,gBAAe;EACf,iBAAgB;EAChB,uBAAsB;EACtB,aAAY;EACZ,aAAY;EACZ,iCR/PgC;EQgQhC,iBAAgB;EAChB,eAAc,EAQjB;EAhBD;IAYQ,kBAAiB;IACjB,iBAAgB;IAChB,mBAAkB,EACrB;;AAGL;;;;EAKQ,oBAA6C,EAChD;;AAGL;EACI,YAAW;EACX,WAAU;EACV,iBAAgB;EAChB,gBAAe,EAClB;;AAED;EACI,gBAAe,EAClB;;AAGD;EACE,WAAU;EACV,mBAAkB;EAClB,OAAM;EACN,SAAQ;EACR,UAAS;EACT,QAAO;EACP,YAAW;EACX,aAAY;EACZ,aAAY,EACb;;AAED;EACI,oBRrKmC,EQsKtC;;AAED;EACI,WAAU;EACV,mBAAkB;EAClB,eAAc;EACd,iBAAgB,EACnB;;AAED;;EAGQ,yBAAwB;EACxB,kBAAiB;EACjB,iBAAgB,EACnB;;AANL;EASQ,oBAAmB,EAKtB;EAdL;IAYW,gBAAe,EAClB;;AAbR;EAiBQ,iBAAgB;EAChB,yBAAwB,EAC3B;;AAnBL;EAsBQ,gBAAe,EAClB;;ACtWL;;;;;EAKI,+DTD2E,ESE9E;;AACD;EACI,iBT+J+B,ES9JlC;;AAED;EACI,eTsCgC,ESjCnC;EAND;IAIQ,eTmC4B,ESlC/B;;AAEL;EACI,iBTmIgC;ESlIhC,kBAAiB;EACjB,oBAAwC,EAO3C;EAVD;IAMQ,iBTiJ2B;IShJ3B,0BAAyB;IACzB,YAAW,EACd;;AAEL;EACI,iBTyHgC;ESxHhC,oBAAwC,EAC3C;;AACD;EACI,eTsH8B;ESrH9B,oBAAwC;EACxC,mBAAkB,EACrB;;AACD;EACI,mBTkHkC;ESjHlC,oBAAmB;EACnB,iBAAqC;EACrC,oBTkF+B,ES5ElC;EAVD;;;IAQQ,kBAAiB,EACpB;;AAEL;EACI,kBTwGiC;ESvGjC,mBAAkB;EAClB,oBAAmB,EACtB;;AACD;EACI,eToG8B;ESnG9B,iBTiH+B;EShH/B,0BAAyB,EAC5B;;AACD;EAEQ,kBAAiB,EACpB;;AASL;EACI,iBTiG+B,ESpFlC;EAdD;IAIQ,0BAAyB,EAM5B;IAVL;MAOY,eT3DwB;MS4DxB,sBAAqB,EACxB;EATT;IAYQ,kBAAiB,EACpB;;AAGL;;;;EAII,eTjEgC;ESkEhC,iBT0E+B,ESzElC;;AACD;;EAEI,2BAA0B;EAC1B,iBTsE+B;ESrE/B,eTxEgC;ESyEhC,oBT4DmC,ES3DtC;;AAED;EACI,eToD8B,ESnDjC;;AAED;;EAEE,0BAAgC,EACjC;;AACD;;EAEE,0BAA6B,EAC9B;;AACD;;EAEE,0BAAgC,EACjC;;AACD;;EAEE,0BAAgC,EACjC;;AACD;;EAEE,0BAA+B,EAChC;;AAED;;EAEI,0BAA6B,EAChC;;AAGD;EACI,kBAAiB;EACjB,uBTzF6B;ES0F7B,cAAa;EACb,iBT2BgC;ES1BhC,iBAAgB,EAkCnB;EAvCD;IAQQ,YT/FyB;ISgGzB,oBTkB+B;ISjB/B,0BAAyB,EAC5B;EAXL;IAcQ,sBTjG4B;ISkG5B,eTlG4B,ESuG/B;IApBL;MAkBY,eTrGwB,ESsG3B;EAnBT;IAuBQ,sBTtF4B;ISuF5B,eTvF4B,ES4F/B;IA7BL;MA2BY,eT1FwB,ES2F3B;EA5BT;IAgCQ,uCTnI0C;ISoI1C,eT5J4B,ESiK/B;IAtCL;MAoCY,gCTvIsC,ESwIzC;;AC1KT;EACI,eVkBgC;EUjBhC,gBV+J+B;EU9J/B,+DVC2E;EUA3E,mCAAkC;EAClC,oCAAmC,EACtC;;AAED;EACI,mBAAkB;EAClB,oBVAgC,EUCnC;;AACD,gBAAgB;AAChB;;;;;;;;;;;;;;;;;;;;;;;;;;EJEI,sCNqL+B;EMjL/B,8BNiL+B,EU5KlC;;AAGD;;;EJZI,sCNqL+B;EMjL/B,8BNiL+B,EUrKlC;;AAED;;;;EJVI,iEAAgE;EAChE,kCAAiC;EAEjC,0BAAyB,EIY5B;;AAED;EACI,eAAc;EACd,mBAAkB;EAClB,YAAW;EACX,YAAW;EACX,mBAAkB;EAClB,oBVnCgC,EU4CnC;EAfD;IASQ,gBAAe,EAClB;EAVL;IAaQ,YAAW,EACd;;AAGL;EACI,sBAAqB;EACrB,SAAQ;EACR,UAAS;EACT,iBAAgB;EAChB,uBAAsB;EACtB,uBAAsB;EACtB,wBAAuB;EACvB,oCAAmC;EACnC,mCAAkC,EACrC;;ACnED;EACC,kBAAiB,EACjB;;AAED;EACE,sBAAqB;EACrB,mBAAkB;EAClB,gBAAe;EACf,mBAAkB;EAClB,kBAAiB;EACjB,iBAAgB;EAChB,sCAAqC;EAIrC,8BAA6B,EAC9B;;AACD;EACI,mBAAkB,EACrB;;AAED;;EAEE,aAAY;EACZ,sBAAqB;EACrB,mBAAkB;EAClB,YAAW;EACX,aAAY;EACZ,QAAO;EACP,gBAAe;EACf,mBAAkB;EAClB,OAAM;EACN,8BAA6B;EAC7B,0BXTkC;EWUlC,wCAAuC;EAIvC,gCAA+B,EAChC;;AAEA;EACC,8BAA6B;EAC7B,iBAAgB;EAChB,SAAQ;EACR,mBAAkB;EAClB,gBAAe;EACf,WAAU;EACV,eXJkC;EWKlC,UAAS;EACT,0BAAyB,EAC1B;;AAED;;EAEI,eX7BgC;EW8BhC,YAAW;EACX,oBAAmB,EACtB;;AAED;;EAEE,WAAU;EACV,mBAAkB;EAClB,mBAAkB,EACnB;;AACD;EACE,WAAU,EACX;;AAED;;EAEI,oBAAmB,EACtB;;AAED;;EAEI,qBAAoB,EACvB;;AAED;;EAEE,aAAY;EACZ,YAAW;EACX,aAAY;EACZ,mBAAkB;EAClB,0BX9DkC;EW+DlC,sBAAqB;EACrB,mBAAkB;EAClB,UAAS;EACT,SAAQ;EACR,aAAY;EACZ,wCAAuC;EAIvC,gCAA+B,EAChC;;AAED;;EAEI,WAAU,EACb;;AACD;EACI,WAAU;EACV,YAAW;EACX,0BX9DgC;EW+DhC,sBX/DgC;EWgEhC,UAAS;EACT,WAAU;EACV,WAAU,EACb;;AAED;EACI,WAAU,EACb;;AAED;EACE,eX5FkC,EW6FnC;;AAED;;EAEE,eXjGkC,EWkGnC;;AC5HD;EACI,sBZiNqC;EYhNrC,yBZgNqC;EY/MrC,iBAAgB;EAChB,oBAAmB;EACnB,yDAAgD;UAAhD,iDAAgD,EA+OnD;EApPD;IAQQ,uBAAsB,EASzB;IAjBL;MAWY,eZDwB,EYE3B;IAZT;MAeY,YZ+BqB,EY9BxB;EAhBT;;IAwBQ,YZsByB,EYjB1B;IA7BP;;MA2BU,YZmBuB,EOtBE;IKxBnC;;MA2BU,YZmBuB,EOrBM;IKzBvC;;MA2BU,YZmBuB,EOpBY;EK1B7C;IA+BQ,YZeyB;IYdzB,YAAW,EACZ;EAjCP;;IAsCM,UAAS;IACT,kBAAiB;IACjB,kBAAiB,EAclB;IAtDL;;;;MA2CQ,eZjC4B,EYkC7B;IA5CP;;MA+CU,eZrC0B,EY0C3B;MApDT;;QAkDY,eZxCwB,EOcD;MKxBnC;;QAkDY,eZxCwB,EOeG;MKzBvC;;QAkDY,eZxCwB,EOgBS;EK1B7C;IAyDQ,sBAAqB;IACrB,UAAS;IACT,mBAAkB;IAClB,eAAc;IACd,iBAAgB,EACnB;EA9DL;IAiEQ,mBAAkB;IAClB,YAAW;IACX,kBAAiB;IACjB,cAAa,EAChB;EAED;IAEQ,QAAO;IACP,eAAc,EACjB;EA3ET;IA+EQ,4BAAoB;IAApB,4BAAoB;IAApB,qBAAoB;IACpB,0BAAmB;QAAnB,uBAAmB;YAAnB,oBAAmB,EAqBtB;IArGL;MAmFY,oBAAmB,EAKtB;MAxFT;QAsFgB,UAAS,EACZ;IAvFb;MA4FgB,gBAAe,EAClB;IA7Fb;MAiGoB,YAAW,EACd;EAlGjB;IA2GY,mBAAkB;IAClB,QAAO;IACP,SAAQ;IACR,eAAc;IACd,YAAW;IACX,UAAS,EACZ;EAjHT;IAoHY,mBZfuB,EYsB1B;IA3HT;MAsHgB,mBZNmB,EYOtB;IAvHb;MAyHgB,kBZNmB,EYOtB;EA1Hb;IA8HY,0BAAyB;IACzB,oBZgC2B;IY/B3B,uBZxBwB;IYyBxB,sBZ2CyB;IY1CzB,kBAAiB,EAgCpB;IAlKT;;MAsIgB,iBAAgB,EACnB;IAvIb;;MA2IgB,gBAAe;MACf,mBAAkB;MAClB,SAAQ;MACR,mBAAkB;MAClB,YAAW,EACd;IAhJb;MAmJgB,SAAQ;MACR,gBAAe,EAClB;IArJb;MAyJoB,YAAW;MACX,aAAY,EACf;IA3JjB;MA+JgB,YAAW;MACX,eZtJoB,EYuJvB;EAjKb;;;;IAwKY,2CZ/HsC;IYgItC,yBZtC6B;IYuC7B,eZhKwB,EYiK3B;EA3KT;IA+KQ,YAAW;IACX,aAAY;IACZ,iBAAgB;IAChB,eAAc;IACd,mBAAkB;IAClB,8BAA6B,EAChC;EArLL;IAwLQ,0BAAyB;IACzB,oBZzB+B;IY0B/B,oBZnF4B;IYoF5B,uBZpF4B;IYqF5B,sBZhB6B,EYiBhC;EA7LL;IAgMQ,YAAW;IACX,aAAY;IACZ,uBAAsB;IACtB,WAAU;IACV,gBAAe,EAQlB;IA5ML;MAuMY,WAAU;MACV,YAAW;MACX,mBAAkB;MAClB,eAAc,EACjB;EA3MT;IAgNY,YAAW,EACd;EAjNT;IAqNQ,yCAA4C;IAC5C,yBAAgB;YAAhB,iBAAgB;IAChB,eZ7M4B,EY8M/B;EAxNL;IA4NY,YZ9KqB,EYoLxB;IAlOT;MA+NgB,YAAW;MACX,YZlLiB,EYmLpB;EAjOb;IAqOY,iBZvLqB,EYwLxB;EAtOT;;;;IA4OY,2CZ9MsC;IY+MtC,YZ/LqB,EYgMxB;EA9OT;IAiPY,uBZnMqB,EYoMxB;;AAIT;EACI,kCAA2C,EAC9C;;AAED;EACI,qCAA2C,EAC9C;;AAED;EACI,qCAAwC,EAC3C;;AAED;EACI,qCAA2C,EAC9C;;AAED;EACI,qCAA0C,EAC7C;;AAED;EACI,qCAA2C,EAC9C;;AAED;EACI,qCAAyC,EAC5C;;AChRD;EACI,kBAAiB;EACjB,kBAAiB;EACjB,WAAU;EACV,ebMgC;EaLhC,mBAAkB,EA+ErB;EApFD;IAQQ,mBAAkB;IAClB,uBAAsB;IACtB,mCAAkC;IAClC,YAAW;IACX,aAAY;IACZ,YAAW,EACd;EAdL;IAiBQ,mBAAkB;IAClB,SAAQ;IACR,UAAS;IACT,WAAU;IAEV,yCAAwC;IACxC,iCAAgC;IAChC,mBAAkB;IAClB,eAAc;IACd,gBAAe;IACf,YAAW;IACX,iBAAgB,EAEnB;EA9BL;IAiCQ,mBAAkB;IAClB,UAAS;IACT,YAAW,EACd;EApCL;IAuCQ,aAAY;IACZ,WAAU,EACb;EAzCL;;IA6CQ,gCbX0C,EaY7C;EA9CL;IAiDQ,iBAAgB;IAChB,kBAAiB,EACpB;EAnDL;IAsDQ,iBAAgB;IAChB,kBAAiB,EACpB;EAxDL;IA2DQ,oBAAmB,EACtB;EA5DL;IA8DQ,iBAAgB,EACnB;EA/DL;IAmEQ,mBAAkB;IAClB,WAAU;IACV,YAAW;IACX,aAAY;IACZ,eAAc;IACd,QAAO;IACP,OAAM;IACN,YAAW,EACd;EA3EL;IA8EQ,qCAAgC,EACnC;EA/EL;ICCI,kCdkBgC;IclBX,gDAAgD;IACN,2BAA2B;IACjC,4BAA4B;IAC1B,2BAA2B;IACtF,oHAAoD;IAApD,gFAAoD;IAAE,qBAAqB,ED8E1E;;AEnFL;EACI,UAAS;EACT,yDAAgD;UAAhD,iDAAgD;EAChD,wBf+HoC;EMnHpC,qCNmL8B;EM/K9B,6BN+K8B;Ee7L9B,gBf4J+B,Ee6BlC;EA9LD;IASY,WAAS;IACT,YAAW,EACd;EAXT;IAeQ,kBAAiB;IACjB,mBAAkB;IAClB,SAAQ,EACX;EAlBL;IAqBQ,mBAAkB;IAClB,mBAAkB;IAClB,SAAQ;IACR,gBAAe;IACf,iBAAgB;IAChB,YAAW,EACd;EA3BL;IAgCY,eAAc,EACjB;EAGL;IAEQ,cAAa,EAChB;EAHL;IAMQ,sBAAqB;IACrB,mBAAkB;IAClB,SAAQ;IACR,UAAS;IACT,uBAAsB;IACtB,YAAW;IACX,UAAS;IACT,aAAY;IACZ,YAAW;IACX,WAAU;IACV,ef1CwB;Ie2CxB,uBAAsB;IACtB,qCAAoC;IACpC,oCAAmC,EACtC;EApBL;IAwBY,YAAW;IACX,WAAU,EACb;EA9Db;IAoEQ,sBAAqB;IACrB,mBAAkB;IAClB,SAAQ;IACR,UAAS;IACT,uBAAsB;IACtB,YAAW;IACX,UAAS;IACT,WAAU;IACV,YAAW;IACX,efnE4B;IeoE5B,0BAAyB;IACzB,qCAAoC;IACpC,oCAAmC,EACtC;EAjFL;IAoFM,oBAAmB;IACnB,sBAAqB,EACtB;EAtFL;;IA0FQ,oBfsE+B;IerE/B,mBAAkB;IAClB,sBAAqB;IACrB,gBAAe;IT9EnB,qCNmL8B;IM/K9B,6BN+K8B,EepF7B;IA9GL;;;MAkGY,2CftEsC,EeuEzC;IAnGT;;;MAuGY,gCfvDwC,Ee6D3C;MA7GT;;;;;QA2GgB,8BAA6B,EAChC;EA5Gb;IAkHQ,2CfrF0C,EesF7C;EAnHL;IAsHQ,gCftE4C;IeuE5C,oBfwC+B;IevC/B,0BAAyB;IACzB,iBfgD2B,Ee/C9B;EA1HL;ICCI,0BD4HuD,EACtD;IC3HD;MACI,eDyHmD,ECxHtD;IAED;MACI,gChB0B0C,EgBzB7C;IAED;MACI,ehBF4B,EgBQ/B;MAPD;QAKQ,2ChByBsC,EgBxBzC;IAGL;MACI,2ChBoB0C,EgBnB7C;EDtBL;ICCI,0BDgIoD,EACnD;IC/HD;MACI,eD6HgD,EC5HnD;IAED;MACI,gChB0B0C,EgBzB7C;IAED;MACI,ehBF4B,EgBQ/B;MAPD;QAKQ,2ChByBsC,EgBxBzC;IAGL;MACI,2ChBoB0C,EgBnB7C;EDtBL;ICCI,0BDoIsD,EACrD;ICnID;MACI,eDiIkD,EChIrD;IAED;MACI,gChB0B0C,EgBzB7C;IAED;MACI,ehBF4B,EgBQ/B;MAPD;QAKQ,2ChByBsC,EgBxBzC;IAGL;MACI,2ChBoB0C,EgBnB7C;EDtBL;ICCI,0BDwIuD,EACtD;ICvID;MACI,eDqImD,ECpItD;IAED;MACI,gChB0B0C,EgBzB7C;IAED;MACI,ehBF4B,EgBQ/B;MAPD;QAKQ,2ChByBsC,EgBxBzC;IAGL;MACI,2ChBoB0C,EgBnB7C;EDtBL;ICCI,0BD4IuD,EACtD;IC3ID;MACI,eDyImD,ECxItD;IAED;MACI,gChB0B0C,EgBzB7C;IAED;MACI,ehBF4B,EgBQ/B;MAPD;QAKQ,2ChByBsC,EgBxBzC;IAGL;MACI,2ChBoB0C,EgBnB7C;ED0HD;;;ITjGA,uDAAsD;IAInD,+CAA6C;ISmG5C,mBAAkB;IAClB,eAAc;IVpJpB,WUqJwB;IVlJxB,yBAAQ;IUmJF,qBAAoB,EACvB;EA1JL;IT+CI,uDAAsD;IAInD,+CAA6C,ES4G/C;EAED;ITlHA,sDAAsD;IAInD,8CAA6C,ESgH/C;EAED;ITtHA,sDAAsD;IAInD,8CAA6C;ISoH5C,qBAAoB;IACpB,aAAY,EACf;EAED;;;;IVxKF,WU8KwB;IV3KxB,2BAAQ;IU4KF,oBAAmB;ITnIvB,qDAAsD;IAInD,6CAA6C,ESiI/C;EApLL;IT+CI,qDAAsD;IAInD,6CAA6C,ESsI/C;EAED;IT5IA,sDAAsD;IAInD,8CAA6C,ES0I/C;;AAGL;EACI,sBfzFgC;Ee0FhC,gBAAe,EAWlB;EAbD;IAKQ,oBf9F4B;Ie+F5B,uBf/F4B;IegG5B,eAAc,EAKjB;IAZL;MAUY,cAAa,EAChB;;AE3MT;EACI,UAAS;EACT,yBjBiIqC;EiBhIrC,ejBOgC;EiBNhC,mBAAkB;EAClB,sBAAqB;EACrB,mBAAkB,EA+DrB;EArED;IASQ,0BAA6C,EAChD;EAVL;IAaQ,0BAA4C,EAC/C;EAdL;IAiBQ,0BAA6C,EAChD;EAlBL;IAqBQ,0BAA0C,EAC7C;EAtBL;IAyBQ,0BAA6C,EAChD;EA1BL;;IA+BQ,gBAAe,EAClB;EAhCL;IAmCQ,ejBzB4B;IiB0B5B,YAAW;IACX,kBAAiB;IACjB,eAAc;IACd,WAAU,EACb;EAxCL;IA2CQ,gBAAe;IACf,eAAc;IACd,WAAU;IACV,mBAAkB;IAClB,SAAQ;IACR,kBAAiB,EACpB;EAjDL;IAoDQ,mBAAkB;IAClB,YAAW;IACX,SAAQ;IACR,kBAAiB;IACjB,YAAW;IACX,aAAY;IACZ,aAAY,EACf;EA3DL;IA8DQ,eAAc;IACd,eAAc,EACjB;EAhEL;IAmEQ,mBAAkB,EACrB;;ACpEL;EACI,gBAAe;EACf,yBlBiIqC,EkBhIxC;;AACD;EACI,yDlBiL2D;UkBjL3D,iDlBiL2D,EkBhL9D;;ACND;;;;;;mCAMmC;AAEnC;EACE,8BAA6B;EAC7B,wCAAuC;EACvC,uRAIgD;EAChD,oBAAmB;EACnB,mBAAkB,EAAA;;AAGpB;;2BAE2B;AAE3B;EACE,sBAAqB;EACrB,mDAAkD;EAClD,mBAAkB;EAClB,YAAW;EACX,qBAAoB;EACpB,2BAA2B;EAC3B,oCAAmC;EACnC,mCAAkC,EACnC;;AAED;;2BAE2B;AAE3B;;qCAEqC;AAErC;EACE,sBAAqB;EACrB,qBAAoB;EACpB,uBAAsB,EACvB;;AAED;EACE,mBAAkB,EACnB;;AAED;;2BAE2B;AAE3B;EACE,gBAAe;EACf,0BAAyB;EACzB,sBAAqB,EACtB;;AAED;EACE,mBAAkB,EACnB;;AAED;EACE,mBAAkB;EAClB,oBAAmB;EACnB,kBAAiB;EACjB,mBAAkB,EACnB;;AAED;EACE,mBAAkB;EAClB,mBAAkB,EACnB;;AAED;;2BAE2B;AAE3B;EACE,mDAAkD;EAElD,2CAA0C,EAC3C;;AAED;EACE;IACE,gCAA+B,EAAA;EAGjC;IACE,kCAAiC,EAAA,EAAA;;AAcrC;EACE;IACE,gCAA+B;IAI/B,wBAAuB,EAAA;EAGzB;IACE,kCAAiC;IAIjC,0BAAyB,EAAA,EAAA;;AAI7B;;2BAE2B;AAE3B;;2BAE2B;AAE3B;EACI,iBAAgB,EACnB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAED;EACE,iBAAgB,EACjB;;AAGD;EACI,mBAAkB;EAClB,uBAAsB;EACtB,0BAAyB;EACzB,yBAAwB;EACxB,eAAc;EACd,kBAAiB,EACpB;;AAED;EACI,gBAAe,EAClB;;AAED;EACI,oBAAmB;EACnB,YAAW;EACX,mBAAkB;EAClB,eAAc;EACd,eAAc;EACd,gBAAc;EACd,oBAAmB,EACtB;;AC7iBD;EAGM,YAAW;EACX,aAAY;EACZ,mBAAkB;EAClB,iBAAgB;EAChB,eAAc,EACf;;AARL;EAWM,gBAAe;EACf,YAAW,EACZ;;AAbL;EAgBQ,UAAS,EAOZ;EAvBL;;IAoBY,WAAU;IACV,UAAS,EACZ;;AAtBT;EA0BQ,UAAS,EACZ;;AA3BL;EA8BM,iBAAgB,EACjB;;AAED;EACI,iBAAgB,EAWnB;EAZD;;;;;;IASQ,eAAc;IACd,kBAAiB,EACpB;;AA5CT;EAgDO,yBAAwB;EACxB,kBAAiB;EACjB,iBpBoH4B;EoBnH5B,UAAS,EACZ;;AApDJ;;EAwDO,cAAa;EACb,iBAAgB;EAChB,WAAU;EACV,YAAW,EAad;EAxEJ;;IA8DW,mBAAkB,EACrB;EA/DR;;;IAoEgB,WAAU;IACV,WAAU,EACb;;AAtEb;;;;;;EA+EO,kBAAiB;EACjB,uBAAsB,EACzB;;AAjFJ;EAoFO,iBAAgB,EACnB;;AArFJ;EAuFO,gBAAe;EACf,iBpB8E4B;EoB7E5B,gBAAe;EACf,mBAAkB;EAClB,SAAQ;EACR,kBAAiB,EACpB;;AA7FJ;EA+FQ,iBpB0E2B;EoBzE3B,kBpB0D6B;EoBzD7B,kBAAiB;EACjB,kBAAiB,EACpB;;AAnGL;EAsGI,YAAW,EACV;;AAvGL;EA0GQ,mBAAkB,EACrB;;AAGL;EAEQ,epB2C0B;EoB1C1B,0BAAyB,EAC5B;;AAJL;EAMQ,epByC0B,EoBnC7B;EAZL;IASY,eAAc;IACd,mBAAkB,EACrB;;AAXT;EAcQ,iBpB2C2B;EoB1C3B,iBAAgB,EAMnB;EArBL;IAiBY,epBrGwB;IoBsGxB,kBAAiB;IACjB,iBpBqCuB,EoBpC1B;;AApBT;EAuBO,iBpBiC4B;EoBhC5B,mBpBmB+B,EoBlBlC;;AAzBJ;EA2BQ,iBAAgB,EACnB;;AA5BL;EA8BQ,kBAAiB;EACjB,iBAAgB,EAKnB;EApCL;IAkCY,kBAAiB,EACpB;;AAnCT;EAuCQ,aAAY;EACZ,kBAAiB;EACjB,iBAAgB;EAChB,eAAc,EAKjB;EA/CL;IA6CY,YAAW,EACd;;AAIT;EACI,oBAAmB,EACtB;;AClKD;EACI,mBAAkB;EAClB,OAAM;EACN,cAAa,EAMhB;EATD;IAMQ,kBAAiB;IACjB,aAAY,EACf;;AAGL;;EAEI,gBAAe;EACf,OAAM;EACN,aAAY;EACZ,UAAS;EACT,aAAY;EACZ,QAAO;EACP,cAAa,EAiPhB;EAzPD;;IAWQ,mBAAkB;IAClB,2BAA0B;IAC1B,eAAc;IACd,aAAY;IACZ,WAAU;IACV,sBAAqB,EASxB;IAzBL;;MAmBU,yBAAwB,EACzB;IApBT;;MAuBY,aAAY,EACf;EAxBT;;IA4BM,mBAAkB;IAClB,YAAW;IACX,SAAQ;IACR,WAAU,EAGX;EAlCL;;IAoCM,mBAAkB;IAClB,uBAAsB;IACtB,eAAc;IACd,aAAY;IACZ,YAAW;IACX,YAAW;IACX,iBAAgB,EAMjB;IAhDL;;MA6CU,YAAW;MACX,aAAY,EACf;EA/CP;;IAmDQ,iBAAgB;IAChB,eAAc,EAkEjB;IAtHL;;MAuDY,UAAS;MACT,mBAAkB;MAClB,YAAW,EACd;IA1DT;;MA8DgB,gBAAe,EAClB;IA/Db;;MAkEgB,oBAAmB;MACnB,oBrB4DmB;MqB3DnB,erBrEoB;MqBsEpB,eAAc;MACd,sBAAqB;MACrB,mBAAkB;MAClB,0BAAyB;MACzB,gBAAe;MACf,oBrB0EuB;MqBzEvB,kBAAiB;MACjB,sBrBqFqB,EqBpFxB;IA7Eb;;MAgFgB,eAAc,EACjB;IAjFb;;;;MAqFgB,2CrBxDkC,EqB6DrC;MA1Fb;;;;QAwFkB,erBzFkB,EqB0FnB;IAzFjB;;MA6Fc,0BrB9FsB;MqB+FtB,yDrB8EiD;cqB9EjD,iDrB8EiD,EqB7ElD;IA/Fb;;MAmGY,UAAS;MACT,kBAAiB;MACjB,mBAAkB;MAClB,eAAc;MACd,aAAY;MACZ,oBAAmB,EAEtB;IA1GT;;MA6GY,gBAAe;MACf,YAAW;MACX,mBAAkB;MAClB,kBAAiB;MACjB,YAAW;MACX,mBAAkB;MAClB,gCrB7FsC;MqB8FtC,mBAAkB,EACrB;EArHT;;IAyHQ,mBAAkB;IAClB,WAAU;IACV,aAAY;IACZ,YAAW;IACX,eAAc;IACd,OAAM;IACN,QAAO;IACP,uBAAsB;IACtB,mCAAkC,EAYrC;IA7IL;;MAoIY,mBAAkB;MAClB,WAAU;MACV,YAAW;MACX,aAAY;MACZ,YAAW;MACX,eAAc;MACd,oBAAmB;MACnB,WAAU,EACb;EA5IT;;IAgJQ,mBAAkB;IAClB,uBrBpD4B;IqBqD5B,WAAU,EAsDb;IAxML;;MA0JY,WAAU;MACV,YAAW;MACX,YAAW;MACX,mBAAkB;MAClB,kBAAiB;MACjB,mBAAkB,EACrB;IAhKT;;MAmKY,eAAc;MACd,WAAU;MfhJjB,0CAA6C;MAI1C,kCAAoC,Ee8InC;IAtKT;;MAyKY,YAAW;MACX,mBAAkB;MAClB,UAAS;MACT,YAAW;MACX,YAAW;MACX,yBAAwB;MACxB,2CrBzJsC,EqB2JzC;IAjLT;;MAoLY,YAAW;MACX,gBAAe;MACf,kBAAiB;MACjB,erBxLwB;MqByLxB,kBAAiB;MACjB,4DAA2D,EAC9D;IA1LT;;MA6LY,0BAAyB;MACzB,kBAAiC;MACjC,eAAc;MACd,oBAAmB;MACnB,erB1CsB;MqB2CtB,erBnMwB;MqBoMxB,sBAAqB;MACrB,iBrBxCuB;MqByCvB,kBAAiB;MACjB,iBAAgB,EACnB;EAvMT;;IA2MQ,mBAAkB;IAClB,uBAAsB;IACtB,eAAc;IACd,aAAY;IACZ,YAAW;IACX,YAAW;IACX,iBAAgB,EAMnB;IAvNL;;MAoNY,YAAW;MACX,aAAY,EACf;EAtNT;;;IA2NQ,eAAc;IACd,YAAW;IACX,WAAU;IACV,mBAAkB;IAClB,YAAW;IACX,aAAY;IACZ,OAAM;IACN,QAAO,EACV;EAnOL;;If4CI,iBNT6B;IMa7B,+FAAwD;IAAxD,+CAAwD;IeuLpD,WAAU,EACb;EfpLH;;IACE,oBNJgC,EMKjC;EAEgB;;IACf,eNRgC,EMajC;IAHC;;MACE,eNX8B,EMY/B;EATH;;IACE,oBNTgC,EMUjC;EAEgB;;IACf,eNbgC,EMkBjC;IAHC;;MACE,eNhB8B,EMiB/B;EATH;;IACE,oBNWgC,EMVjC;EAEgB;;IACf,eNOgC,EMFjC;IAHC;;MACE,eNI8B,EMH/B;EATH;;IACE,oBNMgC,EMLjC;EAEgB;;IACf,eNEgC,EMGjC;IAHC;;MACE,eND8B,EME/B;EATH;;IACE,oBNCgC,EMAjC;EAEgB;;IACf,eNHgC,EMQjC;IAHC;;MACE,eNN8B,EMO/B;;Ae8LL;EACI,iCAAgC,EACnC;;AACD;EACI,yBAAwB,EAC3B;;AAED;;EAIY,erBvQwB,EqBwQ3B;;AALT;EAQY,qCAAoC,EACvC;;AAKT;EACI,mBAAkB;EAClB,aAAY;EACZ,0BrBxB2C;EqB0B3C,0BrBxQgC;EqByQhC,0BAAyB;EflRzB,mEeoRiE;EfhRjE,2DegRiE,EAgBpE;EAxBD;IAWQ,qBAAoB;IACpB,gCAA+B;IAC/B,kBAAiB,EACpB;EAdL;IAiBQ,iBAAgB,EACnB;EAlBL;IAsBQ,oBAAmB,EACtB;;AAIL;;EAGM,aAAY;EACZ,iBAAgB,EACnB;;AAIH;EACE;IACE,eAAc;IACd,0FrB1IyF;YqB0IzF,kFrB1IyF,EqB2I1F,EAAA;;AAGH;EACE,cAAa;EACb,kBAAiB;EACjB,qBAAoB;EACpB,oBAAmB;EAAI,+BAA+B;EAEtD,gHAA4E;EAA5E,6EAA4E;EAC5E,mBAAkB;EAClB,iBAAgB,EAiBjB;EAzBD;IAYM,erBxU8B,EqByU/B;EAbL;IAeM,iBAAgB;IAChB,gCrBrT4C;IqBsT5C,eAAc;IACd,gBAAe,EAKhB;IAvBL;MAqBQ,erBjV4B,EqBkV7B;;AAKP;EACE,cAAa,EACd;;AAED;EACE,cACF,EAAE;;ACvWF;EACI,UAAS;EACT,yBtBiIqC;EsBhIrC,sBAAqB;EACrB,mBAAkB;EAClB,YAAW;EACX,oBAAmB;EACnB,yDtBgL2D;UsBhL3D,iDtBgL2D,EsB7E9D;EA1GD;IAUQ,6BAA4B,EAM/B;IAhBL;MAaY,gBAAe;MACf,iBAAgB,EACnB;EAfT;IAsBM,qBAAoB;IACpB,UAAS,EAKV;IA5BL;MAoBQ,8BAA6B,EAC9B;IArBP;MA0BU,iBAAgB,EACnB;EA3BP;IA+BQ,cAAa;IACb,yBtBmGiC,EsB9FpC;IArCL;MAmCU,cAAa,EACd;EApCT;IAwCQ,0BtBU4B,EsBC/B;IAnDL;MA2CY,0BtBOwB,EsBN3B;IA5CT;MAgDgB,etBtCoB,EsBuCvB;EAjDb;IAsDQ,0BtBgB4B,EsBf/B;EAvDL;IA0DQ,0BtBO4B,EsBN/B;EA3DL;IA8DQ,0BtBF4B,EsBG/B;EA/DL;IAkEQ,0BtBX4B,EsBY/B;EAnEL;IAsEQ,iBAAgB;IAChB,cAAa;IACb,mBAAkB,EACrB;EAzEL;IA4EQ,YAAW;IACX,aAAY;IACZ,iBAAgB;IAChB,mBAAkB;IAClB,oBAAmB,EACtB;EAjFL;IAoFQ,oBtB4E+B;IsB3E/B,mBAAkB;IAClB,etB5D4B,EsB6D/B;EAvFL;IA0FQ,8BAA6B;IAC7B,UAAS,EAcZ;IAzGL;MAgGgB,kBAAiB;MACjB,mBAAkB;MAClB,SAAQ,EACX;IAnGb;MAuGY,UAAS,EACZ;;AAIT;EAEQ,cAAa,EAChB;;AAHL;EAMQ,mBAAkB;EAClB,qBAAoB;EACpB,kBAAiB,EAKpB;EAbL;IAWY,iBAAgB,EACnB;;AAZT;EAgBQ,aAAY;EACZ,cAAa;EACb,0BtBpH4B;EsBqH5B,mBAAkB,EACrB;;AApBL;EAuBQ,kBAAiB,EACpB;;AAxBL;EA2BQ,iBAAgB,EACnB;;AA5BL;EA+BQ,mBAAkB;EAClB,mBAAkB,EACrB;;AAGL;EACI,wBAAuB;EACvB,yBAAgB;UAAhB,iBAAgB,EAanB;EAfD;;IAMQ,eAAc;IACd,gBAAe;IACf,8BAA6B,EAChC;EATL;IAYQ,gBAAe;IACf,iBAAgB,EACnB;;AC9JL;EAGM,iBAAgB;EAChB,iBAAgB,EACjB;;AALL;EAOM,mBAAkB,EACnB;;AARL;EAYI,iBAAgB,EAMjB;EAlBH;IAeM,iBAAgB;IAChB,iCAAgC,EACjC;;AAjBL;EAqBI,iBAAgB,EACjB;;AAtBH;EAyBI,cAAa;EACb,yBAAwB;EACxB,mBAAkB;EAClB,oBAAmB,EACpB;;AA7BH;EA+BI,iBAAgB,EAKjB;EApCH;IAkCM,evBR8B,EuBS/B;;AAnCL;EAuCI,mBAAkB;EAClB,YAAW;EACX,UAAS,EAKV;EA9CH;IA4CM,UAAS,EACV;;AC7CL;EACI,gBAAe,EA4ClB;EA7CD;IAIQ,0BAAyB,EAC5B;EALL;IAQQ,sBAAqB;IACrB,YAAW;IACX,kBAAiB,EACpB;EAXL;IAcQ,iBAAgB;IAChB,WAAU;IACV,iBAAgB,EAiBnB;IAjCL;MAmBY,sBAAqB,EAaxB;MAhCT;QAsBgB,eAAc;QACd,gBxBgFoB;QwB/EpB,oBxBwIuB;QwBvIvB,0BAAyB;QACzB,sBAAqB,EAKxB;QA/Bb;UA6BoB,sBAAqB,EACxB;EA9BjB;IAoCQ,oBxB4H+B;IwB3H/B,iBAAgB,EACnB;EAtCL;IAyCQ,eAAc;IACd,YAAW;IACX,aAAY,EACf;;AC5CL;EACI,gBAAe;EACf,SAAQ;EACR,YAAW;EACX,+BAA0B;EAC1B,cAAa;EACb,2BAA0B;EAC1B,mBAAkB;EAClB,WAAU,EAoTb;EA5TD;;IAYQ,qBAAoB;IACpB,6BAA4B;IAC5B,0BAAyB,EAC5B;EAfL;IAkBQ,eAAc;IACd,cAAa;IACb,2BAA0B;IAC1B,YAAW,EACd;EAtBL;IAyBQ,YAAW;IACX,sBAAqB;IACrB,sBAAqB;IACrB,aAAY;IACZ,yBAAwB;IACxB,gBAAe,EAClB;EA/BL;IAkCM,SAAQ,EACT;EAnCL;;IAuCQ,YAAW;IACX,kBAAiB;IACjB,WAAU,EACb;EA1CL;IA6CQ,eAAc,EACjB;EA9CL;IAiDQ,eAAc,EACjB;EAlDL;;;IAuDQ,eAAc;IACd,mBAAkB,EACrB;EAzDL;IA4DQ,iBAAgB;IAChB,YAAW;IACX,cAAa;IACb,eAAc,EACjB;EAhEL;;IAoEQ,yBAAgB;YAAhB,iBAAgB,EACnB;EArEL;IAwEQ,0BAAyB;IACzB,mBAAkB;IAClB,gBAAe;IACf,sBAAqB;IACrB,aAAY;IACZ,kBAAiB;IACjB,mBAAkB;IAClB,YAAW,EACd;EAhFL;;IAoFQ,sBAAqB,EACxB;EArFL;IAwFQ,0BzB5B4B,EyB6B/B;EAzFL;IA2FQ,0BzBpC4B,EyBqC/B;EA5FL;IA8FQ,0BzB5C4B,EyB6C/B;EA/FL;IAiGQ,0BzBhC4B,EyBiC/B;EAlGL;IAoGQ,0BzB9B4B,EyB+B/B;EArGL;IAwGQ,gBAAe;IACf,aAAY,EACf;EA1GL;IA6GQ,eAAc;IACd,kBAAiB;IACjB,WAAU;IACV,YAAW,EACd;EAjHL;;;IAsHQ,YAAW;IACX,aAAY;IACZ,oBAAmB,EACtB;EAzHL;IA4HQ,aAAY,EAKf;IAjIL;MA+HY,mBAAkB,EACrB;EAhIT;IAoIQ,mBAAkB;IAClB,gBAAe;IACf,aAAY,EACf;EAvIL;IA0IQ,aAAY;IACZ,kBAAiB;IACjB,gBAAe;IACf,iBAAgB;IAChB,mBAAkB;IAClB,0BAAyB,EAC5B;EAhJL;IAoJY,YAAW;IACX,sBAAqB;IACrB,iBAAgB;IAChB,eAAc;IACd,eAAc,EACjB;EAzJT;IA4JY,mBAAkB,EAWrB;IAvKT;MA+JgB,mBAAkB;MAClB,UAAS,EACZ;IAjKb;;MAqKgB,mBAAkB,EACrB;EAtKb;IA0KY,mBAAkB,EAgBrB;IA1LT;MA6Kc,mBAAkB;MAClB,YAAW;MACX,oBzBhByB;MyBiBzB,YzBlImB,EyBuIpB;MArLb;QAmLgB,WAAU,EACX;IApLf;MAwLgB,gBAAe,EAClB;EAzLb;IA6Lc,iBAAgB;IAChB,gBAAe;IACf,8BAA6B;IAC7B,iBAAgB;IAChB,UAAS,EACd;EAlMT;IA0MkB,gBAAe;IACf,mBAAkB;IAClB,oBAAmB;IACnB,uBAAsB;IACtB,uBAAsB;IACtB,gBAAe;IACf,iBAAgB;IAChB,WAAU;IACV,gBAAe;IACf,eAAc;IACd,kBAAiB;IACjB,iBAAgB;IAChB,WAAU,EAKf;IA3Nb;MAyNqB,iBAAgB,EAClB;EA1NnB;;IA+NgB,8BAA6B,EAChC;EAhOb;IAqOoB,sCAAqC,EACxC;EAtOjB;;IA4OY,sBAAqB;IACrB,0BAAyB,EAC5B;EA9OT;IAmPQ,WAAU;IACV,eAAc;IACd,WAAU;IACV,YAAW;IACX,iBAAgB,EACnB;EAxPL;IA4PY,kBAAiB,EACpB;EA7PT;IAgQY,iBAAgB,EACnB;EAjQT;IAsQa,oCAAmC;IAInC,4BAA2B;IAC3B,UAAS;IACT,WAAU;IAEV,8BAAqB;YAArB,sBAAqB,EA4BzB;IA1ST;MAiRiB,uCAA0C;MAC1C,4CAAuC;MACvC,oCAAoC;MACpC,aAAY;MACZ,UAAS,EACZ;IAtRd;MAyRiB,uCAA0C;MAC1C,gCAA+B;MAC/B,oCAAoC;MACpC,aAAY,EACf;IA7Rd;MAiSiB,YAAW;MACX,sBAAqB;MACrB,mBAAkB;MAClB,UAAS;MACT,YAAW;MACX,4BAA2B;MAC3B,oCAAmC;MACnC,iCAAgC,EACnC;EAzSd;IA6Sa,WAAU;IAEV,oCAAmC;IAInC,4BAA2B;IAE3B,8BAAqB;YAArB,sBAAqB,EACzB;EAtTT;IA0TQ,UAAQ,EACX;;AC3TL;EACI;IACI,kBAAiB,EACpB;EAED;IACI,cAAa,EAChB;EAED;IACI,cAAa,EAChB;EAED;IAEQ,oBAAmB;IACnB,mBAAkB,EACrB;EAJL;IAQQ,UAAS;IACT,gBAAe,EAChB;EAVP;IAeU,iBAAgB,EACjB;EAhBT;IAkBY,oBAAmB,EACtB;EAnBT;IAuBQ,eAAc,EACjB;EAxBL;IA2BQ,cAAa,EAChB;EA5BL;;IAgCQ,8BAA6B;IAC7B,UAAS;IACT,yBAAgB;IAAhB,iBAAgB;IAChB,yBAAwB;IACxB,iBAAgB;IAChB,YAAW;IACX,iBAAgB;IAChB,gBAAe,EAKlB;IA5CL;;MA0CY,cAAa,EAChB;EA3CT;;IAgDQ,e1BnDwB,E0BoD3B;EAjDL;;IAqDQ,Y1BpBqB,E0BqBxB;EAtDL;IAyDQ,eAAc;IACd,mBAAkB;IAClB,YAAW;IACX,YAAW;IACX,mBAAkB;IAClB,oB1BhEwB,E0B8E3B;IA5EL;MAiEY,gBAAe,EAClB;IAlET;MAqEY,gBAAe,EAClB;IAtET;MAyEY,YAAW;MACX,qCAA4B;MAA5B,6BAA4B,EAC/B;EA3ET;IA+EQ,uB1B9CqB,E0B+CxB;EAhFL;IAmFQ,YAAW,EAKd;IAxFL;MAsFY,gBAAe,EAClB;EAKT;IpB1FA,mEoB2FqE;IpBvFrE,2DoBuFqE,EACpE;EAED;IAEQ,SAAQ;IpBhFf,4CAA6C;IAI1C,oCAAoC,EoB8EnC;EAJL;IpB9EC,0CAA6C;IAI1C,kCAAoC,EoBkFnC;EARL;IAWQ,mBAAkB;IAClB,mBAAkB,EACrB;EAbL;IpB9EC,6CAA6C;IAI1C,qCAAoC,EoB4F/B;EAlBT;;IpB9EC,0CAA6C;IAI1C,kCAAoC,EoBiG/B;EAvBT;IpB9EC,6CAA6C;IAI1C,qCAAoC,EoBqG/B;EA3BT;IA8BY,aAAY;IACZ,WAAU,EACb;EAIT;IAEQ,WAAU;IACV,SAAO;IpBrHd,4CAA6C;IAI1C,oCAAoC,EoBmHnC;EAGL;;;IAGE,+BAA8B,EAC/B;EACD;IACE,SAAQ;IpBlFT,+CAAwC;IAExC,gCAAyB;IACzB,sCAAqC;IAErC,8BAA6B,EoB+E7B;EACD;IACE,WAAU,EACX;EACD;IACE,YAAW;IpBzFZ,kDAAwC;IAExC,mCAAyB;IACzB,sCAAqC;IAErC,8BAA6B,EoBsF7B;EACD;IACE,SAAQ;IpB7FT,4CAAwC;IAExC,6BAAyB;IACzB,sCAAqC;IAErC,8BAA6B,EoB0F7B;EACD;IACE,WAAU,EACX;EACD;IACE,YAAW;IpBpGZ,+CAAwC;IAExC,gCAAyB;IACzB,sCAAqC;IAErC,8BAA6B,EoBiG7B;EpB7FD;IACE;MAAI,SAAQ;MAAG,gCAAuB;cAAvB,wBAAuB,EAAA;IACtC;MAAK,SAAQ;MAAG,kCAAyB;cAAzB,0BAAyB,EAAA;IACzC;MAAK,kCAAyB;cAAzB,0BAAyB,EAAA;IAC9B;MAAM,kCAAyB;cAAzB,0BAAyB,EAAA,EAAA;EAEjC;IACE;MAAI,SAAQ;MAAG,gCAA+B,EAAA;IAC9C;MAAK,SAAQ;MAAG,kCAAiC,EAAA;IACjD;MAAK,kCAAiC,EAAA;IACtC;MAAO,kCAAiC,EAAA,EAAA;EAW1C;IACE;MAAK,SAAQ;MAAG,kCAAyB;cAAzB,0BAAyB,EAAA;IACzC;MAAM,kCAAyB;cAAzB,0BAAyB,EAAA;IAC/B;MAAM,gCAAuB;cAAvB,wBAAuB,EAAA;IAC7B;MAAO,SAAQ;MAAG,6BAAoB;cAApB,qBAAoB,EAAA,EAAA;EAGxC;IACE;MAAK,SAAQ;MAAG,kCAAiC,EAAA;IACjD;MAAM,kCAAiC,EAAA;IACvC;MAAM,gCAA+B,EAAA;IACrC;MAAO,SAAQ;MAAG,6BAA4B,EAAA,EAAA;EAYhD;IACE;MAAI,YAAW;MAAG,gCAAuB;cAAvB,wBAAuB,EAAA;IACzC;MAAK,YAAW;MAAG,mCAA0B;cAA1B,2BAA0B,EAAA;IAC7C;MAAK,mCAA0B;cAA1B,2BAA0B,EAAA;IAC/B;MAAM,mCAA0B;cAA1B,2BAA0B,EAAA,EAAA;EAElC;IACE;MAAI,YAAW;MAAG,gCAA+B,EAAA;IACjD;MAAK,YAAW;MAAG,mCAAkC,EAAA;IACrD;MAAK,mCAAkC,EAAA;IACvC;MAAM,mCAAkC,EAAA,EAAA;EAW1C;IACE;MAAK,YAAW;MAAE,mCAA0B;cAA1B,2BAA0B,EAAA;IAC5C;MAAM,iCAAwB;cAAxB,yBAAwB,EAAA;IAC9B;MAAM,iCAAwB;cAAxB,yBAAwB,EAAA;IAC9B;MAAO,YAAW;MAAE,6BAAoB;cAApB,qBAAoB,EAAA,EAAA;EAE1C;IACE;MAAI,YAAW;MAAE,mCAAkC,EAAA;IACnD;MAAK,iCAAgC,EAAA;IACrC;MAAK,iCAAgC,EAAA;IACrC;MAAM,YAAW;MAAE,6BAA4B,EAAA,EAAA;EoByBjD;IACE;MAAI,WAAU,EAAA;IACd;MAAM,WAAU,EAAA,EAAA;EAMlB;IACE;MAAI,WAAU,EAAA;IACd;MAAM,WAAU,EAAA,EAAA;EAGlB;IACI,aAAY;IACZ,YAAW;IACX,gBAAe;IACf,WAAU;IACV,OAAM;IACN,SAAQ;IACR,YAAW;IACX,YAAW;IACX,cAAa;IACb,mBAAkB;IAClB,8BAA6B;IpBnMjC,mEoBoMqE;IpBhMrE,2DoBgMqE,EACpE;EAED;IAEQ,kBAAiB,EACpB;EAGL;IACI,iBAAgB,EACnB;EAED;;IAIY,YAAW,EACd;EAIT;;IAEI,gBAAe;IACf,eAAc;IACd,OAAM;IACN,aAAY;IACZ,aAAY;IACZ,YAAW;IACX,QAAO;IACP,cAAa;IACb,oBAAmB;IACnB,oBAAmB;IACnB,WAAU;IpBtOd,mEoBuOqE;IpBnOrE,2DoBmOqE;IpBvNpE,6CAA6C;IAI1C,qCAAoC,EoBsNvC;EAID;IACI,YAAW,EACd,EAAA;;AAGL;EACI;IACI,4BAA2B,EAC9B;EAED;IACI,cAAa,EAChB;EAQD;IAGY,WAAU;IACV,mB1B7KoB,E0B8KvB;EAIT;IACI,mBAAkB,EACrB;EAED;IACI,eAAc,EACjB;EAED;IAEQ,aAAY;IACZ,oBAAmB,EACtB,EAAA;;AAIT;EACI;IACI,sBAAqB;IACrB,YAAW;IACX,oBAAmB;IACnB,qBAAoB;IACpB,mBAAkB,EAKrB;IAVD;MAQQ,mBAAkB,EACrB;EAGP;IACE,cAAa,EACd;EAED;IACE,mBAAkB;IAClB,oBAAmB,EACpB;EAEC;IAEQ,eAAc;IACd,mBAAkB;IAClB,YAAW,EACd;EAGL;IACI,eAAc;IACd,oBAAmB,EACtB,EAAA;;AAGL;EACI;IACI,eAAc;IACd,gBAAe,EAClB;EAED;IACE,6BAAsB;IAAtB,8BAAsB;QAAtB,2BAAsB;YAAtB,uBAAsB,EAKvB;IAND;MAII,oBAAmB,EACpB;EAGH;IAEQ,mBAAkB,EACrB;EAGL;IAGY,gBAAe,EAKlB;IART;MAMgB,gBAAe,EAClB;EAKb;IAEQ,WAAU,EACb,EAAA","file":"now-ui-dashboard.css","sourcesContent":["/*!\n\n =========================================================\n * Now UI Dashboard - v1.0.1\n =========================================================\n\n * Product Page: http://www.creative-tim.com/product/now-ui-dashboard\n * Copyright 2017 Creative Tim (http://www.creative-tim.com)\n * Licensed under MIT (https://github.com/creativetimofficial/now-ui-dashboard/blob/master/LICENSE.md)\n\n * Designed by www.invisionapp.com Coded by www.creative-tim.com\n\n =========================================================\n\n * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\n */\n\n@import 'now-ui-dashboard/variables';\n@import 'now-ui-dashboard/mixins';\n\n// Plugins CSS\n@import \"now-ui-dashboard/plugins/plugin-animate-bootstrap-notify\";\n@import \"now-ui-dashboard/plugins/plugin-perfect-scrollbar\";\n\n// Core CSS\n@import \"now-ui-dashboard/buttons\";\n@import \"now-ui-dashboard/inputs\";\n@import \"now-ui-dashboard/typography\";\n@import \"now-ui-dashboard/misc\";\n@import \"now-ui-dashboard/checkboxes-radio\";\n\n// components\n@import \"now-ui-dashboard/navbar\";\n@import \"now-ui-dashboard/page-header\";\n@import \"now-ui-dashboard/dropdown\";\n@import \"now-ui-dashboard/alerts\";\n@import \"now-ui-dashboard/images\";\n@import \"now-ui-dashboard/nucleo-outline\";\n@import \"now-ui-dashboard/tables\";\n@import \"now-ui-dashboard/sidebar-and-main-panel\";\n@import \"now-ui-dashboard/cards\";\n@import \"now-ui-dashboard/footers\";\n@import \"now-ui-dashboard/fixed-plugin\";\n\n@import \"now-ui-dashboard/responsive\";\n","//== Buttons\n//\n//## For each of Bootstrap's buttons, define text, background and border color.\n\n$sans-serif-family: 'Montserrat', 'Helvetica Neue', Arial, sans-serif;\n\n$none: 0 !default;\n$border-thin: 1px !default;\n$border-thick: 2px !default;\n\n$white-color: #FFFFFF !default;\n$white-bg: #FFFFFF !default;\n$orange-bg: #e95e38 !default;\n\n$smoke-bg: #F5F5F5 !default;\n$light-black: #444 !default;\n\n$black-bg: rgba(30,30,30,.97) !default;\n\n$black-color: #2c2c2c !default;\n$black-hr: #444444 !default;\n\n$hr-line: rgba(0,0,0, .1) !default;\n\n$light-gray: #E3E3E3 !default;\n$medium-gray: #DDDDDD !default;\n$dark-gray: #9A9A9A !default;\n\n$opacity-gray-3: rgba(222,222,222, .3) !default;\n$opacity-gray-5: rgba(222,222,222, .5) !default;\n$opacity-gray-8: rgba(222,222,222, .8) !default;\n\n\n$opacity-5: rgba(255,255,255, .5) !default;\n$opacity-8: rgba(255,255,255, .8) !default;\n\n$datepicker-color-days: rgba(255,255,255, .8) !default;\n$datepicker-color-old-new-days: rgba(255,255,255, .4) !default;\n\n\n$opacity-1: rgba(255,255,255, .1) !default;\n$opacity-2: rgba(255,255,255, .2) !default;\n\n$transparent-bg: transparent !default;\n$dark-background: #555555 !default;\n\n$default-color: #888 !default;\n$default-states-color: lighten($default-color, 6%) !default;\n$default-color-opacity: rgba(182, 182, 182, .6) !default;\n\n$primary-color: #f96332 !default;\n$primary-states-color: lighten($primary-color, 6%) !default;\n$primary-color-opacity: rgba(249, 99, 50, .3) !default;\n$primary-color-alert: rgba(249, 99, 50, .8) !default;\n\n$success-color: #18ce0f !default;\n$success-states-color: lighten($success-color, 6%) !default;\n$success-color-opacity: rgba(24, 206, 15, .3) !default;\n$success-color-alert: rgba(24, 206, 15, .8) !default;\n\n$info-color: #2CA8FF !default;\n$info-states-color: lighten($info-color, 6%) !default;\n$info-color-opacity: rgba(44, 168, 255, .3) !default;\n$info-color-alert: rgba(44, 168, 255, .8) !default;\n\n$warning-color: #FFB236 !default;\n$warning-states-color: lighten($warning-color, 6%) !default;\n$warning-color-opacity: rgba(255, 178, 54, .3) !default;\n$warning-color-alert: rgba(255, 178, 54, .8) !default;\n\n$danger-color: #FF3636 !default;\n$danger-states-color: lighten($danger-color, 6%) !default;\n$danger-color-opacity: rgba(255, 54, 54, .3) !default;\n$danger-color-alert: rgba(255, 54, 54, .8) !default;\n\n$orange-color: #f96332 !default;\n\n/* brand Colors */\n$brand-primary: $primary-color !default;\n$brand-info: $info-color !default;\n$brand-success: $success-color !default;\n$brand-warning: $warning-color !default;\n$brand-danger: $danger-color !default;\n$brand-inverse: $black-color !default;\n\n$link-disabled-color: #666666 !default;\n\n/* light colors */\n$light-blue: rgba($primary-color, .2);\n$light-azure: rgba($info-color, .2);\n$light-green: rgba($success-color, .2);\n$light-orange: rgba($warning-color, .2);\n$light-red: rgba($danger-color, .2);\n\n//== Components\n//\n\n$padding-input-vertical: 11px !default;\n$padding-input-horizontal: 19px !default;\n\n$padding-btn-vertical: 11px !default;\n$padding-btn-horizontal: 22px !default;\n\n$padding-base-vertical: .5rem !default;\n$padding-base-horizontal: .7rem !default;\n\n$padding-round-horizontal: 23px !default;\n\n$padding-simple-vertical: 10px !default;\n$padding-simple-horizontal: 17px !default;\n\n$padding-large-vertical: 15px !default;\n$padding-large-horizontal: 48px !default;\n\n$padding-small-vertical: 5px !default;\n$padding-small-horizontal: 15px !default;\n\n// $padding-xs-vertical: 1px !default;\n// $padding-xs-horizontal: 5px !default;\n\n$padding-label-vertical: 2px !default;\n$padding-label-horizontal: 12px !default;\n\n$margin-large-vertical: 30px !default;\n$margin-base-vertical: 15px !default;\n\n$margin-base-horizontal: 15px !default;\n\n$margin-bottom: 10px !default;\n$border: 1px solid !default;\n$border-radius-extra-small: 0.125rem !default;\n$border-radius-small: 0.1875rem !default;\n$border-radius-large: 0.25rem !default;\n$border-radius-extreme: 0.875rem !default;\n\n$border-radius-large-top: $border-radius-large $border-radius-large 0 0 !default;\n$border-radius-large-bottom: 0 0 $border-radius-large $border-radius-large !default;\n\n$btn-round-radius: 30px !default;\n\n$height-base: 55px !default;\n\n$btn-icon-size: 3.5rem !default;\n$btn-icon-size-regular: 2.375rem !default;\n$btn-icon-font-size-regular: 0.9375rem !default;\n$btn-icon-font-size-small: 0.6875rem !default;\n$btn-icon-size-small: 1.875rem !default;\n$btn-icon-font-size-lg: 1.325rem !default;\n$btn-icon-size-lg: 3.6rem !default;\n\n$font-size-h1: 3.5em !default; // ~ 49px\n$font-size-h2: 2.5em !default; // ~ 35px\n$font-size-h3: 2em !default; // ~ 28px\n$font-size-h4: 1.714em !default; // ~ 24px\n$font-size-h5: 1.57em !default; // ~ 22px\n$font-size-h6: 1em !default; // ~ 14px\n\n$font-paragraph: 1em !default;\n$font-size-navbar: 1em !default;\n$font-size-mini: 0.7142em !default;\n$font-size-small: 0.8571em !default;\n$font-size-base: 14px !default;\n$font-size-large: 1em !default;\n$font-size-large-navbar: 20px !default;\n$font-size-blockquote: 1.1em !default; // ~ 15px\n\n$font-weight-light: 300 !default;\n$font-weight-normal: 400 !default;\n$font-weight-semi: 600 !default;\n$font-weight-bold: 700 !default;\n\n$line-height-general: 1.5 !default;\n$line-height-nav-link: 1.625rem !default;\n$btn-icon-line-height: 2.4em !default;\n$line-height: 1.35em !default;\n$line-height-lg: 54px !default;\n\n\n$border-radius-top: 10px 10px 0 0 !default;\n$border-radius-bottom: 0 0 10px 10px !default;\n\n$dropdown-shadow: 1px 2px 3px 0px rgba(0, 0, 0, 0.125);\n$box-shadow-raised: 0px 10px 25px 0px rgba(0, 0, 0, 0.3);\n$box-shadow: 0 1px 15px 1px rgba(39, 39, 39, 0.1);\n$sidebar-box-shadow: 0px 2px 22px 0 rgba(0, 0, 0,.20), 0px 2px 30px 0 rgba(0, 0, 0,.35);\n\n$general-transition-time: 300ms !default;\n\n$slow-transition-time: 370ms !default;\n$dropdown-coordinates: 29px -50px !default;\n\n$fast-transition-time: 150ms !default;\n$select-coordinates: 50% -40px !default;\n\n$transition-linear: linear !default;\n$transition-bezier: cubic-bezier(0.34, 1.61, 0.7, 1) !default;\n$transition-ease: ease 0s;\n\n\n//$navbar-padding-a: 9px 13px;\n$navbar-margin-a: 15px 0px;\n\n$padding-social-a: 10px 5px;\n\n$navbar-margin-a-btn: 15px 0px;\n$navbar-margin-a-btn-round: 16px 0px;\n\n$navbar-padding-a-icons: 6px 15px;\n$navbar-margin-a-icons: 6px 3px;\n\n$navbar-padding-base: 0.625rem;\n//$navbar-margin-brand: 5px 0px;\n\n$navbar-margin-brand-icons: 12px auto;\n$navbar-margin-btn: 15px 3px;\n\n$height-icon-sm:\t\t\t\t 32px;\n$width-icon-sm:\t\t\t\t\t 32px;\n$padding-icon-sm:\t\t\t 4px;\n$border-radius-icon-sm:\t\t\t 7px;\n\n$height-icon-message:\t\t\t 40px;\n$width-icon-message:\t\t\t 40px;\n\n$height-icon-message-sm: \t\t 20px;\n$width-icon-message-sm:\t\t\t 20px;\n\n$white-navbar: rgba(#FFFFFF, .96);\n$primary-navbar: rgba(#34ACDC, .98);\n$info-navbar: rgba(#5BCAFF, .98);\n$success-navbar: rgba(#4CD964, .98);\n$warning-navbar: rgba(#FF9500, .98);\n$danger-navbar: rgba(#FF4C40, .98);\n\n$topbar-x: topbar-x !default;\n$topbar-back: topbar-back !default;\n$bottombar-x: bottombar-x !default;\n$bottombar-back: bottombar-back !default;\n\n//Nucleo Icons\n\n$nc-font-path: '../fonts' !default;\n$nc-font-size-base: 14px !default;\n$nc-css-prefix: now-ui !default;\n$nc-background-color: #eee !default;\n$nc-li-width: (30em / 14) !default;\n$nc-padding-width: (1em/3) !default;\n\n// Social icons color\n$social-twitter: #55acee !default;\n$social-twitter-state-color: darken(#55acee, 5%) !default;\n\n$social-facebook: \t\t\t #3b5998 !default;\n$social-facebook-state-color: darken(#3b5998, 5%) !default;\n\n$social-google: \t\t\t #dd4b39 !default;\n$social-google-state-color: darken(#dd4b39, 5%) !default;\n\n$social-linkedin: \t\t\t #0077B5 !default;\n$social-linkedin-state-color: darken(#0077B5, 5%) !default;\n\n// Sidebar variables\n$sidebar-width: calc(100% - 260px) !default;\n$sidebar-mini-width: calc(100% - 80px) !default;\n\n\n// Social icons color\n$social-twitter: #55acee !default;\n$social-twitter-state-color: lighten(#55acee, 6%) !default;\n\n$social-facebook: \t\t\t #3b5998 !default;\n$social-facebook-state-color: lighten(#3b5998, 6%) !default;\n\n$social-google: \t\t\t #dd4b39 !default;\n$social-google-state-color: lighten(#dd4b39, 6%) !default;\n\n$social-linkedin: \t\t\t #0077B5 !default;\n$social-linkedin-state-color: lighten(#0077B5, 6%) !default;\n\n$social-pinterest: \t\t\t #cc2127 !default;\n$social-pinterest-state-color: lighten(#cc2127, 6%) !default;\n\n$social-dribbble: \t\t #ea4c89 !default;\n$social-dribbble-state-color: lighten(#ea4c89, 6%) !default;\n\n$social-github: \t\t \t #333333 !default;\n$social-github-state-color: lighten(#333333, 6%) !default;\n\n$social-youtube: \t\t \t #e52d27 !default;\n$social-youtube-state-color: lighten(#e52d27, 6%) !default;\n\n$social-instagram: \t\t #125688 !default;\n$social-instagram-state-color: lighten(#125688, 6%) !default;\n\n$social-reddit: \t\t \t #ff4500 !default;\n$social-reddit-state-color: lighten(#ff4500, 6%) !default;\n\n$social-tumblr: \t\t\t #35465c !default;\n$social-tumblr-state-color: lighten(#35465c, 6%) !default;\n\n$social-behance: \t\t\t #1769ff !default;\n$social-behance-state-color: lighten(#1769ff, 6%) !default;\n","\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n// This file was modified by Creative Tim to keep only the animation that we need for Bootstrap Notify\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n@charset \"UTF-8\";\n\n/*!\nAnimate.css - http://daneden.me/animate\nLicensed under the MIT license - http://opensource.org/licenses/MIT\n\nCopyright (c) 2015 Daniel Eden\n*/\n\n.animated {\n -webkit-animation-duration: 1s;\n animation-duration: 1s;\n -webkit-animation-fill-mode: both;\n animation-fill-mode: both;\n}\n\n.animated.infinite {\n -webkit-animation-iteration-count: infinite;\n animation-iteration-count: infinite;\n}\n\n.animated.hinge {\n -webkit-animation-duration: 2s;\n animation-duration: 2s;\n}\n\n.animated.bounceIn,\n.animated.bounceOut {\n -webkit-animation-duration: .75s;\n animation-duration: .75s;\n}\n\n.animated.flipOutX,\n.animated.flipOutY {\n -webkit-animation-duration: .75s;\n animation-duration: .75s;\n}\n\n@-webkit-keyframes shake {\n from, to {\n -webkit-transform: translate3d(0, 0, 0);\n transform: translate3d(0, 0, 0);\n }\n\n 10%, 30%, 50%, 70%, 90% {\n -webkit-transform: translate3d(-10px, 0, 0);\n transform: translate3d(-10px, 0, 0);\n }\n\n 20%, 40%, 60%, 80% {\n -webkit-transform: translate3d(10px, 0, 0);\n transform: translate3d(10px, 0, 0);\n }\n}\n\n@keyframes shake {\n from, to {\n -webkit-transform: translate3d(0, 0, 0);\n transform: translate3d(0, 0, 0);\n }\n\n 10%, 30%, 50%, 70%, 90% {\n -webkit-transform: translate3d(-10px, 0, 0);\n transform: translate3d(-10px, 0, 0);\n }\n\n 20%, 40%, 60%, 80% {\n -webkit-transform: translate3d(10px, 0, 0);\n transform: translate3d(10px, 0, 0);\n }\n}\n\n.shake {\n -webkit-animation-name: shake;\n animation-name: shake;\n}\n\n\n\n@-webkit-keyframes fadeInDown {\n from {\n opacity: 0;\n -webkit-transform: translate3d(0, -100%, 0);\n transform: translate3d(0, -100%, 0);\n }\n\n to {\n opacity: 1;\n -webkit-transform: none;\n transform: none;\n }\n}\n\n@keyframes fadeInDown {\n from {\n opacity: 0;\n -webkit-transform: translate3d(0, -100%, 0);\n transform: translate3d(0, -100%, 0);\n }\n\n to {\n opacity: 1;\n -webkit-transform: none;\n transform: none;\n }\n}\n\n.fadeInDown {\n -webkit-animation-name: fadeInDown;\n animation-name: fadeInDown;\n}\n\n\n@-webkit-keyframes fadeOut {\n from {\n opacity: 1;\n }\n\n to {\n opacity: 0;\n }\n}\n\n@keyframes fadeOut {\n from {\n opacity: 1;\n }\n\n to {\n opacity: 0;\n }\n}\n\n.fadeOut {\n -webkit-animation-name: fadeOut;\n animation-name: fadeOut;\n}\n\n@-webkit-keyframes fadeOutDown {\n from {\n opacity: 1;\n }\n\n to {\n opacity: 0;\n -webkit-transform: translate3d(0, 100%, 0);\n transform: translate3d(0, 100%, 0);\n }\n}\n\n@keyframes fadeOutDown {\n from {\n opacity: 1;\n }\n\n to {\n opacity: 0;\n -webkit-transform: translate3d(0, 100%, 0);\n transform: translate3d(0, 100%, 0);\n }\n}\n\n.fadeOutDown {\n -webkit-animation-name: fadeOutDown;\n animation-name: fadeOutDown;\n}\n\n@-webkit-keyframes fadeOutUp {\n from {\n opacity: 1;\n }\n\n to {\n opacity: 0;\n -webkit-transform: translate3d(0, -100%, 0);\n transform: translate3d(0, -100%, 0);\n }\n}\n\n@keyframes fadeOutUp {\n from {\n opacity: 1;\n }\n\n to {\n opacity: 0;\n -webkit-transform: translate3d(0, -100%, 0);\n transform: translate3d(0, -100%, 0);\n }\n}\n\n.fadeOutUp {\n -webkit-animation-name: fadeOutUp;\n animation-name: fadeOutUp;\n}\n","/* perfect-scrollbar v0.6.13 */\n.ps-container {\n -ms-touch-action: auto;\n touch-action: auto;\n overflow: hidden !important;\n -ms-overflow-style: none; }\n @supports (-ms-overflow-style: none) {\n .ps-container {\n overflow: auto !important; } }\n @media screen and (-ms-high-contrast: active), (-ms-high-contrast: none) {\n .ps-container {\n overflow: auto !important; } }\n .ps-container.ps-active-x > .ps-scrollbar-x-rail,\n .ps-container.ps-active-y > .ps-scrollbar-y-rail {\n display: block;\n background-color: transparent; }\n .ps-container.ps-in-scrolling.ps-x > .ps-scrollbar-x-rail {\n background-color: #eee;\n opacity: 0.9; }\n .ps-container.ps-in-scrolling.ps-x > .ps-scrollbar-x-rail > .ps-scrollbar-x {\n background-color: #999;\n height: 11px; }\n .ps-container.ps-in-scrolling.ps-y > .ps-scrollbar-y-rail {\n background-color: #eee;\n opacity: 0.9; }\n .ps-container.ps-in-scrolling.ps-y > .ps-scrollbar-y-rail > .ps-scrollbar-y {\n background-color: #999;\n width: 11px; }\n .ps-container > .ps-scrollbar-x-rail {\n display: none;\n position: absolute;\n /* please don't change 'position' */\n opacity: 0;\n -webkit-transition: background-color .2s linear, opacity .2s linear;\n -o-transition: background-color .2s linear, opacity .2s linear;\n -moz-transition: background-color .2s linear, opacity .2s linear;\n transition: background-color .2s linear, opacity .2s linear;\n bottom: 0px;\n /* there must be 'bottom' for ps-scrollbar-x-rail */\n height: 15px; }\n .ps-container > .ps-scrollbar-x-rail > .ps-scrollbar-x {\n position: absolute;\n /* please don't change 'position' */\n background-color: #aaa;\n -webkit-border-radius: 6px;\n -moz-border-radius: 6px;\n border-radius: 6px;\n -webkit-transition: background-color .2s linear, height .2s linear, width .2s ease-in-out, -webkit-border-radius .2s ease-in-out;\n transition: background-color .2s linear, height .2s linear, width .2s ease-in-out, -webkit-border-radius .2s ease-in-out;\n -o-transition: background-color .2s linear, height .2s linear, width .2s ease-in-out, border-radius .2s ease-in-out;\n -moz-transition: background-color .2s linear, height .2s linear, width .2s ease-in-out, border-radius .2s ease-in-out, -moz-border-radius .2s ease-in-out;\n transition: background-color .2s linear, height .2s linear, width .2s ease-in-out, border-radius .2s ease-in-out;\n transition: background-color .2s linear, height .2s linear, width .2s ease-in-out, border-radius .2s ease-in-out, -webkit-border-radius .2s ease-in-out, -moz-border-radius .2s ease-in-out;\n bottom: 2px;\n /* there must be 'bottom' for ps-scrollbar-x */\n height: 6px; }\n .ps-container > .ps-scrollbar-x-rail:hover > .ps-scrollbar-x, .ps-container > .ps-scrollbar-x-rail:active > .ps-scrollbar-x {\n height: 11px; }\n .ps-container > .ps-scrollbar-y-rail {\n display: none;\n position: absolute;\n /* please don't change 'position' */\n opacity: 0;\n -webkit-transition: background-color .2s linear, opacity .2s linear;\n -o-transition: background-color .2s linear, opacity .2s linear;\n -moz-transition: background-color .2s linear, opacity .2s linear;\n transition: background-color .2s linear, opacity .2s linear;\n right: 0;\n /* there must be 'right' for ps-scrollbar-y-rail */\n width: 15px; }\n .ps-container > .ps-scrollbar-y-rail > .ps-scrollbar-y {\n position: absolute;\n /* please don't change 'position' */\n background-color: #aaa;\n -webkit-border-radius: 6px;\n -moz-border-radius: 6px;\n border-radius: 6px;\n -webkit-transition: background-color .2s linear, height .2s linear, width .2s ease-in-out, -webkit-border-radius .2s ease-in-out;\n transition: background-color .2s linear, height .2s linear, width .2s ease-in-out, -webkit-border-radius .2s ease-in-out;\n -o-transition: background-color .2s linear, height .2s linear, width .2s ease-in-out, border-radius .2s ease-in-out;\n -moz-transition: background-color .2s linear, height .2s linear, width .2s ease-in-out, border-radius .2s ease-in-out, -moz-border-radius .2s ease-in-out;\n transition: background-color .2s linear, height .2s linear, width .2s ease-in-out, border-radius .2s ease-in-out;\n transition: background-color .2s linear, height .2s linear, width .2s ease-in-out, border-radius .2s ease-in-out, -webkit-border-radius .2s ease-in-out, -moz-border-radius .2s ease-in-out;\n right: 2px;\n /* there must be 'right' for ps-scrollbar-y */\n width: 6px; }\n .ps-container > .ps-scrollbar-y-rail:hover > .ps-scrollbar-y, .ps-container > .ps-scrollbar-y-rail:active > .ps-scrollbar-y {\n width: 11px; }\n .ps-container:hover.ps-in-scrolling.ps-x > .ps-scrollbar-x-rail {\n background-color: #eee;\n opacity: 0.9; }\n .ps-container:hover.ps-in-scrolling.ps-x > .ps-scrollbar-x-rail > .ps-scrollbar-x {\n background-color: #999;\n height: 11px; }\n .ps-container:hover.ps-in-scrolling.ps-y > .ps-scrollbar-y-rail {\n background-color: #eee;\n opacity: 0.9; }\n .ps-container:hover.ps-in-scrolling.ps-y > .ps-scrollbar-y-rail > .ps-scrollbar-y {\n background-color: #999;\n width: 11px; }\n .ps-container:hover > .ps-scrollbar-x-rail,\n .ps-container:hover > .ps-scrollbar-y-rail {\n opacity: 0.6; }\n .ps-container:hover > .ps-scrollbar-x-rail:hover {\n background-color: #eee;\n opacity: 0.9; }\n .ps-container:hover > .ps-scrollbar-x-rail:hover > .ps-scrollbar-x {\n background-color: #999; }\n .ps-container:hover > .ps-scrollbar-y-rail:hover {\n background-color: #eee;\n opacity: 0.9; }\n .ps-container:hover > .ps-scrollbar-y-rail:hover > .ps-scrollbar-y {\n background-color: #999; }\n",".btn,\n.navbar .navbar-nav > a.btn{\n border-width: $border-thick;\n font-weight: $font-weight-normal;\n font-size: $font-size-small;\n line-height: $line-height;\n margin: 5px 1px;\n border: none;\n margin:10px 1px;\n border-radius: $border-radius-small;\n padding: $padding-btn-vertical $padding-btn-horizontal;\n cursor: pointer;\n\n @include btn-styles($default-color, $default-states-color);\n\n &:hover,\n &:focus{\n @include opacity(1);\n outline: 0 !important;\n }\n &:active,\n &.active,\n .open > &.dropdown-toggle {\n @include box-shadow(none);\n outline: 0 !important;\n }\n\n .badge{\n margin: 0;\n }\n\n &.btn-icon {\n // see above for color variations\n height: $btn-icon-size-regular;\n min-width: $btn-icon-size-regular;\n width: $btn-icon-size-regular;\n padding: 0;\n font-size: $btn-icon-font-size-regular;\n overflow: hidden;\n position: relative;\n line-height: normal;\n\n &.btn-simple{\n padding: 0;\n }\n\n &.btn-sm{\n height: $btn-icon-size-small;\n min-width: $btn-icon-size-small;\n width: $btn-icon-size-small;\n\n i.fa,\n i.now-ui-icons{\n font-size: $btn-icon-font-size-small;\n }\n }\n\n &.btn-lg{\n height: $btn-icon-size-lg;\n min-width: $btn-icon-size-lg;\n width: $btn-icon-size-lg;\n\n i.now-ui-icons,\n i.fa{\n font-size: $btn-icon-font-size-lg;\n }\n }\n\n &:not(.btn-footer) i.now-ui-icons,\n &:not(.btn-footer) i.fa{\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-12px, -12px);\n line-height: 1.5626rem;\n width: 24px;\n }\n\n }\n\n &:not(.btn-icon) .now-ui-icons{\n position: relative;\n top: 1px;\n }\n}\n\n// Apply the mixin to the buttons\n// .btn-default { @include btn-styles($default-color, $default-states-color); }\n.btn-primary { @include btn-styles($primary-color, $primary-states-color); }\n.btn-success { @include btn-styles($success-color, $success-states-color); }\n.btn-info { @include btn-styles($info-color, $info-states-color); }\n.btn-warning { @include btn-styles($warning-color, $warning-states-color); }\n.btn-danger { @include btn-styles($danger-color, $danger-states-color); }\n.btn-neutral { @include btn-styles($white-color, $white-color); }\n\n.btn{\n &:disabled,\n &[disabled],\n &.disabled{\n @include opacity(.5);\n pointer-events: none;\n }\n}\n.btn-simple{\n border: $border;\n border-color: $default-color;\n padding: $padding-btn-vertical - 1 $padding-round-horizontal - 1;\n background-color: $transparent-bg;\n}\n\n.btn-simple,\n.btn-link{\n &.disabled,\n &:disabled,\n &[disabled],\n fieldset[disabled] & {\n &,\n &:hover,\n &:focus,\n &.focus,\n &:active,\n &.active {\n background-color: $transparent-bg;\n }\n }\n}\n\n.btn-link{\n border: $none;\n padding: $padding-base-vertical $padding-base-horizontal;\n background-color: $transparent-bg;\n}\n\n.btn-lg{\n @include btn-size($padding-large-vertical, $padding-large-horizontal, $font-size-large, $border-radius-large);\n}\n.btn-sm{\n @include btn-size($padding-small-vertical, $padding-small-horizontal, $font-size-base, $border-radius-small);\n}\n\n.btn-wd {\n min-width: 140px;\n}\n.btn-group.select{\n width: 100%;\n}\n.btn-group.select .btn{\n text-align: left;\n}\n.btn-group.select .caret{\n position: absolute;\n top: 50%;\n margin-top: -1px;\n right: 8px;\n}\n\n.btn-round{\n border-width: $border-thin;\n border-radius: $btn-round-radius;\n padding-right: $padding-round-horizontal;\n padding-left: $padding-round-horizontal;\n\n &.btn-simple{\n padding: $padding-btn-vertical - 1 $padding-round-horizontal - 1;\n }\n}\n\n.no-caret {\n &.dropdown-toggle::after {\n display: none;\n }\n}\n","// Mixin for generating new styles\n@mixin btn-styles($btn-color, $btn-states-color) {\n background-color: $btn-color;\n\n &:hover,\n &:focus,\n &:active,\n &.active,\n &:active:focus,\n &:active:hover,\n &.active:focus,\n &.active:hover,\n .show > &.dropdown-toggle,\n .show > &.dropdown-toggle:focus,\n .show > &.dropdown-toggle:hover {\n background-color: $btn-states-color;\n color: $white-color;\n box-shadow: none;\n }\n\n &:not([data-action]):hover{\n box-shadow: 0 3px 8px 0 rgba(0,0,0, 0.17);\n }\n\n &.disabled,\n &:disabled,\n &[disabled],\n fieldset[disabled] & {\n &,\n &:hover,\n &:focus,\n &.focus,\n &:active,\n &.active {\n background-color: $btn-color;\n border-color: $btn-color;\n }\n }\n\n // btn-neutral style\n @if $btn-color == $white-color{\n color: $primary-color;\n\n &.btn-danger{\n color: $danger-color;\n\n &:hover,\n &:focus,\n &:active,\n &:active:focus{\n color: $danger-states-color;\n }\n }\n\n &.btn-info{\n color: $info-color;\n\n &:hover,\n &:focus,\n &:active,\n &:active:focus{\n color: $info-states-color;\n }\n }\n\n &.btn-warning{\n color: $warning-color;\n\n &:hover,\n &:focus,\n &:active,\n &:active:focus{\n color: $warning-states-color;\n }\n }\n\n &.btn-success{\n color: $success-color;\n\n &:hover,\n &:focus,\n &:active,\n &:active:focus{\n color: $success-states-color;\n }\n }\n\n &.btn-default{\n color: $default-color;\n\n &:hover,\n &:focus,\n &:active,\n &:active:focus{\n color: $default-states-color;\n }\n }\n\n &.active,\n &:active,\n &:active:focus,\n &:active:hover,\n &.active:focus,\n &.active:hover,\n .show > &.dropdown-toggle,\n .show > &.dropdown-toggle:focus,\n .show > &.dropdown-toggle:hover {\n background-color: $white-color;\n color: $primary-states-color;\n box-shadow: none;\n }\n\n &:hover,\n &:focus{\n color: $primary-states-color;\n\n &:not(.nav-link){\n box-shadow: none;\n }\n\n }\n\n } @else {\n color: $white-color;\n }\n\n &.btn-simple{\n color: $btn-color;\n border-color: $btn-color;\n\n &:hover,\n &:focus,\n &:active{\n background-color: $transparent-bg;\n color: $btn-states-color;\n border-color: $btn-states-color;\n box-shadow: none;\n }\n }\n\n &.btn-link{\n color: $btn-color;\n\n &:hover,\n &:focus,\n &:active{\n background-color: $transparent-bg;\n color: $btn-states-color;\n text-decoration: none;\n box-shadow: none;\n }\n }\n}\n\n\n@mixin btn-size($padding-vertical, $padding-horizontal, $font-size, $border){\n font-size: $font-size;\n border-radius: $border;\n padding: $padding-vertical $padding-horizontal;\n\n &.btn-simple{\n padding: $padding-vertical - 1 $padding-horizontal - 1;\n }\n\n}\n","// Opacity\n\n@mixin opacity($opacity) {\n opacity: $opacity;\n // IE8 filter\n $opacity-ie: ($opacity * 100);\n filter: #{alpha(opacity=$opacity-ie)};\n}\n","@mixin box-shadow($shadow...) {\n -webkit-box-shadow: $shadow; // iOS <4.3 & Android <4.1\n box-shadow: $shadow;\n}\n\n@mixin transition-input-focus-color() {\n -webkit-transition: color 0.3s ease-in-out, border-color 0.3s ease-in-out, background-color 0.3s ease-in-out;\n -moz-transition: color 0.3s ease-in-out, border-color 0.3s ease-in-out, background-color 0.3s ease-in-out;\n -o-transition: color 0.3s ease-in-out, border-color 0.3s ease-in-out, background-color 0.3s ease-in-out;\n -ms-transition: color 0.3s ease-in-out, border-color 0.3s ease-in-out, background-color 0.3s ease-in-out;\n transition: color 0.3s ease-in-out, border-color 0.3s ease-in-out, background-color 0.3s ease-in-out;\n}\n\n\n@mixin transition($time, $type){\n -webkit-transition: all $time $type;\n -moz-transition: all $time $type;\n -o-transition: all $time $type;\n -ms-transition: all $time $type;\n transition: all $time $type;\n}\n\n@mixin rotate-180(){\n filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=2);\n -webkit-transform: rotate(180deg);\n -ms-transform: rotate(180deg);\n transform: rotate(180deg);\n}\n\n\n@mixin transform-translate-x($value){\n -webkit-transform: translate3d($value, 0, 0);\n -moz-transform: translate3d($value, 0, 0);\n -o-transform: translate3d($value, 0, 0);\n -ms-transform: translate3d($value, 0, 0);\n transform: translate3d($value, 0, 0);\n}\n\n@mixin transform-translate-y($value){\n -webkit-transform: translate3d(0,$value,0);\n -moz-transform: translate3d(0,$value,0);\n -o-transform: translate3d(0,$value,0);\n -ms-transform: translate3d(0,$value,0);\n transform: translate3d(0,$value,0);\n}\n\n@mixin transform-translate-y-dropdown($value) {\n -webkit-transform: translate3d(0,$value,0) !important;\n -moz-transform: translate3d(0,$value,0) !important;\n -o-transform: translate3d(0,$value,0) !important;\n -ms-transform: translate3d(0,$value,0) !important;\n transform: translate3d(0,$value,0) !important;\n}\n\n@mixin icon-gradient($color, $bottomColor: #000){\n background: $color;\n background: -webkit-linear-gradient($color 0%, $bottomColor 80%);\n background: -o-linear-gradient($color 0%, $bottomColor 80%);\n background: -moz-linear-gradient($color 0%, $bottomColor 80%);\n background: linear-gradient($color 0%, $bottomColor 80%);\n}\n\n@mixin sidebar-color($color){\n &:after{\n background: $color;\n }\n\n .nav li.active > a{\n color: $color;\n\n i{\n color: $color;\n }\n }\n}\n\n@mixin bar-animation($type){\n -webkit-animation: $type 500ms linear 0s;\n -moz-animation: $type 500ms linear 0s;\n animation: $type 500ms 0s;\n -webkit-animation-fill-mode: forwards;\n -moz-animation-fill-mode: forwards;\n animation-fill-mode: forwards;\n}\n\n@mixin topbar-x-rotation(){\n @keyframes topbar-x {\n 0% {top: 0px; transform: rotate(0deg); }\n 45% {top: 6px; transform: rotate(145deg); }\n 75% {transform: rotate(130deg); }\n 100% {transform: rotate(135deg); }\n }\n @-webkit-keyframes topbar-x {\n 0% {top: 0px; -webkit-transform: rotate(0deg); }\n 45% {top: 6px; -webkit-transform: rotate(145deg); }\n 75% {-webkit-transform: rotate(130deg); }\n 100% { -webkit-transform: rotate(135deg); }\n }\n @-moz-keyframes topbar-x {\n 0% {top: 0px; -moz-transform: rotate(0deg); }\n 45% {top: 6px; -moz-transform: rotate(145deg); }\n 75% {-moz-transform: rotate(130deg); }\n 100% { -moz-transform: rotate(135deg); }\n }\n}\n\n@mixin topbar-back-rotation(){\n @keyframes topbar-back {\n 0% { top: 6px; transform: rotate(135deg); }\n 45% { transform: rotate(-10deg); }\n 75% { transform: rotate(5deg); }\n 100% { top: 0px; transform: rotate(0); }\n }\n\n @-webkit-keyframes topbar-back {\n 0% { top: 6px; -webkit-transform: rotate(135deg); }\n 45% { -webkit-transform: rotate(-10deg); }\n 75% { -webkit-transform: rotate(5deg); }\n 100% { top: 0px; -webkit-transform: rotate(0); }\n }\n\n @-moz-keyframes topbar-back {\n 0% { top: 6px; -moz-transform: rotate(135deg); }\n 45% { -moz-transform: rotate(-10deg); }\n 75% { -moz-transform: rotate(5deg); }\n 100% { top: 0px; -moz-transform: rotate(0); }\n }\n}\n\n@mixin bottombar-x-rotation(){\n @keyframes bottombar-x {\n 0% {bottom: 0px; transform: rotate(0deg);}\n 45% {bottom: 6px; transform: rotate(-145deg);}\n 75% {transform: rotate(-130deg);}\n 100% {transform: rotate(-135deg);}\n }\n @-webkit-keyframes bottombar-x {\n 0% {bottom: 0px; -webkit-transform: rotate(0deg);}\n 45% {bottom: 6px; -webkit-transform: rotate(-145deg);}\n 75% {-webkit-transform: rotate(-130deg);}\n 100% {-webkit-transform: rotate(-135deg);}\n }\n @-moz-keyframes bottombar-x {\n 0% {bottom: 0px; -moz-transform: rotate(0deg);}\n 45% {bottom: 6px; -moz-transform: rotate(-145deg);}\n 75% {-moz-transform: rotate(-130deg);}\n 100% {-moz-transform: rotate(-135deg);}\n }\n}\n\n@mixin bottombar-back-rotation{\n @keyframes bottombar-back {\n 0% { bottom: 6px;transform: rotate(-135deg);}\n 45% { transform: rotate(10deg);}\n 75% { transform: rotate(-5deg);}\n 100% { bottom: 0px;transform: rotate(0);}\n }\n @-webkit-keyframes bottombar-back {\n 0% {bottom: 6px;-webkit-transform: rotate(-135deg);}\n 45% {-webkit-transform: rotate(10deg);}\n 75% {-webkit-transform: rotate(-5deg);}\n 100% {bottom: 0px;-webkit-transform: rotate(0);}\n }\n @-moz-keyframes bottombar-back {\n 0% {bottom: 6px;-moz-transform: rotate(-135deg);}\n 45% {-moz-transform: rotate(10deg);}\n 75% {-moz-transform: rotate(-5deg);}\n 100% {bottom: 0px;-moz-transform: rotate(0);}\n }\n\n}\n\n\n@mixin nc-rotate($degrees, $rotation) {\n filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=#{$rotation});\n -webkit-transform: rotate($degrees);\n -moz-transform: rotate($degrees);\n -ms-transform: rotate($degrees);\n -o-transform: rotate($degrees);\n transform: rotate($degrees);\n}\n\n@mixin nc-flip($horiz, $vert, $rotation) {\n filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=#{$rotation});\n -webkit-transform: scale($horiz, $vert);\n -moz-transform: scale($horiz, $vert);\n -ms-transform: scale($horiz, $vert);\n -o-transform: scale($horiz, $vert);\n transform: scale($horiz, $vert);\n}\n","@mixin input-size($padding-vertical, $padding-horizontal){\n padding: $padding-vertical $padding-horizontal;\n}\n\n@mixin form-control-placeholder($color, $opacity){\n .form-control::-moz-placeholder{\n color: $color;\n @include opacity(1);\n }\n .form-control:-moz-placeholder{\n color: $color;\n @include opacity(1);\n }\n .form-control::-webkit-input-placeholder{\n color: $color;\n @include opacity(1);\n }\n .form-control:-ms-input-placeholder{\n color: $color;\n @include opacity(1);\n }\n}\n\n@mixin placeholder() {\n &::-moz-placeholder {@content; } // Firefox\n &:-ms-input-placeholder {@content; } // Internet Explorer 10+\n &::-webkit-input-placeholder {@content; } // Safari and Chrome\n}\n\n@mixin light-form(){\n border-radius: 0;\n border:0;\n padding: 0;\n background-color: transparent;\n\n}\n\n\n@mixin form-control-lg-padding($padding-vertical, $padding-horizontal) {\n .form-group.no-border.form-control-lg,\n .input-group.no-border.form-control-lg{\n .input-group-addon{\n padding: $padding-vertical 0 $padding-vertical $padding-horizontal;\n }\n\n .form-control{\n padding: $padding-vertical $padding-horizontal;\n\n & + .input-group-addon{\n padding: $padding-vertical $padding-horizontal $padding-vertical 0;\n }\n }\n }\n\n .form-group.form-control-lg,\n .input-group.form-control-lg{\n .form-control{\n padding: $padding-vertical - 1 $padding-horizontal - 1;\n\n & + .input-group-addon{\n padding: $padding-vertical - 1 $padding-horizontal - 1 $padding-vertical - 1 0;\n }\n }\n\n .input-group-addon{\n padding: $padding-vertical - 1 0 $padding-vertical $padding-horizontal - 1;\n\n & + .form-control{\n padding: $padding-vertical $padding-horizontal - 1 $padding-vertical $padding-horizontal - 3;\n }\n }\n }\n}\n\n\n\n@mixin input-base-padding($padding-vertical, $padding-horizontal) {\n .form-group.no-border,\n .input-group.no-border{\n .form-control{\n padding: $padding-vertical $padding-horizontal;\n\n & + .input-group-addon{\n padding: $padding-vertical $padding-horizontal $padding-vertical 0;\n }\n }\n\n .input-group-addon{\n padding: $padding-vertical 0 $padding-vertical $padding-horizontal;\n }\n }\n\n .form-group,\n .input-group{\n .form-control{\n padding: $padding-vertical - 1 $padding-horizontal - 1 $padding-vertical - 1 $padding-horizontal - 1;\n\n & + .input-group-addon{\n padding: $padding-vertical - 1 $padding-horizontal - 1 $padding-vertical - 1 0;\n }\n }\n\n .input-group-addon{\n padding: $padding-vertical - 1 0 $padding-vertical - 1 $padding-horizontal - 1;\n\n & + .form-control,\n & ~ .form-control{\n padding:$padding-vertical - 1 $padding-horizontal $padding-vertical $padding-horizontal - 3;\n }\n }\n }\n}\n\n\n//color1 = $opacity-5\n//color2 = $opacity-8\n//color3 = $white-color\n//color4 = $transparent-bg\n//color5 = $opacity-1\n//color6 = $opacity-2\n\n\n@mixin input-coloured-bg($color1, $color2, $color3, $color4, $color5, $color6) {\n @include form-control-placeholder(darken($color2, 8%), 1);\n\n .form-control{\n border-color: $color1;\n color: $color2;\n\n &:focus{\n border-color: $color3;\n background-color: $color4;\n color: $color3;\n }\n }\n\n .has-success,\n .has-danger{\n &:after{\n color: $color3;\n }\n }\n\n .has-danger{\n .form-control{\n background-color: $color4;\n }\n }\n\n .input-group-addon{\n background-color: $color4;\n border-color: $color1;\n color: $color2;\n }\n\n .input-group-focus{\n .input-group-addon{\n background-color: $color4;\n border-color: $color3;\n color: $color3;\n }\n }\n\n .form-group.no-border,\n .input-group.no-border{\n .form-control{\n background-color: $color5;\n color: $color2;\n\n &:focus,\n &:active,\n &:active{\n background-color: $color6;\n color: $color3;\n }\n }\n\n .form-control + .input-group-addon{\n background-color: $color5;\n\n &:focus,\n &:active,\n &:active{\n background-color: $color6;\n color: $color3;\n }\n }\n\n .form-control{\n &:focus{\n & + .input-group-addon{\n background-color: $color6;\n color: $color3;\n }\n }\n }\n\n .input-group-addon{\n background-color: $color5;\n border: none;\n color: $color2;\n }\n\n &.input-group-focus{\n .input-group-addon{\n background-color: $color6;\n color: $color3;\n }\n }\n }\n}\n","@include form-control-placeholder($medium-gray, 1);\n\n.form-control {\n background-color: $transparent-bg;\n border: 1px solid $light-gray;\n border-radius: $btn-round-radius;\n color: $black-color;\n line-height: normal;\n font-size: $font-size-small;\n @include transition-input-focus-color();\n @include box-shadow(none);\n\n\n\n &:focus{\n border: 1px solid $primary-color;\n @include box-shadow(none);\n outline: 0 !important;\n color: $black-color;\n\n & + .input-group-addon,\n & ~ .input-group-addon{\n border: 1px solid $primary-color;\n border-left: none;\n background-color: $transparent-bg;\n }\n }\n\n .has-success &,\n .has-error &,\n .has-success &:focus,\n .has-error &:focus{\n @include box-shadow(none);\n }\n\n .has-danger &,\n .has-success &{\n &.form-control-success,\n &.form-control-danger{\n background-image: none;\n }\n }\n\n & + .form-control-feedback{\n border-radius: $border-radius-large;\n font-size: $font-size-base;\n margin-top: -7px;\n position: absolute;\n right: 10px;\n top: 50%;\n vertical-align: middle;\n }\n\n .open &{\n border-radius: $border-radius-large $border-radius-large 0 0;\n border-bottom-color: transparent;\n }\n\n & + .input-group-addon{\n background-color: $white-bg;\n }\n}\n\n.has-success .input-group-addon,\n.has-success .form-control{\n border-color: $light-gray;\n}\n\n.has-success .form-control:focus,\n.has-success.input-group-focus .input-group-addon{\n border-color: lighten($success-color, 5%);\n}\n\n.has-danger .form-control,\n.has-danger .input-group-addon,\n.has-danger.input-group-focus .input-group-addon{\n border-color: lighten($danger-color, 30%);\n color: $danger-color;\n background-color: rgba(222,222,222, .1);\n\n &:focus{\n background-color: $white-color;\n }\n}\n\n.has-success,\n.has-danger{\n &:after{\n font-family: 'Nucleo Outline';\n content: \"\\ea22\";\n display: inline-block;\n position: absolute;\n right: 20px;\n bottom: 10px;\n color: $success-color;\n font-size: 11px;\n }\n\n &.form-control-lg{\n &:after{\n font-size: 13px;\n top: 24px;\n }\n }\n\n &.has-label{\n &:after{\n top: 35px;\n }\n }\n\n .form-control + label,\n &.form-check .form-check-label label,\n &.form-check:after{\n display: none !important;\n }\n\n &.form-check .form-check-label{\n color: $success-color;\n }\n}\n\n.has-danger{\n &:after{\n content: \"\\ea53\";\n color: $danger-color;\n }\n\n &.form-check .form-check-label{\n color: $danger-color;\n }\n}\n\n@include form-control-lg-padding($padding-large-vertical, $padding-input-horizontal);\n@include input-base-padding($padding-input-vertical, $padding-input-horizontal);\n\n.form-group.no-border,\n.input-group.no-border{\n .form-control,\n .form-control + .input-group-addon{\n background-color: $opacity-gray-3;\n border: medium none;\n &:focus,\n &:active,\n &:active{\n border: medium none;\n background-color: $opacity-gray-5;\n }\n }\n\n .form-control{\n &:focus{\n & + .input-group-addon{\n background-color: $opacity-gray-5;\n }\n }\n }\n\n .input-group-addon{\n background-color: $opacity-gray-3;\n border: none;\n }\n}\n\n.has-error{\n .form-control-feedback, .control-label{\n color: $danger-color;\n }\n}\n.has-success{\n .form-control-feedback, .control-label{\n color: $success-color;\n }\n}\n\n.input-group-addon {\n background-color: $white-bg;\n border: 1px solid $light-gray;\n border-radius: $btn-round-radius;\n color: $dark-background;\n padding: $padding-base-vertical - 1 0 $padding-base-vertical - 1 $padding-base-horizontal - 1;\n\n @include transition-input-focus-color();\n\n .has-danger.input-group-focus &{\n background-color: $white-color;\n }\n\n .has-success &{\n background-color: $white-color;\n }\n .has-danger .form-control:focus + &{\n color: $danger-color;\n }\n .has-success .form-control:focus + &{\n color: $success-color;\n }\n\n & + .form-control,\n & ~ .form-control{\n @include input-size($padding-base-vertical - 1, $padding-base-horizontal);\n padding-left: 18px;\n }\n\n i{\n width: 17px;\n }\n}\n\n.input-group-focus{\n .input-group-addon{\n background-color: $white-bg;\n border-color: $primary-color;\n }\n\n &.no-border{\n .input-group-addon{\n background-color: $opacity-gray-5;\n }\n }\n}\n\n.input-group,\n.form-group{\n margin-bottom: 10px;\n position: relative;\n\n .form-control-static{\n margin-top: 9px;\n }\n}\n.input-group[disabled]{\n .input-group-addon{\n background-color: $light-gray;\n }\n}\n\n.input-group .form-control:not(:first-child):not(:last-child), .input-group-addon:not(:first-child):not(:last-child), .input-group-btn:not(:first-child):not(:last-child){\n border-radius: $btn-round-radius;\n border-top-left-radius: 0;\n border-bottom-left-radius: 0;\n border-left: 0 none;\n}\n\n.input-group .form-control:first-child,\n.input-group-addon:first-child,\n.input-group-btn:first-child > .dropdown-toggle,\n.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle) {\n border-right: 0 none;\n}\n.input-group .form-control:last-child,\n.input-group-addon:last-child,\n.input-group-btn:last-child > .dropdown-toggle,\n.input-group-btn:first-child > .btn:not(:first-child) {\n border-left: 0 none;\n}\n.form-control[disabled], .form-control[readonly], fieldset[disabled] .form-control {\n background-color: $light-gray;\n color: $default-color;\n cursor: not-allowed;\n}\n\n.input-group-btn .btn{\n border-width: $border-thin;\n padding: $padding-btn-vertical $padding-base-horizontal;\n}\n.input-group-btn .btn-default:not(.btn-fill){\n border-color: $medium-gray;\n}\n\n.input-group-btn:last-child > .btn{\n margin-left: 0;\n}\ntextarea.form-control{\n max-width: 100%;\n max-height: 80px;\n padding: 10px 10px 0 0;\n resize: none;\n border: none;\n border-bottom: 1px solid $light-gray;\n border-radius: 0;\n line-height: 2;\n\n &:focus,\n &:active{\n border-left: none;\n border-top: none;\n border-right: none;\n }\n}\n\n.has-success,\n.has-danger{\n\n &.form-group .form-control,\n &.form-group.no-border .form-control{\n padding-right: $padding-input-horizontal + 21;\n }\n}\n\n.form.form-newsletter .form-group{\n float: left;\n width: 78%;\n margin-right: 2%;\n margin-top: 9px;\n}\n\n.input-group .input-group-btn{\n padding: 0 12px;\n}\n\n// Input files - hide actual input - requires specific markup in the sample.\n.form-group input[type=file] {\n opacity: 0;\n position: absolute;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n width: 100%;\n height: 100%;\n z-index: 100;\n}\n\n.form-text{\n font-size: $font-size-small;\n}\n\n.form-control-lg{\n padding: 0;\n font-size: inherit;\n line-height: 0;\n border-radius: 0;\n}\n\n.form-horizontal{\n .col-form-label,\n .label-on-right{\n padding: 10px 5px 0 15px;\n text-align: right;\n max-width: 180px;\n }\n\n .checkbox-radios{\n margin-bottom: 15px;\n\n .form-check:first-child{\n margin-top: 8px;\n }\n }\n\n .label-on-right{\n text-align: left;\n padding: 10px 15px 0 5px;\n }\n\n .form-check-inline{\n margin-top: 6px;\n }\n}\n","button,\ninput,\noptgroup,\nselect,\ntextarea{\n font-family: $sans-serif-family;\n}\nh1,h2,h3,h4,h5,h6{\n font-weight: $font-weight-normal;\n}\n\na{\n color: $primary-color;\n &:hover,\n &:focus{\n color: $primary-color;\n }\n}\nh1, .h1 {\n font-size: $font-size-h1;\n line-height: 1.15;\n margin-bottom: $margin-base-vertical * 2;\n\n small{\n font-weight: $font-weight-bold;\n text-transform: uppercase;\n opacity: .8;\n }\n}\nh2, .h2{\n font-size: $font-size-h2;\n margin-bottom: $margin-base-vertical * 2;\n}\nh3, .h3{\n font-size: $font-size-h3;\n margin-bottom: $margin-base-vertical * 2;\n line-height: 1.4em;\n}\nh4, .h4{\n font-size: $font-size-h4;\n line-height: 1.45em;\n margin-top: $margin-base-vertical * 2;\n margin-bottom: $margin-base-vertical;\n\n & + .category,\n &.title + .category{\n margin-top: -10px;\n }\n}\nh5, .h5 {\n font-size: $font-size-h5;\n line-height: 1.4em;\n margin-bottom: 15px;\n}\nh6, .h6{\n font-size: $font-size-h6;\n font-weight: $font-weight-bold;\n text-transform: uppercase;\n}\np{\n &.description{\n font-size: 1.14em;\n }\n}\n\n// i.fa{\n// font-size: 18px;\n// position: relative;\n// top: 1px;\n// }\n\n.title{\n font-weight: $font-weight-bold;\n\n &.title-up{\n text-transform: uppercase;\n\n a{\n color: $black-color;\n text-decoration: none;\n }\n }\n & + .category{\n margin-top: -10px;\n }\n}\n\n.description,\n.card-description,\n.footer-big p,\n.card .footer .stats{\n color: $dark-gray;\n font-weight: $font-weight-light;\n}\n.category,\n.card-category{\n text-transform: capitalize;\n font-weight: $font-weight-normal;\n color: $dark-gray;\n font-size: $font-size-mini;\n}\n\n.card-category{\n font-size: $font-size-h6;\n}\n\n.text-primary,\na.text-primary:focus, a.text-primary:hover {\n color: $brand-primary !important;\n}\n.text-info,\na.text-info:focus, a.text-info:hover {\n color: $brand-info !important;\n}\n.text-success,\na.text-success:focus, a.text-success:hover {\n color: $brand-success !important;\n}\n.text-warning,\na.text-warning:focus, a.text-warning:hover {\n color: $brand-warning !important;\n}\n.text-danger,\na.text-danger:focus, a.text-danger:hover {\n color: $brand-danger !important;\n}\n\n.text-gray,\na.text-gray:focus, a.text-gray:hover{\n color: $light-gray !important;\n}\n\n\n.blockquote{\n border-left: none;\n border: 1px solid $default-color;\n padding: 20px;\n font-size: $font-size-blockquote;\n line-height: 1.8;\n\n small{\n color: $default-color;\n font-size: $font-size-small;\n text-transform: uppercase;\n }\n\n &.blockquote-primary{\n border-color: $primary-color;\n color: $primary-color;\n\n small{\n color: $primary-color;\n }\n }\n\n &.blockquote-danger{\n border-color: $danger-color;\n color: $danger-color;\n\n small{\n color: $danger-color;\n }\n }\n\n &.blockquote-white{\n border-color: $opacity-8;\n color: $white-color;\n\n small{\n color: $opacity-8;\n }\n }\n}\n","body{\n color: $black-color;\n font-size: $font-size-base;\n font-family: $sans-serif-family;\n -moz-osx-font-smoothing: grayscale;\n -webkit-font-smoothing: antialiased;\n}\n\n.main{\n position: relative;\n background: $white-color;\n}\n/* Animations */\n.nav-pills .nav-link,\n.navbar,\n.nav-tabs .nav-link,\n.sidebar .nav a,\n.sidebar .nav a i,\n.navbar-collapse .navbar-nav .nav-link,\n.animation-transition-general,\n.tag,\n.tag [data-role=\"remove\"],\n.animation-transition-general{\n @include transition($general-transition-time, $transition-ease);\n}\n\n//transition for dropdown caret\n.dropdown-toggle:after,\n.bootstrap-switch-label:before,\n.caret{\n @include transition($fast-transition-time, $transition-ease);\n}\n\n.dropdown-toggle[aria-expanded=\"true\"]:after,\na[data-toggle=\"collapse\"][aria-expanded=\"true\"] .caret,\n.card-collapse .card a[data-toggle=\"collapse\"][aria-expanded=\"true\"] i,\n.card-collapse .card a[data-toggle=\"collapse\"].expanded i{\n @include rotate-180();\n}\n\n.button-bar{\n display: block;\n position: relative;\n width: 22px;\n height: 1px;\n border-radius: 1px;\n background: $white-bg;\n\n & + .button-bar{\n margin-top: 7px;\n }\n\n &:nth-child(2){\n width: 17px;\n }\n}\n\n.caret{\n display: inline-block;\n width: 0;\n height: 0;\n margin-left: 2px;\n vertical-align: middle;\n border-top: 4px dashed;\n border-top: 4px solid\\9;\n border-right: 4px solid transparent;\n border-left: 4px solid transparent;\n}\n",".form-check{\n margin-top: .5rem;\n}\n\n.form-check .form-check-label{\n display: inline-block;\n position: relative;\n cursor: pointer;\n padding-left: 35px;\n line-height: 26px;\n margin-bottom: 0;\n -webkit-transition: color 0.3s linear;\n -moz-transition: color 0.3s linear;\n -o-transition: color 0.3s linear;\n -ms-transition: color 0.3s linear;\n transition: color 0.3s linear;\n}\n.radio .form-check-sign{\n padding-left: 28px;\n}\n\n.form-check .form-check-sign::before,\n.form-check .form-check-sign::after{\n content: \" \";\n display: inline-block;\n position: absolute;\n width: 26px;\n height: 26px;\n left: 0;\n cursor: pointer;\n border-radius: 3px;\n top: 0;\n background-color: transparent;\n border: 1px solid $light-gray;\n -webkit-transition: opacity 0.3s linear;\n -moz-transition: opacity 0.3s linear;\n -o-transition: opacity 0.3s linear;\n -ms-transition: opacity 0.3s linear;\n transition: opacity 0.3s linear;\n}\n\n .form-check .form-check-sign::after{\n font-family: 'Nucleo Outline';\n content: \"\\ea22\";\n top: 0px;\n text-align: center;\n font-size: 14px;\n opacity: 0;\n color: $dark-background;\n border: 0;\n background-color: inherit;\n}\n\n.form-check.disabled .form-check-label,\n.form-check.disabled .form-check-label {\n color: $dark-gray;\n opacity: .5;\n cursor: not-allowed;\n}\n\n.form-check input[type=\"checkbox\"],\n.radio input[type=\"radio\"]{\n opacity: 0;\n position: absolute;\n visibility: hidden;\n}\n.form-check input[type=\"checkbox\"]:checked + .form-check-sign::after{\n opacity: 1;\n}\n\n.form-control input[type=\"checkbox\"]:disabled + .form-check-sign::before,\n.checkbox input[type=\"checkbox\"]:disabled + .form-check-sign::after{\n cursor: not-allowed;\n}\n\n.form-check input[type=\"checkbox\"]:disabled + .form-check-sign,\n.form-check input[type=\"radio\"]:disabled + .form-check-sign{\n pointer-events: none;\n}\n\n.form-check-radio .form-check-sign::before,\n.form-check-radio .form-check-sign::after{\n content: \" \";\n width: 20px;\n height: 20px;\n border-radius: 50%;\n border: 1px solid $light-gray;\n display: inline-block;\n position: absolute;\n left: 3px;\n top: 3px;\n padding: 1px;\n -webkit-transition: opacity 0.3s linear;\n -moz-transition: opacity 0.3s linear;\n -o-transition: opacity 0.3s linear;\n -ms-transition: opacity 0.3s linear;\n transition: opacity 0.3s linear;\n}\n\n.form-check-radio input[type=\"radio\"] + .form-check-sign:after,\n.form-check-radio input[type=\"radio\"] {\n opacity: 0;\n}\n.form-check-radio input[type=\"radio\"]:checked + .form-check-sign::after {\n width: 4px;\n height: 4px;\n background-color: $dark-background;\n border-color: $dark-background;\n top: 11px;\n left: 11px;\n opacity: 1;\n}\n\n.form-check-radio input[type=\"radio\"]:checked + .form-check-sign::after{\n opacity: 1;\n}\n\n.form-check-radio input[type=\"radio\"]:disabled + .form-check-sign {\n color: $dark-gray;\n}\n\n.form-check-radio input[type=\"radio\"]:disabled + .form-check-sign::before,\n.form-check-radio input[type=\"radio\"]:disabled + .form-check-sign::after {\n color: $dark-gray;\n}\n",".navbar{\n padding-top: $navbar-padding-base;\n padding-bottom: $navbar-padding-base;\n min-height: 53px;\n margin-bottom: 20px;\n box-shadow: 0px 0px 20px 0px rgba(0, 0, 0, 0.15);\n\n a{\n vertical-align: middle;\n\n &:not(.btn):not(.dropdown-item){\n color: $white-color;\n }\n\n &.dropdown-item{\n color: $default-color;\n }\n }\n\n\n\n &.bg-white{\n .input-group .form-control,\n .input-group.no-border .form-control{\n color: $default-color;\n\n @include placeholder(){\n color: $default-color;\n };\n }\n .input-group-addon i{\n color: $default-color;\n opacity: .5;\n }\n }\n\n .form-group,\n .input-group{\n margin: 0;\n margin-left: -3px;\n margin-right: 5px;\n .form-group-addon,\n .input-group-addon{\n color: $white-color;\n }\n &.no-border{\n .form-control{\n color: $white-color;\n\n @include placeholder(){\n color: $white-color;\n };\n }\n }\n }\n\n p{\n display: inline-block;\n margin: 0;\n line-height: 1.8em;\n font-size: 1em;\n font-weight: 400;\n }\n\n &.navbar-absolute{\n position: absolute;\n width: 100%;\n padding-top: 10px;\n z-index: 1029;\n }\n\n .documentation &{\n &.fixed-top{\n left: 0;\n width: initial;\n }\n }\n\n .navbar-wrapper{\n display: inline-flex;\n align-items: center;\n\n .navbar-minimize{\n padding-right: 10px;\n\n .btn{\n margin: 0;\n }\n }\n\n .navbar-toggle{\n .navbar-toggler{\n padding-left: 0;\n }\n\n &:hover{\n & .navbar-toggler-bar.bar2{\n width: 22px;\n }\n }\n }\n }\n\n\n\n .navbar-nav{\n &.navbar-logo{\n position: absolute;\n left: 0;\n right: 0;\n margin: 0 auto;\n width: 49px;\n top: -4px;\n }\n\n .nav-link.btn{\n padding: $padding-btn-vertical $padding-btn-horizontal;\n &.btn-lg{\n padding: $padding-large-vertical $padding-large-horizontal;\n }\n &.btn-sm{\n padding: $padding-small-vertical $padding-small-horizontal;\n }\n }\n\n .nav-link{\n text-transform: uppercase;\n font-size: $font-size-mini;\n padding: $padding-base-vertical $padding-base-horizontal;\n line-height: $line-height-nav-link;\n margin-right: 3px;\n\n i.fa + p,\n i.now-ui-icons + p{\n margin-left: 3px;\n }\n\n i.fa,\n i.now-ui-icons{\n font-size: 18px;\n position: relative;\n top: 3px;\n text-align: center;\n width: 21px;\n }\n\n i.now-ui-icons{\n top: 4px;\n font-size: 16px;\n }\n\n &.profile-photo{\n .profile-photo-small{\n width: 27px;\n height: 27px;\n }\n }\n\n &.disabled{\n opacity: .5;\n color: $white-color;\n }\n }\n\n .nav-item.active .nav-link:not(.btn),\n .nav-item .nav-link:not(.btn):focus,\n .nav-item .nav-link:not(.btn):hover,\n .nav-item .nav-link:not(.btn):active{\n background-color: $opacity-2;\n border-radius: $border-radius-small;\n color: $white-color;\n }\n }\n\n .logo-container{\n width: 27px;\n height: 27px;\n overflow: hidden;\n margin: 0 auto;\n border-radius: 50%;\n border: 1px solid transparent;\n }\n\n .navbar-brand{\n text-transform: uppercase;\n font-size: $font-size-small;\n padding-top: $padding-base-vertical;\n padding-bottom: $padding-base-vertical;\n line-height: $line-height-nav-link;\n }\n\n .navbar-toggler{\n width: 37px;\n height: 27px;\n vertical-align: middle;\n outline: 0;\n cursor: pointer;\n\n & .navbar-toggler-bar.navbar-kebab{\n width: 3px;\n height: 3px;\n border-radius: 50%;\n margin: 0 auto;\n }\n }\n\n .button-dropdown{\n .navbar-toggler-bar:nth-child(2){\n width: 17px;\n }\n }\n\n &.navbar-transparent{\n background-color: $transparent-bg !important;\n box-shadow: none;\n color: $white-color;\n }\n\n &.bg-white:not(.navbar-transparent){\n a:not(.dropdown-item):not(.btn){\n color: $default-color;\n\n &.disabled{\n opacity: .5;\n color: $default-color;\n }\n }\n\n .button-bar{\n background: $default-color;\n }\n\n .nav-item.active .nav-link:not(.btn),\n .nav-item .nav-link:not(.btn):focus,\n .nav-item .nav-link:not(.btn):hover,\n .nav-item .nav-link:not(.btn):active{\n background-color: $opacity-gray-8;\n color: $default-color;\n }\n\n .logo-container{\n border: 1px solid $default-color;\n }\n }\n}\n\n.bg-default{\n background-color: $default-color !important;\n}\n\n.bg-primary{\n background-color: $primary-color !important;\n}\n\n.bg-info{\n background-color: $info-color !important;\n}\n\n.bg-success{\n background-color: $success-color !important;\n}\n\n.bg-danger{\n background-color: $danger-color !important;\n}\n\n.bg-warning{\n background-color: $warning-color !important;\n}\n\n.bg-white{\n background-color: $white-color !important;\n}\n",".page-header{\n min-height: 100vh;\n max-height: 999px;\n padding: 0;\n color: $white-color;\n position: relative;\n\n .page-header-image{\n position: absolute;\n background-size: cover;\n background-position: center center;\n width: 100%;\n height: 100%;\n z-index: -1;\n }\n\n .content-center{\n position: absolute;\n top: 50%;\n left: 50%;\n z-index: 2;\n -ms-transform: translate(-50%, -50%);\n -webkit-transform: translate(-50%, -50%);\n transform: translate(-50%, -50%);\n text-align: center;\n color: #FFFFFF;\n padding: 0 15px;\n width: 100%;\n max-width: 880px;\n\n }\n\n footer{\n position: absolute;\n bottom: 0;\n width: 100%;\n }\n\n .container{\n height: 100%;\n z-index: 1;\n }\n\n .category,\n .description{\n color: $opacity-8;\n }\n\n &.page-header-small{\n min-height: 60vh;\n max-height: 440px;\n }\n\n &.page-header-mini{\n min-height: 40vh;\n max-height: 340px;\n }\n\n .title{\n margin-bottom: 15px;\n }\n .title + h4{\n margin-top: 10px;\n }\n\n &:after,\n &:before{\n position: absolute;\n z-index: 0;\n width: 100%;\n height: 100%;\n display: block;\n left: 0;\n top: 0;\n content: \"\";\n }\n\n &:before{\n background-color: rgba(0,0,0,.3);\n }\n\n &[filter-color=\"orange\"]{\n @include linear-gradient(rgba($black-color,.20), rgba(224, 23, 3, 0.6));\n }\n}\n","@mixin linear-gradient($color1, $color2){\n background: $color1; /* For browsers that do not support gradients */\n background: -webkit-linear-gradient(90deg, $color1 , $color2); /* For Safari 5.1 to 6.0 */\n background: -o-linear-gradient(90deg, $color1, $color2); /* For Opera 11.1 to 12.0 */\n background: -moz-linear-gradient(90deg, $color1, $color2); /* For Firefox 3.6 to 15 */\n background: linear-gradient(0deg, $color1 , $color2); /* Standard syntax */\n}\n",".dropdown-menu{\n border: 0;\n box-shadow: 0px 10px 50px 0px rgba(0, 0, 0, 0.2);\n border-radius: $border-radius-extra-small;\n @include transition($fast-transition-time, $transition-linear);\n font-size: $font-size-base;\n\n &.dropdown-menu-right{\n &:before{\n left:auto;\n right: 10px;\n }\n }\n\n i{\n margin-right: 5px;\n position: relative;\n top: 1px;\n }\n\n .now-ui-icons{\n margin-right: 10px;\n position: relative;\n top: 4px;\n font-size: 18px;\n margin-top: -5px;\n opacity: .5;\n }\n\n .dropdown-item{\n &.active,\n &:active{\n color: inherit;\n }\n }\n\n .dropup &{\n &:before{\n display: none;\n }\n\n &:after{\n display: inline-block;\n position: absolute;\n width: 0;\n height: 0;\n vertical-align: middle;\n content: \"\";\n top: auto;\n bottom: -5px;\n right: auto;\n left: 10px;\n color: $white-color;\n border-top: .4em solid;\n border-right: .4em solid transparent;\n border-left: .4em solid transparent;\n }\n\n &.dropdown-menu-right{\n &:after{\n right: 10px;\n left: auto;\n }\n }\n\n }\n\n &:before{\n display: inline-block;\n position: absolute;\n width: 0;\n height: 0;\n vertical-align: middle;\n content: \"\";\n top: -5px;\n left: 10px;\n right: auto;\n color: $white-color;\n border-bottom: .4em solid;\n border-right: .4em solid transparent;\n border-left: .4em solid transparent;\n }\n\n &.dropdown-menu-right{\n right: 0 !important;\n left: auto !important;\n }\n\n .dropdown-item,\n .bootstrap-select &.inner li a{\n font-size: $font-size-small;\n padding-top: .6rem;\n padding-bottom: .6rem;\n margin-top: 5px;\n @include transition($fast-transition-time, $transition-linear);\n\n &:hover,\n &:focus{\n background-color: $opacity-gray-3;\n }\n\n &.disabled,\n &:disabled{\n color: $default-color-opacity;\n\n &:hover,\n &:focus{\n background-color: transparent;\n }\n }\n }\n\n\n .dropdown-divider{\n background-color: $opacity-gray-5;\n }\n\n .dropdown-header:not([href]):not([tabindex]){\n color: $default-color-opacity;\n font-size: $font-size-mini;\n text-transform: uppercase;\n font-weight: $font-weight-bold;\n }\n\n &.dropdown-primary{\n @include dropdown-colors(darken($primary-color, 3%),$opacity-8,$white-color, $opacity-2);\n }\n\n &.dropdown-info{\n @include dropdown-colors(darken($info-color, 3%),$opacity-8,$white-color, $opacity-2);\n }\n\n &.dropdown-danger{\n @include dropdown-colors(darken($danger-color, 3%),$opacity-8,$white-color, $opacity-2);\n }\n\n &.dropdown-success{\n @include dropdown-colors(darken($success-color, 3%),$opacity-8,$white-color, $opacity-2);\n }\n\n &.dropdown-warning{\n @include dropdown-colors(darken($warning-color, 3%),$opacity-8,$white-color, $opacity-2);\n }\n\n .dropdown &,\n .dropup:not(.bootstrap-select) &,\n .bootstrap-select &:not(.inner),\n &.bootstrap-datetimepicker-widget.top,\n &.bootstrap-datetimepicker-widget.bottom{\n @include transform-translate-y-dropdown(-20px);\n visibility: hidden;\n display: block;\n @include opacity(0);\n top: 100% !important;\n }\n\n &.bootstrap-datetimepicker-widget.top,\n &.bootstrap-datetimepicker-widget.bottom{\n @include transform-translate-y-dropdown(-20px);\n }\n\n .bootstrap-select.dropup &:not(.inner){\n @include transform-translate-y-dropdown(25px);\n }\n\n .dropup:not(.bootstrap-select) &{\n @include transform-translate-y-dropdown(20px);\n top: auto !important;\n bottom: 100%;\n }\n\n .dropdown.show &,\n .bootstrap-select.show &:not(.inner),\n &.bootstrap-datetimepicker-widget.top.open,\n &.bootstrap-datetimepicker-widget.bottom.open,\n .dropup.show:not(.bootstrap-select) &,\n .navbar .dropdown.show &{\n @include opacity(1);\n visibility: visible;\n @include transform-translate-y-dropdown(1px);\n }\n\n &.bootstrap-datetimepicker-widget.top.open,\n &.bootstrap-datetimepicker-widget.bottom.open{\n @include transform-translate-y-dropdown(0px);\n }\n\n .dropup.show:not(.bootstrap-select) &{\n @include transform-translate-y-dropdown(-2px);\n }\n}\n\n.button-dropdown{\n padding-right: $padding-base-horizontal;\n cursor: pointer;\n\n & .dropdown-toggle{\n padding-top: $padding-base-vertical;\n padding-bottom: $padding-base-vertical;\n display: block;\n\n &:after{\n display: none;\n }\n }\n}\n","@mixin dropdown-colors($brand-color, $dropdown-header-color, $dropdown-color, $background-color ) {\n background-color: $brand-color;\n\n &:before{\n color: $brand-color;\n }\n\n .dropdown-header:not([href]):not([tabindex]){\n color: $dropdown-header-color;\n }\n\n .dropdown-item{\n color: $dropdown-color;\n\n &:hover,\n &:focus{\n background-color: $background-color;\n }\n }\n\n .dropdown-divider{\n background-color: $background-color;\n }\n}\n",".alert{\n border: 0;\n border-radius: $border-radius-small;\n color: $white-color;\n padding-top: .9rem;\n padding-bottom: .9rem;\n position: relative;\n\n &.alert-success{\n background-color: lighten($success-color, 5%);\n }\n\n &.alert-danger{\n background-color: lighten($danger-color, 5%);\n }\n\n &.alert-warning{\n background-color: lighten($warning-color, 5%);\n }\n\n &.alert-info{\n background-color: lighten($info-color, 5%);\n }\n\n &.alert-primary{\n background-color: lighten($primary-color, 5%);\n }\n\n\n i.fa,\n i.now-ui-icons{\n font-size: 20px;\n }\n\n .close{\n color: $white-color;\n opacity: .9;\n text-shadow: none;\n line-height: 0;\n outline: 0;\n }\n\n span[data-notify=\"icon\"]{\n font-size: 22px;\n display: block;\n left: 19px;\n position: absolute;\n top: 50%;\n margin-top: -11px;\n }\n\n button.close{\n position: absolute;\n right: 10px;\n top: 50%;\n margin-top: -13px;\n width: 25px;\n height: 25px;\n padding: 3px;\n }\n\n .close ~ span{\n display: block;\n max-width: 89%;\n }\n\n &.alert-with-icon{\n padding-left: 65px;\n }\n}\n","img{\n max-width: 100%;\n border-radius: $border-radius-small;\n}\n.img-raised{\n box-shadow: $box-shadow-raised;\n}\n","/* --------------------------------\n\nNucleo Outline Web Font - nucleoapp.com/\nLicense - nucleoapp.com/license/\nCreated using IcoMoon - icomoon.io\n\n-------------------------------- */\n\n@font-face {\n font-family: 'Nucleo Outline';\n src: url('../fonts/nucleo-outline.eot');\n src: url('../fonts/nucleo-outline.eot') format('embedded-opentype'),\n url('../fonts/nucleo-outline.woff2') format('woff2'),\n url('../fonts/nucleo-outline.woff') format('woff'),\n url('../fonts/nucleo-outline.ttf') format('truetype'),\n url('../fonts/nucleo-outline.svg') format('svg');\n font-weight: normal;\n font-style: normal;\n}\n\n/*------------------------\n\tbase class definition\n-------------------------*/\n\n.now-ui-icons {\n display: inline-block;\n font: normal normal normal 14px/1 'Nucleo Outline';\n font-size: inherit;\n speak: none;\n text-transform: none;\n /* Better Font Rendering */\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n}\n\n/*------------------------\n change icon size\n-------------------------*/\n\n/*----------------------------------\n add a square/circle background\n-----------------------------------*/\n\n.now-ui-icons.circle {\n padding: 0.33333333em;\n vertical-align: -16%;\n background-color: #eee;\n}\n\n.now-ui-icons.circle {\n border-radius: 50%;\n}\n\n/*------------------------\n list icons\n-------------------------*/\n\n.nc-icon-ul {\n padding-left: 0;\n margin-left: 2.14285714em;\n list-style-type: none;\n}\n\n.nc-icon-ul > li {\n position: relative;\n}\n\n.nc-icon-ul > li > .now-ui-icons {\n position: absolute;\n left: -1.57142857em;\n top: 0.14285714em;\n text-align: center;\n}\n\n.nc-icon-ul > li > .now-ui-icons.circle {\n top: -0.19047619em;\n left: -1.9047619em;\n}\n\n/*------------------------\n spinning icons\n-------------------------*/\n\n.now-ui-icons.spin {\n -webkit-animation: nc-icon-spin 2s infinite linear;\n -moz-animation: nc-icon-spin 2s infinite linear;\n animation: nc-icon-spin 2s infinite linear;\n}\n\n@-webkit-keyframes nc-icon-spin {\n 0% {\n -webkit-transform: rotate(0deg);\n }\n\n 100% {\n -webkit-transform: rotate(360deg);\n }\n}\n\n@-moz-keyframes nc-icon-spin {\n 0% {\n -moz-transform: rotate(0deg);\n }\n\n 100% {\n -moz-transform: rotate(360deg);\n }\n}\n\n@keyframes nc-icon-spin {\n 0% {\n -webkit-transform: rotate(0deg);\n -moz-transform: rotate(0deg);\n -ms-transform: rotate(0deg);\n -o-transform: rotate(0deg);\n transform: rotate(0deg);\n }\n\n 100% {\n -webkit-transform: rotate(360deg);\n -moz-transform: rotate(360deg);\n -ms-transform: rotate(360deg);\n -o-transform: rotate(360deg);\n transform: rotate(360deg);\n }\n}\n\n/*------------------------\n rotated/flipped icons\n-------------------------*/\n\n/*------------------------\n\tfont icons\n-------------------------*/\n\n.now-ui-icons.ui-1_check:before{\n content: \"\\ea22\";\n}\n\n.now-ui-icons.ui-1_email-85:before {\n content: \"\\ea2a\";\n}\n\n.now-ui-icons.arrows-1_cloud-download-93:before {\n content: \"\\ea21\";\n}\n\n.now-ui-icons.arrows-1_cloud-upload-94:before {\n content: \"\\ea24\";\n}\n\n.now-ui-icons.arrows-1_minimal-down:before {\n content: \"\\ea39\";\n}\n\n.now-ui-icons.arrows-1_minimal-left:before {\n content: \"\\ea3a\";\n}\n\n.now-ui-icons.arrows-1_minimal-right:before {\n content: \"\\ea3b\";\n}\n\n.now-ui-icons.arrows-1_minimal-up:before {\n content: \"\\ea3c\";\n}\n\n.now-ui-icons.arrows-1_refresh-69:before {\n content: \"\\ea44\";\n}\n\n.now-ui-icons.arrows-1_share-66:before {\n content: \"\\ea4c\";\n}\n\n.now-ui-icons.business_badge:before {\n content: \"\\ea09\";\n}\n\n.now-ui-icons.business_bank:before {\n content: \"\\ea0a\";\n}\n\n.now-ui-icons.business_briefcase-24:before {\n content: \"\\ea13\";\n}\n\n.now-ui-icons.business_bulb-63:before {\n content: \"\\ea15\";\n}\n\n.now-ui-icons.business_chart-bar-32:before {\n content: \"\\ea1e\";\n}\n\n.now-ui-icons.business_chart-pie-36:before {\n content: \"\\ea1f\";\n}\n\n.now-ui-icons.business_globe:before {\n content: \"\\ea2f\";\n}\n\n.now-ui-icons.business_money-coins:before {\n content: \"\\ea40\";\n}\n\n.now-ui-icons.clothes_tie-bow:before {\n content: \"\\ea5b\";\n}\n\n.now-ui-icons.design_vector:before {\n content: \"\\ea61\";\n}\n\n.now-ui-icons.design_app:before {\n content: \"\\ea08\";\n}\n\n.now-ui-icons.design_bullet-list-67:before {\n content: \"\\ea14\";\n}\n\n.now-ui-icons.design_image:before {\n content: \"\\ea33\";\n}\n\n.now-ui-icons.design_palette:before {\n content: \"\\ea41\";\n}\n\n.now-ui-icons.design_scissors:before {\n content: \"\\ea4a\";\n}\n\n.now-ui-icons.design-2_html5:before {\n content: \"\\ea32\";\n}\n\n.now-ui-icons.design-2_ruler-pencil:before {\n content: \"\\ea48\";\n}\n\n.now-ui-icons.emoticons_satisfied:before {\n content: \"\\ea49\";\n}\n\n.now-ui-icons.files_box:before {\n content: \"\\ea12\";\n}\n\n.now-ui-icons.files_paper:before {\n content: \"\\ea43\";\n}\n\n.now-ui-icons.files_single-copy-04:before {\n content: \"\\ea52\";\n}\n\n.now-ui-icons.health_ambulance:before {\n content: \"\\ea07\";\n}\n\n.now-ui-icons.loader_gear:before {\n content: \"\\ea4e\";\n}\n\n.now-ui-icons.loader_refresh:before {\n content: \"\\ea44\";\n}\n\n.now-ui-icons.location_bookmark:before {\n content: \"\\ea10\";\n}\n\n.now-ui-icons.location_compass-05:before {\n content: \"\\ea25\";\n}\n\n.now-ui-icons.location_map-big:before {\n content: \"\\ea3d\";\n}\n\n.now-ui-icons.location_pin:before {\n content: \"\\ea47\";\n}\n\n.now-ui-icons.location_world:before {\n content: \"\\ea63\";\n}\n\n.now-ui-icons.media-1_album:before {\n content: \"\\ea02\";\n}\n\n.now-ui-icons.media-1_button-pause:before {\n content: \"\\ea16\";\n}\n\n.now-ui-icons.media-1_button-play:before {\n content: \"\\ea18\";\n}\n\n.now-ui-icons.media-1_button-power:before {\n content: \"\\ea19\";\n}\n\n.now-ui-icons.media-1_camera-compact:before {\n content: \"\\ea1c\";\n}\n\n.now-ui-icons.media-2_note-03:before {\n content: \"\\ea3f\";\n}\n\n.now-ui-icons.media-2_sound-wave:before {\n content: \"\\ea57\";\n}\n\n.now-ui-icons.objects_diamond:before {\n content: \"\\ea29\";\n}\n\n.now-ui-icons.objects_globe:before {\n content: \"\\ea2f\";\n}\n\n.now-ui-icons.objects_key-25:before {\n content: \"\\ea38\";\n}\n\n.now-ui-icons.objects_planet:before {\n content: \"\\ea46\";\n}\n\n.now-ui-icons.objects_spaceship:before {\n content: \"\\ea55\";\n}\n\n.now-ui-icons.objects_support-17:before {\n content: \"\\ea56\";\n}\n\n.now-ui-icons.objects_umbrella-13:before {\n content: \"\\ea5f\";\n}\n\n.now-ui-icons.education_agenda-bookmark:before {\n content: \"\\ea01\";\n}\n\n.now-ui-icons.education_atom:before {\n content: \"\\ea0c\";\n}\n\n.now-ui-icons.education_glasses:before {\n content: \"\\ea2d\";\n}\n\n.now-ui-icons.education_hat:before {\n content: \"\\ea30\";\n}\n\n.now-ui-icons.education_paper:before {\n content: \"\\ea42\";\n}\n\n.now-ui-icons.shopping_bag-16:before {\n content: \"\\ea0d\";\n}\n\n.now-ui-icons.shopping_basket:before {\n content: \"\\ea0b\";\n}\n\n.now-ui-icons.shopping_box:before {\n content: \"\\ea11\";\n}\n\n.now-ui-icons.shopping_cart-simple:before {\n content: \"\\ea1d\";\n}\n\n.now-ui-icons.shopping_credit-card:before {\n content: \"\\ea28\";\n}\n\n.now-ui-icons.shopping_delivery-fast:before {\n content: \"\\ea27\";\n}\n\n.now-ui-icons.shopping_shop:before {\n content: \"\\ea50\";\n}\n\n.now-ui-icons.shopping_tag-content:before {\n content: \"\\ea59\";\n}\n\n.now-ui-icons.sport_trophy:before {\n content: \"\\ea5d\";\n}\n\n.now-ui-icons.sport_user-run:before {\n content: \"\\ea60\";\n}\n\n.now-ui-icons.tech_controller-modern:before {\n content: \"\\ea26\";\n}\n\n.now-ui-icons.tech_headphones:before {\n content: \"\\ea31\";\n}\n\n.now-ui-icons.tech_laptop:before {\n content: \"\\ea36\";\n}\n\n.now-ui-icons.tech_mobile:before {\n content: \"\\ea3e\";\n}\n\n.now-ui-icons.tech_tablet:before {\n content: \"\\ea58\";\n}\n\n.now-ui-icons.tech_tv:before {\n content: \"\\ea5e\";\n}\n\n.now-ui-icons.tech_watch-time:before {\n content: \"\\ea62\";\n}\n\n.now-ui-icons.text_align-center:before {\n content: \"\\ea05\";\n}\n\n.now-ui-icons.text_align-left:before {\n content: \"\\ea06\";\n}\n\n.now-ui-icons.text_bold:before {\n content: \"\\ea0e\";\n}\n\n.now-ui-icons.text_caps-small:before {\n content: \"\\ea1b\";\n}\n\n.now-ui-icons.gestures_tap-01:before {\n content: \"\\ea5a\";\n}\n\n.now-ui-icons.transportation_air-baloon:before {\n content: \"\\ea03\";\n}\n\n.now-ui-icons.transportation_bus-front-12:before {\n content: \"\\ea17\";\n}\n\n.now-ui-icons.travel_info:before {\n content: \"\\ea04\";\n}\n\n.now-ui-icons.travel_istanbul:before {\n content: \"\\ea34\";\n}\n\n.now-ui-icons.ui-1_bell-53:before {\n content: \"\\ea0f\";\n}\n\n.now-ui-icons.ui-1_calendar-60:before {\n content: \"\\ea1a\";\n}\n\n.now-ui-icons.ui-1_lock-circle-open:before {\n content: \"\\ea35\";\n}\n\n.now-ui-icons.ui-1_send:before {\n content: \"\\ea4d\";\n}\n\n.now-ui-icons.ui-1_settings-gear-63:before {\n content: \"\\ea4e\";\n}\n\n.now-ui-icons.ui-1_simple-add:before {\n content: \"\\ea4f\";\n}\n\n.now-ui-icons.ui-1_simple-delete:before {\n content: \"\\ea54\";\n}\n\n.now-ui-icons.ui-1_simple-remove:before {\n content: \"\\ea53\";\n}\n\n.now-ui-icons.ui-1_zoom-bold:before {\n content: \"\\ea64\";\n}\n\n.now-ui-icons.ui-2_chat-round:before {\n content: \"\\ea20\";\n}\n\n.now-ui-icons.ui-2_favourite-28:before {\n content: \"\\ea2b\";\n}\n\n.now-ui-icons.ui-2_like:before {\n content: \"\\ea37\";\n}\n\n.now-ui-icons.ui-2_settings-90:before {\n content: \"\\ea4b\";\n}\n\n.now-ui-icons.ui-2_time-alarm:before {\n content: \"\\ea5c\";\n}\n\n.now-ui-icons.users_circle-08:before {\n content: \"\\ea23\";\n}\n\n.now-ui-icons.users_single-02:before {\n content: \"\\ea51\";\n}\n\n\n.all-icons .font-icon-detail {\n text-align: center;\n padding: 45px 0px 30px;\n border: 1px solid #e5e5e5;\n border-radius: 0.1875rem;\n margin: 15px 0;\n min-height: 168px;\n}\n\n.all-icons [class*=\"now-ui-icons\"] {\n font-size: 32px;\n}\n\n.all-icons .font-icon-detail p {\n margin: 25px auto 0;\n width: 100%;\n text-align: center;\n display: block;\n color: #B8B8B8;\n padding:0 10px;\n font-size: 0.7142em;\n}\n",".table{\n\n .img-wrapper{\n width: 40px;\n height: 40px;\n border-radius: 50%;\n overflow: hidden;\n margin: 0 auto;\n }\n\n .img-row{\n max-width: 60px;\n width: 60px;\n }\n\n .form-check{\n margin: 0;\n\n & label .form-check-sign::before,\n & label .form-check-sign::after{\n top: -17px;\n left: 4px;\n }\n }\n\n .btn{\n margin: 0;\n }\n\n small,.small{\n font-weight: 300;\n }\n\n .card-tasks .card-body &{\n margin-bottom: 0;\n\n > thead > tr > th,\n > tbody > tr > th,\n > tfoot > tr > th,\n > thead > tr > td,\n > tbody > tr > td,\n > tfoot > tr > td{\n padding-top: 0;\n padding-bottom: 0;\n }\n }\n\n > thead > tr > th{\n border-bottom-width: 1px;\n font-size: 1.45em;\n font-weight: $font-weight-light;\n border: 0;\n }\n\n .radio,\n .checkbox{\n margin-top: 0;\n margin-bottom: 0;\n padding: 0;\n width: 15px;\n\n .icons{\n position: relative;\n }\n\n label{\n &:after,\n &:before{\n top: -17px;\n left: -3px;\n }\n }\n }\n > thead > tr > th,\n > tbody > tr > th,\n > tfoot > tr > th,\n > thead > tr > td,\n > tbody > tr > td,\n > tfoot > tr > td{\n padding: 12px 7px;\n vertical-align: middle;\n }\n\n .th-description{\n max-width: 150px;\n }\n .td-price{\n font-size: 26px;\n font-weight: $font-weight-light;\n margin-top: 5px;\n position: relative;\n top: 4px;\n text-align: right;\n }\n .td-total{\n font-weight: $font-weight-bold;\n font-size: $font-size-h5;\n padding-top: 20px;\n text-align: right;\n }\n\n .td-actions .btn{\n margin: 0px;\n }\n\n > tbody > tr{\n position: relative;\n }\n}\n\n.table-shopping{\n > thead > tr > th{\n font-size: $font-size-h6;\n text-transform: uppercase;\n }\n > tbody > tr > td{\n font-size: $font-paragraph;\n\n b{\n display: block;\n margin-bottom: 5px;\n }\n }\n .td-name{\n font-weight: $font-weight-normal;\n font-size: 1.5em;\n small{\n color: $dark-gray;\n font-size: 0.75em;\n font-weight: $font-weight-light;\n }\n }\n .td-number{\n font-weight: $font-weight-light;\n font-size: $font-size-h4;\n }\n .td-name{\n min-width: 200px;\n }\n .td-number{\n text-align: right;\n min-width: 145px;\n\n small{\n margin-right: 3px;\n }\n }\n\n .img-container{\n width: 120px;\n max-height: 160px;\n overflow: hidden;\n display: block;\n\n img{\n width: 100%;\n }\n }\n}\n\n#tables .table-responsive{\n margin-bottom: 30px;\n}\n",".wrapper{\n position: relative;\n top: 0;\n height: 100vh;\n\n &.wrapper-full-page{\n min-height: 100vh;\n height: auto;\n }\n}\n\n.sidebar,\n.off-canvas-sidebar{\n position: fixed;\n top: 0;\n height: 100%;\n bottom: 0;\n width: 260px;\n left: 0;\n z-index: 1030;\n\n .sidebar-wrapper{\n position: relative;\n height: calc(100vh - 75px);\n overflow: auto;\n width: 260px;\n z-index: 4;\n padding-bottom: 100px;\n\n .dropdown .dropdown-backdrop{\n display: none !important;\n }\n\n .navbar-form{\n border: none;\n }\n }\n\n .navbar-minimize{\n position: absolute;\n right: 20px;\n top: 2px;\n opacity: 1;\n\n @extend .animation-transition-general;\n }\n .logo-tim{\n border-radius: 50%;\n border: 1px solid #333;\n display: block;\n height: 61px;\n width: 61px;\n float: left;\n overflow: hidden;\n\n img{\n width: 60px;\n height: 60px;\n }\n }\n\n .nav{\n margin-top: 20px;\n display: block;\n\n .caret{\n top: 14px;\n position: absolute;\n right: 10px;\n }\n\n li{\n > a + div .nav li > a{\n margin-top: 7px;\n }\n\n > a{\n margin: 10px 15px 0;\n border-radius: $btn-round-radius;\n color: $white-color;\n display: block;\n text-decoration: none;\n position: relative;\n text-transform: uppercase;\n cursor: pointer;\n font-size: $font-size-mini;\n padding: 10px 8px;\n line-height: $line-height-nav-link;\n }\n\n &:first-child > a{\n margin: 0 15px;\n }\n\n &:hover:not(.active) > a,\n &:focus:not(.active) > a{\n background-color: $opacity-1;\n\n i{\n color: $white-color;\n }\n }\n\n &.active > a{\n background-color: $white-color;\n box-shadow: $box-shadow;\n }\n }\n\n p{\n margin: 0;\n line-height: 30px;\n position: relative;\n display: block;\n height: auto;\n white-space: nowrap;\n @extend .animation-transition-general;\n }\n\n i{\n font-size: 20px;\n float: left;\n margin-right: 12px;\n line-height: 30px;\n width: 34px;\n text-align: center;\n color: $opacity-5;\n position: relative;\n }\n }\n\n .sidebar-background{\n position: absolute;\n z-index: 1;\n height: 100%;\n width: 100%;\n display: block;\n top: 0;\n left: 0;\n background-size: cover;\n background-position: center center;\n\n &:after{\n position: absolute;\n z-index: 3;\n width: 100%;\n height: 100%;\n content: \"\";\n display: block;\n background: #FFFFFF;\n opacity: 1;\n }\n }\n\n .logo{\n position: relative;\n padding: $padding-base-vertical $padding-base-horizontal;\n z-index: 4;\n\n a.logo-mini,\n a.logo-normal{\n @extend .animation-transition-general;\n }\n\n a.logo-mini{\n opacity: 1;\n float: left;\n width: 34px;\n text-align: center;\n margin-left: 10px;\n margin-right: 12px;\n }\n\n a.logo-normal{\n display: block;\n opacity: 1;\n @include transform-translate-x(0px);\n }\n\n &:after{\n content: '';\n position: absolute;\n bottom: 0;\n right: 15px;\n height: 1px;\n width: calc(100% - 30px);\n background-color: $opacity-5;\n\n }\n\n p{\n float: left;\n font-size: 20px;\n margin: 10px 10px;\n color: $white-color;\n line-height: 20px;\n font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n }\n\n .simple-text{\n text-transform: uppercase;\n padding: $padding-base-vertical 0;\n display: block;\n white-space: nowrap;\n font-size: $font-size-large;\n color: $white-color;\n text-decoration: none;\n font-weight: $font-weight-normal;\n line-height: 30px;\n overflow: hidden;\n }\n }\n\n .logo-tim{\n border-radius: 50%;\n border: 1px solid #333;\n display: block;\n height: 61px;\n width: 61px;\n float: left;\n overflow: hidden;\n\n img{\n width: 60px;\n height: 60px;\n }\n }\n\n &:before,\n &:after{\n display: block;\n content: \"\";\n opacity: 1;\n position: absolute;\n width: 100%;\n height: 100%;\n top: 0;\n left: 0;\n }\n\n &:after{\n @include icon-gradient($default-color);\n z-index: 3;\n }\n\n &[data-color=\"blue\"]{\n @include sidebar-color($info-color);\n }\n &[data-color=\"green\"]{\n @include sidebar-color($success-color);\n }\n &[data-color=\"orange\"]{\n @include sidebar-color($orange-color);\n }\n &[data-color=\"red\"]{\n @include sidebar-color($danger-color);\n }\n &[data-color=\"yellow\"]{\n @include sidebar-color($warning-color);\n }\n}\n\n.visible-on-sidebar-regular{\n display: inline-block !important;\n}\n.visible-on-sidebar-mini{\n display: none !important;\n}\n\n.off-canvas-sidebar{\n .nav {\n > li > a,\n > li > a:hover{\n color: $white-color;\n }\n\n > li > a:focus{\n background: rgba(200, 200, 200, 0.2);\n }\n }\n}\n\n\n.main-panel{\n position: relative;\n float: right;\n width: $sidebar-width;\n // width: 100%;\n background-color: $light-gray;\n background-color: #ebecf1;\n\n @include transition (0.50s, cubic-bezier(0.685, 0.0473, 0.346, 1));\n\n > .content{\n padding: 0 30px 30px;\n min-height: calc(100vh - 123px);\n margin-top: -30px;\n }\n\n > .navbar{\n margin-bottom: 0;\n }\n\n\n .header{\n margin-bottom: 50px;\n }\n}\n\n\n.perfect-scrollbar-on{\n .sidebar,\n .main-panel{\n height: 100%;\n max-height: 100%;\n }\n}\n\n\n@media (min-width: 991px) {\n .sidebar{\n display: block;\n box-shadow: $sidebar-box-shadow;\n }\n}\n\n.panel-header {\n height: 260px;\n padding-top: 80px;\n padding-bottom: 45px;\n background: #141E30; /* fallback for old browsers */\n background: -webkit-gradient(linear, left top, right top, from(#0c2646), color-stop(60%, #204065), to(#2a5788));\n background: linear-gradient(to right, #0c2646 0%, #204065 60%, #2a5788 100%);\n position: relative;\n overflow: hidden;\n\n .header{\n .title{\n color: $white-color;\n }\n .category{\n max-width: 600px;\n color: $opacity-5;\n margin: 0 auto;\n font-size: 13px;\n\n a{\n color: $white-color;\n }\n }\n }\n}\n\n.panel-header-sm{\n height: 135px;\n}\n\n.panel-header-lg{\n height: 380px\n}\n",".card{\n border: 0;\n border-radius: $border-radius-small;\n display: inline-block;\n position: relative;\n width: 100%;\n margin-bottom: 20px;\n box-shadow: $box-shadow;\n\n .card-body{\n padding: 15px 15px 10px 15px;\n\n &.table-full-width{\n padding-left: 0;\n padding-right: 0;\n }\n }\n\n .card-header{\n &:not([data-background-color]){\n background-color: transparent;\n }\n padding: 15px 15px 0;\n border: 0;\n\n .card-title{\n margin-top: 10px;\n }\n }\n\n .map{\n height: 500px;\n border-radius: $border-radius-small;\n\n &.map-big{\n height: 400px;\n }\n }\n\n &[data-background-color=\"orange\"]{\n background-color: $primary-color;\n\n .card-header{\n background-color: $primary-color;\n }\n\n .card-footer{\n .stats{\n color: $white-color;\n }\n }\n }\n\n &[data-background-color=\"red\"]{\n background-color: $danger-color;\n }\n\n &[data-background-color=\"yellow\"]{\n background-color: $warning-color;\n }\n\n &[data-background-color=\"blue\"]{\n background-color: $info-color;\n }\n\n &[data-background-color=\"green\"]{\n background-color: $success-color;\n }\n\n .image{\n overflow: hidden;\n height: 200px;\n position: relative;\n }\n\n .avatar{\n width: 30px;\n height: 30px;\n overflow: hidden;\n border-radius: 50%;\n margin-bottom: 15px;\n }\n\n label{\n font-size: $font-size-small;\n margin-bottom: 5px;\n color: $dark-gray;\n }\n\n .card-footer{\n background-color: transparent;\n border: 0;\n\n\n .stats{\n i{\n margin-right: 5px;\n position: relative;\n top: 2px;\n }\n }\n\n .btn{\n margin: 0;\n }\n }\n}\n\n.card-user{\n .image{\n height: 120px;\n }\n\n .author{\n text-align: center;\n text-transform: none;\n margin-top: -77px;\n\n a + p.description{\n margin-top: -7px;\n }\n }\n\n .avatar{\n width: 124px;\n height: 124px;\n border: 1px solid $white-color;\n position: relative;\n }\n\n .card-body{\n min-height: 240px;\n }\n\n hr{\n margin: 5px 15px;\n }\n\n .button-container{\n margin-bottom: 6px;\n text-align: center;\n }\n}\n\n.card-plain{\n background: transparent;\n box-shadow: none;\n\n .card-header,\n .card-footer{\n margin-left: 0;\n margin-right: 0;\n background-color: transparent;\n }\n\n &:not(.card-subcategories).card-body{\n padding-left: 0;\n padding-right: 0;\n }\n}\n\n@import \"cards/card-chart\";\n",".card-chart {\n .card-header{\n .card-title{\n margin-top: 10px;\n margin-bottom: 0;\n }\n .card-category{\n margin-bottom: 5px;\n }\n }\n\n .table{\n margin-bottom: 0;\n\n td{\n border-top: none;\n border-bottom: 1px solid #e9ecef;\n }\n }\n\n .card-progress {\n margin-top: 30px;\n }\n\n .chart-area {\n height: 190px;\n width: calc(100% + 30px);\n margin-left: -15px;\n margin-right: -15px;\n }\n .card-footer {\n margin-top: 15px;\n\n .stats{\n color: $dark-gray;\n }\n }\n\n .dropdown{\n position: absolute;\n right: 20px;\n top: 20px;\n\n .btn{\n margin: 0;\n }\n }\n}\n",".footer{\n padding: 24px 0;\n\n &.footer-default{\n background-color: #f2f2f2;\n }\n\n nav{\n display: inline-block;\n float: left;\n padding-left: 7px;\n }\n\n ul{\n margin-bottom: 0;\n padding: 0;\n list-style: none;\n\n li{\n display: inline-block;\n\n a{\n color: inherit;\n padding: $padding-base-vertical;\n font-size: $font-size-small;\n text-transform: uppercase;\n text-decoration: none;\n\n &:hover{\n text-decoration: none;\n }\n }\n }\n }\n\n .copyright{\n font-size: $font-size-small;\n line-height: 1.8;\n }\n\n &:after{\n display: table;\n clear: both;\n content: \" \";\n }\n}\n",".fixed-plugin{\n position: fixed;\n right: 0;\n width: 64px;\n background: rgba(0,0,0,.3);\n z-index: 1031;\n border-radius: 8px 0 0 8px;\n text-align: center;\n top: 120px;\n\n li > a,\n .badge{\n transition: all .34s;\n -webkit-transition: all .34s;\n -moz-transition: all .34s;\n }\n\n .fa-cog{\n color: #FFFFFF;\n padding: 10px;\n border-radius: 0 0 6px 6px;\n width: auto;\n }\n\n .dropdown-menu{\n right: 80px;\n left: auto !important;\n top: -52px !important;\n width: 290px;\n border-radius: 0.1875rem;\n padding: 0 10px;\n }\n\n .dropdown .dropdown-menu .now-ui-icons{\n top: 5px;\n }\n\n .dropdown-menu:after,\n .dropdown-menu:before{\n right: 10px;\n margin-left: auto;\n left: auto;\n }\n\n .fa-circle-thin{\n color: #FFFFFF;\n }\n\n .active .fa-circle-thin{\n color: #00bbff;\n }\n\n .dropdown-menu > .active > a,\n .dropdown-menu > .active > a:hover,\n .dropdown-menu > .active > a:focus{\n color: #777777;\n text-align: center;\n }\n\n img{\n border-radius: 0;\n width: 100%;\n height: 100px;\n margin: 0 auto;\n }\n\n .dropdown-menu li > a:hover,\n .dropdown-menu li > a:focus{\n box-shadow: none;\n }\n\n .badge{\n border: 3px solid #FFFFFF;\n border-radius: 50%;\n cursor: pointer;\n display: inline-block;\n height: 23px;\n margin-right: 5px;\n position: relative;\n width: 23px;\n }\n\n .badge.active,\n .badge:hover{\n border-color: #00bbff;\n }\n\n .badge-blue{\n background-color: $brand-info;\n }\n .badge-green{\n background-color: $brand-success;\n }\n .badge-orange{\n background-color: $brand-primary;\n }\n .badge-yellow{\n background-color: $brand-warning;\n }\n .badge-red{\n background-color: $brand-danger;\n }\n\n h5{\n font-size: 14px;\n margin: 10px;\n }\n\n .dropdown-menu li{\n display: block;\n padding: 18px 2px;\n width: 25%;\n float: left;\n }\n\n li.adjustments-line,\n li.header-title,\n li.button-container{\n width: 100%;\n height: 50px;\n min-height: inherit;\n }\n\n li.button-container{\n height: auto;\n\n div{\n margin-bottom: 5px;\n }\n }\n\n #sharrreTitle{\n text-align: center;\n padding: 10px 0;\n height: 50px;\n }\n\n li.header-title{\n height: 30px;\n line-height: 25px;\n font-size: 12px;\n font-weight: 600;\n text-align: center;\n text-transform: uppercase;\n }\n\n .adjustments-line{\n p{\n float: left;\n display: inline-block;\n margin-bottom: 0;\n font-size: 1em;\n color: #3C4858;\n }\n\n a{\n color: transparent;\n\n .badge-colors{\n position: relative;\n top: -2px;\n }\n\n a:hover,\n a:focus{\n color: transparent;\n }\n }\n\n .togglebutton{\n text-align: center;\n\n .label-switch{\n position: relative;\n left: -10px;\n font-size: $font-size-mini;\n color: $default-color;\n\n &.label-right{\n left: 10px;\n }\n }\n\n .toggle{\n margin-right: 0;\n }\n }\n\n .dropdown-menu > li.adjustments-line > a{\n padding-right: 0;\n padding-left: 0;\n border-bottom: 1px solid #ddd;\n border-radius: 0;\n margin: 0;\n }\n }\n\n\n\n .dropdown-menu{\n > li{\n & > a.img-holder{\n font-size: 16px;\n text-align: center;\n border-radius: 10px;\n background-color: #FFF;\n border: 3px solid #FFF;\n padding-left: 0;\n padding-right: 0;\n opacity: 1;\n cursor: pointer;\n display: block;\n max-height: 100px;\n overflow: hidden;\n padding: 0;\n\n img{\n margin-top: auto;\n }\n }\n\n a.switch-trigger:hover,\n & > a.switch-trigger:focus{\n background-color: transparent;\n }\n\n &:hover,\n &:focus{\n > a.img-holder{\n border-color: rgba(0, 187, 255, 0.53);;\n }\n }\n }\n\n > .active > a.img-holder,\n > .active > a.img-holder{\n border-color: #00bbff;\n background-color: #FFFFFF;\n }\n\n }\n\n .btn-social{\n width: 50%;\n display: block;\n width: 48%;\n float: left;\n font-weight: 600;\n }\n\n .btn-social{\n i{\n margin-right: 5px;\n }\n\n &:first-child{\n margin-right: 2%;\n }\n }\n\n .dropdown{\n .dropdown-menu{\n -webkit-transform: translateY(-15%);\n -moz-transform: translateY(-15%);\n -o-transform: translateY(-15%);\n -ms-transform: translateY(-15%);\n transform: translateY(-15%);\n top: 27px;\n opacity: 0;\n\n transform-origin: 0 0;\n\n &:before{\n border-bottom: .4em solid rgba(0, 0, 0, 0);\n border-left: .4em solid rgba(0,0,0,0.2);\n border-top: .4em solid rgba(0,0,0,0);\n right: -16px;\n top: 46px;\n }\n\n &:after{\n border-bottom: .4em solid rgba(0, 0, 0, 0);\n border-left: .4em solid #FFFFFF;\n border-top: .4em solid rgba(0,0,0,0);\n right: -16px;\n }\n\n &:before,\n &:after{\n content: \"\";\n display: inline-block;\n position: absolute;\n top: 74px;\n width: 16px;\n transform: translateY(-50%);\n -webkit-transform: translateY(-50%);\n -moz-transform: translateY(-50%);\n }\n }\n\n &.show .dropdown-menu{\n opacity: 1;\n\n -webkit-transform: translateY(-13%);\n -moz-transform: translateY(-13%);\n -o-transform: translateY(-13%);\n -ms-transform: translateY(-13%);\n transform: translateY(-13%);\n\n transform-origin: 0 0;\n }\n }\n\n .bootstrap-switch{\n margin:0;\n }\n}\n","@media screen and (max-width: 991px){\n .profile-photo .profile-photo-small{\n margin-left: -2px;\n }\n\n .button-dropdown{\n display: none;\n }\n\n #minimizeSidebar{\n display: none;\n }\n\n .navbar{\n .container-fluid{\n padding-right: 15px;\n padding-left: 15px;\n }\n\n .navbar-collapse{\n .input-group{\n margin: 0;\n margin-top: 5px;\n }\n }\n\n .navbar-nav{\n .nav-item:first-child{\n margin-top: 10px;\n }\n .nav-item:not(:last-child){\n margin-bottom: 10px;\n }\n }\n\n .dropdown.show .dropdown-menu{\n display: block;\n }\n\n .dropdown .dropdown-menu{\n display: none;\n }\n\n .dropdown.show .dropdown-menu,\n .dropdown .dropdown-menu{\n background-color: transparent;\n border: 0;\n transition: none;\n -webkit-box-shadow: none;\n box-shadow: none;\n width: auto;\n margin: 0px 1rem;\n margin-top: 0px;\n\n &:before{\n display: none;\n }\n }\n\n .dropdown-menu .dropdown-item:focus,\n .dropdown-menu .dropdown-item:hover{\n color: $white-color;\n }\n\n &.bg-white .dropdown-menu .dropdown-item:focus,\n &.bg-white .dropdown-menu .dropdown-item:hover{\n color: $default-color;\n }\n\n .navbar-toggler-bar{\n display: block;\n position: relative;\n width: 22px;\n height: 1px;\n border-radius: 1px;\n background: $white-bg;\n\n & + .navbar-toggler-bar{\n margin-top: 7px;\n }\n\n & + .navbar-toggler-bar.navbar-kebab{\n margin-top: 3px;\n }\n\n &.bar2{\n width: 17px;\n transition: width .2s linear;\n }\n }\n\n &.bg-white:not(.navbar-transparent) .navbar-toggler-bar{\n background-color: $default-color;\n }\n\n & .toggled .navbar-toggler-bar{\n width: 24px;\n\n & + .navbar-toggler-bar{\n margin-top: 5px;\n }\n }\n\n }\n\n .wrapper{\n @include transition (0.50s, cubic-bezier(0.685, 0.0473, 0.346, 1));\n }\n\n .nav-open{\n .main-panel{\n right: 0;\n @include transform-translate-x(260px);\n }\n\n .sidebar{\n @include transform-translate-x(0px);\n }\n\n body{\n position: relative;\n overflow-x: hidden;\n }\n\n .menu-on-right{\n .main-panel{\n @include transform-translate-x(-260px);\n }\n\n .navbar-collapse,\n .sidebar{\n @include transform-translate-x(0px);\n }\n\n .navbar-translate{\n @include transform-translate-x(-300px);\n }\n\n #bodyClick{\n right: 260px;\n left: auto;\n }\n }\n }\n\n .menu-on-right{\n .sidebar{\n left: auto;\n right:0;\n @include transform-translate-x(260px);\n }\n }\n\n .bar1,\n .bar2,\n .bar3 {\n outline: 1px solid transparent;\n }\n .bar1 {\n top: 0px;\n @include bar-animation($topbar-back);\n }\n .bar2 {\n opacity: 1;\n }\n .bar3 {\n bottom: 0px;\n @include bar-animation($bottombar-back);\n }\n .toggled .bar1 {\n top: 6px;\n @include bar-animation($topbar-x);\n }\n .toggled .bar2 {\n opacity: 0;\n }\n .toggled .bar3 {\n bottom: 6px;\n @include bar-animation($bottombar-x);\n }\n\n @include topbar-x-rotation();\n @include topbar-back-rotation();\n @include bottombar-x-rotation();\n @include bottombar-back-rotation();\n\n @-webkit-keyframes fadeIn {\n 0% {opacity: 0;}\n 100% {opacity: 1;}\n }\n @-moz-keyframes fadeIn {\n 0% {opacity: 0;}\n 100% {opacity: 1;}\n }\n @keyframes fadeIn {\n 0% {opacity: 0;}\n 100% {opacity: 1;}\n }\n\n #bodyClick{\n height: 100%;\n width: 100%;\n position: fixed;\n opacity: 1;\n top: 0;\n right: 0;\n left: 260px;\n content: \"\";\n z-index: 9999;\n overflow-x: hidden;\n background-color: transparent;\n @include transition (0.50s, cubic-bezier(0.685, 0.0473, 0.346, 1));\n }\n\n .footer{\n .copyright{\n text-align: right;\n }\n }\n\n .section-nucleo-icons .icons-container{\n margin-top: 65px;\n }\n\n .navbar-nav{\n .nav-link{\n i.fa,\n i.now-ui-icons{\n opacity: .5;\n }\n }\n }\n\n .sidebar,\n .bootstrap-navbar {\n position: fixed;\n display: block;\n top: 0;\n height: 100%;\n width: 260px;\n right: auto;\n left: 0;\n z-index: 1032;\n visibility: visible;\n overflow-y: visible;\n padding: 0;\n @include transition (0.50s, cubic-bezier(0.685, 0.0473, 0.346, 1));\n\n @include transform-translate-x(-260px);\n }\n\n\n\n .main-panel{\n width: 100%;\n }\n}\n\n@media screen and (min-width: 992px){\n .navbar-collapse{\n background: none !important;\n }\n\n .navbar .navbar-toggle{\n display: none;\n }\n\n // .navbar.fixed-top{\n // width: $sidebar-width;\n // right: 0;\n // left: auto;\n // }\n\n .navbar-nav{\n .nav-link{\n &.profile-photo{\n padding: 0;\n margin: 7px $padding-base-horizontal;\n }\n }\n }\n\n .section-nucleo-icons .icons-container{\n margin: 0 0 0 auto;\n }\n\n .dropdown-menu .dropdown-item{\n color: inherit;\n }\n\n .footer{\n .copyright{\n float: right;\n padding-right: 15px;\n }\n }\n}\n\n@media screen and (max-width: 768px){\n .nav-tabs{\n display: inline-block;\n width: 100%;\n padding-left: 100px;\n padding-right: 100px;\n text-align: center;\n\n .nav-item > .nav-link{\n margin-bottom: 5px;\n }\n }\n\n .card-stats [class*=\"col-\"] .statistics::after {\n display: none;\n }\n\n .main-panel .content {\n padding-left: 15px;\n padding-right: 15px;\n }\n\n .footer{\n nav{\n display: block;\n margin-bottom: 5px;\n float: none;\n }\n }\n\n .landing-page .section-story-overview .image-container:nth-child(2){\n margin-left: 0;\n margin-bottom: 30px;\n }\n}\n\n@media screen and (max-width: 576px){\n .navbar[class*='navbar-toggleable-'] .container{\n margin-left: 0;\n margin-right: 0;\n }\n\n .card-contributions .card-stats{\n flex-direction: column;\n\n .bootstrap-switch{\n margin-bottom: 15px;\n }\n }\n\n .footer{\n .copyright{\n text-align: center;\n }\n }\n\n .section-nucleo-icons{\n .icons-container{\n i{\n font-size: 30px;\n\n &:nth-child(6){\n font-size: 48px;\n }\n }\n }\n }\n\n .page-header{\n .container h6.category-absolute{\n width: 90%;\n }\n }\n}\n"]} \ No newline at end of file diff --git a/web/templates/boilerplate/assets/css/now-ui-dashboard.min.css b/web/templates/boilerplate/assets/css/now-ui-dashboard.min.css deleted file mode 100644 index 8bc8ffa..0000000 --- a/web/templates/boilerplate/assets/css/now-ui-dashboard.min.css +++ /dev/null @@ -1,24 +0,0 @@ -/*! - - ========================================================= - * Now UI Dashboard - v1.0.1 - ========================================================= - - * Product Page: http://www.creative-tim.com/product/now-ui-dashboard - * Copyright 2017 Creative Tim (http://www.creative-tim.com) - * Licensed under MIT (https://github.com/creativetimofficial/now-ui-dashboard/blob/master/LICENSE.md) - - - * Designed by www.invisionapp.com Coded by www.creative-tim.com - - ========================================================= - - * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - - */ -/*! -Animate.css - http://daneden.me/animate -Licensed under the MIT license - http://opensource.org/licenses/MIT - -Copyright (c) 2015 Daniel Eden -*/.animated{-webkit-animation-duration:1s;animation-duration:1s;-webkit-animation-fill-mode:both;animation-fill-mode:both}.animated.infinite{-webkit-animation-iteration-count:infinite;animation-iteration-count:infinite}.animated.hinge{-webkit-animation-duration:2s;animation-duration:2s}.animated.bounceIn,.animated.bounceOut,.animated.flipOutX,.animated.flipOutY{-webkit-animation-duration:.75s;animation-duration:.75s}@-webkit-keyframes a{0%,to{-webkit-transform:translateZ(0);transform:translateZ(0)}10%,30%,50%,70%,90%{-webkit-transform:translate3d(-10px,0,0);transform:translate3d(-10px,0,0)}20%,40%,60%,80%{-webkit-transform:translate3d(10px,0,0);transform:translate3d(10px,0,0)}}@keyframes a{0%,to{-webkit-transform:translateZ(0);transform:translateZ(0)}10%,30%,50%,70%,90%{-webkit-transform:translate3d(-10px,0,0);transform:translate3d(-10px,0,0)}20%,40%,60%,80%{-webkit-transform:translate3d(10px,0,0);transform:translate3d(10px,0,0)}}.shake{-webkit-animation-name:a;animation-name:a}@-webkit-keyframes b{0%{opacity:0;-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0)}to{opacity:1;-webkit-transform:none;transform:none}}@keyframes b{0%{opacity:0;-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0)}to{opacity:1;-webkit-transform:none;transform:none}}.fadeInDown{-webkit-animation-name:b;animation-name:b}@-webkit-keyframes c{0%{opacity:1}to{opacity:0}}@keyframes c{0%{opacity:1}to{opacity:0}}.fadeOut{-webkit-animation-name:c;animation-name:c}@-webkit-keyframes d{0%{opacity:1}to{opacity:0;-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}}@keyframes d{0%{opacity:1}to{opacity:0;-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}}.fadeOutDown{-webkit-animation-name:d;animation-name:d}@-webkit-keyframes e{0%{opacity:1}to{opacity:0;-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0)}}@keyframes e{0%{opacity:1}to{opacity:0;-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0)}}.fadeOutUp{-webkit-animation-name:e;animation-name:e}.ps-container{-ms-touch-action:auto;touch-action:auto;overflow:hidden!important;-ms-overflow-style:none}@supports (-ms-overflow-style:none){.ps-container{overflow:auto!important}}@media (-ms-high-contrast:none),screen and (-ms-high-contrast:active){.ps-container{overflow:auto!important}}.ps-container.ps-active-x>.ps-scrollbar-x-rail,.ps-container.ps-active-y>.ps-scrollbar-y-rail{display:block;background-color:transparent}.ps-container.ps-in-scrolling.ps-x>.ps-scrollbar-x-rail{background-color:#eee;opacity:.9}.ps-container.ps-in-scrolling.ps-x>.ps-scrollbar-x-rail>.ps-scrollbar-x{background-color:#999;height:11px}.ps-container.ps-in-scrolling.ps-y>.ps-scrollbar-y-rail{background-color:#eee;opacity:.9}.ps-container.ps-in-scrolling.ps-y>.ps-scrollbar-y-rail>.ps-scrollbar-y{background-color:#999;width:11px}.ps-container>.ps-scrollbar-x-rail{display:none;position:absolute;opacity:0;transition:background-color .2s linear,opacity .2s linear;bottom:0;height:15px}.ps-container>.ps-scrollbar-x-rail>.ps-scrollbar-x{position:absolute;background-color:#aaa;border-radius:6px;transition:background-color .2s linear,height .2s linear,width .2s ease-in-out,border-radius .2s ease-in-out;bottom:2px;height:6px}.ps-container>.ps-scrollbar-x-rail:active>.ps-scrollbar-x,.ps-container>.ps-scrollbar-x-rail:hover>.ps-scrollbar-x{height:11px}.ps-container>.ps-scrollbar-y-rail{display:none;position:absolute;opacity:0;transition:background-color .2s linear,opacity .2s linear;right:0;width:15px}.ps-container>.ps-scrollbar-y-rail>.ps-scrollbar-y{position:absolute;background-color:#aaa;border-radius:6px;transition:background-color .2s linear,height .2s linear,width .2s ease-in-out,border-radius .2s ease-in-out;right:2px;width:6px}.ps-container>.ps-scrollbar-y-rail:active>.ps-scrollbar-y,.ps-container>.ps-scrollbar-y-rail:hover>.ps-scrollbar-y{width:11px}.ps-container:hover.ps-in-scrolling.ps-x>.ps-scrollbar-x-rail{background-color:#eee;opacity:.9}.ps-container:hover.ps-in-scrolling.ps-x>.ps-scrollbar-x-rail>.ps-scrollbar-x{background-color:#999;height:11px}.ps-container:hover.ps-in-scrolling.ps-y>.ps-scrollbar-y-rail{background-color:#eee;opacity:.9}.ps-container:hover.ps-in-scrolling.ps-y>.ps-scrollbar-y-rail>.ps-scrollbar-y{background-color:#999;width:11px}.ps-container:hover>.ps-scrollbar-x-rail,.ps-container:hover>.ps-scrollbar-y-rail{opacity:.6}.ps-container:hover>.ps-scrollbar-x-rail:hover{background-color:#eee;opacity:.9}.ps-container:hover>.ps-scrollbar-x-rail:hover>.ps-scrollbar-x{background-color:#999}.ps-container:hover>.ps-scrollbar-y-rail:hover{background-color:#eee;opacity:.9}.ps-container:hover>.ps-scrollbar-y-rail:hover>.ps-scrollbar-y{background-color:#999}.btn,.navbar .navbar-nav>a.btn{border-width:2px;font-weight:400;font-size:.8571em;line-height:1.35em;margin:5px 1px;border:none;margin:10px 1px;border-radius:.1875rem;padding:11px 22px;cursor:pointer;background-color:#888;color:#fff}.btn.active,.btn.active:focus,.btn.active:hover,.btn:active,.btn:active:focus,.btn:active:hover,.btn:focus,.btn:hover,.navbar .navbar-nav>a.btn.active,.navbar .navbar-nav>a.btn.active:focus,.navbar .navbar-nav>a.btn.active:hover,.navbar .navbar-nav>a.btn:active,.navbar .navbar-nav>a.btn:active:focus,.navbar .navbar-nav>a.btn:active:hover,.navbar .navbar-nav>a.btn:focus,.navbar .navbar-nav>a.btn:hover,.show>.btn.dropdown-toggle,.show>.btn.dropdown-toggle:focus,.show>.btn.dropdown-toggle:hover,.show>.navbar .navbar-nav>a.btn.dropdown-toggle,.show>.navbar .navbar-nav>a.btn.dropdown-toggle:focus,.show>.navbar .navbar-nav>a.btn.dropdown-toggle:hover{background-color:#979797;color:#fff;box-shadow:none}.btn:not([data-action]):hover,.navbar .navbar-nav>a.btn:not([data-action]):hover{box-shadow:0 3px 8px 0 rgba(0,0,0,.17)}.btn.disabled,.btn.disabled.active,.btn.disabled.focus,.btn.disabled:active,.btn.disabled:focus,.btn.disabled:hover,.btn:disabled,.btn:disabled.active,.btn:disabled.focus,.btn:disabled:active,.btn:disabled:focus,.btn:disabled:hover,.btn[disabled],.btn[disabled].active,.btn[disabled].focus,.btn[disabled]:active,.btn[disabled]:focus,.btn[disabled]:hover,.navbar .navbar-nav>a.btn.disabled,.navbar .navbar-nav>a.btn.disabled.active,.navbar .navbar-nav>a.btn.disabled.focus,.navbar .navbar-nav>a.btn.disabled:active,.navbar .navbar-nav>a.btn.disabled:focus,.navbar .navbar-nav>a.btn.disabled:hover,.navbar .navbar-nav>a.btn:disabled,.navbar .navbar-nav>a.btn:disabled.active,.navbar .navbar-nav>a.btn:disabled.focus,.navbar .navbar-nav>a.btn:disabled:active,.navbar .navbar-nav>a.btn:disabled:focus,.navbar .navbar-nav>a.btn:disabled:hover,.navbar .navbar-nav>a.btn[disabled],.navbar .navbar-nav>a.btn[disabled].active,.navbar .navbar-nav>a.btn[disabled].focus,.navbar .navbar-nav>a.btn[disabled]:active,.navbar .navbar-nav>a.btn[disabled]:focus,.navbar .navbar-nav>a.btn[disabled]:hover,fieldset[disabled] .btn,fieldset[disabled] .btn.active,fieldset[disabled] .btn.focus,fieldset[disabled] .btn:active,fieldset[disabled] .btn:focus,fieldset[disabled] .btn:hover,fieldset[disabled] .navbar .navbar-nav>a.btn,fieldset[disabled] .navbar .navbar-nav>a.btn.active,fieldset[disabled] .navbar .navbar-nav>a.btn.focus,fieldset[disabled] .navbar .navbar-nav>a.btn:active,fieldset[disabled] .navbar .navbar-nav>a.btn:focus,fieldset[disabled] .navbar .navbar-nav>a.btn:hover{background-color:#888;border-color:#888}.btn.btn-simple,.navbar .navbar-nav>a.btn.btn-simple{color:#888;border-color:#888}.btn.btn-simple:active,.btn.btn-simple:focus,.btn.btn-simple:hover,.navbar .navbar-nav>a.btn.btn-simple:active,.navbar .navbar-nav>a.btn.btn-simple:focus,.navbar .navbar-nav>a.btn.btn-simple:hover{background-color:transparent;color:#979797;border-color:#979797;box-shadow:none}.btn.btn-link,.navbar .navbar-nav>a.btn.btn-link{color:#888}.btn.btn-link:active,.btn.btn-link:focus,.btn.btn-link:hover,.navbar .navbar-nav>a.btn.btn-link:active,.navbar .navbar-nav>a.btn.btn-link:focus,.navbar .navbar-nav>a.btn.btn-link:hover{background-color:transparent;color:#979797;text-decoration:none;box-shadow:none}.btn:focus,.btn:hover,.navbar .navbar-nav>a.btn:focus,.navbar .navbar-nav>a.btn:hover{opacity:1;filter:alpha(opacity=100);outline:0!important}.btn.active,.btn:active,.navbar .navbar-nav>a.btn.active,.navbar .navbar-nav>a.btn:active,.open>.btn.dropdown-toggle,.open>.navbar .navbar-nav>a.btn.dropdown-toggle{box-shadow:none;outline:0!important}.btn .badge,.navbar .navbar-nav>a.btn .badge{margin:0}.btn.btn-icon,.navbar .navbar-nav>a.btn.btn-icon{height:2.375rem;min-width:2.375rem;width:2.375rem;padding:0;font-size:.9375rem;overflow:hidden;position:relative;line-height:normal}.btn.btn-icon.btn-simple,.navbar .navbar-nav>a.btn.btn-icon.btn-simple{padding:0}.btn.btn-icon.btn-sm,.navbar .navbar-nav>a.btn.btn-icon.btn-sm{height:1.875rem;min-width:1.875rem;width:1.875rem}.btn.btn-icon.btn-sm i.fa,.btn.btn-icon.btn-sm i.now-ui-icons,.navbar .navbar-nav>a.btn.btn-icon.btn-sm i.fa,.navbar .navbar-nav>a.btn.btn-icon.btn-sm i.now-ui-icons{font-size:.6875rem}.btn.btn-icon.btn-lg,.navbar .navbar-nav>a.btn.btn-icon.btn-lg{height:3.6rem;min-width:3.6rem;width:3.6rem}.btn.btn-icon.btn-lg i.fa,.btn.btn-icon.btn-lg i.now-ui-icons,.navbar .navbar-nav>a.btn.btn-icon.btn-lg i.fa,.navbar .navbar-nav>a.btn.btn-icon.btn-lg i.now-ui-icons{font-size:1.325rem}.btn.btn-icon:not(.btn-footer) i.fa,.btn.btn-icon:not(.btn-footer) i.now-ui-icons,.navbar .navbar-nav>a.btn.btn-icon:not(.btn-footer) i.fa,.navbar .navbar-nav>a.btn.btn-icon:not(.btn-footer) i.now-ui-icons{position:absolute;top:50%;left:50%;transform:translate(-12px,-12px);line-height:1.5626rem;width:24px}.btn:not(.btn-icon) .now-ui-icons,.navbar .navbar-nav>a.btn:not(.btn-icon) .now-ui-icons{position:relative;top:1px}.btn-primary{background-color:#f96332;color:#fff}.btn-primary.active,.btn-primary.active:focus,.btn-primary.active:hover,.btn-primary:active,.btn-primary:active:focus,.btn-primary:active:hover,.btn-primary:focus,.btn-primary:hover,.show>.btn-primary.dropdown-toggle,.show>.btn-primary.dropdown-toggle:focus,.show>.btn-primary.dropdown-toggle:hover{background-color:#fa7a50;color:#fff;box-shadow:none}.btn-primary:not([data-action]):hover{box-shadow:0 3px 8px 0 rgba(0,0,0,.17)}.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,.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:#f96332;border-color:#f96332}.btn-primary.btn-simple{color:#f96332;border-color:#f96332}.btn-primary.btn-simple:active,.btn-primary.btn-simple:focus,.btn-primary.btn-simple:hover{background-color:transparent;color:#fa7a50;border-color:#fa7a50;box-shadow:none}.btn-primary.btn-link{color:#f96332}.btn-primary.btn-link:active,.btn-primary.btn-link:focus,.btn-primary.btn-link:hover{background-color:transparent;color:#fa7a50;text-decoration:none;box-shadow:none}.btn-success{background-color:#18ce0f;color:#fff}.btn-success.active,.btn-success.active:focus,.btn-success.active:hover,.btn-success:active,.btn-success:active:focus,.btn-success:active:hover,.btn-success:focus,.btn-success:hover,.show>.btn-success.dropdown-toggle,.show>.btn-success.dropdown-toggle:focus,.show>.btn-success.dropdown-toggle:hover{background-color:#1beb11;color:#fff;box-shadow:none}.btn-success:not([data-action]):hover{box-shadow:0 3px 8px 0 rgba(0,0,0,.17)}.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,.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:#18ce0f;border-color:#18ce0f}.btn-success.btn-simple{color:#18ce0f;border-color:#18ce0f}.btn-success.btn-simple:active,.btn-success.btn-simple:focus,.btn-success.btn-simple:hover{background-color:transparent;color:#1beb11;border-color:#1beb11;box-shadow:none}.btn-success.btn-link{color:#18ce0f}.btn-success.btn-link:active,.btn-success.btn-link:focus,.btn-success.btn-link:hover{background-color:transparent;color:#1beb11;text-decoration:none;box-shadow:none}.btn-info{background-color:#2ca8ff;color:#fff}.btn-info.active,.btn-info.active:focus,.btn-info.active:hover,.btn-info:active,.btn-info:active:focus,.btn-info:active:hover,.btn-info:focus,.btn-info:hover,.show>.btn-info.dropdown-toggle,.show>.btn-info.dropdown-toggle:focus,.show>.btn-info.dropdown-toggle:hover{background-color:#4bb5ff;color:#fff;box-shadow:none}.btn-info:not([data-action]):hover{box-shadow:0 3px 8px 0 rgba(0,0,0,.17)}.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,.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:#2ca8ff;border-color:#2ca8ff}.btn-info.btn-simple{color:#2ca8ff;border-color:#2ca8ff}.btn-info.btn-simple:active,.btn-info.btn-simple:focus,.btn-info.btn-simple:hover{background-color:transparent;color:#4bb5ff;border-color:#4bb5ff;box-shadow:none}.btn-info.btn-link{color:#2ca8ff}.btn-info.btn-link:active,.btn-info.btn-link:focus,.btn-info.btn-link:hover{background-color:transparent;color:#4bb5ff;text-decoration:none;box-shadow:none}.btn-warning{background-color:#ffb236;color:#fff}.btn-warning.active,.btn-warning.active:focus,.btn-warning.active:hover,.btn-warning:active,.btn-warning:active:focus,.btn-warning:active:hover,.btn-warning:focus,.btn-warning:hover,.show>.btn-warning.dropdown-toggle,.show>.btn-warning.dropdown-toggle:focus,.show>.btn-warning.dropdown-toggle:hover{background-color:#ffbe55;color:#fff;box-shadow:none}.btn-warning:not([data-action]):hover{box-shadow:0 3px 8px 0 rgba(0,0,0,.17)}.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,.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:#ffb236;border-color:#ffb236}.btn-warning.btn-simple{color:#ffb236;border-color:#ffb236}.btn-warning.btn-simple:active,.btn-warning.btn-simple:focus,.btn-warning.btn-simple:hover{background-color:transparent;color:#ffbe55;border-color:#ffbe55;box-shadow:none}.btn-warning.btn-link{color:#ffb236}.btn-warning.btn-link:active,.btn-warning.btn-link:focus,.btn-warning.btn-link:hover{background-color:transparent;color:#ffbe55;text-decoration:none;box-shadow:none}.btn-danger{background-color:#ff3636;color:#fff}.btn-danger.active,.btn-danger.active:focus,.btn-danger.active:hover,.btn-danger:active,.btn-danger:active:focus,.btn-danger:active:hover,.btn-danger:focus,.btn-danger:hover,.show>.btn-danger.dropdown-toggle,.show>.btn-danger.dropdown-toggle:focus,.show>.btn-danger.dropdown-toggle:hover{background-color:#f55;color:#fff;box-shadow:none}.btn-danger:not([data-action]):hover{box-shadow:0 3px 8px 0 rgba(0,0,0,.17)}.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,.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:#ff3636;border-color:#ff3636}.btn-danger.btn-simple{color:#ff3636;border-color:#ff3636}.btn-danger.btn-simple:active,.btn-danger.btn-simple:focus,.btn-danger.btn-simple:hover{background-color:transparent;color:#f55;border-color:#f55;box-shadow:none}.btn-danger.btn-link{color:#ff3636}.btn-danger.btn-link:active,.btn-danger.btn-link:focus,.btn-danger.btn-link:hover{background-color:transparent;color:#f55;text-decoration:none;box-shadow:none}.btn-neutral{background-color:#fff;color:#f96332}.btn-neutral.active,.btn-neutral.active:focus,.btn-neutral.active:hover,.btn-neutral:active,.btn-neutral:active:focus,.btn-neutral:active:hover,.btn-neutral:focus,.btn-neutral:hover,.show>.btn-neutral.dropdown-toggle,.show>.btn-neutral.dropdown-toggle:focus,.show>.btn-neutral.dropdown-toggle:hover{background-color:#fff;color:#fff;box-shadow:none}.btn-neutral:not([data-action]):hover{box-shadow:0 3px 8px 0 rgba(0,0,0,.17)}.btn-neutral.disabled,.btn-neutral.disabled.active,.btn-neutral.disabled.focus,.btn-neutral.disabled:active,.btn-neutral.disabled:focus,.btn-neutral.disabled:hover,.btn-neutral:disabled,.btn-neutral:disabled.active,.btn-neutral:disabled.focus,.btn-neutral:disabled:active,.btn-neutral:disabled:focus,.btn-neutral:disabled:hover,.btn-neutral[disabled],.btn-neutral[disabled].active,.btn-neutral[disabled].focus,.btn-neutral[disabled]:active,.btn-neutral[disabled]:focus,.btn-neutral[disabled]:hover,fieldset[disabled] .btn-neutral,fieldset[disabled] .btn-neutral.active,fieldset[disabled] .btn-neutral.focus,fieldset[disabled] .btn-neutral:active,fieldset[disabled] .btn-neutral:focus,fieldset[disabled] .btn-neutral:hover{background-color:#fff;border-color:#fff}.btn-neutral.btn-danger{color:#ff3636}.btn-neutral.btn-danger:active,.btn-neutral.btn-danger:active:focus,.btn-neutral.btn-danger:focus,.btn-neutral.btn-danger:hover{color:#f55}.btn-neutral.btn-info{color:#2ca8ff}.btn-neutral.btn-info:active,.btn-neutral.btn-info:active:focus,.btn-neutral.btn-info:focus,.btn-neutral.btn-info:hover{color:#4bb5ff}.btn-neutral.btn-warning{color:#ffb236}.btn-neutral.btn-warning:active,.btn-neutral.btn-warning:active:focus,.btn-neutral.btn-warning:focus,.btn-neutral.btn-warning:hover{color:#ffbe55}.btn-neutral.btn-success{color:#18ce0f}.btn-neutral.btn-success:active,.btn-neutral.btn-success:active:focus,.btn-neutral.btn-success:focus,.btn-neutral.btn-success:hover{color:#1beb11}.btn-neutral.btn-default{color:#888}.btn-neutral.btn-default:active,.btn-neutral.btn-default:active:focus,.btn-neutral.btn-default:focus,.btn-neutral.btn-default:hover{color:#979797}.btn-neutral.active,.btn-neutral.active:focus,.btn-neutral.active:hover,.btn-neutral:active,.btn-neutral:active:focus,.btn-neutral:active:hover,.show>.btn-neutral.dropdown-toggle,.show>.btn-neutral.dropdown-toggle:focus,.show>.btn-neutral.dropdown-toggle:hover{background-color:#fff;color:#fa7a50;box-shadow:none}.btn-neutral:focus,.btn-neutral:hover{color:#fa7a50}.btn-neutral:focus:not(.nav-link),.btn-neutral:hover:not(.nav-link){box-shadow:none}.btn-neutral.btn-simple{color:#fff;border-color:#fff}.btn-neutral.btn-simple:active,.btn-neutral.btn-simple:focus,.btn-neutral.btn-simple:hover{background-color:transparent;color:#fff;border-color:#fff;box-shadow:none}.btn-neutral.btn-link{color:#fff}.btn-neutral.btn-link:active,.btn-neutral.btn-link:focus,.btn-neutral.btn-link:hover{background-color:transparent;color:#fff;text-decoration:none;box-shadow:none}.btn.disabled,.btn:disabled,.btn[disabled]{opacity:.5;filter:alpha(opacity=50);pointer-events:none}.btn-simple{border:1px solid;border-color:#888;padding:10px 22px}.btn-link,.btn-link.disabled,.btn-link.disabled.active,.btn-link.disabled.focus,.btn-link.disabled:active,.btn-link.disabled:focus,.btn-link.disabled:hover,.btn-link:disabled,.btn-link:disabled.active,.btn-link:disabled.focus,.btn-link:disabled:active,.btn-link:disabled:focus,.btn-link:disabled:hover,.btn-link[disabled],.btn-link[disabled].active,.btn-link[disabled].focus,.btn-link[disabled]:active,.btn-link[disabled]:focus,.btn-link[disabled]:hover,.btn-simple,.btn-simple.disabled,.btn-simple.disabled.active,.btn-simple.disabled.focus,.btn-simple.disabled:active,.btn-simple.disabled:focus,.btn-simple.disabled:hover,.btn-simple:disabled,.btn-simple:disabled.active,.btn-simple:disabled.focus,.btn-simple:disabled:active,.btn-simple:disabled:focus,.btn-simple:disabled:hover,.btn-simple[disabled],.btn-simple[disabled].active,.btn-simple[disabled].focus,.btn-simple[disabled]:active,.btn-simple[disabled]:focus,.btn-simple[disabled]:hover,fieldset[disabled] .btn-link,fieldset[disabled] .btn-link.active,fieldset[disabled] .btn-link.focus,fieldset[disabled] .btn-link:active,fieldset[disabled] .btn-link:focus,fieldset[disabled] .btn-link:hover,fieldset[disabled] .btn-simple,fieldset[disabled] .btn-simple.active,fieldset[disabled] .btn-simple.focus,fieldset[disabled] .btn-simple:active,fieldset[disabled] .btn-simple:focus,fieldset[disabled] .btn-simple:hover{background-color:transparent}.btn-link{border:0;padding:.5rem .7rem}.btn-lg{font-size:1em;border-radius:.25rem;padding:15px 48px}.btn-lg.btn-simple{padding:14px 47px}.btn-sm{font-size:14px;border-radius:.1875rem;padding:5px 15px}.btn-sm.btn-simple{padding:4px 14px}.btn-wd{min-width:140px}.btn-group.select{width:100%}.btn-group.select .btn{text-align:left}.btn-group.select .caret{position:absolute;top:50%;margin-top:-1px;right:8px}.btn-round{border-width:1px;border-radius:30px;padding-right:23px;padding-left:23px}.btn-round.btn-simple{padding:10px 22px}.no-caret.dropdown-toggle:after{display:none}.form-control:-moz-placeholder,.form-control::-moz-placeholder{color:#ddd;opacity:1;filter:alpha(opacity=100)}.form-control::-webkit-input-placeholder{color:#ddd;opacity:1;filter:alpha(opacity=100)}.form-control:-ms-input-placeholder{color:#ddd;opacity:1;filter:alpha(opacity=100)}.form-control{background-color:transparent;border:1px solid #e3e3e3;border-radius:30px;color:#2c2c2c;line-height:normal;font-size:.8571em;transition:color .3s ease-in-out,border-color .3s ease-in-out,background-color .3s ease-in-out;box-shadow:none}.form-control:focus{border:1px solid #f96332;box-shadow:none;outline:0!important;color:#2c2c2c}.form-control:focus+.input-group-addon,.form-control:focus~.input-group-addon{border:1px solid #f96332;border-left:none;background-color:transparent}.has-error .form-control,.has-error .form-control:focus,.has-success .form-control,.has-success .form-control:focus{box-shadow:none}.has-danger .form-control.form-control-danger,.has-danger .form-control.form-control-success,.has-success .form-control.form-control-danger,.has-success .form-control.form-control-success{background-image:none}.form-control+.form-control-feedback{border-radius:.25rem;font-size:14px;margin-top:-7px;position:absolute;right:10px;top:50%;vertical-align:middle}.open .form-control{border-radius:.25rem .25rem 0 0;border-bottom-color:transparent}.form-control+.input-group-addon{background-color:#fff}.has-success .form-control,.has-success .input-group-addon{border-color:#e3e3e3}.has-success .form-control:focus,.has-success.input-group-focus .input-group-addon{border-color:#1be611}.has-danger .form-control,.has-danger .input-group-addon,.has-danger.input-group-focus .input-group-addon{border-color:#ffcfcf;color:#ff3636;background-color:hsla(0,0%,87%,.1)}.has-danger .form-control:focus,.has-danger .input-group-addon:focus,.has-danger.input-group-focus .input-group-addon:focus{background-color:#fff}.has-danger:after,.has-success:after{font-family:Nucleo Outline;content:"\ea22";display:inline-block;position:absolute;right:20px;bottom:10px;color:#18ce0f;font-size:11px}.has-danger.form-control-lg:after,.has-success.form-control-lg:after{font-size:13px;top:24px}.has-danger.has-label:after,.has-success.has-label:after{top:35px}.has-danger.form-check .form-check-label label,.has-danger.form-check:after,.has-danger .form-control+label,.has-success.form-check .form-check-label label,.has-success.form-check:after,.has-success .form-control+label{display:none!important}.has-danger.form-check .form-check-label,.has-success.form-check .form-check-label{color:#18ce0f}.has-danger:after{content:"\ea53";color:#ff3636}.has-danger.form-check .form-check-label{color:#ff3636}.form-group.no-border.form-control-lg .input-group-addon,.input-group.no-border.form-control-lg .input-group-addon{padding:15px 0 15px 19px}.form-group.no-border.form-control-lg .form-control,.input-group.no-border.form-control-lg .form-control{padding:15px 19px}.form-group.no-border.form-control-lg .form-control+.input-group-addon,.input-group.no-border.form-control-lg .form-control+.input-group-addon{padding:15px 19px 15px 0}.form-group.form-control-lg .form-control,.input-group.form-control-lg .form-control{padding:14px 18px}.form-group.form-control-lg .form-control+.input-group-addon,.input-group.form-control-lg .form-control+.input-group-addon{padding:14px 18px 14px 0}.form-group.form-control-lg .input-group-addon,.input-group.form-control-lg .input-group-addon{padding:14px 0 15px 18px}.form-group.form-control-lg .input-group-addon+.form-control,.input-group.form-control-lg .input-group-addon+.form-control{padding:15px 18px 15px 16px}.form-group.no-border .form-control,.input-group.no-border .form-control{padding:11px 19px}.form-group.no-border .form-control+.input-group-addon,.input-group.no-border .form-control+.input-group-addon{padding:11px 19px 11px 0}.form-group.no-border .input-group-addon,.input-group.no-border .input-group-addon{padding:11px 0 11px 19px}.form-group .form-control,.input-group .form-control{padding:10px 18px}.form-group .form-control+.input-group-addon,.input-group .form-control+.input-group-addon{padding:10px 18px 10px 0}.form-group .input-group-addon,.input-group .input-group-addon{padding:10px 0 10px 18px}.form-group .input-group-addon+.form-control,.form-group .input-group-addon~.form-control,.input-group .input-group-addon+.form-control,.input-group .input-group-addon~.form-control{padding:10px 19px 11px 16px}.form-group.no-border .form-control,.form-group.no-border .form-control+.input-group-addon,.input-group.no-border .form-control,.input-group.no-border .form-control+.input-group-addon{background-color:hsla(0,0%,87%,.3);border:medium none}.form-group.no-border .form-control+.input-group-addon:active,.form-group.no-border .form-control+.input-group-addon:focus,.form-group.no-border .form-control:active,.form-group.no-border .form-control:focus,.input-group.no-border .form-control+.input-group-addon:active,.input-group.no-border .form-control+.input-group-addon:focus,.input-group.no-border .form-control:active,.input-group.no-border .form-control:focus{border:medium none;background-color:hsla(0,0%,87%,.5)}.form-group.no-border .form-control:focus+.input-group-addon,.input-group.no-border .form-control:focus+.input-group-addon{background-color:hsla(0,0%,87%,.5)}.form-group.no-border .input-group-addon,.input-group.no-border .input-group-addon{background-color:hsla(0,0%,87%,.3);border:none}.has-error .control-label,.has-error .form-control-feedback{color:#ff3636}.has-success .control-label,.has-success .form-control-feedback{color:#18ce0f}.input-group-addon{border:1px solid #e3e3e3;border-radius:30px;color:#555;padding:-.5rem 0 -.5rem -.3rem;transition:color .3s ease-in-out,border-color .3s ease-in-out,background-color .3s ease-in-out}.has-danger.input-group-focus .input-group-addon,.has-success .input-group-addon,.input-group-addon{background-color:#fff}.has-danger .form-control:focus+.input-group-addon{color:#ff3636}.has-success .form-control:focus+.input-group-addon{color:#18ce0f}.input-group-addon+.form-control,.input-group-addon~.form-control{padding:-.5rem .7rem;padding-left:18px}.input-group-addon i{width:17px}.input-group-focus .input-group-addon{background-color:#fff;border-color:#f96332}.input-group-focus.no-border .input-group-addon{background-color:hsla(0,0%,87%,.5)}.form-group,.input-group{margin-bottom:10px;position:relative}.form-group .form-control-static,.input-group .form-control-static{margin-top:9px}.input-group[disabled] .input-group-addon{background-color:#e3e3e3}.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:30px;border-top-left-radius:0;border-bottom-left-radius:0;border-left:0 none}.input-group-addon:first-child,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle),.input-group .form-control:first-child{border-right:0 none}.input-group-addon:last-child,.input-group-btn:first-child>.btn:not(:first-child),.input-group-btn:last-child>.dropdown-toggle,.input-group .form-control:last-child{border-left:0 none}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{background-color:#e3e3e3;color:#888;cursor:not-allowed}.input-group-btn .btn{border-width:1px;padding:11px .7rem}.input-group-btn .btn-default:not(.btn-fill){border-color:#ddd}.input-group-btn:last-child>.btn{margin-left:0}textarea.form-control{max-width:100%;max-height:80px;padding:10px 10px 0 0;resize:none;border:none;border-bottom:1px solid #e3e3e3;border-radius:0;line-height:2}textarea.form-control:active,textarea.form-control:focus{border-left:none;border-top:none;border-right:none}.has-danger.form-group .form-control,.has-danger.form-group.no-border .form-control,.has-success.form-group .form-control,.has-success.form-group.no-border .form-control{padding-right:40px}.form.form-newsletter .form-group{float:left;width:78%;margin-right:2%;margin-top:9px}.input-group .input-group-btn{padding:0 12px}.form-group input[type=file]{opacity:0;position:absolute;top:0;right:0;bottom:0;left:0;width:100%;height:100%;z-index:100}.form-text{font-size:.8571em}.form-control-lg{padding:0;font-size:inherit;line-height:0;border-radius:0}.form-horizontal .col-form-label,.form-horizontal .label-on-right{padding:10px 5px 0 15px;text-align:right;max-width:180px}.form-horizontal .checkbox-radios{margin-bottom:15px}.form-horizontal .checkbox-radios .form-check:first-child{margin-top:8px}.form-horizontal .label-on-right{text-align:left;padding:10px 15px 0 5px}.form-horizontal .form-check-inline{margin-top:6px}button,input,optgroup,select,textarea{font-family:Montserrat,Helvetica Neue,Arial,sans-serif}h1,h2,h3,h4,h5,h6{font-weight:400}a,a:focus,a:hover{color:#f96332}.h1,h1{font-size:3.5em;line-height:1.15;margin-bottom:30px}.h1 small,h1 small{font-weight:700;text-transform:uppercase;opacity:.8}.h2,h2{font-size:2.5em}.h2,.h3,h2,h3{margin-bottom:30px}.h3,h3{font-size:2em;line-height:1.4em}.h4,h4{font-size:1.714em;line-height:1.45em;margin-top:30px;margin-bottom:15px}.h4+.category,.h4.title+.category,h4+.category,h4.title+.category{margin-top:-10px}.h5,h5{font-size:1.57em;line-height:1.4em;margin-bottom:15px}.h6,h6{font-size:1em;font-weight:700;text-transform:uppercase}p.description{font-size:1.14em}.title{font-weight:700}.title.title-up{text-transform:uppercase}.title.title-up a{color:#2c2c2c;text-decoration:none}.title+.category{margin-top:-10px}.card-description,.card .footer .stats,.description,.footer-big p{color:#9a9a9a;font-weight:300}.card-category,.category{text-transform:capitalize;font-weight:400;color:#9a9a9a;font-size:.7142em}.card-category{font-size:1em}.text-primary,a.text-primary:focus,a.text-primary:hover{color:#f96332!important}.text-info,a.text-info:focus,a.text-info:hover{color:#2ca8ff!important}.text-success,a.text-success:focus,a.text-success:hover{color:#18ce0f!important}.text-warning,a.text-warning:focus,a.text-warning:hover{color:#ffb236!important}.text-danger,a.text-danger:focus,a.text-danger:hover{color:#ff3636!important}.text-gray,a.text-gray:focus,a.text-gray:hover{color:#e3e3e3!important}.blockquote{border-left:none;border:1px solid #888;padding:20px;font-size:1.1em;line-height:1.8}.blockquote small{color:#888;font-size:.8571em;text-transform:uppercase}.blockquote.blockquote-primary{border-color:#f96332;color:#f96332}.blockquote.blockquote-primary small{color:#f96332}.blockquote.blockquote-danger{border-color:#ff3636;color:#ff3636}.blockquote.blockquote-danger small{color:#ff3636}.blockquote.blockquote-white{border-color:hsla(0,0%,100%,.8);color:#fff}.blockquote.blockquote-white small{color:hsla(0,0%,100%,.8)}body{color:#2c2c2c;font-size:14px;font-family:Montserrat,Helvetica Neue,Arial,sans-serif;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}.main{position:relative;background:#fff}.animation-transition-general,.nav-pills .nav-link,.nav-tabs .nav-link,.navbar,.navbar-collapse .navbar-nav .nav-link,.off-canvas-sidebar .logo a.logo-mini,.off-canvas-sidebar .logo a.logo-normal,.off-canvas-sidebar .navbar-minimize,.off-canvas-sidebar .nav p,.sidebar .logo a.logo-mini,.sidebar .logo a.logo-normal,.sidebar .nav a,.sidebar .nav a i,.sidebar .navbar-minimize,.sidebar .nav p,.tag,.tag [data-role=remove]{transition:all .3s ease 0s}.bootstrap-switch-label:before,.caret,.dropdown-toggle:after{transition:all .15s ease 0s}.card-collapse .card a[data-toggle=collapse].expanded i,.card-collapse .card a[data-toggle=collapse][aria-expanded=true] i,.dropdown-toggle[aria-expanded=true]:after,a[data-toggle=collapse][aria-expanded=true] .caret{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2);-webkit-transform:rotate(180deg);transform:rotate(180deg)}.button-bar{display:block;position:relative;width:22px;height:1px;border-radius:1px;background:#fff}.button-bar+.button-bar{margin-top:7px}.button-bar:nth-child(2){width:17px}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px dashed;border-top:4px solid\9;border-right:4px solid transparent;border-left:4px solid transparent}.form-check{margin-top:.5rem}.form-check .form-check-label{display:inline-block;position:relative;cursor:pointer;padding-left:35px;line-height:26px;margin-bottom:0;transition:color .3s linear}.radio .form-check-sign{padding-left:28px}.form-check .form-check-sign:after,.form-check .form-check-sign:before{content:" ";display:inline-block;position:absolute;width:26px;height:26px;left:0;cursor:pointer;border-radius:3px;top:0;background-color:transparent;border:1px solid #e3e3e3;transition:opacity .3s linear}.form-check .form-check-sign:after{font-family:Nucleo Outline;content:"\ea22";top:0;text-align:center;font-size:14px;opacity:0;color:#555;border:0;background-color:inherit}.form-check.disabled .form-check-label{color:#9a9a9a;opacity:.5;cursor:not-allowed}.form-check input[type=checkbox],.radio input[type=radio]{opacity:0;position:absolute;visibility:hidden}.form-check input[type=checkbox]:checked+.form-check-sign:after{opacity:1}.checkbox input[type=checkbox]:disabled+.form-check-sign:after,.form-control input[type=checkbox]:disabled+.form-check-sign:before{cursor:not-allowed}.form-check input[type=checkbox]:disabled+.form-check-sign,.form-check input[type=radio]:disabled+.form-check-sign{pointer-events:none}.form-check-radio .form-check-sign:after,.form-check-radio .form-check-sign:before{content:" ";width:20px;height:20px;border-radius:50%;border:1px solid #e3e3e3;display:inline-block;position:absolute;left:3px;top:3px;padding:1px;transition:opacity .3s linear}.form-check-radio input[type=radio],.form-check-radio input[type=radio]+.form-check-sign:after{opacity:0}.form-check-radio input[type=radio]:checked+.form-check-sign:after{width:4px;height:4px;background-color:#555;border-color:#555;top:11px;left:11px;opacity:1}.form-check-radio input[type=radio]:disabled+.form-check-sign,.form-check-radio input[type=radio]:disabled+.form-check-sign:after,.form-check-radio input[type=radio]:disabled+.form-check-sign:before{color:#9a9a9a}.navbar{padding-top:.625rem;padding-bottom:.625rem;min-height:53px;margin-bottom:20px;box-shadow:0 0 20px 0 rgba(0,0,0,.15)}.navbar a{vertical-align:middle}.navbar a:not(.btn):not(.dropdown-item){color:#fff}.navbar.bg-white .input-group .form-control,.navbar.bg-white .input-group.no-border .form-control,.navbar a.dropdown-item{color:#888}.navbar.bg-white .input-group .form-control::-moz-placeholder,.navbar.bg-white .input-group.no-border .form-control::-moz-placeholder{color:#888}.navbar.bg-white .input-group .form-control:-ms-input-placeholder,.navbar.bg-white .input-group.no-border .form-control:-ms-input-placeholder{color:#888}.navbar.bg-white .input-group .form-control::-webkit-input-placeholder,.navbar.bg-white .input-group.no-border .form-control::-webkit-input-placeholder{color:#888}.navbar.bg-white .input-group-addon i{color:#888;opacity:.5}.navbar .form-group,.navbar .input-group{margin:0;margin-left:-3px;margin-right:5px}.navbar .form-group .form-group-addon,.navbar .form-group .input-group-addon,.navbar .form-group.no-border .form-control,.navbar .input-group .form-group-addon,.navbar .input-group .input-group-addon,.navbar .input-group.no-border .form-control{color:#fff}.navbar .form-group.no-border .form-control::-moz-placeholder,.navbar .input-group.no-border .form-control::-moz-placeholder{color:#fff}.navbar .form-group.no-border .form-control:-ms-input-placeholder,.navbar .input-group.no-border .form-control:-ms-input-placeholder{color:#fff}.navbar .form-group.no-border .form-control::-webkit-input-placeholder,.navbar .input-group.no-border .form-control::-webkit-input-placeholder{color:#fff}.navbar p{display:inline-block;margin:0;line-height:1.8em;font-size:1em;font-weight:400}.navbar.navbar-absolute{position:absolute;width:100%;padding-top:10px;z-index:1029}.documentation .navbar.fixed-top{left:0;width:auto}.navbar .navbar-wrapper{display:inline-flex;align-items:center}.navbar .navbar-wrapper .navbar-minimize{padding-right:10px}.navbar .navbar-wrapper .navbar-minimize .btn{margin:0}.navbar .navbar-wrapper .navbar-toggle .navbar-toggler{padding-left:0}.navbar .navbar-wrapper .navbar-toggle:hover .navbar-toggler-bar.bar2{width:22px}.navbar .navbar-nav.navbar-logo{position:absolute;left:0;right:0;margin:0 auto;width:49px;top:-4px}.navbar .navbar-nav .nav-link.btn{padding:11px 22px}.navbar .navbar-nav .nav-link.btn.btn-lg{padding:15px 48px}.navbar .navbar-nav .nav-link.btn.btn-sm{padding:5px 15px}.navbar .navbar-nav .nav-link{text-transform:uppercase;font-size:.7142em;padding:.5rem .7rem;line-height:1.625rem;margin-right:3px}.navbar .navbar-nav .nav-link i.fa+p,.navbar .navbar-nav .nav-link i.now-ui-icons+p{margin-left:3px}.navbar .navbar-nav .nav-link i.fa,.navbar .navbar-nav .nav-link i.now-ui-icons{font-size:18px;position:relative;top:3px;text-align:center;width:21px}.navbar .navbar-nav .nav-link i.now-ui-icons{top:4px;font-size:16px}.navbar .navbar-nav .nav-link.profile-photo .profile-photo-small{width:27px;height:27px}.navbar .navbar-nav .nav-link.disabled{opacity:.5;color:#fff}.navbar .navbar-nav .nav-item.active .nav-link:not(.btn),.navbar .navbar-nav .nav-item .nav-link:not(.btn):active,.navbar .navbar-nav .nav-item .nav-link:not(.btn):focus,.navbar .navbar-nav .nav-item .nav-link:not(.btn):hover{background-color:hsla(0,0%,100%,.2);border-radius:.1875rem;color:#fff}.navbar .logo-container{width:27px;height:27px;overflow:hidden;margin:0 auto;border-radius:50%;border:1px solid transparent}.navbar .navbar-brand{text-transform:uppercase;font-size:.8571em;padding-top:.5rem;padding-bottom:.5rem;line-height:1.625rem}.navbar .navbar-toggler{width:37px;height:27px;vertical-align:middle;outline:0;cursor:pointer}.navbar .navbar-toggler .navbar-toggler-bar.navbar-kebab{width:3px;height:3px;border-radius:50%;margin:0 auto}.navbar .button-dropdown .navbar-toggler-bar:nth-child(2){width:17px}.navbar.navbar-transparent{background-color:transparent!important;box-shadow:none;color:#fff}.navbar.bg-white:not(.navbar-transparent) a:not(.dropdown-item):not(.btn){color:#888}.navbar.bg-white:not(.navbar-transparent) a:not(.dropdown-item):not(.btn).disabled{opacity:.5;color:#888}.navbar.bg-white:not(.navbar-transparent) .button-bar{background:#888}.navbar.bg-white:not(.navbar-transparent) .nav-item.active .nav-link:not(.btn),.navbar.bg-white:not(.navbar-transparent) .nav-item .nav-link:not(.btn):active,.navbar.bg-white:not(.navbar-transparent) .nav-item .nav-link:not(.btn):focus,.navbar.bg-white:not(.navbar-transparent) .nav-item .nav-link:not(.btn):hover{background-color:hsla(0,0%,87%,.8);color:#888}.navbar.bg-white:not(.navbar-transparent) .logo-container{border:1px solid #888}.bg-default{background-color:#888!important}.bg-primary{background-color:#f96332!important}.bg-info{background-color:#2ca8ff!important}.bg-success{background-color:#18ce0f!important}.bg-danger{background-color:#ff3636!important}.bg-warning{background-color:#ffb236!important}.bg-white{background-color:#fff!important}.page-header{min-height:100vh;max-height:999px;padding:0;color:#fff;position:relative}.page-header .page-header-image{position:absolute;background-size:cover;background-position:50%;width:100%;height:100%;z-index:-1}.page-header .content-center{position:absolute;top:50%;left:50%;z-index:2;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);text-align:center;color:#fff;padding:0 15px;width:100%;max-width:880px}.page-header footer{position:absolute;bottom:0;width:100%}.page-header .container{height:100%;z-index:1}.page-header .category,.page-header .description{color:hsla(0,0%,100%,.8)}.page-header.page-header-small{min-height:60vh;max-height:440px}.page-header.page-header-mini{min-height:40vh;max-height:340px}.page-header .title{margin-bottom:15px}.page-header .title+h4{margin-top:10px}.page-header:after,.page-header:before{position:absolute;z-index:0;width:100%;height:100%;display:block;left:0;top:0;content:""}.page-header:before{background-color:rgba(0,0,0,.3)}.page-header[filter-color=orange]{background:rgba(44,44,44,.2);background:linear-gradient(0deg,rgba(44,44,44,.2),rgba(224,23,3,.6))}.dropdown-menu{border:0;box-shadow:0 10px 50px 0 rgba(0,0,0,.2);border-radius:.125rem;transition:all .15s linear;font-size:14px}.dropdown-menu.dropdown-menu-right:before{left:auto;right:10px}.dropdown-menu i{margin-right:5px;position:relative;top:1px}.dropdown-menu .now-ui-icons{margin-right:10px;position:relative;top:4px;font-size:18px;margin-top:-5px;opacity:.5}.dropdown-menu .dropdown-item.active,.dropdown-menu .dropdown-item:active{color:inherit}.dropup .dropdown-menu:before{display:none}.dropup .dropdown-menu:after{display:inline-block;position:absolute;width:0;height:0;vertical-align:middle;content:"";top:auto;bottom:-5px;right:auto;left:10px;color:#fff;border-top:.4em solid;border-right:.4em solid transparent;border-left:.4em solid transparent}.dropup .dropdown-menu.dropdown-menu-right:after{right:10px;left:auto}.dropdown-menu:before{display:inline-block;position:absolute;width:0;height:0;vertical-align:middle;content:"";top:-5px;left:10px;right:auto;color:#fff;border-bottom:.4em solid;border-right:.4em solid transparent;border-left:.4em solid transparent}.dropdown-menu.dropdown-menu-right{right:0!important;left:auto!important}.bootstrap-select .dropdown-menu.inner li a,.dropdown-menu .dropdown-item{font-size:.8571em;padding-top:.6rem;padding-bottom:.6rem;margin-top:5px;transition:all .15s linear}.bootstrap-select .dropdown-menu.inner li a:focus,.bootstrap-select .dropdown-menu.inner li a:hover,.dropdown-menu .dropdown-item:focus,.dropdown-menu .dropdown-item:hover{background-color:hsla(0,0%,87%,.3)}.bootstrap-select .dropdown-menu.inner li a.disabled,.bootstrap-select .dropdown-menu.inner li a:disabled,.dropdown-menu .dropdown-item.disabled,.dropdown-menu .dropdown-item:disabled{color:hsla(0,0%,71%,.6)}.bootstrap-select .dropdown-menu.inner li a.disabled:focus,.bootstrap-select .dropdown-menu.inner li a.disabled:hover,.bootstrap-select .dropdown-menu.inner li a:disabled:focus,.bootstrap-select .dropdown-menu.inner li a:disabled:hover,.dropdown-menu .dropdown-item.disabled:focus,.dropdown-menu .dropdown-item.disabled:hover,.dropdown-menu .dropdown-item:disabled:focus,.dropdown-menu .dropdown-item:disabled:hover{background-color:transparent}.dropdown-menu .dropdown-divider{background-color:hsla(0,0%,87%,.5)}.dropdown-menu .dropdown-header:not([href]):not([tabindex]){color:hsla(0,0%,71%,.6);font-size:.7142em;text-transform:uppercase;font-weight:700}.dropdown-menu.dropdown-primary{background-color:#f95823}.dropdown-menu.dropdown-primary:before{color:#f95823}.dropdown-menu.dropdown-primary .dropdown-header:not([href]):not([tabindex]){color:hsla(0,0%,100%,.8)}.dropdown-menu.dropdown-primary .dropdown-item{color:#fff}.dropdown-menu.dropdown-primary .dropdown-divider,.dropdown-menu.dropdown-primary .dropdown-item:focus,.dropdown-menu.dropdown-primary .dropdown-item:hover{background-color:hsla(0,0%,100%,.2)}.dropdown-menu.dropdown-info{background-color:#1da2ff}.dropdown-menu.dropdown-info:before{color:#1da2ff}.dropdown-menu.dropdown-info .dropdown-header:not([href]):not([tabindex]){color:hsla(0,0%,100%,.8)}.dropdown-menu.dropdown-info .dropdown-item{color:#fff}.dropdown-menu.dropdown-info .dropdown-divider,.dropdown-menu.dropdown-info .dropdown-item:focus,.dropdown-menu.dropdown-info .dropdown-item:hover{background-color:hsla(0,0%,100%,.2)}.dropdown-menu.dropdown-danger{background-color:#ff2727}.dropdown-menu.dropdown-danger:before{color:#ff2727}.dropdown-menu.dropdown-danger .dropdown-header:not([href]):not([tabindex]){color:hsla(0,0%,100%,.8)}.dropdown-menu.dropdown-danger .dropdown-item{color:#fff}.dropdown-menu.dropdown-danger .dropdown-divider,.dropdown-menu.dropdown-danger .dropdown-item:focus,.dropdown-menu.dropdown-danger .dropdown-item:hover{background-color:hsla(0,0%,100%,.2)}.dropdown-menu.dropdown-success{background-color:#16c00e}.dropdown-menu.dropdown-success:before{color:#16c00e}.dropdown-menu.dropdown-success .dropdown-header:not([href]):not([tabindex]){color:hsla(0,0%,100%,.8)}.dropdown-menu.dropdown-success .dropdown-item{color:#fff}.dropdown-menu.dropdown-success .dropdown-divider,.dropdown-menu.dropdown-success .dropdown-item:focus,.dropdown-menu.dropdown-success .dropdown-item:hover{background-color:hsla(0,0%,100%,.2)}.dropdown-menu.dropdown-warning{background-color:#ffac27}.dropdown-menu.dropdown-warning:before{color:#ffac27}.dropdown-menu.dropdown-warning .dropdown-header:not([href]):not([tabindex]){color:hsla(0,0%,100%,.8)}.dropdown-menu.dropdown-warning .dropdown-item{color:#fff}.dropdown-menu.dropdown-warning .dropdown-divider,.dropdown-menu.dropdown-warning .dropdown-item:focus,.dropdown-menu.dropdown-warning .dropdown-item:hover{background-color:hsla(0,0%,100%,.2)}.bootstrap-select .dropdown-menu:not(.inner),.dropdown-menu.bootstrap-datetimepicker-widget.bottom,.dropdown-menu.bootstrap-datetimepicker-widget.top,.dropdown .dropdown-menu,.dropup:not(.bootstrap-select) .dropdown-menu{-webkit-transform:translate3d(0,-20px,0)!important;transform:translate3d(0,-20px,0)!important;visibility:hidden;display:block;opacity:0;filter:alpha(opacity=0);top:100%!important}.dropdown-menu.bootstrap-datetimepicker-widget.bottom,.dropdown-menu.bootstrap-datetimepicker-widget.top{-webkit-transform:translate3d(0,-20px,0)!important;transform:translate3d(0,-20px,0)!important}.bootstrap-select.dropup .dropdown-menu:not(.inner){-webkit-transform:translate3d(0,25px,0)!important;transform:translate3d(0,25px,0)!important}.dropup:not(.bootstrap-select) .dropdown-menu{-webkit-transform:translate3d(0,20px,0)!important;transform:translate3d(0,20px,0)!important;top:auto!important;bottom:100%}.bootstrap-select.show .dropdown-menu:not(.inner),.dropdown-menu.bootstrap-datetimepicker-widget.bottom.open,.dropdown-menu.bootstrap-datetimepicker-widget.top.open,.dropdown.show .dropdown-menu,.dropup.show:not(.bootstrap-select) .dropdown-menu,.navbar .dropdown.show .dropdown-menu{opacity:1;filter:alpha(opacity=100);visibility:visible;-webkit-transform:translate3d(0,1px,0)!important;transform:translate3d(0,1px,0)!important}.dropdown-menu.bootstrap-datetimepicker-widget.bottom.open,.dropdown-menu.bootstrap-datetimepicker-widget.top.open{-webkit-transform:translateZ(0)!important;transform:translateZ(0)!important}.dropup.show:not(.bootstrap-select) .dropdown-menu{-webkit-transform:translate3d(0,-2px,0)!important;transform:translate3d(0,-2px,0)!important}.button-dropdown{padding-right:.7rem;cursor:pointer}.button-dropdown .dropdown-toggle{padding-top:.5rem;padding-bottom:.5rem;display:block}.button-dropdown .dropdown-toggle:after{display:none}.alert{border:0;border-radius:.1875rem;color:#fff;padding-top:.9rem;padding-bottom:.9rem;position:relative}.alert.alert-success{background-color:#1be611}.alert.alert-danger{background-color:#ff5050}.alert.alert-warning{background-color:#ffbc50}.alert.alert-info{background-color:#46b3ff}.alert.alert-primary{background-color:#fa764b}.alert i.fa,.alert i.now-ui-icons{font-size:20px}.alert .close{color:#fff;opacity:.9;text-shadow:none;line-height:0;outline:0}.alert span[data-notify=icon]{font-size:22px;display:block;left:19px;position:absolute;top:50%;margin-top:-11px}.alert button.close{position:absolute;right:10px;top:50%;margin-top:-13px;width:25px;height:25px;padding:3px}.alert .close~span{display:block;max-width:89%}.alert.alert-with-icon{padding-left:65px}img{max-width:100%;border-radius:.1875rem}.img-raised{box-shadow:0 10px 25px 0 rgba(0,0,0,.3)}@font-face{font-family:Nucleo Outline;src:url(../fonts/nucleo-outline.eot);src:url(../fonts/nucleo-outline.eot) format("embedded-opentype"),url(../fonts/nucleo-outline.woff2) format("woff2"),url(../fonts/nucleo-outline.woff) format("woff"),url(../fonts/nucleo-outline.ttf) format("truetype"),url(../fonts/nucleo-outline.svg) format("svg");font-weight:400;font-style:normal}.now-ui-icons{display:inline-block;font:normal normal normal 14px/1 Nucleo Outline;font-size:inherit;speak:none;text-transform:none;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.now-ui-icons.circle{padding:.33333333em;vertical-align:-16%;background-color:#eee;border-radius:50%}.nc-icon-ul{padding-left:0;margin-left:2.14285714em;list-style-type:none}.nc-icon-ul>li{position:relative}.nc-icon-ul>li>.now-ui-icons{position:absolute;left:-1.57142857em;top:.14285714em;text-align:center}.nc-icon-ul>li>.now-ui-icons.circle{top:-.19047619em;left:-1.9047619em}.now-ui-icons.spin{-webkit-animation:f 2s infinite linear;animation:f 2s infinite linear}@-webkit-keyframes f{0%{-webkit-transform:rotate(0deg)}to{-webkit-transform:rotate(1turn)}}@keyframes f{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}.now-ui-icons.ui-1_check:before{content:"\ea22"}.now-ui-icons.ui-1_email-85:before{content:"\ea2a"}.now-ui-icons.arrows-1_cloud-download-93:before{content:"\ea21"}.now-ui-icons.arrows-1_cloud-upload-94:before{content:"\ea24"}.now-ui-icons.arrows-1_minimal-down:before{content:"\ea39"}.now-ui-icons.arrows-1_minimal-left:before{content:"\ea3a"}.now-ui-icons.arrows-1_minimal-right:before{content:"\ea3b"}.now-ui-icons.arrows-1_minimal-up:before{content:"\ea3c"}.now-ui-icons.arrows-1_refresh-69:before{content:"\ea44"}.now-ui-icons.arrows-1_share-66:before{content:"\ea4c"}.now-ui-icons.business_badge:before{content:"\ea09"}.now-ui-icons.business_bank:before{content:"\ea0a"}.now-ui-icons.business_briefcase-24:before{content:"\ea13"}.now-ui-icons.business_bulb-63:before{content:"\ea15"}.now-ui-icons.business_chart-bar-32:before{content:"\ea1e"}.now-ui-icons.business_chart-pie-36:before{content:"\ea1f"}.now-ui-icons.business_globe:before{content:"\ea2f"}.now-ui-icons.business_money-coins:before{content:"\ea40"}.now-ui-icons.clothes_tie-bow:before{content:"\ea5b"}.now-ui-icons.design_vector:before{content:"\ea61"}.now-ui-icons.design_app:before{content:"\ea08"}.now-ui-icons.design_bullet-list-67:before{content:"\ea14"}.now-ui-icons.design_image:before{content:"\ea33"}.now-ui-icons.design_palette:before{content:"\ea41"}.now-ui-icons.design_scissors:before{content:"\ea4a"}.now-ui-icons.design-2_html5:before{content:"\ea32"}.now-ui-icons.design-2_ruler-pencil:before{content:"\ea48"}.now-ui-icons.emoticons_satisfied:before{content:"\ea49"}.now-ui-icons.files_box:before{content:"\ea12"}.now-ui-icons.files_paper:before{content:"\ea43"}.now-ui-icons.files_single-copy-04:before{content:"\ea52"}.now-ui-icons.health_ambulance:before{content:"\ea07"}.now-ui-icons.loader_gear:before{content:"\ea4e"}.now-ui-icons.loader_refresh:before{content:"\ea44"}.now-ui-icons.location_bookmark:before{content:"\ea10"}.now-ui-icons.location_compass-05:before{content:"\ea25"}.now-ui-icons.location_map-big:before{content:"\ea3d"}.now-ui-icons.location_pin:before{content:"\ea47"}.now-ui-icons.location_world:before{content:"\ea63"}.now-ui-icons.media-1_album:before{content:"\ea02"}.now-ui-icons.media-1_button-pause:before{content:"\ea16"}.now-ui-icons.media-1_button-play:before{content:"\ea18"}.now-ui-icons.media-1_button-power:before{content:"\ea19"}.now-ui-icons.media-1_camera-compact:before{content:"\ea1c"}.now-ui-icons.media-2_note-03:before{content:"\ea3f"}.now-ui-icons.media-2_sound-wave:before{content:"\ea57"}.now-ui-icons.objects_diamond:before{content:"\ea29"}.now-ui-icons.objects_globe:before{content:"\ea2f"}.now-ui-icons.objects_key-25:before{content:"\ea38"}.now-ui-icons.objects_planet:before{content:"\ea46"}.now-ui-icons.objects_spaceship:before{content:"\ea55"}.now-ui-icons.objects_support-17:before{content:"\ea56"}.now-ui-icons.objects_umbrella-13:before{content:"\ea5f"}.now-ui-icons.education_agenda-bookmark:before{content:"\ea01"}.now-ui-icons.education_atom:before{content:"\ea0c"}.now-ui-icons.education_glasses:before{content:"\ea2d"}.now-ui-icons.education_hat:before{content:"\ea30"}.now-ui-icons.education_paper:before{content:"\ea42"}.now-ui-icons.shopping_bag-16:before{content:"\ea0d"}.now-ui-icons.shopping_basket:before{content:"\ea0b"}.now-ui-icons.shopping_box:before{content:"\ea11"}.now-ui-icons.shopping_cart-simple:before{content:"\ea1d"}.now-ui-icons.shopping_credit-card:before{content:"\ea28"}.now-ui-icons.shopping_delivery-fast:before{content:"\ea27"}.now-ui-icons.shopping_shop:before{content:"\ea50"}.now-ui-icons.shopping_tag-content:before{content:"\ea59"}.now-ui-icons.sport_trophy:before{content:"\ea5d"}.now-ui-icons.sport_user-run:before{content:"\ea60"}.now-ui-icons.tech_controller-modern:before{content:"\ea26"}.now-ui-icons.tech_headphones:before{content:"\ea31"}.now-ui-icons.tech_laptop:before{content:"\ea36"}.now-ui-icons.tech_mobile:before{content:"\ea3e"}.now-ui-icons.tech_tablet:before{content:"\ea58"}.now-ui-icons.tech_tv:before{content:"\ea5e"}.now-ui-icons.tech_watch-time:before{content:"\ea62"}.now-ui-icons.text_align-center:before{content:"\ea05"}.now-ui-icons.text_align-left:before{content:"\ea06"}.now-ui-icons.text_bold:before{content:"\ea0e"}.now-ui-icons.text_caps-small:before{content:"\ea1b"}.now-ui-icons.gestures_tap-01:before{content:"\ea5a"}.now-ui-icons.transportation_air-baloon:before{content:"\ea03"}.now-ui-icons.transportation_bus-front-12:before{content:"\ea17"}.now-ui-icons.travel_info:before{content:"\ea04"}.now-ui-icons.travel_istanbul:before{content:"\ea34"}.now-ui-icons.ui-1_bell-53:before{content:"\ea0f"}.now-ui-icons.ui-1_calendar-60:before{content:"\ea1a"}.now-ui-icons.ui-1_lock-circle-open:before{content:"\ea35"}.now-ui-icons.ui-1_send:before{content:"\ea4d"}.now-ui-icons.ui-1_settings-gear-63:before{content:"\ea4e"}.now-ui-icons.ui-1_simple-add:before{content:"\ea4f"}.now-ui-icons.ui-1_simple-delete:before{content:"\ea54"}.now-ui-icons.ui-1_simple-remove:before{content:"\ea53"}.now-ui-icons.ui-1_zoom-bold:before{content:"\ea64"}.now-ui-icons.ui-2_chat-round:before{content:"\ea20"}.now-ui-icons.ui-2_favourite-28:before{content:"\ea2b"}.now-ui-icons.ui-2_like:before{content:"\ea37"}.now-ui-icons.ui-2_settings-90:before{content:"\ea4b"}.now-ui-icons.ui-2_time-alarm:before{content:"\ea5c"}.now-ui-icons.users_circle-08:before{content:"\ea23"}.now-ui-icons.users_single-02:before{content:"\ea51"}.all-icons .font-icon-detail{text-align:center;padding:45px 0 30px;border:1px solid #e5e5e5;border-radius:.1875rem;margin:15px 0;min-height:168px}.all-icons [class*=now-ui-icons]{font-size:32px}.all-icons .font-icon-detail p{margin:25px auto 0;width:100%;text-align:center;display:block;color:#b8b8b8;padding:0 10px;font-size:.7142em}.table .img-wrapper{width:40px;height:40px;border-radius:50%;overflow:hidden;margin:0 auto}.table .img-row{max-width:60px;width:60px}.table .form-check{margin:0}.table .form-check label .form-check-sign:after,.table .form-check label .form-check-sign:before{top:-17px;left:4px}.table .btn{margin:0}.table .small,.table small{font-weight:300}.card-tasks .card-body .table{margin-bottom:0}.card-tasks .card-body .table>tbody>tr>td,.card-tasks .card-body .table>tbody>tr>th,.card-tasks .card-body .table>tfoot>tr>td,.card-tasks .card-body .table>tfoot>tr>th,.card-tasks .card-body .table>thead>tr>td,.card-tasks .card-body .table>thead>tr>th{padding-top:0;padding-bottom:0}.table>thead>tr>th{border-bottom-width:1px;font-size:1.45em;font-weight:300;border:0}.table .checkbox,.table .radio{margin-top:0;margin-bottom:0;padding:0;width:15px}.table .checkbox .icons,.table .radio .icons{position:relative}.table .checkbox label:after,.table .checkbox label:before,.table .radio label:after,.table .radio label:before{top:-17px;left:-3px}.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:12px 7px;vertical-align:middle}.table .th-description{max-width:150px}.table .td-price{font-size:26px;font-weight:300;margin-top:5px;position:relative;top:4px;text-align:right}.table .td-total{font-weight:700;font-size:1.57em;padding-top:20px;text-align:right}.table .td-actions .btn{margin:0}.table>tbody>tr{position:relative}.table-shopping>thead>tr>th{font-size:1em;text-transform:uppercase}.table-shopping>tbody>tr>td{font-size:1em}.table-shopping>tbody>tr>td b{display:block;margin-bottom:5px}.table-shopping .td-name{font-weight:400;font-size:1.5em}.table-shopping .td-name small{color:#9a9a9a;font-size:.75em;font-weight:300}.table-shopping .td-number{font-weight:300;font-size:1.714em}.table-shopping .td-name{min-width:200px}.table-shopping .td-number{text-align:right;min-width:145px}.table-shopping .td-number small{margin-right:3px}.table-shopping .img-container{width:120px;max-height:160px;overflow:hidden;display:block}.table-shopping .img-container img{width:100%}#tables .table-responsive{margin-bottom:30px}.wrapper{position:relative;top:0;height:100vh}.wrapper.wrapper-full-page{min-height:100vh;height:auto}.off-canvas-sidebar,.sidebar{position:fixed;top:0;height:100%;bottom:0;width:260px;left:0;z-index:1030}.off-canvas-sidebar .sidebar-wrapper,.sidebar .sidebar-wrapper{position:relative;height:calc(100vh - 75px);overflow:auto;width:260px;z-index:4;padding-bottom:100px}.off-canvas-sidebar .sidebar-wrapper .dropdown .dropdown-backdrop,.sidebar .sidebar-wrapper .dropdown .dropdown-backdrop{display:none!important}.off-canvas-sidebar .sidebar-wrapper .navbar-form,.sidebar .sidebar-wrapper .navbar-form{border:none}.off-canvas-sidebar .navbar-minimize,.sidebar .navbar-minimize{position:absolute;right:20px;top:2px;opacity:1}.off-canvas-sidebar .nav,.sidebar .nav{margin-top:20px;display:block}.off-canvas-sidebar .nav .caret,.sidebar .nav .caret{top:14px;position:absolute;right:10px}.off-canvas-sidebar .nav li>a+div .nav li>a,.sidebar .nav li>a+div .nav li>a{margin-top:7px}.off-canvas-sidebar .nav li>a,.sidebar .nav li>a{margin:10px 15px 0;border-radius:30px;color:#fff;display:block;text-decoration:none;position:relative;text-transform:uppercase;cursor:pointer;font-size:.7142em;padding:10px 8px;line-height:1.625rem}.off-canvas-sidebar .nav li:first-child>a,.sidebar .nav li:first-child>a{margin:0 15px}.off-canvas-sidebar .nav li:focus:not(.active)>a,.off-canvas-sidebar .nav li:hover:not(.active)>a,.sidebar .nav li:focus:not(.active)>a,.sidebar .nav li:hover:not(.active)>a{background-color:hsla(0,0%,100%,.1)}.off-canvas-sidebar .nav li:focus:not(.active)>a i,.off-canvas-sidebar .nav li:hover:not(.active)>a i,.sidebar .nav li:focus:not(.active)>a i,.sidebar .nav li:hover:not(.active)>a i{color:#fff}.off-canvas-sidebar .nav li.active>a,.sidebar .nav li.active>a{background-color:#fff;box-shadow:0 1px 15px 1px rgba(39,39,39,.1)}.off-canvas-sidebar .nav p,.sidebar .nav p{margin:0;line-height:30px;position:relative;display:block;height:auto;white-space:nowrap}.off-canvas-sidebar .nav i,.sidebar .nav i{font-size:20px;float:left;margin-right:12px;line-height:30px;width:34px;text-align:center;color:hsla(0,0%,100%,.5);position:relative}.off-canvas-sidebar .sidebar-background,.sidebar .sidebar-background{position:absolute;z-index:1;height:100%;width:100%;display:block;top:0;left:0;background-size:cover;background-position:50%}.off-canvas-sidebar .sidebar-background:after,.sidebar .sidebar-background:after{position:absolute;z-index:3;width:100%;height:100%;content:"";display:block;background:#fff;opacity:1}.off-canvas-sidebar .logo,.sidebar .logo{position:relative;padding:.5rem .7rem;z-index:4}.off-canvas-sidebar .logo a.logo-mini,.sidebar .logo a.logo-mini{opacity:1;float:left;width:34px;text-align:center;margin-left:10px;margin-right:12px}.off-canvas-sidebar .logo a.logo-normal,.sidebar .logo a.logo-normal{display:block;opacity:1;-webkit-transform:translateZ(0);transform:translateZ(0)}.off-canvas-sidebar .logo:after,.sidebar .logo:after{content:"";position:absolute;bottom:0;right:15px;height:1px;width:calc(100% - 30px);background-color:hsla(0,0%,100%,.5)}.off-canvas-sidebar .logo p,.sidebar .logo p{float:left;font-size:20px;margin:10px;color:#fff;line-height:20px;font-family:Helvetica Neue,Helvetica,Arial,sans-serif}.off-canvas-sidebar .logo .simple-text,.sidebar .logo .simple-text{text-transform:uppercase;padding:.5rem 0;display:block;white-space:nowrap;font-size:1em;color:#fff;text-decoration:none;font-weight:400;line-height:30px;overflow:hidden}.off-canvas-sidebar .logo-tim,.sidebar .logo-tim{border-radius:50%;border:1px solid #333;display:block;height:61px;width:61px;float:left;overflow:hidden}.off-canvas-sidebar .logo-tim img,.sidebar .logo-tim img{width:60px;height:60px}.off-canvas-sidebar:after,.off-canvas-sidebar:before,.sidebar:after,.sidebar:before{display:block;content:"";opacity:1;position:absolute;width:100%;height:100%;top:0;left:0}.off-canvas-sidebar:after,.sidebar:after{background:#888;background:linear-gradient(#888,#000 80%);z-index:3}.off-canvas-sidebar[data-color=blue]:after,.sidebar[data-color=blue]:after{background:#2ca8ff}.off-canvas-sidebar[data-color=blue] .nav li.active>a,.off-canvas-sidebar[data-color=blue] .nav li.active>a i,.sidebar[data-color=blue] .nav li.active>a,.sidebar[data-color=blue] .nav li.active>a i{color:#2ca8ff}.off-canvas-sidebar[data-color=green]:after,.sidebar[data-color=green]:after{background:#18ce0f}.off-canvas-sidebar[data-color=green] .nav li.active>a,.off-canvas-sidebar[data-color=green] .nav li.active>a i,.sidebar[data-color=green] .nav li.active>a,.sidebar[data-color=green] .nav li.active>a i{color:#18ce0f}.off-canvas-sidebar[data-color=orange]:after,.sidebar[data-color=orange]:after{background:#f96332}.off-canvas-sidebar[data-color=orange] .nav li.active>a,.off-canvas-sidebar[data-color=orange] .nav li.active>a i,.sidebar[data-color=orange] .nav li.active>a,.sidebar[data-color=orange] .nav li.active>a i{color:#f96332}.off-canvas-sidebar[data-color=red]:after,.sidebar[data-color=red]:after{background:#ff3636}.off-canvas-sidebar[data-color=red] .nav li.active>a,.off-canvas-sidebar[data-color=red] .nav li.active>a i,.sidebar[data-color=red] .nav li.active>a,.sidebar[data-color=red] .nav li.active>a i{color:#ff3636}.off-canvas-sidebar[data-color=yellow]:after,.sidebar[data-color=yellow]:after{background:#ffb236}.off-canvas-sidebar[data-color=yellow] .nav li.active>a,.off-canvas-sidebar[data-color=yellow] .nav li.active>a i,.sidebar[data-color=yellow] .nav li.active>a,.sidebar[data-color=yellow] .nav li.active>a i{color:#ffb236}.visible-on-sidebar-regular{display:inline-block!important}.visible-on-sidebar-mini{display:none!important}.off-canvas-sidebar .nav>li>a,.off-canvas-sidebar .nav>li>a:hover{color:#fff}.off-canvas-sidebar .nav>li>a:focus{background:hsla(0,0%,78%,.2)}.main-panel{position:relative;float:right;width:calc(100% - 260px);background-color:#e3e3e3;background-color:#ebecf1;transition:all .5s cubic-bezier(.685,.0473,.346,1)}.main-panel>.content{padding:0 30px 30px;min-height:calc(100vh - 123px);margin-top:-30px}.main-panel>.navbar{margin-bottom:0}.main-panel .header{margin-bottom:50px}.perfect-scrollbar-on .main-panel,.perfect-scrollbar-on .sidebar{height:100%;max-height:100%}@media (min-width:991px){.sidebar{display:block;box-shadow:0 2px 22px 0 rgba(0,0,0,.2),0 2px 30px 0 rgba(0,0,0,.35)}}.panel-header{height:260px;padding-top:80px;padding-bottom:45px;background:#141e30;background:linear-gradient(90deg,#0c2646 0,#204065 60%,#2a5788);position:relative;overflow:hidden}.panel-header .header .title{color:#fff}.panel-header .header .category{max-width:600px;color:hsla(0,0%,100%,.5);margin:0 auto;font-size:13px}.panel-header .header .category a{color:#fff}.panel-header-sm{height:135px}.panel-header-lg{height:380px}.card{border:0;border-radius:.1875rem;display:inline-block;position:relative;width:100%;margin-bottom:20px;box-shadow:0 1px 15px 1px rgba(39,39,39,.1)}.card .card-body{padding:15px 15px 10px}.card .card-body.table-full-width{padding-left:0;padding-right:0}.card .card-header{padding:15px 15px 0;border:0}.card .card-header:not([data-background-color]){background-color:transparent}.card .card-header .card-title{margin-top:10px}.card .map{height:500px;border-radius:.1875rem}.card .map.map-big{height:400px}.card[data-background-color=orange],.card[data-background-color=orange] .card-header{background-color:#f96332}.card[data-background-color=orange] .card-footer .stats{color:#fff}.card[data-background-color=red]{background-color:#ff3636}.card[data-background-color=yellow]{background-color:#ffb236}.card[data-background-color=blue]{background-color:#2ca8ff}.card[data-background-color=green]{background-color:#18ce0f}.card .image{overflow:hidden;height:200px;position:relative}.card .avatar{width:30px;height:30px;overflow:hidden;border-radius:50%;margin-bottom:15px}.card label{font-size:.8571em;margin-bottom:5px;color:#9a9a9a}.card .card-footer{background-color:transparent;border:0}.card .card-footer .stats i{margin-right:5px;position:relative;top:2px}.card .card-footer .btn{margin:0}.card-user .image{height:120px}.card-user .author{text-align:center;text-transform:none;margin-top:-77px}.card-user .author a+p.description{margin-top:-7px}.card-user .avatar{width:124px;height:124px;border:1px solid #fff;position:relative}.card-user .card-body{min-height:240px}.card-user hr{margin:5px 15px}.card-user .button-container{margin-bottom:6px;text-align:center}.card-plain{background:transparent;box-shadow:none}.card-plain .card-footer,.card-plain .card-header{margin-left:0;margin-right:0;background-color:transparent}.card-plain:not(.card-subcategories).card-body{padding-left:0;padding-right:0}.card-chart .card-header .card-title{margin-top:10px;margin-bottom:0}.card-chart .card-header .card-category{margin-bottom:5px}.card-chart .table{margin-bottom:0}.card-chart .table td{border-top:none;border-bottom:1px solid #e9ecef}.card-chart .card-progress{margin-top:30px}.card-chart .chart-area{height:190px;width:calc(100% + 30px);margin-left:-15px;margin-right:-15px}.card-chart .card-footer{margin-top:15px}.card-chart .card-footer .stats{color:#9a9a9a}.card-chart .dropdown{position:absolute;right:20px;top:20px}.card-chart .dropdown .btn{margin:0}.footer{padding:24px 0}.footer.footer-default{background-color:#f2f2f2}.footer nav{display:inline-block;float:left;padding-left:7px}.footer ul{margin-bottom:0;padding:0;list-style:none}.footer ul li{display:inline-block}.footer ul li a{color:inherit;padding:.5rem;font-size:.8571em;text-transform:uppercase}.footer ul li a,.footer ul li a:hover{text-decoration:none}.footer .copyright{font-size:.8571em;line-height:1.8}.footer:after{display:table;clear:both;content:" "}.fixed-plugin{position:fixed;right:0;width:64px;background:rgba(0,0,0,.3);z-index:1031;border-radius:8px 0 0 8px;text-align:center;top:120px}.fixed-plugin .badge,.fixed-plugin li>a{transition:all .34s;-webkit-transition:all .34s;-moz-transition:all .34s}.fixed-plugin .fa-cog{color:#fff;padding:10px;border-radius:0 0 6px 6px;width:auto}.fixed-plugin .dropdown-menu{right:80px;left:auto!important;top:-52px!important;width:290px;border-radius:.1875rem;padding:0 10px}.fixed-plugin .dropdown .dropdown-menu .now-ui-icons{top:5px}.fixed-plugin .dropdown-menu:after,.fixed-plugin .dropdown-menu:before{right:10px;margin-left:auto;left:auto}.fixed-plugin .fa-circle-thin{color:#fff}.fixed-plugin .active .fa-circle-thin{color:#0bf}.fixed-plugin .dropdown-menu>.active>a,.fixed-plugin .dropdown-menu>.active>a:focus,.fixed-plugin .dropdown-menu>.active>a:hover{color:#777;text-align:center}.fixed-plugin img{border-radius:0;width:100%;height:100px;margin:0 auto}.fixed-plugin .dropdown-menu li>a:focus,.fixed-plugin .dropdown-menu li>a:hover{box-shadow:none}.fixed-plugin .badge{border:3px solid #fff;border-radius:50%;cursor:pointer;display:inline-block;height:23px;margin-right:5px;position:relative;width:23px}.fixed-plugin .badge.active,.fixed-plugin .badge:hover{border-color:#0bf}.fixed-plugin .badge-blue{background-color:#2ca8ff}.fixed-plugin .badge-green{background-color:#18ce0f}.fixed-plugin .badge-orange{background-color:#f96332}.fixed-plugin .badge-yellow{background-color:#ffb236}.fixed-plugin .badge-red{background-color:#ff3636}.fixed-plugin h5{font-size:14px;margin:10px}.fixed-plugin .dropdown-menu li{display:block;padding:18px 2px;width:25%;float:left}.fixed-plugin li.adjustments-line,.fixed-plugin li.button-container,.fixed-plugin li.header-title{width:100%;height:50px;min-height:inherit}.fixed-plugin li.button-container{height:auto}.fixed-plugin li.button-container div{margin-bottom:5px}.fixed-plugin #sharrreTitle{text-align:center;padding:10px 0;height:50px}.fixed-plugin li.header-title{height:30px;line-height:25px;font-size:12px;font-weight:600;text-align:center;text-transform:uppercase}.fixed-plugin .adjustments-line p{float:left;display:inline-block;margin-bottom:0;font-size:1em;color:#3c4858}.fixed-plugin .adjustments-line a{color:transparent}.fixed-plugin .adjustments-line a .badge-colors{position:relative;top:-2px}.fixed-plugin .adjustments-line a a:focus,.fixed-plugin .adjustments-line a a:hover{color:transparent}.fixed-plugin .adjustments-line .togglebutton{text-align:center}.fixed-plugin .adjustments-line .togglebutton .label-switch{position:relative;left:-10px;font-size:.7142em;color:#888}.fixed-plugin .adjustments-line .togglebutton .label-switch.label-right{left:10px}.fixed-plugin .adjustments-line .togglebutton .toggle{margin-right:0}.fixed-plugin .adjustments-line .dropdown-menu>li.adjustments-line>a{padding-right:0;padding-left:0;border-bottom:1px solid #ddd;border-radius:0;margin:0}.fixed-plugin .dropdown-menu>li>a.img-holder{font-size:16px;text-align:center;border-radius:10px;background-color:#fff;border:3px solid #fff;padding-left:0;padding-right:0;opacity:1;cursor:pointer;display:block;max-height:100px;overflow:hidden;padding:0}.fixed-plugin .dropdown-menu>li>a.img-holder img{margin-top:auto}.fixed-plugin .dropdown-menu>li>a.switch-trigger:focus,.fixed-plugin .dropdown-menu>li a.switch-trigger:hover{background-color:transparent}.fixed-plugin .dropdown-menu>li:focus>a.img-holder,.fixed-plugin .dropdown-menu>li:hover>a.img-holder{border-color:rgba(0,187,255,.53)}.fixed-plugin .dropdown-menu>.active>a.img-holder{border-color:#0bf;background-color:#fff}.fixed-plugin .btn-social{width:50%;display:block;width:48%;float:left;font-weight:600}.fixed-plugin .btn-social i{margin-right:5px}.fixed-plugin .btn-social:first-child{margin-right:2%}.fixed-plugin .dropdown .dropdown-menu{-webkit-transform:translateY(-15%);transform:translateY(-15%);top:27px;opacity:0;transform-origin:0 0}.fixed-plugin .dropdown .dropdown-menu:before{border-bottom:.4em solid transparent;border-left:.4em solid rgba(0,0,0,.2);border-top:.4em solid transparent;right:-16px;top:46px}.fixed-plugin .dropdown .dropdown-menu:after{border-bottom:.4em solid transparent;border-left:.4em solid #fff;border-top:.4em solid transparent;right:-16px}.fixed-plugin .dropdown .dropdown-menu:after,.fixed-plugin .dropdown .dropdown-menu:before{content:"";display:inline-block;position:absolute;top:74px;width:16px;transform:translateY(-50%);-webkit-transform:translateY(-50%);-moz-transform:translateY(-50%)}.fixed-plugin .dropdown.show .dropdown-menu{opacity:1;-webkit-transform:translateY(-13%);transform:translateY(-13%);transform-origin:0 0}.fixed-plugin .bootstrap-switch{margin:0}@media screen and (max-width:991px){.profile-photo .profile-photo-small{margin-left:-2px}#minimizeSidebar,.button-dropdown{display:none}.navbar .container-fluid{padding-right:15px;padding-left:15px}.navbar .navbar-collapse .input-group{margin:0;margin-top:5px}.navbar .navbar-nav .nav-item:first-child{margin-top:10px}.navbar .navbar-nav .nav-item:not(:last-child){margin-bottom:10px}.navbar .dropdown.show .dropdown-menu{display:block}.navbar .dropdown .dropdown-menu{display:none}.navbar .dropdown .dropdown-menu,.navbar .dropdown.show .dropdown-menu{background-color:transparent;border:0;transition:none;box-shadow:none;width:auto;margin:0 1rem;margin-top:0}.navbar .dropdown .dropdown-menu:before,.navbar .dropdown.show .dropdown-menu:before{display:none}.navbar .dropdown-menu .dropdown-item:focus,.navbar .dropdown-menu .dropdown-item:hover{color:#fff}.navbar.bg-white .dropdown-menu .dropdown-item:focus,.navbar.bg-white .dropdown-menu .dropdown-item:hover{color:#888}.navbar .navbar-toggler-bar{display:block;position:relative;width:22px;height:1px;border-radius:1px;background:#fff}.navbar .navbar-toggler-bar+.navbar-toggler-bar{margin-top:7px}.navbar .navbar-toggler-bar+.navbar-toggler-bar.navbar-kebab{margin-top:3px}.navbar .navbar-toggler-bar.bar2{width:17px;transition:width .2s linear}.navbar.bg-white:not(.navbar-transparent) .navbar-toggler-bar{background-color:#888}.navbar .toggled .navbar-toggler-bar{width:24px}.navbar .toggled .navbar-toggler-bar+.navbar-toggler-bar{margin-top:5px}.wrapper{transition:all .5s cubic-bezier(.685,.0473,.346,1)}.nav-open .main-panel{right:0;-webkit-transform:translate3d(260px,0,0);transform:translate3d(260px,0,0)}.nav-open .sidebar{-webkit-transform:translateZ(0);transform:translateZ(0)}.nav-open body{position:relative;overflow-x:hidden}.nav-open .menu-on-right .main-panel{-webkit-transform:translate3d(-260px,0,0);transform:translate3d(-260px,0,0)}.nav-open .menu-on-right .navbar-collapse,.nav-open .menu-on-right .sidebar{-webkit-transform:translateZ(0);transform:translateZ(0)}.nav-open .menu-on-right .navbar-translate{-webkit-transform:translate3d(-300px,0,0);transform:translate3d(-300px,0,0)}.nav-open .menu-on-right #bodyClick{right:260px;left:auto}.menu-on-right .sidebar{left:auto;right:0;-webkit-transform:translate3d(260px,0,0);transform:translate3d(260px,0,0)}.bar1,.bar2,.bar3{outline:1px solid transparent}.bar1{top:0;-webkit-animation:h .5s linear 0s;animation:h .5s 0s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards}.bar2{opacity:1}.bar3{bottom:0;-webkit-animation:j .5s linear 0s;animation:j .5s 0s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards}.toggled .bar1{top:6px;-webkit-animation:g .5s linear 0s;animation:g .5s 0s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards}.toggled .bar2{opacity:0}.toggled .bar3{bottom:6px;-webkit-animation:i .5s linear 0s;animation:i .5s 0s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards}@keyframes g{0%{top:0;transform:rotate(0deg)}45%{top:6px;transform:rotate(145deg)}75%{transform:rotate(130deg)}to{transform:rotate(135deg)}}@-webkit-keyframes g{0%{top:0;-webkit-transform:rotate(0deg)}45%{top:6px;-webkit-transform:rotate(145deg)}75%{-webkit-transform:rotate(130deg)}to{-webkit-transform:rotate(135deg)}}@keyframes h{0%{top:6px;transform:rotate(135deg)}45%{transform:rotate(-10deg)}75%{transform:rotate(5deg)}to{top:0;transform:rotate(0)}}@-webkit-keyframes h{0%{top:6px;-webkit-transform:rotate(135deg)}45%{-webkit-transform:rotate(-10deg)}75%{-webkit-transform:rotate(5deg)}to{top:0;-webkit-transform:rotate(0)}}@keyframes i{0%{bottom:0;transform:rotate(0deg)}45%{bottom:6px;transform:rotate(-145deg)}75%{transform:rotate(-130deg)}to{transform:rotate(-135deg)}}@-webkit-keyframes i{0%{bottom:0;-webkit-transform:rotate(0deg)}45%{bottom:6px;-webkit-transform:rotate(-145deg)}75%{-webkit-transform:rotate(-130deg)}to{-webkit-transform:rotate(-135deg)}}@keyframes j{0%{bottom:6px;transform:rotate(-135deg)}45%{transform:rotate(10deg)}75%{transform:rotate(-5deg)}to{bottom:0;transform:rotate(0)}}@-webkit-keyframes j{0%{bottom:6px;-webkit-transform:rotate(-135deg)}45%{-webkit-transform:rotate(10deg)}75%{-webkit-transform:rotate(-5deg)}to{bottom:0;-webkit-transform:rotate(0)}}#bodyClick{height:100%;width:100%;position:fixed;opacity:1;top:0;right:0;left:260px;content:"";z-index:9999;overflow-x:hidden;background-color:transparent;transition:all .5s cubic-bezier(.685,.0473,.346,1)}.footer .copyright{text-align:right}.section-nucleo-icons .icons-container{margin-top:65px}.navbar-nav .nav-link i.fa,.navbar-nav .nav-link i.now-ui-icons{opacity:.5}.bootstrap-navbar,.sidebar{position:fixed;display:block;top:0;height:100%;width:260px;right:auto;left:0;z-index:1032;visibility:visible;overflow-y:visible;padding:0;transition:all .5s cubic-bezier(.685,.0473,.346,1);-webkit-transform:translate3d(-260px,0,0);transform:translate3d(-260px,0,0)}.main-panel{width:100%}}@media screen and (min-width:992px){.navbar-collapse{background:none!important}.navbar .navbar-toggle{display:none}.navbar-nav .nav-link.profile-photo{padding:0;margin:7px .7rem}.section-nucleo-icons .icons-container{margin:0 0 0 auto}.dropdown-menu .dropdown-item{color:inherit}.footer .copyright{float:right;padding-right:15px}}@media screen and (max-width:768px){.nav-tabs{display:inline-block;width:100%;padding-left:100px;padding-right:100px;text-align:center}.nav-tabs .nav-item>.nav-link{margin-bottom:5px}.card-stats [class*=col-] .statistics:after{display:none}.main-panel .content{padding-left:15px;padding-right:15px}.footer nav{display:block;margin-bottom:5px;float:none}.landing-page .section-story-overview .image-container:nth-child(2){margin-left:0;margin-bottom:30px}}@media screen and (max-width:576px){.navbar[class*=navbar-toggleable-] .container{margin-left:0;margin-right:0}.card-contributions .card-stats{flex-direction:column}.card-contributions .card-stats .bootstrap-switch{margin-bottom:15px}.footer .copyright{text-align:center}.section-nucleo-icons .icons-container i{font-size:30px}.section-nucleo-icons .icons-container i:nth-child(6){font-size:48px}.page-header .container h6.category-absolute{width:90%}} diff --git a/web/templates/boilerplate/assets/css/styles.css b/web/templates/boilerplate/assets/css/styles.css deleted file mode 100644 index 0b2f07b..0000000 --- a/web/templates/boilerplate/assets/css/styles.css +++ /dev/null @@ -1,51 +0,0 @@ -.display-table{display:table;width:100%} -.display-table-cell{display:table-cell;padding:5px 10px;width:20%;vertical-align: top} -.grid-stack-item h4{margin: 0 10px 10px 0} -.grid-stack-item [run="exitStackItem"]{position: absolute;z-index: 10;top: 5px;right:5px;opacity: 0;transition: 0.2s} -.grid-stack-item:hover [run="exitStackItem"]{opacity: 1} -.grid-stack-item pre div>div{margin-left:10px} -.grid-stack-item .dropdown{display:inline-block} -.grid-stack-item .progress{height:5px} -.dropdown-menu {padding:2.5px} -.dropdown-menu a.btn:not(.btn-block){margin:2.5px 5px;} - -a,[run]{cursor: pointer!important} - - -::-webkit-scrollbar-thumb:hover { - background-color:#bd9565; -} -::-webkit-scrollbar-thumb { - background-color:#bd9565; - border: 2px solid transparent; - border-radius: 10px; - background-clip: padding-box; -} -@media (min-width: 768px){ - .modal.full,.modal.medium{padding-left:0!important;} - .modal.full .modal-dialog{width:calc(100% - 10px)!important;margin: 30px auto;} - .modal.medium .modal-dialog{width:calc(70% - 10px)!important;margin: 30px auto;} - .full.modal .modal-body,.medium.modal .modal-body{max-height:calc(100% - 200px);overflow:auto} -} - -.flex-container-modal-body{overflow: auto} -.flex-container-modal-body .flex-block>div{flex:1;float:none} - -.modal{overflow:auto!important} -.modal .modal-dialog{max-width:none} -.table-scroll{max-height:300px;overflow:auto;} -.car-intro video{width:100%} -.modal tbody tr video {height:75px} -.car-intro{ width:100%; float:left; position:relative; margin:10px 0 0; border:40px solid #454545; border-bottom:none; border-radius: 10px} -.module-top{ position:absolute; top:-39px; left:0; right:0;} -a.green-btn{ background:#14eda2; min-width:185px; line-height:38px; color:#FFFFFF; font-size:16px; text-align:center; display:inline-block; margin:0 10px;} -a.green-btn:hover{ background:#22d496;} -.module-hud{opacity:0;transition:0.5s} -.car-intro:hover .module-hud{opacity:1} -.module-upper{ position:absolute; left:0; right:0; top:5%; padding: 0 10px 0 10px;} -.module-upper a.left{ float:left;} -.module-upper a.right{ float:right;} -.module-upper.middle{ top:40%;} -.module-upper.lower{ top:70%;} - -.grid-stack.grid-stack-one-column-mode>.grid-stack-item{width:100%!important} \ No newline at end of file diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-Black.eot b/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-Black.eot deleted file mode 100644 index 3a5362d..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-Black.eot and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-Black.woff b/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-Black.woff deleted file mode 100644 index 5c60ad0..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-Black.woff and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-Black.woff2 b/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-Black.woff2 deleted file mode 100644 index 3ac8d46..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-Black.woff2 and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-BlackItalic.eot b/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-BlackItalic.eot deleted file mode 100644 index 4b92a25..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-BlackItalic.eot and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-BlackItalic.woff b/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-BlackItalic.woff deleted file mode 100644 index 0caeeb5..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-BlackItalic.woff and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-BlackItalic.woff2 b/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-BlackItalic.woff2 deleted file mode 100644 index 1e5d135..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-BlackItalic.woff2 and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-Bold.eot b/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-Bold.eot deleted file mode 100644 index 5ab4fd5..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-Bold.eot and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-Bold.woff b/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-Bold.woff deleted file mode 100644 index aad827f..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-Bold.woff and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-Bold.woff2 b/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-Bold.woff2 deleted file mode 100644 index ad25d26..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-Bold.woff2 and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-BoldItalic.eot b/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-BoldItalic.eot deleted file mode 100644 index 5eeff1e..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-BoldItalic.eot and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-BoldItalic.woff b/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-BoldItalic.woff deleted file mode 100644 index 875f5b5..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-BoldItalic.woff and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-BoldItalic.woff2 b/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-BoldItalic.woff2 deleted file mode 100644 index f9a3d40..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-BoldItalic.woff2 and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-ExtraBold.eot b/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-ExtraBold.eot deleted file mode 100644 index 203ed8e..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-ExtraBold.eot and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-ExtraBold.woff b/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-ExtraBold.woff deleted file mode 100644 index 08c7e2e..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-ExtraBold.woff and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-ExtraBold.woff2 b/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-ExtraBold.woff2 deleted file mode 100644 index e961597..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-ExtraBold.woff2 and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-ExtraBoldItalic.eot b/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-ExtraBoldItalic.eot deleted file mode 100644 index 329171b..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-ExtraBoldItalic.eot and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-ExtraBoldItalic.woff b/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-ExtraBoldItalic.woff deleted file mode 100644 index 935251b..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-ExtraBoldItalic.woff and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-ExtraBoldItalic.woff2 b/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-ExtraBoldItalic.woff2 deleted file mode 100644 index 97b0e28..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-ExtraBoldItalic.woff2 and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-ExtraLight.eot b/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-ExtraLight.eot deleted file mode 100644 index 1a9012b..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-ExtraLight.eot and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-ExtraLight.woff b/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-ExtraLight.woff deleted file mode 100644 index a9a848e..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-ExtraLight.woff and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-ExtraLight.woff2 b/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-ExtraLight.woff2 deleted file mode 100644 index 5fee343..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-ExtraLight.woff2 and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-ExtraLightItalic.eot b/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-ExtraLightItalic.eot deleted file mode 100644 index 0c5369b..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-ExtraLightItalic.eot and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-ExtraLightItalic.woff b/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-ExtraLightItalic.woff deleted file mode 100644 index 112038e..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-ExtraLightItalic.woff and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-ExtraLightItalic.woff2 b/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-ExtraLightItalic.woff2 deleted file mode 100644 index 959479b..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-ExtraLightItalic.woff2 and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-Italic.eot b/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-Italic.eot deleted file mode 100644 index 867a104..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-Italic.eot and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-Italic.woff b/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-Italic.woff deleted file mode 100644 index 1c15293..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-Italic.woff and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-Italic.woff2 b/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-Italic.woff2 deleted file mode 100644 index 8ccfb98..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-Italic.woff2 and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-Light.eot b/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-Light.eot deleted file mode 100644 index 62d678e..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-Light.eot and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-Light.woff b/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-Light.woff deleted file mode 100644 index 7aa52b2..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-Light.woff and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-Light.woff2 b/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-Light.woff2 deleted file mode 100644 index 0b253c4..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-Light.woff2 and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-LightItalic.eot b/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-LightItalic.eot deleted file mode 100644 index 9e70f97..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-LightItalic.eot and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-LightItalic.woff b/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-LightItalic.woff deleted file mode 100644 index ef12fe2..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-LightItalic.woff and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-LightItalic.woff2 b/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-LightItalic.woff2 deleted file mode 100644 index c4cc5a3..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-LightItalic.woff2 and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-Medium.eot b/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-Medium.eot deleted file mode 100644 index abb0a84..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-Medium.eot and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-Medium.woff b/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-Medium.woff deleted file mode 100644 index 2778c8b..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-Medium.woff and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-Medium.woff2 b/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-Medium.woff2 deleted file mode 100644 index 80d6f58..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-Medium.woff2 and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-MediumItalic.eot b/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-MediumItalic.eot deleted file mode 100644 index d7986e9..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-MediumItalic.eot and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-MediumItalic.woff b/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-MediumItalic.woff deleted file mode 100644 index 7a2329f..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-MediumItalic.woff and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-MediumItalic.woff2 b/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-MediumItalic.woff2 deleted file mode 100644 index a7f9cfd..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-MediumItalic.woff2 and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-Regular.eot b/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-Regular.eot deleted file mode 100644 index d030e7f..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-Regular.eot and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-Regular.woff b/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-Regular.woff deleted file mode 100644 index ebb48a9..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-Regular.woff and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-Regular.woff2 b/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-Regular.woff2 deleted file mode 100644 index 3261a6a..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-Regular.woff2 and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-SemiBold.eot b/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-SemiBold.eot deleted file mode 100644 index 92bdd9b..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-SemiBold.eot and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-SemiBold.woff b/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-SemiBold.woff deleted file mode 100644 index 32904f5..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-SemiBold.woff and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-SemiBold.woff2 b/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-SemiBold.woff2 deleted file mode 100644 index 0c9bc28..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-SemiBold.woff2 and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-SemiBoldItalic.eot b/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-SemiBoldItalic.eot deleted file mode 100644 index 9caec26..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-SemiBoldItalic.eot and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-SemiBoldItalic.woff b/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-SemiBoldItalic.woff deleted file mode 100644 index d990b52..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-SemiBoldItalic.woff and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-SemiBoldItalic.woff2 b/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-SemiBoldItalic.woff2 deleted file mode 100644 index 4d597b3..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-SemiBoldItalic.woff2 and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-Thin.eot b/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-Thin.eot deleted file mode 100644 index 125b165..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-Thin.eot and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-Thin.woff b/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-Thin.woff deleted file mode 100644 index 43cffac..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-Thin.woff and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-Thin.woff2 b/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-Thin.woff2 deleted file mode 100644 index ef8d0d5..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-Thin.woff2 and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-ThinItalic.eot b/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-ThinItalic.eot deleted file mode 100644 index a53bd66..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-ThinItalic.eot and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-ThinItalic.woff b/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-ThinItalic.woff deleted file mode 100644 index dd4a314..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-ThinItalic.woff and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-ThinItalic.woff2 b/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-ThinItalic.woff2 deleted file mode 100644 index e5e9367..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat-ThinItalic.woff2 and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat.css b/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat.css deleted file mode 100644 index a52ef06..0000000 --- a/web/templates/boilerplate/assets/fonts/Montserrat/Montserrat.css +++ /dev/null @@ -1,399 +0,0 @@ -/** =================== MONTSERRAT =================== **/ - -/** Montserrat Thin **/ -@font-face { - font-family: "Montserrat"; - font-weight: 100; - font-style: normal; - src: url("Montserrat-Thin.eot"); - src: url("Montserrat-Thin.eot?#iefix") format('embedded-opentype'), - url("Montserrat-Thin.woff2") format("woff2"), - url("Montserrat-Thin.woff") format("woff"); -} - -/** Montserrat Thin-Italic **/ -@font-face { - font-family: "Montserrat"; - font-weight: 100; - font-style: italic; - src: url("Montserrat-ThinItalic.eot"); - src: url("Montserrat-ThinItalic.eot?#iefix") format('embedded-opentype'), - url("Montserrat-ThinItalic.woff2") format("woff2"), - url("Montserrat-ThinItalic.woff") format("woff"); -} - -/** Montserrat ExtraLight **/ -@font-face { - font-family: "Montserrat"; - font-weight: 200; - font-style: normal; - src: url("Montserrat-ExtraLight.eot"); - src: url("Montserrat-ExtraLight.eot?#iefix") format('embedded-opentype'), - url("Montserrat-ExtraLight.woff2") format("woff2"), - url("Montserrat-ExtraLight.woff") format("woff"); -} - -/** Montserrat ExtraLight-Italic **/ -@font-face { - font-family: "Montserrat"; - font-weight: 200; - font-style: italic; - src: url("Montserrat-ExtraLightItalic.eot"); - src: url("Montserrat-ExtraLightItalic.eot?#iefix") format('embedded-opentype'), - url("Montserrat-ExtraLightItalic.woff2") format("woff2"), - url("Montserrat-ExtraLightItalic.woff") format("woff"); -} - -/** Montserrat Light **/ -@font-face { - font-family: "Montserrat"; - font-weight: 300; - font-style: normal; - src: url("Montserrat-Light.eot"); - src: url("Montserrat-Light.eot?#iefix") format('embedded-opentype'), - url("Montserrat-Light.woff2") format("woff2"), - url("Montserrat-Light.woff") format("woff"); -} - -/** Montserrat Light-Italic **/ -@font-face { - font-family: "Montserrat"; - font-weight: 300; - font-style: italic; - src: url("Montserrat-LightItalic.eot"); - src: url("Montserrat-LightItalic.eot?#iefix") format('embedded-opentype'), - url("Montserrat-LightItalic.woff2") format("woff2"), - url("Montserrat-LightItalic.woff") format("woff"); -} - -/** Montserrat Regular **/ -@font-face { - font-family: "Montserrat"; - font-weight: 400; - font-style: normal; - src: url("Montserrat-Regular.eot"); - src: url("Montserrat-Regular.eot?#iefix") format('embedded-opentype'), - url("Montserrat-Regular.woff2") format("woff2"), - url("Montserrat-Regular.woff") format("woff"); -} - -/** Montserrat Regular-Italic **/ -@font-face { - font-family: "Montserrat"; - font-weight: 400; - font-style: italic; - src: url("Montserrat-Italic.eot"); - src: url("Montserrat-Italic.eot?#iefix") format('embedded-opentype'), - url("Montserrat-Italic.woff2") format("woff2"), - url("Montserrat-Italic.woff") format("woff"); -} - -/** Montserrat Medium **/ -@font-face { - font-family: "Montserrat"; - font-weight: 500; - font-style: normal; - src: url("Montserrat-Medium.eot"); - src: url("Montserrat-Medium.eot?#iefix") format('embedded-opentype'), - url("Montserrat-Medium.woff2") format("woff2"), - url("Montserrat-Medium.woff") format("woff"); -} - -/** Montserrat Medium-Italic **/ -@font-face { - font-family: "Montserrat"; - font-weight: 500; - font-style: italic; - src: url("Montserrat-MediumItalic.eot"); - src: url("Montserrat-MediumItalic.eot?#iefix") format('embedded-opentype'), - url("Montserrat-MediumItalic.woff2") format("woff2"), - url("Montserrat-MediumItalic.woff") format("woff"); -} - -/** Montserrat SemiBold **/ -@font-face { - font-family: "Montserrat"; - font-weight: 600; - font-style: normal; - src: url("Montserrat-SemiBold.eot"); - src: url("Montserrat-SemiBold.eot?#iefix") format('embedded-opentype'), - url("Montserrat-SemiBold.woff2") format("woff2"), - url("Montserrat-SemiBold.woff") format("woff"); -} - -/** Montserrat SemiBold-Italic **/ -@font-face { - font-family: "Montserrat"; - font-weight: 600; - font-style: italic; - src: url("Montserrat-SemiBoldItalic.eot"); - src: url("Montserrat-SemiBoldItalic.eot?#iefix") format('embedded-opentype'), - url("Montserrat-SemiBoldItalic.woff2") format("woff2"), - url("Montserrat-SemiBoldItalic.woff") format("woff"); -} - -/** Montserrat Bold **/ -@font-face { - font-family: "Montserrat"; - font-weight: 700; - font-style: normal; - src: url("Montserrat-Bold.eot"); - src: url("Montserrat-Bold.eot?#iefix") format('embedded-opentype'), - url("Montserrat-Bold.woff2") format("woff2"), - url("Montserrat-Bold.woff") format("woff"); -} - -/** Montserrat Bold-Italic **/ -@font-face { - font-family: "Montserrat"; - font-weight: 700; - font-style: italic; - src: url("Montserrat-BoldItalic.eot"); - src: url("Montserrat-BoldItalic.eot?#iefix") format('embedded-opentype'), - url("Montserrat-BoldItalic.woff2") format("woff2"), - url("Montserrat-BoldItalic.woff") format("woff"); -} - -/** Montserrat ExtraBold **/ -@font-face { - font-family: "Montserrat"; - font-weight: 800; - font-style: normal; - src: url("Montserrat-ExtraBold.eot"); - src: url("Montserrat-ExtraBold.eot?#iefix") format('embedded-opentype'), - url("Montserrat-ExtraBold.woff2") format("woff2"), - url("Montserrat-ExtraBold.woff") format("woff"); -} - -/** Montserrat ExtraBold-Italic **/ -@font-face { - font-family: "Montserrat"; - font-weight: 800; - font-style: italic; - src: url("Montserrat-ExtraBoldItalic.eot"); - src: url("Montserrat-ExtraBoldItalic.eot?#iefix") format('embedded-opentype'), - url("Montserrat-ExtraBoldItalic.woff2") format("woff2"), - url("Montserrat-ExtraBoldItalic.woff") format("woff"); -} - -/** Montserrat Black **/ -@font-face { - font-family: "Montserrat"; - font-weight: 900; - font-style: normal; - src: url("Montserrat-Black.eot"); - src: url("Montserrat-Black.eot?#iefix") format('embedded-opentype'), - url("Montserrat-Black.woff2") format("woff2"), - url("Montserrat-Black.woff") format("woff"); -} - -/** Montserrat Black-Italic **/ -@font-face { - font-family: "Montserrat"; - font-weight: 900; - font-style: italic; - src: url("Montserrat-BlackItalic.eot"); - src: url("Montserrat-BlackItalic.eot?#iefix") format('embedded-opentype'), - url("Montserrat-BlackItalic.woff2") format("woff2"), - url("Montserrat-BlackItalic.woff") format("woff"); -} - -/** =================== MONTSERRAT ALTERNATES =================== **/ - -/** Montserrat Alternates Thin **/ -@font-face { - font-family: "Montserrat Alternates"; - font-weight: 100; - font-style: normal; - src: url("MontserratAlternates-Thin.eot"); - src: url("MontserratAlternates-Thin.eot?#iefix") format('embedded-opentype'), - url("MontserratAlternates-Thin.woff2") format("woff2"), - url("MontserratAlternates-Thin.woff") format("woff"); -} - -/** Montserrat Alternates Thin-Italic **/ -@font-face { - font-family: "Montserrat Alternates"; - font-weight: 100; - font-style: italic; - src: url("MontserratAlternates-ThinItalic.eot"); - src: url("MontserratAlternates-ThinItalic.eot?#iefix") format('embedded-opentype'), - url("MontserratAlternates-ThinItalic.woff2") format("woff2"), - url("MontserratAlternates-ThinItalic.woff") format("woff"); -} - -/** Montserrat Alternates ExtraLight **/ -@font-face { - font-family: "Montserrat Alternates"; - font-weight: 200; - font-style: normal; - src: url("MontserratAlternates-ExtraLight.eot"); - src: url("MontserratAlternates-ExtraLight.eot?#iefix") format('embedded-opentype'), - url("MontserratAlternates-ExtraLight.woff2") format("woff2"), - url("MontserratAlternates-ExtraLight.woff") format("woff"); -} - -/** Montserrat Alternates ExtraLight-Italic **/ -@font-face { - font-family: "Montserrat Alternates"; - font-weight: 200; - font-style: italic; - src: url("MontserratAlternates-ExtraLightItalic.eot"); - src: url("MontserratAlternates-ExtraLightItalic.eot?#iefix") format('embedded-opentype'), - url("MontserratAlternates-ExtraLightItalic.woff2") format("woff2"), - url("MontserratAlternates-ExtraLightItalic.woff") format("woff"); -} - -/** Montserrat Alternates Light **/ -@font-face { - font-family: "Montserrat Alternates"; - font-weight: 300; - font-style: normal; - src: url("MontserratAlternates-Light.eot"); - src: url("MontserratAlternates-Light.eot?#iefix") format('embedded-opentype'), - url("MontserratAlternates-Light.woff2") format("woff2"), - url("MontserratAlternates-Light.woff") format("woff"); -} - -/** Montserrat Alternates Light-Italic **/ -@font-face { - font-family: "Montserrat Alternates"; - font-weight: 300; - font-style: italic; - src: url("MontserratAlternates-LightItalic.eot"); - src: url("MontserratAlternates-LightItalic.eot?#iefix") format('embedded-opentype'), - url("MontserratAlternates-LightItalic.woff2") format("woff2"), - url("MontserratAlternates-LightItalic.woff") format("woff"); -} - -/** Montserrat Alternates Regular **/ -@font-face { - font-family: "Montserrat Alternates"; - font-weight: 400; - font-style: normal; - src: url("MontserratAlternates-Regular.eot"); - src: url("MontserratAlternates-Regular.eot?#iefix") format('embedded-opentype'), - url("MontserratAlternates-Regular.woff2") format("woff2"), - url("MontserratAlternates-Regular.woff") format("woff"); -} - -/** Montserrat Alternates Regular-Italic **/ -@font-face { - font-family: "Montserrat Alternates"; - font-weight: 400; - font-style: italic; - src: url("MontserratAlternates-Italic.eot"); - src: url("MontserratAlternates-Italic.eot?#iefix") format('embedded-opentype'), - url("MontserratAlternates-Italic.woff2") format("woff2"), - url("MontserratAlternates-Italic.woff") format("woff"); -} - -/** Montserrat Alternates Medium **/ -@font-face { - font-family: "Montserrat Alternates"; - font-weight: 500; - font-style: normal; - src: url("MontserratAlternates-Medium.eot"); - src: url("MontserratAlternates-Medium.eot?#iefix") format('embedded-opentype'), - url("MontserratAlternates-Medium.woff2") format("woff2"), - url("MontserratAlternates-Medium.woff") format("woff"); -} - -/** Montserrat Alternates Medium-Italic **/ -@font-face { - font-family: "Montserrat Alternates"; - font-weight: 500; - font-style: italic; - src: url("MontserratAlternates-MediumItalic.eot"); - src: url("MontserratAlternates-MediumItalic.eot?#iefix") format('embedded-opentype'), - url("MontserratAlternates-MediumItalic.woff2") format("woff2"), - url("MontserratAlternates-MediumItalic.woff") format("woff"); -} - -/** Montserrat Alternates SemiBold **/ -@font-face { - font-family: "Montserrat Alternates"; - font-weight: 600; - font-style: normal; - src: url("MontserratAlternates-SemiBold.eot"); - src: url("MontserratAlternates-SemiBold.eot?#iefix") format('embedded-opentype'), - url("MontserratAlternates-SemiBold.woff2") format("woff2"), - url("MontserratAlternates-SemiBold.woff") format("woff"); -} - -/** Montserrat Alternates SemiBold-Italic **/ -@font-face { - font-family: "Montserrat Alternates"; - font-weight: 600; - font-style: italic; - src: url("MontserratAlternates-SemiBoldItalic.eot"); - src: url("MontserratAlternates-SemiBoldItalic.eot?#iefix") format('embedded-opentype'), - url("MontserratAlternates-SemiBoldItalic.woff2") format("woff2"), - url("MontserratAlternates-SemiBoldItalic.woff") format("woff"); -} - -/** Montserrat Alternates Bold **/ -@font-face { - font-family: "Montserrat Alternates"; - font-weight: 700; - font-style: normal; - src: url("MontserratAlternates-Bold.eot"); - src: url("MontserratAlternates-Bold.eot?#iefix") format('embedded-opentype'), - url("MontserratAlternates-Bold.woff2") format("woff2"), - url("MontserratAlternates-Bold.woff") format("woff"); -} - -/** Montserrat Alternates Bold-Italic **/ -@font-face { - font-family: "Montserrat Alternates"; - font-weight: 700; - font-style: italic; - src: url("MontserratAlternates-BoldItalic.eot"); - src: url("MontserratAlternates-BoldItalic.eot?#iefix") format('embedded-opentype'), - url("MontserratAlternates-BoldItalic.woff2") format("woff2"), - url("MontserratAlternates-BoldItalic.woff") format("woff"); -} - -/** Montserrat Alternates ExtraBold **/ -@font-face { - font-family: "Montserrat Alternates"; - font-weight: 800; - font-style: normal; - src: url("MontserratAlternates-ExtraBold.eot"); - src: url("MontserratAlternates-ExtraBold.eot?#iefix") format('embedded-opentype'), - url("MontserratAlternates-ExtraBold.woff2") format("woff2"), - url("MontserratAlternates-ExtraBold.woff") format("woff"); -} - -/** Montserrat Alternates ExtraBold-Italic **/ -@font-face { - font-family: "Montserrat Alternates"; - font-weight: 800; - font-style: italic; - src: url("MontserratAlternates-ExtraBoldItalic.eot"); - src: url("MontserratAlternates-ExtraBoldItalic.eot?#iefix") format('embedded-opentype'), - url("MontserratAlternates-ExtraBoldItalic.woff2") format("woff2"), - url("MontserratAlternates-ExtraBoldItalic.woff") format("woff"); -} - -/** Montserrat Alternates Black **/ -@font-face { - font-family: "Montserrat Alternates"; - font-weight: 900; - font-style: normal; - src: url("MontserratAlternates-Black.eot"); - src: url("MontserratAlternates-Black.eot?#iefix") format('embedded-opentype'), - url("MontserratAlternates-Black.woff2") format("woff2"), - url("MontserratAlternates-Black.woff") format("woff"); -} - -/** Montserrat Alternates Black-Italic **/ -@font-face { - font-family: "Montserrat"; - font-weight: 900; - font-style: italic; - src: url("MontserratAlternates-BlackItalic.eot"); - src: url("MontserratAlternates-BlackItalic.eot?#iefix") format('embedded-opentype'), - url("MontserratAlternates-BlackItalic.woff2") format("woff2"), - url("MontserratAlternates-BlackItalic.woff") format("woff"); -} \ No newline at end of file diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-Black.eot b/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-Black.eot deleted file mode 100644 index fc23ac4..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-Black.eot and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-Black.woff b/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-Black.woff deleted file mode 100644 index 11a3ce6..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-Black.woff and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-Black.woff2 b/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-Black.woff2 deleted file mode 100644 index 235a3c8..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-Black.woff2 and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-BlackItalic.eot b/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-BlackItalic.eot deleted file mode 100644 index a965308..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-BlackItalic.eot and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-BlackItalic.woff b/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-BlackItalic.woff deleted file mode 100644 index a2ddfd3..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-BlackItalic.woff and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-BlackItalic.woff2 b/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-BlackItalic.woff2 deleted file mode 100644 index a8004a1..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-BlackItalic.woff2 and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-Bold.eot b/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-Bold.eot deleted file mode 100644 index f17c416..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-Bold.eot and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-Bold.woff b/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-Bold.woff deleted file mode 100644 index 9fc7e5e..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-Bold.woff and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-Bold.woff2 b/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-Bold.woff2 deleted file mode 100644 index 22ff691..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-Bold.woff2 and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-BoldItalic.eot b/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-BoldItalic.eot deleted file mode 100644 index 90cf559..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-BoldItalic.eot and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-BoldItalic.woff b/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-BoldItalic.woff deleted file mode 100644 index e1483bd..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-BoldItalic.woff and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-BoldItalic.woff2 b/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-BoldItalic.woff2 deleted file mode 100644 index bed052a..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-BoldItalic.woff2 and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-ExtraBold.eot b/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-ExtraBold.eot deleted file mode 100644 index 3b1d443..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-ExtraBold.eot and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-ExtraBold.woff b/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-ExtraBold.woff deleted file mode 100644 index f6a794d..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-ExtraBold.woff and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-ExtraBold.woff2 b/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-ExtraBold.woff2 deleted file mode 100644 index e2cd944..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-ExtraBold.woff2 and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-ExtraBoldItalic.eot b/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-ExtraBoldItalic.eot deleted file mode 100644 index 9af7c24..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-ExtraBoldItalic.eot and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-ExtraBoldItalic.woff b/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-ExtraBoldItalic.woff deleted file mode 100644 index 1403e27..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-ExtraBoldItalic.woff and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-ExtraBoldItalic.woff2 b/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-ExtraBoldItalic.woff2 deleted file mode 100644 index 979839f..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-ExtraBoldItalic.woff2 and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-ExtraLight.eot b/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-ExtraLight.eot deleted file mode 100644 index 345c60d..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-ExtraLight.eot and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-ExtraLight.woff b/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-ExtraLight.woff deleted file mode 100644 index 6c47d58..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-ExtraLight.woff and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-ExtraLight.woff2 b/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-ExtraLight.woff2 deleted file mode 100644 index 9fe8bb2..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-ExtraLight.woff2 and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-ExtraLightItalic.eot b/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-ExtraLightItalic.eot deleted file mode 100644 index 29b4c1f..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-ExtraLightItalic.eot and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-ExtraLightItalic.woff b/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-ExtraLightItalic.woff deleted file mode 100644 index 622cc9a..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-ExtraLightItalic.woff and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-ExtraLightItalic.woff2 b/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-ExtraLightItalic.woff2 deleted file mode 100644 index 2632c08..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-ExtraLightItalic.woff2 and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-Italic.eot b/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-Italic.eot deleted file mode 100644 index 6e8c22e..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-Italic.eot and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-Italic.woff b/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-Italic.woff deleted file mode 100644 index 65094d4..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-Italic.woff and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-Italic.woff2 b/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-Italic.woff2 deleted file mode 100644 index 40944d4..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-Italic.woff2 and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-Light.eot b/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-Light.eot deleted file mode 100644 index e999003..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-Light.eot and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-Light.woff b/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-Light.woff deleted file mode 100644 index 4a9a0d4..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-Light.woff and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-Light.woff2 b/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-Light.woff2 deleted file mode 100644 index c7ef715..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-Light.woff2 and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-LightItalic.eot b/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-LightItalic.eot deleted file mode 100644 index fd1b318..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-LightItalic.eot and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-LightItalic.woff b/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-LightItalic.woff deleted file mode 100644 index 22f432f..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-LightItalic.woff and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-LightItalic.woff2 b/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-LightItalic.woff2 deleted file mode 100644 index 9f3b5d0..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-LightItalic.woff2 and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-Medium.eot b/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-Medium.eot deleted file mode 100644 index 4dd10f2..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-Medium.eot and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-Medium.woff b/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-Medium.woff deleted file mode 100644 index 92bd129..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-Medium.woff and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-Medium.woff2 b/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-Medium.woff2 deleted file mode 100644 index f8f0530..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-Medium.woff2 and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-MediumItalic.eot b/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-MediumItalic.eot deleted file mode 100644 index 9f33af7..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-MediumItalic.eot and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-MediumItalic.woff b/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-MediumItalic.woff deleted file mode 100644 index aefdeee..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-MediumItalic.woff and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-MediumItalic.woff2 b/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-MediumItalic.woff2 deleted file mode 100644 index 9775f42..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-MediumItalic.woff2 and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-Regular.eot b/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-Regular.eot deleted file mode 100644 index ad10b6b..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-Regular.eot and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-Regular.woff b/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-Regular.woff deleted file mode 100644 index 3aaf1f7..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-Regular.woff and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-Regular.woff2 b/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-Regular.woff2 deleted file mode 100644 index f7d23ca..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-Regular.woff2 and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-SemiBold.eot b/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-SemiBold.eot deleted file mode 100644 index 13a121d..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-SemiBold.eot and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-SemiBold.woff b/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-SemiBold.woff deleted file mode 100644 index 35ba984..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-SemiBold.woff and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-SemiBold.woff2 b/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-SemiBold.woff2 deleted file mode 100644 index 80bf4c2..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-SemiBold.woff2 and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-SemiBoldItalic.eot b/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-SemiBoldItalic.eot deleted file mode 100644 index 799cae5..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-SemiBoldItalic.eot and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-SemiBoldItalic.woff b/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-SemiBoldItalic.woff deleted file mode 100644 index 39283e1..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-SemiBoldItalic.woff and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-SemiBoldItalic.woff2 b/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-SemiBoldItalic.woff2 deleted file mode 100644 index 0bb26ae..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-SemiBoldItalic.woff2 and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-Thin.eot b/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-Thin.eot deleted file mode 100644 index d49ba52..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-Thin.eot and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-Thin.woff b/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-Thin.woff deleted file mode 100644 index 9f031c2..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-Thin.woff and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-Thin.woff2 b/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-Thin.woff2 deleted file mode 100644 index 23a80f9..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-Thin.woff2 and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-ThinItalic.eot b/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-ThinItalic.eot deleted file mode 100644 index 2fcd16d..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-ThinItalic.eot and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-ThinItalic.woff b/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-ThinItalic.woff deleted file mode 100644 index c601966..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-ThinItalic.woff and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-ThinItalic.woff2 b/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-ThinItalic.woff2 deleted file mode 100644 index d98a952..0000000 Binary files a/web/templates/boilerplate/assets/fonts/Montserrat/MontserratAlternates-ThinItalic.woff2 and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/nucleo-outline.eot b/web/templates/boilerplate/assets/fonts/nucleo-outline.eot deleted file mode 100644 index 3625494..0000000 Binary files a/web/templates/boilerplate/assets/fonts/nucleo-outline.eot and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/nucleo-outline.ttf b/web/templates/boilerplate/assets/fonts/nucleo-outline.ttf deleted file mode 100644 index 5caf555..0000000 Binary files a/web/templates/boilerplate/assets/fonts/nucleo-outline.ttf and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/nucleo-outline.woff b/web/templates/boilerplate/assets/fonts/nucleo-outline.woff deleted file mode 100644 index 425ee84..0000000 Binary files a/web/templates/boilerplate/assets/fonts/nucleo-outline.woff and /dev/null differ diff --git a/web/templates/boilerplate/assets/fonts/nucleo-outline.woff2 b/web/templates/boilerplate/assets/fonts/nucleo-outline.woff2 deleted file mode 100644 index 791b3b9..0000000 Binary files a/web/templates/boilerplate/assets/fonts/nucleo-outline.woff2 and /dev/null differ diff --git a/web/templates/boilerplate/assets/js/bootstrap-notify.js b/web/templates/boilerplate/assets/js/bootstrap-notify.js deleted file mode 100644 index c0022cb..0000000 --- a/web/templates/boilerplate/assets/js/bootstrap-notify.js +++ /dev/null @@ -1,433 +0,0 @@ -/* - - - - Creative Tim Modifications - - Lines: 238, 239 was changed from top: 5px to top: 50% and we added margin-top: -13px. In this way the close button will be aligned vertically - Line:222 - modified when the icon is set, we add the class "alert-with-icon", so there will be enough space for the icon. - - - - -*/ - - -/* -* Project: Bootstrap Notify = v3.1.5 -* Description: Turns standard Bootstrap alerts into "Growl-like" notifications. -* Author: Mouse0270 aka Robert McIntosh -* License: MIT License -* Website: https://github.com/mouse0270/bootstrap-growl -*/ - -/* global define:false, require: false, jQuery:false */ - -(function (factory) { - if (typeof define === 'function' && define.amd) { - // AMD. Register as an anonymous module. - define(['jquery'], factory); - } else if (typeof exports === 'object') { - // Node/CommonJS - factory(require('jquery')); - } else { - // Browser globals - factory(jQuery); - } -}(function ($) { - // Create the defaults once - var defaults = { - element: 'body', - position: null, - type: "info", - allow_dismiss: true, - allow_duplicates: true, - newest_on_top: false, - showProgressbar: false, - placement: { - from: "top", - align: "right" - }, - offset: 20, - spacing: 10, - z_index: 1060, - delay: 5000, - timer: 1000, - url_target: '_blank', - mouse_over: null, - animate: { - enter: 'animated fadeInDown', - exit: 'animated fadeOutUp' - }, - onShow: null, - onShown: null, - onClose: null, - onClosed: null, - onClick: null, - icon_type: 'class', - template: '' - }; - - String.format = function () { - var args = arguments; - var str = arguments[0]; - return str.replace(/(\{\{\d\}\}|\{\d\})/g, function (str) { - if (str.substring(0, 2) === "{{") return str; - var num = parseInt(str.match(/\d/)[0]); - return args[num + 1]; - }); - }; - - function isDuplicateNotification(notification) { - var isDupe = false; - - $('[data-notify="container"]').each(function (i, el) { - var $el = $(el); - var title = $el.find('[data-notify="title"]').html().trim(); - var message = $el.find('[data-notify="message"]').html().trim(); - - // The input string might be different than the actual parsed HTML string! - // (
      vs
      for example) - // So we have to force-parse this as HTML here! - var isSameTitle = title === $("
      " + notification.settings.content.title + "
      ").html().trim(); - var isSameMsg = message === $("
      " + notification.settings.content.message + "
      ").html().trim(); - var isSameType = $el.hasClass('alert-' + notification.settings.type); - - if (isSameTitle && isSameMsg && isSameType) { - //we found the dupe. Set the var and stop checking. - isDupe = true; - } - return !isDupe; - }); - - return isDupe; - } - - function Notify(element, content, options) { - // Setup Content of Notify - var contentObj = { - content: { - message: typeof content === 'object' ? content.message : content, - title: content.title ? content.title : '', - icon: content.icon ? content.icon : '', - url: content.url ? content.url : '#', - target: content.target ? content.target : '-' - } - }; - - options = $.extend(true, {}, contentObj, options); - this.settings = $.extend(true, {}, defaults, options); - this._defaults = defaults; - if (this.settings.content.target === "-") { - this.settings.content.target = this.settings.url_target; - } - this.animations = { - start: 'webkitAnimationStart oanimationstart MSAnimationStart animationstart', - end: 'webkitAnimationEnd oanimationend MSAnimationEnd animationend' - }; - - if (typeof this.settings.offset === 'number') { - this.settings.offset = { - x: this.settings.offset, - y: this.settings.offset - }; - } - - //if duplicate messages are not allowed, then only continue if this new message is not a duplicate of one that it already showing - if (this.settings.allow_duplicates || (!this.settings.allow_duplicates && !isDuplicateNotification(this))) { - this.init(); - } - } - - $.extend(Notify.prototype, { - init: function () { - var self = this; - - this.buildNotify(); - if (this.settings.content.icon) { - this.setIcon(); - } - if (this.settings.content.url != "#") { - this.styleURL(); - } - this.styleDismiss(); - this.placement(); - this.bind(); - - this.notify = { - $ele: this.$ele, - update: function (command, update) { - var commands = {}; - if (typeof command === "string") { - commands[command] = update; - } else { - commands = command; - } - for (var cmd in commands) { - switch (cmd) { - case "type": - this.$ele.removeClass('alert-' + self.settings.type); - this.$ele.find('[data-notify="progressbar"] > .progress-bar').removeClass('progress-bar-' + self.settings.type); - self.settings.type = commands[cmd]; - this.$ele.addClass('alert-' + commands[cmd]).find('[data-notify="progressbar"] > .progress-bar').addClass('progress-bar-' + commands[cmd]); - break; - case "icon": - var $icon = this.$ele.find('[data-notify="icon"]'); - if (self.settings.icon_type.toLowerCase() === 'class') { - $icon.removeClass(self.settings.content.icon).addClass(commands[cmd]); - } else { - if (!$icon.is('img')) { - $icon.find('img'); - } - $icon.attr('src', commands[cmd]); - } - self.settings.content.icon = commands[command]; - break; - case "progress": - var newDelay = self.settings.delay - (self.settings.delay * (commands[cmd] / 100)); - this.$ele.data('notify-delay', newDelay); - this.$ele.find('[data-notify="progressbar"] > div').attr('aria-valuenow', commands[cmd]).css('width', commands[cmd] + '%'); - break; - case "url": - this.$ele.find('[data-notify="url"]').attr('href', commands[cmd]); - break; - case "target": - this.$ele.find('[data-notify="url"]').attr('target', commands[cmd]); - break; - default: - this.$ele.find('[data-notify="' + cmd + '"]').html(commands[cmd]); - } - } - var posX = this.$ele.outerHeight() + parseInt(self.settings.spacing) + parseInt(self.settings.offset.y); - self.reposition(posX); - }, - close: function () { - self.close(); - } - }; - - }, - buildNotify: function () { - var content = this.settings.content; - this.$ele = $(String.format(this.settings.template, this.settings.type, content.title, content.message, content.url, content.target)); - this.$ele.attr('data-notify-position', this.settings.placement.from + '-' + this.settings.placement.align); - if (!this.settings.allow_dismiss) { - this.$ele.find('[data-notify="dismiss"]').css('display', 'none'); - } - if ((this.settings.delay <= 0 && !this.settings.showProgressbar) || !this.settings.showProgressbar) { - this.$ele.find('[data-notify="progressbar"]').remove(); - } - }, - setIcon: function () { - this.$ele.addClass('alert-with-icon'); - - if (this.settings.icon_type.toLowerCase() === 'class') { - this.$ele.find('[data-notify="icon"]').addClass(this.settings.content.icon); - } else { - if (this.$ele.find('[data-notify="icon"]').is('img')) { - this.$ele.find('[data-notify="icon"]').attr('src', this.settings.content.icon); - } else { - this.$ele.find('[data-notify="icon"]').append('Notify Icon'); - } - } - }, - styleDismiss: function () { - this.$ele.find('[data-notify="dismiss"]').css({ - position: 'absolute', - right: '10px', - top: '50%', - marginTop: '-13px', - zIndex: this.settings.z_index + 2 - }); - }, - styleURL: function () { - this.$ele.find('[data-notify="url"]').css({ - backgroundImage: 'url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)', - height: '100%', - left: 0, - position: 'absolute', - top: 0, - width: '100%', - zIndex: this.settings.z_index + 1 - }); - }, - placement: function () { - var self = this, - offsetAmt = this.settings.offset.y, - css = { - display: 'inline-block', - margin: '0px auto', - position: this.settings.position ? this.settings.position : (this.settings.element === 'body' ? 'fixed' : 'absolute'), - transition: 'all .5s ease-in-out', - zIndex: this.settings.z_index - }, - hasAnimation = false, - settings = this.settings; - - $('[data-notify-position="' + this.settings.placement.from + '-' + this.settings.placement.align + '"]:not([data-closing="true"])').each(function () { - offsetAmt = Math.max(offsetAmt, parseInt($(this).css(settings.placement.from)) + parseInt($(this).outerHeight()) + parseInt(settings.spacing)); - }); - if (this.settings.newest_on_top === true) { - offsetAmt = this.settings.offset.y; - } - css[this.settings.placement.from] = offsetAmt + 'px'; - - switch (this.settings.placement.align) { - case "left": - case "right": - css[this.settings.placement.align] = this.settings.offset.x + 'px'; - break; - case "center": - css.left = 0; - css.right = 0; - break; - } - this.$ele.css(css).addClass(this.settings.animate.enter); - $.each(Array('webkit-', 'moz-', 'o-', 'ms-', ''), function (index, prefix) { - self.$ele[0].style[prefix + 'AnimationIterationCount'] = 1; - }); - - $(this.settings.element).append(this.$ele); - - if (this.settings.newest_on_top === true) { - offsetAmt = (parseInt(offsetAmt) + parseInt(this.settings.spacing)) + this.$ele.outerHeight(); - this.reposition(offsetAmt); - } - - if ($.isFunction(self.settings.onShow)) { - self.settings.onShow.call(this.$ele); - } - - this.$ele.one(this.animations.start, function () { - hasAnimation = true; - }).one(this.animations.end, function () { - self.$ele.removeClass(self.settings.animate.enter); - if ($.isFunction(self.settings.onShown)) { - self.settings.onShown.call(this); - } - }); - - setTimeout(function () { - if (!hasAnimation) { - if ($.isFunction(self.settings.onShown)) { - self.settings.onShown.call(this); - } - } - }, 600); - }, - bind: function () { - var self = this; - - this.$ele.find('[data-notify="dismiss"]').on('click', function () { - self.close(); - }); - - if ($.isFunction(self.settings.onClick)) { - this.$ele.on('click', function (event) { - if (event.target != self.$ele.find('[data-notify="dismiss"]')[0]) { - self.settings.onClick.call(this, event); - } - }); - } - - this.$ele.mouseover(function () { - $(this).data('data-hover', "true"); - }).mouseout(function () { - $(this).data('data-hover', "false"); - }); - this.$ele.data('data-hover', "false"); - - if (this.settings.delay > 0) { - self.$ele.data('notify-delay', self.settings.delay); - var timer = setInterval(function () { - var delay = parseInt(self.$ele.data('notify-delay')) - self.settings.timer; - if ((self.$ele.data('data-hover') === 'false' && self.settings.mouse_over === "pause") || self.settings.mouse_over != "pause") { - var percent = ((self.settings.delay - delay) / self.settings.delay) * 100; - self.$ele.data('notify-delay', delay); - self.$ele.find('[data-notify="progressbar"] > div').attr('aria-valuenow', percent).css('width', percent + '%'); - } - if (delay <= -(self.settings.timer)) { - clearInterval(timer); - self.close(); - } - }, self.settings.timer); - } - }, - close: function () { - var self = this, - posX = parseInt(this.$ele.css(this.settings.placement.from)), - hasAnimation = false; - - this.$ele.attr('data-closing', 'true').addClass(this.settings.animate.exit); - self.reposition(posX); - - if ($.isFunction(self.settings.onClose)) { - self.settings.onClose.call(this.$ele); - } - - this.$ele.one(this.animations.start, function () { - hasAnimation = true; - }).one(this.animations.end, function () { - $(this).remove(); - if ($.isFunction(self.settings.onClosed)) { - self.settings.onClosed.call(this); - } - }); - - setTimeout(function () { - if (!hasAnimation) { - self.$ele.remove(); - if (self.settings.onClosed) { - self.settings.onClosed(self.$ele); - } - } - }, 600); - }, - reposition: function (posX) { - var self = this, - notifies = '[data-notify-position="' + this.settings.placement.from + '-' + this.settings.placement.align + '"]:not([data-closing="true"])', - $elements = this.$ele.nextAll(notifies); - if (this.settings.newest_on_top === true) { - $elements = this.$ele.prevAll(notifies); - } - $elements.each(function () { - $(this).css(self.settings.placement.from, posX); - posX = (parseInt(posX) + parseInt(self.settings.spacing)) + $(this).outerHeight(); - }); - } - }); - - $.notify = function (content, options) { - var plugin = new Notify(this, content, options); - return plugin.notify; - }; - $.notifyDefaults = function (options) { - defaults = $.extend(true, {}, defaults, options); - return defaults; - }; - - $.notifyClose = function (selector) { - - if (typeof selector === "undefined" || selector === "all") { - $('[data-notify]').find('[data-notify="dismiss"]').trigger('click'); - }else if(selector === 'success' || selector === 'info' || selector === 'warning' || selector === 'danger'){ - $('.alert-' + selector + '[data-notify]').find('[data-notify="dismiss"]').trigger('click'); - } else if(selector){ - $(selector + '[data-notify]').find('[data-notify="dismiss"]').trigger('click'); - } - else { - $('[data-notify-position="' + selector + '"]').find('[data-notify="dismiss"]').trigger('click'); - } - }; - - $.notifyCloseExcept = function (selector) { - - if(selector === 'success' || selector === 'info' || selector === 'warning' || selector === 'danger'){ - $('[data-notify]').not('.alert-' + selector).find('[data-notify="dismiss"]').trigger('click'); - } else{ - $('[data-notify]').not(selector).find('[data-notify="dismiss"]').trigger('click'); - } - }; - - -})); diff --git a/web/templates/boilerplate/assets/js/bootstrap.min.js b/web/templates/boilerplate/assets/js/bootstrap.min.js deleted file mode 100644 index 3d9c6a1..0000000 --- a/web/templates/boilerplate/assets/js/bootstrap.min.js +++ /dev/null @@ -1,6 +0,0 @@ -/*! - * Bootstrap v4.0.0-beta (https://getbootstrap.com) - * Copyright 2011-2017 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors) - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - */ -if("undefined"==typeof jQuery)throw new Error("Bootstrap's JavaScript requires jQuery. jQuery must be included before Bootstrap's JavaScript.");!function(t){var e=jQuery.fn.jquery.split(" ")[0].split(".");if(e[0]<2&&e[1]<9||1==e[0]&&9==e[1]&&e[2]<1||e[0]>=4)throw new Error("Bootstrap's JavaScript requires at least jQuery v1.9.1 but less than v4.0.0")}(),function(){function t(t,e){if(!t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!e||"object"!=typeof e&&"function"!=typeof e?t:e}function e(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function, not "+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}function n(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}var i="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},o=function(){function t(t,e){for(var n=0;n0?n:null}catch(t){return null}},reflow:function(t){return t.offsetHeight},triggerTransitionEnd:function(e){t(e).trigger(s.end)},supportsTransitionEnd:function(){return Boolean(s)},typeCheckConfig:function(t,i,o){for(var r in o)if(o.hasOwnProperty(r)){var s=o[r],a=i[r],l=a&&n(a)?"element":e(a);if(!new RegExp(s).test(l))throw new Error(t.toUpperCase()+': Option "'+r+'" provided type "'+l+'" but expected type "'+s+'".')}}};return s=o(),t.fn.emulateTransitionEnd=r,l.supportsTransitionEnd()&&(t.event.special[l.TRANSITION_END]=i()),l}(jQuery),s=(function(t){var e="alert",i=t.fn[e],s={DISMISS:'[data-dismiss="alert"]'},a={CLOSE:"close.bs.alert",CLOSED:"closed.bs.alert",CLICK_DATA_API:"click.bs.alert.data-api"},l={ALERT:"alert",FADE:"fade",SHOW:"show"},h=function(){function e(t){n(this,e),this._element=t}return e.prototype.close=function(t){t=t||this._element;var e=this._getRootElement(t);this._triggerCloseEvent(e).isDefaultPrevented()||this._removeElement(e)},e.prototype.dispose=function(){t.removeData(this._element,"bs.alert"),this._element=null},e.prototype._getRootElement=function(e){var n=r.getSelectorFromElement(e),i=!1;return n&&(i=t(n)[0]),i||(i=t(e).closest("."+l.ALERT)[0]),i},e.prototype._triggerCloseEvent=function(e){var n=t.Event(a.CLOSE);return t(e).trigger(n),n},e.prototype._removeElement=function(e){var n=this;t(e).removeClass(l.SHOW),r.supportsTransitionEnd()&&t(e).hasClass(l.FADE)?t(e).one(r.TRANSITION_END,function(t){return n._destroyElement(e,t)}).emulateTransitionEnd(150):this._destroyElement(e)},e.prototype._destroyElement=function(e){t(e).detach().trigger(a.CLOSED).remove()},e._jQueryInterface=function(n){return this.each(function(){var i=t(this),o=i.data("bs.alert");o||(o=new e(this),i.data("bs.alert",o)),"close"===n&&o[n](this)})},e._handleDismiss=function(t){return function(e){e&&e.preventDefault(),t.close(this)}},o(e,null,[{key:"VERSION",get:function(){return"4.0.0-beta"}}]),e}();t(document).on(a.CLICK_DATA_API,s.DISMISS,h._handleDismiss(new h)),t.fn[e]=h._jQueryInterface,t.fn[e].Constructor=h,t.fn[e].noConflict=function(){return t.fn[e]=i,h._jQueryInterface}}(jQuery),function(t){var e="button",i=t.fn[e],r={ACTIVE:"active",BUTTON:"btn",FOCUS:"focus"},s={DATA_TOGGLE_CARROT:'[data-toggle^="button"]',DATA_TOGGLE:'[data-toggle="buttons"]',INPUT:"input",ACTIVE:".active",BUTTON:".btn"},a={CLICK_DATA_API:"click.bs.button.data-api",FOCUS_BLUR_DATA_API:"focus.bs.button.data-api blur.bs.button.data-api"},l=function(){function e(t){n(this,e),this._element=t}return e.prototype.toggle=function(){var e=!0,n=!0,i=t(this._element).closest(s.DATA_TOGGLE)[0];if(i){var o=t(this._element).find(s.INPUT)[0];if(o){if("radio"===o.type)if(o.checked&&t(this._element).hasClass(r.ACTIVE))e=!1;else{var a=t(i).find(s.ACTIVE)[0];a&&t(a).removeClass(r.ACTIVE)}if(e){if(o.hasAttribute("disabled")||i.hasAttribute("disabled")||o.classList.contains("disabled")||i.classList.contains("disabled"))return;o.checked=!t(this._element).hasClass(r.ACTIVE),t(o).trigger("change")}o.focus(),n=!1}}n&&this._element.setAttribute("aria-pressed",!t(this._element).hasClass(r.ACTIVE)),e&&t(this._element).toggleClass(r.ACTIVE)},e.prototype.dispose=function(){t.removeData(this._element,"bs.button"),this._element=null},e._jQueryInterface=function(n){return this.each(function(){var i=t(this).data("bs.button");i||(i=new e(this),t(this).data("bs.button",i)),"toggle"===n&&i[n]()})},o(e,null,[{key:"VERSION",get:function(){return"4.0.0-beta"}}]),e}();t(document).on(a.CLICK_DATA_API,s.DATA_TOGGLE_CARROT,function(e){e.preventDefault();var n=e.target;t(n).hasClass(r.BUTTON)||(n=t(n).closest(s.BUTTON)),l._jQueryInterface.call(t(n),"toggle")}).on(a.FOCUS_BLUR_DATA_API,s.DATA_TOGGLE_CARROT,function(e){var n=t(e.target).closest(s.BUTTON)[0];t(n).toggleClass(r.FOCUS,/^focus(in)?$/.test(e.type))}),t.fn[e]=l._jQueryInterface,t.fn[e].Constructor=l,t.fn[e].noConflict=function(){return t.fn[e]=i,l._jQueryInterface}}(jQuery),function(t){var e="carousel",s="bs.carousel",a="."+s,l=t.fn[e],h={interval:5e3,keyboard:!0,slide:!1,pause:"hover",wrap:!0},c={interval:"(number|boolean)",keyboard:"boolean",slide:"(boolean|string)",pause:"(string|boolean)",wrap:"boolean"},u={NEXT:"next",PREV:"prev",LEFT:"left",RIGHT:"right"},d={SLIDE:"slide"+a,SLID:"slid"+a,KEYDOWN:"keydown"+a,MOUSEENTER:"mouseenter"+a,MOUSELEAVE:"mouseleave"+a,TOUCHEND:"touchend"+a,LOAD_DATA_API:"load.bs.carousel.data-api",CLICK_DATA_API:"click.bs.carousel.data-api"},f={CAROUSEL:"carousel",ACTIVE:"active",SLIDE:"slide",RIGHT:"carousel-item-right",LEFT:"carousel-item-left",NEXT:"carousel-item-next",PREV:"carousel-item-prev",ITEM:"carousel-item"},p={ACTIVE:".active",ACTIVE_ITEM:".active.carousel-item",ITEM:".carousel-item",NEXT_PREV:".carousel-item-next, .carousel-item-prev",INDICATORS:".carousel-indicators",DATA_SLIDE:"[data-slide], [data-slide-to]",DATA_RIDE:'[data-ride="carousel"]'},_=function(){function l(e,i){n(this,l),this._items=null,this._interval=null,this._activeElement=null,this._isPaused=!1,this._isSliding=!1,this.touchTimeout=null,this._config=this._getConfig(i),this._element=t(e)[0],this._indicatorsElement=t(this._element).find(p.INDICATORS)[0],this._addEventListeners()}return l.prototype.next=function(){this._isSliding||this._slide(u.NEXT)},l.prototype.nextWhenVisible=function(){document.hidden||this.next()},l.prototype.prev=function(){this._isSliding||this._slide(u.PREV)},l.prototype.pause=function(e){e||(this._isPaused=!0),t(this._element).find(p.NEXT_PREV)[0]&&r.supportsTransitionEnd()&&(r.triggerTransitionEnd(this._element),this.cycle(!0)),clearInterval(this._interval),this._interval=null},l.prototype.cycle=function(t){t||(this._isPaused=!1),this._interval&&(clearInterval(this._interval),this._interval=null),this._config.interval&&!this._isPaused&&(this._interval=setInterval((document.visibilityState?this.nextWhenVisible:this.next).bind(this),this._config.interval))},l.prototype.to=function(e){var n=this;this._activeElement=t(this._element).find(p.ACTIVE_ITEM)[0];var i=this._getItemIndex(this._activeElement);if(!(e>this._items.length-1||e<0))if(this._isSliding)t(this._element).one(d.SLID,function(){return n.to(e)});else{if(i===e)return this.pause(),void this.cycle();var o=e>i?u.NEXT:u.PREV;this._slide(o,this._items[e])}},l.prototype.dispose=function(){t(this._element).off(a),t.removeData(this._element,s),this._items=null,this._config=null,this._element=null,this._interval=null,this._isPaused=null,this._isSliding=null,this._activeElement=null,this._indicatorsElement=null},l.prototype._getConfig=function(n){return n=t.extend({},h,n),r.typeCheckConfig(e,n,c),n},l.prototype._addEventListeners=function(){var e=this;this._config.keyboard&&t(this._element).on(d.KEYDOWN,function(t){return e._keydown(t)}),"hover"===this._config.pause&&(t(this._element).on(d.MOUSEENTER,function(t){return e.pause(t)}).on(d.MOUSELEAVE,function(t){return e.cycle(t)}),"ontouchstart"in document.documentElement&&t(this._element).on(d.TOUCHEND,function(){e.pause(),e.touchTimeout&&clearTimeout(e.touchTimeout),e.touchTimeout=setTimeout(function(t){return e.cycle(t)},500+e._config.interval)}))},l.prototype._keydown=function(t){if(!/input|textarea/i.test(t.target.tagName))switch(t.which){case 37:t.preventDefault(),this.prev();break;case 39:t.preventDefault(),this.next();break;default:return}},l.prototype._getItemIndex=function(e){return this._items=t.makeArray(t(e).parent().find(p.ITEM)),this._items.indexOf(e)},l.prototype._getItemByDirection=function(t,e){var n=t===u.NEXT,i=t===u.PREV,o=this._getItemIndex(e),r=this._items.length-1;if((i&&0===o||n&&o===r)&&!this._config.wrap)return e;var s=(o+(t===u.PREV?-1:1))%this._items.length;return-1===s?this._items[this._items.length-1]:this._items[s]},l.prototype._triggerSlideEvent=function(e,n){var i=this._getItemIndex(e),o=this._getItemIndex(t(this._element).find(p.ACTIVE_ITEM)[0]),r=t.Event(d.SLIDE,{relatedTarget:e,direction:n,from:o,to:i});return t(this._element).trigger(r),r},l.prototype._setActiveIndicatorElement=function(e){if(this._indicatorsElement){t(this._indicatorsElement).find(p.ACTIVE).removeClass(f.ACTIVE);var n=this._indicatorsElement.children[this._getItemIndex(e)];n&&t(n).addClass(f.ACTIVE)}},l.prototype._slide=function(e,n){var i=this,o=t(this._element).find(p.ACTIVE_ITEM)[0],s=this._getItemIndex(o),a=n||o&&this._getItemByDirection(e,o),l=this._getItemIndex(a),h=Boolean(this._interval),c=void 0,_=void 0,g=void 0;if(e===u.NEXT?(c=f.LEFT,_=f.NEXT,g=u.LEFT):(c=f.RIGHT,_=f.PREV,g=u.RIGHT),a&&t(a).hasClass(f.ACTIVE))this._isSliding=!1;else if(!this._triggerSlideEvent(a,g).isDefaultPrevented()&&o&&a){this._isSliding=!0,h&&this.pause(),this._setActiveIndicatorElement(a);var m=t.Event(d.SLID,{relatedTarget:a,direction:g,from:s,to:l});r.supportsTransitionEnd()&&t(this._element).hasClass(f.SLIDE)?(t(a).addClass(_),r.reflow(a),t(o).addClass(c),t(a).addClass(c),t(o).one(r.TRANSITION_END,function(){t(a).removeClass(c+" "+_).addClass(f.ACTIVE),t(o).removeClass(f.ACTIVE+" "+_+" "+c),i._isSliding=!1,setTimeout(function(){return t(i._element).trigger(m)},0)}).emulateTransitionEnd(600)):(t(o).removeClass(f.ACTIVE),t(a).addClass(f.ACTIVE),this._isSliding=!1,t(this._element).trigger(m)),h&&this.cycle()}},l._jQueryInterface=function(e){return this.each(function(){var n=t(this).data(s),o=t.extend({},h,t(this).data());"object"===(void 0===e?"undefined":i(e))&&t.extend(o,e);var r="string"==typeof e?e:o.slide;if(n||(n=new l(this,o),t(this).data(s,n)),"number"==typeof e)n.to(e);else if("string"==typeof r){if(void 0===n[r])throw new Error('No method named "'+r+'"');n[r]()}else o.interval&&(n.pause(),n.cycle())})},l._dataApiClickHandler=function(e){var n=r.getSelectorFromElement(this);if(n){var i=t(n)[0];if(i&&t(i).hasClass(f.CAROUSEL)){var o=t.extend({},t(i).data(),t(this).data()),a=this.getAttribute("data-slide-to");a&&(o.interval=!1),l._jQueryInterface.call(t(i),o),a&&t(i).data(s).to(a),e.preventDefault()}}},o(l,null,[{key:"VERSION",get:function(){return"4.0.0-beta"}},{key:"Default",get:function(){return h}}]),l}();t(document).on(d.CLICK_DATA_API,p.DATA_SLIDE,_._dataApiClickHandler),t(window).on(d.LOAD_DATA_API,function(){t(p.DATA_RIDE).each(function(){var e=t(this);_._jQueryInterface.call(e,e.data())})}),t.fn[e]=_._jQueryInterface,t.fn[e].Constructor=_,t.fn[e].noConflict=function(){return t.fn[e]=l,_._jQueryInterface}}(jQuery),function(t){var e="collapse",s="bs.collapse",a=t.fn[e],l={toggle:!0,parent:""},h={toggle:"boolean",parent:"string"},c={SHOW:"show.bs.collapse",SHOWN:"shown.bs.collapse",HIDE:"hide.bs.collapse",HIDDEN:"hidden.bs.collapse",CLICK_DATA_API:"click.bs.collapse.data-api"},u={SHOW:"show",COLLAPSE:"collapse",COLLAPSING:"collapsing",COLLAPSED:"collapsed"},d={WIDTH:"width",HEIGHT:"height"},f={ACTIVES:".show, .collapsing",DATA_TOGGLE:'[data-toggle="collapse"]'},p=function(){function a(e,i){n(this,a),this._isTransitioning=!1,this._element=e,this._config=this._getConfig(i),this._triggerArray=t.makeArray(t('[data-toggle="collapse"][href="#'+e.id+'"],[data-toggle="collapse"][data-target="#'+e.id+'"]'));for(var o=t(f.DATA_TOGGLE),s=0;s0&&this._triggerArray.push(l)}this._parent=this._config.parent?this._getParent():null,this._config.parent||this._addAriaAndCollapsedClass(this._element,this._triggerArray),this._config.toggle&&this.toggle()}return a.prototype.toggle=function(){t(this._element).hasClass(u.SHOW)?this.hide():this.show()},a.prototype.show=function(){var e=this;if(!this._isTransitioning&&!t(this._element).hasClass(u.SHOW)){var n=void 0,i=void 0;if(this._parent&&((n=t.makeArray(t(this._parent).children().children(f.ACTIVES))).length||(n=null)),!(n&&(i=t(n).data(s))&&i._isTransitioning)){var o=t.Event(c.SHOW);if(t(this._element).trigger(o),!o.isDefaultPrevented()){n&&(a._jQueryInterface.call(t(n),"hide"),i||t(n).data(s,null));var l=this._getDimension();t(this._element).removeClass(u.COLLAPSE).addClass(u.COLLAPSING),this._element.style[l]=0,this._triggerArray.length&&t(this._triggerArray).removeClass(u.COLLAPSED).attr("aria-expanded",!0),this.setTransitioning(!0);var h=function(){t(e._element).removeClass(u.COLLAPSING).addClass(u.COLLAPSE).addClass(u.SHOW),e._element.style[l]="",e.setTransitioning(!1),t(e._element).trigger(c.SHOWN)};if(r.supportsTransitionEnd()){var d="scroll"+(l[0].toUpperCase()+l.slice(1));t(this._element).one(r.TRANSITION_END,h).emulateTransitionEnd(600),this._element.style[l]=this._element[d]+"px"}else h()}}}},a.prototype.hide=function(){var e=this;if(!this._isTransitioning&&t(this._element).hasClass(u.SHOW)){var n=t.Event(c.HIDE);if(t(this._element).trigger(n),!n.isDefaultPrevented()){var i=this._getDimension();if(this._element.style[i]=this._element.getBoundingClientRect()[i]+"px",r.reflow(this._element),t(this._element).addClass(u.COLLAPSING).removeClass(u.COLLAPSE).removeClass(u.SHOW),this._triggerArray.length)for(var o=0;o0},l.prototype._getPopperConfig=function(){var t={placement:this._getPlacement(),modifiers:{offset:{offset:this._config.offset},flip:{enabled:this._config.flip}}};return this._inNavbar&&(t.modifiers.applyStyle={enabled:!this._inNavbar}),t},l._jQueryInterface=function(e){return this.each(function(){var n=t(this).data(s),o="object"===(void 0===e?"undefined":i(e))?e:null;if(n||(n=new l(this,o),t(this).data(s,n)),"string"==typeof e){if(void 0===n[e])throw new Error('No method named "'+e+'"');n[e]()}})},l._clearMenus=function(e){if(!e||3!==e.which&&("keyup"!==e.type||9===e.which))for(var n=t.makeArray(t(d.DATA_TOGGLE)),i=0;i0&&r--,40===e.which&&rdocument.documentElement.clientHeight;!this._isBodyOverflowing&&t&&(this._element.style.paddingLeft=this._scrollbarWidth+"px"),this._isBodyOverflowing&&!t&&(this._element.style.paddingRight=this._scrollbarWidth+"px")},a.prototype._resetAdjustments=function(){this._element.style.paddingLeft="",this._element.style.paddingRight=""},a.prototype._checkScrollbar=function(){this._isBodyOverflowing=document.body.clientWidth=n){var i=this._targets[this._targets.length-1];this._activeTarget!==i&&this._activate(i)}else{if(this._activeTarget&&t0)return this._activeTarget=null,void this._clear();for(var o=this._offsets.length;o--;)this._activeTarget!==this._targets[o]&&t>=this._offsets[o]&&(void 0===this._offsets[o+1]||t .dropdown-menu .active"},l=function(){function e(t){n(this,e),this._element=t}return e.prototype.show=function(){var e=this;if(!(this._element.parentNode&&this._element.parentNode.nodeType===Node.ELEMENT_NODE&&t(this._element).hasClass(s.ACTIVE)||t(this._element).hasClass(s.DISABLED))){var n=void 0,o=void 0,l=t(this._element).closest(a.NAV_LIST_GROUP)[0],h=r.getSelectorFromElement(this._element);l&&(o=t.makeArray(t(l).find(a.ACTIVE)),o=o[o.length-1]);var c=t.Event(i.HIDE,{relatedTarget:this._element}),u=t.Event(i.SHOW,{relatedTarget:o});if(o&&t(o).trigger(c),t(this._element).trigger(u),!u.isDefaultPrevented()&&!c.isDefaultPrevented()){h&&(n=t(h)[0]),this._activate(this._element,l);var d=function(){var n=t.Event(i.HIDDEN,{relatedTarget:e._element}),r=t.Event(i.SHOWN,{relatedTarget:o});t(o).trigger(n),t(e._element).trigger(r)};n?this._activate(n,n.parentNode,d):d()}}},e.prototype.dispose=function(){t.removeData(this._element,"bs.tab"),this._element=null},e.prototype._activate=function(e,n,i){var o=this,l=t(n).find(a.ACTIVE)[0],h=i&&r.supportsTransitionEnd()&&l&&t(l).hasClass(s.FADE),c=function(){return o._transitionComplete(e,l,h,i)};l&&h?t(l).one(r.TRANSITION_END,c).emulateTransitionEnd(150):c(),l&&t(l).removeClass(s.SHOW)},e.prototype._transitionComplete=function(e,n,i,o){if(n){t(n).removeClass(s.ACTIVE);var l=t(n.parentNode).find(a.DROPDOWN_ACTIVE_CHILD)[0];l&&t(l).removeClass(s.ACTIVE),n.setAttribute("aria-expanded",!1)}if(t(e).addClass(s.ACTIVE),e.setAttribute("aria-expanded",!0),i?(r.reflow(e),t(e).addClass(s.SHOW)):t(e).removeClass(s.FADE),e.parentNode&&t(e.parentNode).hasClass(s.DROPDOWN_MENU)){var h=t(e).closest(a.DROPDOWN)[0];h&&t(h).find(a.DROPDOWN_TOGGLE).addClass(s.ACTIVE),e.setAttribute("aria-expanded",!0)}o&&o()},e._jQueryInterface=function(n){return this.each(function(){var i=t(this),o=i.data("bs.tab");if(o||(o=new e(this),i.data("bs.tab",o)),"string"==typeof n){if(void 0===o[n])throw new Error('No method named "'+n+'"');o[n]()}})},o(e,null,[{key:"VERSION",get:function(){return"4.0.0-beta"}}]),e}();t(document).on(i.CLICK_DATA_API,a.DATA_TOGGLE,function(e){e.preventDefault(),l._jQueryInterface.call(t(this),"show")}),t.fn.tab=l._jQueryInterface,t.fn.tab.Constructor=l,t.fn.tab.noConflict=function(){return t.fn.tab=e,l._jQueryInterface}}(jQuery),function(t){if("undefined"==typeof Popper)throw new Error("Bootstrap tooltips require Popper.js (https://popper.js.org)");var e="tooltip",s=".bs.tooltip",a=t.fn[e],l=new RegExp("(^|\\s)bs-tooltip\\S+","g"),h={animation:"boolean",template:"string",title:"(string|element|function)",trigger:"string",delay:"(number|object)",html:"boolean",selector:"(string|boolean)",placement:"(string|function)",offset:"(number|string)",container:"(string|element|boolean)",fallbackPlacement:"(string|array)"},c={AUTO:"auto",TOP:"top",RIGHT:"right",BOTTOM:"bottom",LEFT:"left"},u={animation:!0,template:'',trigger:"hover focus",title:"",delay:0,html:!1,selector:!1,placement:"top",offset:0,container:!1,fallbackPlacement:"flip"},d={SHOW:"show",OUT:"out"},f={HIDE:"hide"+s,HIDDEN:"hidden"+s,SHOW:"show"+s,SHOWN:"shown"+s,INSERTED:"inserted"+s,CLICK:"click"+s,FOCUSIN:"focusin"+s,FOCUSOUT:"focusout"+s,MOUSEENTER:"mouseenter"+s,MOUSELEAVE:"mouseleave"+s},p={FADE:"fade",SHOW:"show"},_={TOOLTIP:".tooltip",TOOLTIP_INNER:".tooltip-inner",ARROW:".arrow"},g={HOVER:"hover",FOCUS:"focus",CLICK:"click",MANUAL:"manual"},m=function(){function a(t,e){n(this,a),this._isEnabled=!0,this._timeout=0,this._hoverState="",this._activeTrigger={},this._popper=null,this.element=t,this.config=this._getConfig(e),this.tip=null,this._setListeners()}return a.prototype.enable=function(){this._isEnabled=!0},a.prototype.disable=function(){this._isEnabled=!1},a.prototype.toggleEnabled=function(){this._isEnabled=!this._isEnabled},a.prototype.toggle=function(e){if(e){var n=this.constructor.DATA_KEY,i=t(e.currentTarget).data(n);i||(i=new this.constructor(e.currentTarget,this._getDelegateConfig()),t(e.currentTarget).data(n,i)),i._activeTrigger.click=!i._activeTrigger.click,i._isWithActiveTrigger()?i._enter(null,i):i._leave(null,i)}else{if(t(this.getTipElement()).hasClass(p.SHOW))return void this._leave(null,this);this._enter(null,this)}},a.prototype.dispose=function(){clearTimeout(this._timeout),t.removeData(this.element,this.constructor.DATA_KEY),t(this.element).off(this.constructor.EVENT_KEY),t(this.element).closest(".modal").off("hide.bs.modal"),this.tip&&t(this.tip).remove(),this._isEnabled=null,this._timeout=null,this._hoverState=null,this._activeTrigger=null,null!==this._popper&&this._popper.destroy(),this._popper=null,this.element=null,this.config=null,this.tip=null},a.prototype.show=function(){var e=this;if("none"===t(this.element).css("display"))throw new Error("Please use show on visible elements");var n=t.Event(this.constructor.Event.SHOW);if(this.isWithContent()&&this._isEnabled){t(this.element).trigger(n);var i=t.contains(this.element.ownerDocument.documentElement,this.element);if(n.isDefaultPrevented()||!i)return;var o=this.getTipElement(),s=r.getUID(this.constructor.NAME);o.setAttribute("id",s),this.element.setAttribute("aria-describedby",s),this.setContent(),this.config.animation&&t(o).addClass(p.FADE);var l="function"==typeof this.config.placement?this.config.placement.call(this,o,this.element):this.config.placement,h=this._getAttachment(l);this.addAttachmentClass(h);var c=!1===this.config.container?document.body:t(this.config.container);t(o).data(this.constructor.DATA_KEY,this),t.contains(this.element.ownerDocument.documentElement,this.tip)||t(o).appendTo(c),t(this.element).trigger(this.constructor.Event.INSERTED),this._popper=new Popper(this.element,o,{placement:h,modifiers:{offset:{offset:this.config.offset},flip:{behavior:this.config.fallbackPlacement},arrow:{element:_.ARROW}},onCreate:function(t){t.originalPlacement!==t.placement&&e._handlePopperPlacementChange(t)},onUpdate:function(t){e._handlePopperPlacementChange(t)}}),t(o).addClass(p.SHOW),"ontouchstart"in document.documentElement&&t("body").children().on("mouseover",null,t.noop);var u=function(){e.config.animation&&e._fixTransition();var n=e._hoverState;e._hoverState=null,t(e.element).trigger(e.constructor.Event.SHOWN),n===d.OUT&&e._leave(null,e)};r.supportsTransitionEnd()&&t(this.tip).hasClass(p.FADE)?t(this.tip).one(r.TRANSITION_END,u).emulateTransitionEnd(a._TRANSITION_DURATION):u()}},a.prototype.hide=function(e){var n=this,i=this.getTipElement(),o=t.Event(this.constructor.Event.HIDE),s=function(){n._hoverState!==d.SHOW&&i.parentNode&&i.parentNode.removeChild(i),n._cleanTipClass(),n.element.removeAttribute("aria-describedby"),t(n.element).trigger(n.constructor.Event.HIDDEN),null!==n._popper&&n._popper.destroy(),e&&e()};t(this.element).trigger(o),o.isDefaultPrevented()||(t(i).removeClass(p.SHOW),"ontouchstart"in document.documentElement&&t("body").children().off("mouseover",null,t.noop),this._activeTrigger[g.CLICK]=!1,this._activeTrigger[g.FOCUS]=!1,this._activeTrigger[g.HOVER]=!1,r.supportsTransitionEnd()&&t(this.tip).hasClass(p.FADE)?t(i).one(r.TRANSITION_END,s).emulateTransitionEnd(150):s(),this._hoverState="")},a.prototype.update=function(){null!==this._popper&&this._popper.scheduleUpdate()},a.prototype.isWithContent=function(){return Boolean(this.getTitle())},a.prototype.addAttachmentClass=function(e){t(this.getTipElement()).addClass("bs-tooltip-"+e)},a.prototype.getTipElement=function(){return this.tip=this.tip||t(this.config.template)[0]},a.prototype.setContent=function(){var e=t(this.getTipElement());this.setElementContent(e.find(_.TOOLTIP_INNER),this.getTitle()),e.removeClass(p.FADE+" "+p.SHOW)},a.prototype.setElementContent=function(e,n){var o=this.config.html;"object"===(void 0===n?"undefined":i(n))&&(n.nodeType||n.jquery)?o?t(n).parent().is(e)||e.empty().append(n):e.text(t(n).text()):e[o?"html":"text"](n)},a.prototype.getTitle=function(){var t=this.element.getAttribute("data-original-title");return t||(t="function"==typeof this.config.title?this.config.title.call(this.element):this.config.title),t},a.prototype._getAttachment=function(t){return c[t.toUpperCase()]},a.prototype._setListeners=function(){var e=this;this.config.trigger.split(" ").forEach(function(n){if("click"===n)t(e.element).on(e.constructor.Event.CLICK,e.config.selector,function(t){return e.toggle(t)});else if(n!==g.MANUAL){var i=n===g.HOVER?e.constructor.Event.MOUSEENTER:e.constructor.Event.FOCUSIN,o=n===g.HOVER?e.constructor.Event.MOUSELEAVE:e.constructor.Event.FOCUSOUT;t(e.element).on(i,e.config.selector,function(t){return e._enter(t)}).on(o,e.config.selector,function(t){return e._leave(t)})}t(e.element).closest(".modal").on("hide.bs.modal",function(){return e.hide()})}),this.config.selector?this.config=t.extend({},this.config,{trigger:"manual",selector:""}):this._fixTitle()},a.prototype._fixTitle=function(){var t=i(this.element.getAttribute("data-original-title"));(this.element.getAttribute("title")||"string"!==t)&&(this.element.setAttribute("data-original-title",this.element.getAttribute("title")||""),this.element.setAttribute("title",""))},a.prototype._enter=function(e,n){var i=this.constructor.DATA_KEY;(n=n||t(e.currentTarget).data(i))||(n=new this.constructor(e.currentTarget,this._getDelegateConfig()),t(e.currentTarget).data(i,n)),e&&(n._activeTrigger["focusin"===e.type?g.FOCUS:g.HOVER]=!0),t(n.getTipElement()).hasClass(p.SHOW)||n._hoverState===d.SHOW?n._hoverState=d.SHOW:(clearTimeout(n._timeout),n._hoverState=d.SHOW,n.config.delay&&n.config.delay.show?n._timeout=setTimeout(function(){n._hoverState===d.SHOW&&n.show()},n.config.delay.show):n.show())},a.prototype._leave=function(e,n){var i=this.constructor.DATA_KEY;(n=n||t(e.currentTarget).data(i))||(n=new this.constructor(e.currentTarget,this._getDelegateConfig()),t(e.currentTarget).data(i,n)),e&&(n._activeTrigger["focusout"===e.type?g.FOCUS:g.HOVER]=!1),n._isWithActiveTrigger()||(clearTimeout(n._timeout),n._hoverState=d.OUT,n.config.delay&&n.config.delay.hide?n._timeout=setTimeout(function(){n._hoverState===d.OUT&&n.hide()},n.config.delay.hide):n.hide())},a.prototype._isWithActiveTrigger=function(){for(var t in this._activeTrigger)if(this._activeTrigger[t])return!0;return!1},a.prototype._getConfig=function(n){return(n=t.extend({},this.constructor.Default,t(this.element).data(),n)).delay&&"number"==typeof n.delay&&(n.delay={show:n.delay,hide:n.delay}),n.title&&"number"==typeof n.title&&(n.title=n.title.toString()),n.content&&"number"==typeof n.content&&(n.content=n.content.toString()),r.typeCheckConfig(e,n,this.constructor.DefaultType),n},a.prototype._getDelegateConfig=function(){var t={};if(this.config)for(var e in this.config)this.constructor.Default[e]!==this.config[e]&&(t[e]=this.config[e]);return t},a.prototype._cleanTipClass=function(){var e=t(this.getTipElement()),n=e.attr("class").match(l);null!==n&&n.length>0&&e.removeClass(n.join(""))},a.prototype._handlePopperPlacementChange=function(t){this._cleanTipClass(),this.addAttachmentClass(this._getAttachment(t.placement))},a.prototype._fixTransition=function(){var e=this.getTipElement(),n=this.config.animation;null===e.getAttribute("x-placement")&&(t(e).removeClass(p.FADE),this.config.animation=!1,this.hide(),this.show(),this.config.animation=n)},a._jQueryInterface=function(e){return this.each(function(){var n=t(this).data("bs.tooltip"),o="object"===(void 0===e?"undefined":i(e))&&e;if((n||!/dispose|hide/.test(e))&&(n||(n=new a(this,o),t(this).data("bs.tooltip",n)),"string"==typeof e)){if(void 0===n[e])throw new Error('No method named "'+e+'"');n[e]()}})},o(a,null,[{key:"VERSION",get:function(){return"4.0.0-beta"}},{key:"Default",get:function(){return u}},{key:"NAME",get:function(){return e}},{key:"DATA_KEY",get:function(){return"bs.tooltip"}},{key:"Event",get:function(){return f}},{key:"EVENT_KEY",get:function(){return s}},{key:"DefaultType",get:function(){return h}}]),a}();return t.fn[e]=m._jQueryInterface,t.fn[e].Constructor=m,t.fn[e].noConflict=function(){return t.fn[e]=a,m._jQueryInterface},m}(jQuery));!function(r){var a="popover",l=".bs.popover",h=r.fn[a],c=new RegExp("(^|\\s)bs-popover\\S+","g"),u=r.extend({},s.Default,{placement:"right",trigger:"click",content:"",template:''}),d=r.extend({},s.DefaultType,{content:"(string|element|function)"}),f={FADE:"fade",SHOW:"show"},p={TITLE:".popover-header",CONTENT:".popover-body"},_={HIDE:"hide"+l,HIDDEN:"hidden"+l,SHOW:"show"+l,SHOWN:"shown"+l,INSERTED:"inserted"+l,CLICK:"click"+l,FOCUSIN:"focusin"+l,FOCUSOUT:"focusout"+l,MOUSEENTER:"mouseenter"+l,MOUSELEAVE:"mouseleave"+l},g=function(s){function h(){return n(this,h),t(this,s.apply(this,arguments))}return e(h,s),h.prototype.isWithContent=function(){return this.getTitle()||this._getContent()},h.prototype.addAttachmentClass=function(t){r(this.getTipElement()).addClass("bs-popover-"+t)},h.prototype.getTipElement=function(){return this.tip=this.tip||r(this.config.template)[0]},h.prototype.setContent=function(){var t=r(this.getTipElement());this.setElementContent(t.find(p.TITLE),this.getTitle()),this.setElementContent(t.find(p.CONTENT),this._getContent()),t.removeClass(f.FADE+" "+f.SHOW)},h.prototype._getContent=function(){return this.element.getAttribute("data-content")||("function"==typeof this.config.content?this.config.content.call(this.element):this.config.content)},h.prototype._cleanTipClass=function(){var t=r(this.getTipElement()),e=t.attr("class").match(c);null!==e&&e.length>0&&t.removeClass(e.join(""))},h._jQueryInterface=function(t){return this.each(function(){var e=r(this).data("bs.popover"),n="object"===(void 0===t?"undefined":i(t))?t:null;if((e||!/destroy|hide/.test(t))&&(e||(e=new h(this,n),r(this).data("bs.popover",e)),"string"==typeof t)){if(void 0===e[t])throw new Error('No method named "'+t+'"');e[t]()}})},o(h,null,[{key:"VERSION",get:function(){return"4.0.0-beta"}},{key:"Default",get:function(){return u}},{key:"NAME",get:function(){return a}},{key:"DATA_KEY",get:function(){return"bs.popover"}},{key:"Event",get:function(){return _}},{key:"EVENT_KEY",get:function(){return l}},{key:"DefaultType",get:function(){return d}}]),h}(s);r.fn[a]=g._jQueryInterface,r.fn[a].Constructor=g,r.fn[a].noConflict=function(){return r.fn[a]=h,g._jQueryInterface}}(jQuery)}(); diff --git a/web/templates/boilerplate/assets/js/chartjs.min.js b/web/templates/boilerplate/assets/js/chartjs.min.js deleted file mode 100644 index f62dda7..0000000 --- a/web/templates/boilerplate/assets/js/chartjs.min.js +++ /dev/null @@ -1,10 +0,0 @@ -/*! - * Chart.js - * http://chartjs.org/ - * Version: 2.7.1 - * - * Copyright 2017 Nick Downie - * Released under the MIT license - * https://github.com/chartjs/Chart.js/blob/master/LICENSE.md - */ -!function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).Chart=t()}}(function(){return function t(e,n,i){function a(r,l){if(!n[r]){if(!e[r]){var s="function"==typeof require&&require;if(!l&&s)return s(r,!0);if(o)return o(r,!0);var u=new Error("Cannot find module '"+r+"'");throw u.code="MODULE_NOT_FOUND",u}var d=n[r]={exports:{}};e[r][0].call(d.exports,function(t){var n=e[r][1][t];return a(n||t)},d,d.exports,t,e,n,i)}return n[r].exports}for(var o="function"==typeof require&&require,r=0;rn?(e+.05)/(n+.05):(n+.05)/(e+.05)},level:function(t){var e=this.contrast(t);return e>=7.1?"AAA":e>=4.5?"AA":""},dark:function(){var t=this.values.rgb;return(299*t[0]+587*t[1]+114*t[2])/1e3<128},light:function(){return!this.dark()},negate:function(){for(var t=[],e=0;e<3;e++)t[e]=255-this.values.rgb[e];return this.setValues("rgb",t),this},lighten:function(t){var e=this.values.hsl;return e[2]+=e[2]*t,this.setValues("hsl",e),this},darken:function(t){var e=this.values.hsl;return e[2]-=e[2]*t,this.setValues("hsl",e),this},saturate:function(t){var e=this.values.hsl;return e[1]+=e[1]*t,this.setValues("hsl",e),this},desaturate:function(t){var e=this.values.hsl;return e[1]-=e[1]*t,this.setValues("hsl",e),this},whiten:function(t){var e=this.values.hwb;return e[1]+=e[1]*t,this.setValues("hwb",e),this},blacken:function(t){var e=this.values.hwb;return e[2]+=e[2]*t,this.setValues("hwb",e),this},greyscale:function(){var t=this.values.rgb,e=.3*t[0]+.59*t[1]+.11*t[2];return this.setValues("rgb",[e,e,e]),this},clearer:function(t){var e=this.values.alpha;return this.setValues("alpha",e-e*t),this},opaquer:function(t){var e=this.values.alpha;return this.setValues("alpha",e+e*t),this},rotate:function(t){var e=this.values.hsl,n=(e[0]+t)%360;return e[0]=n<0?360+n:n,this.setValues("hsl",e),this},mix:function(t,e){var n=this,i=t,a=void 0===e?.5:e,o=2*a-1,r=n.alpha()-i.alpha(),l=((o*r==-1?o:(o+r)/(1+o*r))+1)/2,s=1-l;return this.rgb(l*n.red()+s*i.red(),l*n.green()+s*i.green(),l*n.blue()+s*i.blue()).alpha(n.alpha()*a+i.alpha()*(1-a))},toJSON:function(){return this.rgb()},clone:function(){var t,e,n=new o,i=this.values,a=n.values;for(var r in i)i.hasOwnProperty(r)&&(t=i[r],"[object Array]"===(e={}.toString.call(t))?a[r]=t.slice(0):"[object Number]"===e?a[r]=t:console.error("unexpected color value:",t));return n}},o.prototype.spaces={rgb:["red","green","blue"],hsl:["hue","saturation","lightness"],hsv:["hue","saturation","value"],hwb:["hue","whiteness","blackness"],cmyk:["cyan","magenta","yellow","black"]},o.prototype.maxes={rgb:[255,255,255],hsl:[360,100,100],hsv:[360,100,100],hwb:[360,100,100],cmyk:[100,100,100,100]},o.prototype.getValues=function(t){for(var e=this.values,n={},i=0;i.04045?Math.pow((e+.055)/1.055,2.4):e/12.92)+.3576*(n=n>.04045?Math.pow((n+.055)/1.055,2.4):n/12.92)+.1805*(i=i>.04045?Math.pow((i+.055)/1.055,2.4):i/12.92)),100*(.2126*e+.7152*n+.0722*i),100*(.0193*e+.1192*n+.9505*i)]}function d(t){var e,n,i,a=u(t),o=a[0],r=a[1],l=a[2];return o/=95.047,r/=100,l/=108.883,o=o>.008856?Math.pow(o,1/3):7.787*o+16/116,r=r>.008856?Math.pow(r,1/3):7.787*r+16/116,l=l>.008856?Math.pow(l,1/3):7.787*l+16/116,e=116*r-16,n=500*(o-r),i=200*(r-l),[e,n,i]}function c(t){var e,n,i,a,o,r=t[0]/360,l=t[1]/100,s=t[2]/100;if(0==l)return o=255*s,[o,o,o];e=2*s-(n=s<.5?s*(1+l):s+l-s*l),a=[0,0,0];for(var u=0;u<3;u++)(i=r+1/3*-(u-1))<0&&i++,i>1&&i--,o=6*i<1?e+6*(n-e)*i:2*i<1?n:3*i<2?e+(n-e)*(2/3-i)*6:e,a[u]=255*o;return a}function h(t){var e=t[0]/60,n=t[1]/100,i=t[2]/100,a=Math.floor(e)%6,o=e-Math.floor(e),r=255*i*(1-n),l=255*i*(1-n*o),s=255*i*(1-n*(1-o)),i=255*i;switch(a){case 0:return[i,s,r];case 1:return[l,i,r];case 2:return[r,i,s];case 3:return[r,l,i];case 4:return[s,r,i];case 5:return[i,r,l]}}function f(t){var e,n,i,a,o=t[0]/360,l=t[1]/100,s=t[2]/100,u=l+s;switch(u>1&&(l/=u,s/=u),e=Math.floor(6*o),n=1-s,i=6*o-e,0!=(1&e)&&(i=1-i),a=l+i*(n-l),e){default:case 6:case 0:r=n,g=a,b=l;break;case 1:r=a,g=n,b=l;break;case 2:r=l,g=n,b=a;break;case 3:r=l,g=a,b=n;break;case 4:r=a,g=l,b=n;break;case 5:r=n,g=l,b=a}return[255*r,255*g,255*b]}function p(t){var e,n,i,a=t[0]/100,o=t[1]/100,r=t[2]/100,l=t[3]/100;return e=1-Math.min(1,a*(1-l)+l),n=1-Math.min(1,o*(1-l)+l),i=1-Math.min(1,r*(1-l)+l),[255*e,255*n,255*i]}function v(t){var e,n,i,a=t[0]/100,o=t[1]/100,r=t[2]/100;return e=3.2406*a+-1.5372*o+-.4986*r,n=-.9689*a+1.8758*o+.0415*r,i=.0557*a+-.204*o+1.057*r,e=e>.0031308?1.055*Math.pow(e,1/2.4)-.055:e*=12.92,n=n>.0031308?1.055*Math.pow(n,1/2.4)-.055:n*=12.92,i=i>.0031308?1.055*Math.pow(i,1/2.4)-.055:i*=12.92,e=Math.min(Math.max(0,e),1),n=Math.min(Math.max(0,n),1),i=Math.min(Math.max(0,i),1),[255*e,255*n,255*i]}function m(t){var e,n,i,a=t[0],o=t[1],r=t[2];return a/=95.047,o/=100,r/=108.883,a=a>.008856?Math.pow(a,1/3):7.787*a+16/116,o=o>.008856?Math.pow(o,1/3):7.787*o+16/116,r=r>.008856?Math.pow(r,1/3):7.787*r+16/116,e=116*o-16,n=500*(a-o),i=200*(o-r),[e,n,i]}function x(t){var e,n,i,a,o=t[0],r=t[1],l=t[2];return o<=8?a=(n=100*o/903.3)/100*7.787+16/116:(n=100*Math.pow((o+16)/116,3),a=Math.pow(n/100,1/3)),e=e/95.047<=.008856?e=95.047*(r/500+a-16/116)/7.787:95.047*Math.pow(r/500+a,3),i=i/108.883<=.008859?i=108.883*(a-l/200-16/116)/7.787:108.883*Math.pow(a-l/200,3),[e,n,i]}function y(t){var e,n,i,a=t[0],o=t[1],r=t[2];return e=Math.atan2(r,o),(n=360*e/2/Math.PI)<0&&(n+=360),i=Math.sqrt(o*o+r*r),[a,i,n]}function k(t){return v(x(t))}function w(t){var e,n,i,a=t[0],o=t[1];return i=t[2]/360*2*Math.PI,e=o*Math.cos(i),n=o*Math.sin(i),[a,e,n]}function M(t){return S[t]}e.exports={rgb2hsl:i,rgb2hsv:a,rgb2hwb:o,rgb2cmyk:l,rgb2keyword:s,rgb2xyz:u,rgb2lab:d,rgb2lch:function(t){return y(d(t))},hsl2rgb:c,hsl2hsv:function(t){var e,n,i=t[0],a=t[1]/100,o=t[2]/100;return 0===o?[0,0,0]:(o*=2,a*=o<=1?o:2-o,n=(o+a)/2,e=2*a/(o+a),[i,100*e,100*n])},hsl2hwb:function(t){return o(c(t))},hsl2cmyk:function(t){return l(c(t))},hsl2keyword:function(t){return s(c(t))},hsv2rgb:h,hsv2hsl:function(t){var e,n,i=t[0],a=t[1]/100,o=t[2]/100;return n=(2-a)*o,e=a*o,e/=n<=1?n:2-n,e=e||0,n/=2,[i,100*e,100*n]},hsv2hwb:function(t){return o(h(t))},hsv2cmyk:function(t){return l(h(t))},hsv2keyword:function(t){return s(h(t))},hwb2rgb:f,hwb2hsl:function(t){return i(f(t))},hwb2hsv:function(t){return a(f(t))},hwb2cmyk:function(t){return l(f(t))},hwb2keyword:function(t){return s(f(t))},cmyk2rgb:p,cmyk2hsl:function(t){return i(p(t))},cmyk2hsv:function(t){return a(p(t))},cmyk2hwb:function(t){return o(p(t))},cmyk2keyword:function(t){return s(p(t))},keyword2rgb:M,keyword2hsl:function(t){return i(M(t))},keyword2hsv:function(t){return a(M(t))},keyword2hwb:function(t){return o(M(t))},keyword2cmyk:function(t){return l(M(t))},keyword2lab:function(t){return d(M(t))},keyword2xyz:function(t){return u(M(t))},xyz2rgb:v,xyz2lab:m,xyz2lch:function(t){return y(m(t))},lab2xyz:x,lab2rgb:k,lab2lch:y,lch2lab:w,lch2xyz:function(t){return x(w(t))},lch2rgb:function(t){return k(w(t))}};var S={aliceblue:[240,248,255],antiquewhite:[250,235,215],aqua:[0,255,255],aquamarine:[127,255,212],azure:[240,255,255],beige:[245,245,220],bisque:[255,228,196],black:[0,0,0],blanchedalmond:[255,235,205],blue:[0,0,255],blueviolet:[138,43,226],brown:[165,42,42],burlywood:[222,184,135],cadetblue:[95,158,160],chartreuse:[127,255,0],chocolate:[210,105,30],coral:[255,127,80],cornflowerblue:[100,149,237],cornsilk:[255,248,220],crimson:[220,20,60],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgoldenrod:[184,134,11],darkgray:[169,169,169],darkgreen:[0,100,0],darkgrey:[169,169,169],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkseagreen:[143,188,143],darkslateblue:[72,61,139],darkslategray:[47,79,79],darkslategrey:[47,79,79],darkturquoise:[0,206,209],darkviolet:[148,0,211],deeppink:[255,20,147],deepskyblue:[0,191,255],dimgray:[105,105,105],dimgrey:[105,105,105],dodgerblue:[30,144,255],firebrick:[178,34,34],floralwhite:[255,250,240],forestgreen:[34,139,34],fuchsia:[255,0,255],gainsboro:[220,220,220],ghostwhite:[248,248,255],gold:[255,215,0],goldenrod:[218,165,32],gray:[128,128,128],green:[0,128,0],greenyellow:[173,255,47],grey:[128,128,128],honeydew:[240,255,240],hotpink:[255,105,180],indianred:[205,92,92],indigo:[75,0,130],ivory:[255,255,240],khaki:[240,230,140],lavender:[230,230,250],lavenderblush:[255,240,245],lawngreen:[124,252,0],lemonchiffon:[255,250,205],lightblue:[173,216,230],lightcoral:[240,128,128],lightcyan:[224,255,255],lightgoldenrodyellow:[250,250,210],lightgray:[211,211,211],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightsalmon:[255,160,122],lightseagreen:[32,178,170],lightskyblue:[135,206,250],lightslategray:[119,136,153],lightslategrey:[119,136,153],lightsteelblue:[176,196,222],lightyellow:[255,255,224],lime:[0,255,0],limegreen:[50,205,50],linen:[250,240,230],magenta:[255,0,255],maroon:[128,0,0],mediumaquamarine:[102,205,170],mediumblue:[0,0,205],mediumorchid:[186,85,211],mediumpurple:[147,112,219],mediumseagreen:[60,179,113],mediumslateblue:[123,104,238],mediumspringgreen:[0,250,154],mediumturquoise:[72,209,204],mediumvioletred:[199,21,133],midnightblue:[25,25,112],mintcream:[245,255,250],mistyrose:[255,228,225],moccasin:[255,228,181],navajowhite:[255,222,173],navy:[0,0,128],oldlace:[253,245,230],olive:[128,128,0],olivedrab:[107,142,35],orange:[255,165,0],orangered:[255,69,0],orchid:[218,112,214],palegoldenrod:[238,232,170],palegreen:[152,251,152],paleturquoise:[175,238,238],palevioletred:[219,112,147],papayawhip:[255,239,213],peachpuff:[255,218,185],peru:[205,133,63],pink:[255,192,203],plum:[221,160,221],powderblue:[176,224,230],purple:[128,0,128],rebeccapurple:[102,51,153],red:[255,0,0],rosybrown:[188,143,143],royalblue:[65,105,225],saddlebrown:[139,69,19],salmon:[250,128,114],sandybrown:[244,164,96],seagreen:[46,139,87],seashell:[255,245,238],sienna:[160,82,45],silver:[192,192,192],skyblue:[135,206,235],slateblue:[106,90,205],slategray:[112,128,144],slategrey:[112,128,144],snow:[255,250,250],springgreen:[0,255,127],steelblue:[70,130,180],tan:[210,180,140],teal:[0,128,128],thistle:[216,191,216],tomato:[255,99,71],turquoise:[64,224,208],violet:[238,130,238],wheat:[245,222,179],white:[255,255,255],whitesmoke:[245,245,245],yellow:[255,255,0],yellowgreen:[154,205,50]},C={};for(var _ in S)C[JSON.stringify(S[_])]=_},{}],5:[function(t,e,n){var i=t(4),a=function(){return new u};for(var o in i){a[o+"Raw"]=function(t){return function(e){return"number"==typeof e&&(e=Array.prototype.slice.call(arguments)),i[t](e)}}(o);var r=/(\w+)2(\w+)/.exec(o),l=r[1],s=r[2];(a[l]=a[l]||{})[s]=a[o]=function(t){return function(e){"number"==typeof e&&(e=Array.prototype.slice.call(arguments));var n=i[t](e);if("string"==typeof n||void 0===n)return n;for(var a=0;a0&&(t[0].yLabel?n=t[0].yLabel:e.labels.length>0&&t[0].index=0&&a>0)&&(v+=a));return o=c.getPixelForValue(v),r=c.getPixelForValue(v+f),l=(r-o)/2,{size:l,base:o,head:r,center:r+l/2}},calculateBarIndexPixels:function(t,e,n){var i,a,r,l,s,u,d=this,c=n.scale.options,h=d.getStackIndex(t),f=n.pixels,g=f[e],p=f.length,v=n.start,m=n.end;return 1===p?(i=g>v?g-v:m-g,a=g0&&(i=(g-f[e-1])/2,e===p-1&&(a=i)),e');var n=t.data,i=n.datasets,a=n.labels;if(i.length)for(var o=0;o'),a[o]&&e.push(a[o]),e.push("");return e.push(""),e.join("")},legend:{labels:{generateLabels:function(t){var e=t.data;return e.labels.length&&e.datasets.length?e.labels.map(function(n,i){var a=t.getDatasetMeta(0),r=e.datasets[0],l=a.data[i],s=l&&l.custom||{},u=o.valueAtIndexOrDefault,d=t.options.elements.arc;return{text:n,fillStyle:s.backgroundColor?s.backgroundColor:u(r.backgroundColor,i,d.backgroundColor),strokeStyle:s.borderColor?s.borderColor:u(r.borderColor,i,d.borderColor),lineWidth:s.borderWidth?s.borderWidth:u(r.borderWidth,i,d.borderWidth),hidden:isNaN(r.data[i])||a.data[i].hidden,index:i}}):[]}},onClick:function(t,e){var n,i,a,o=e.index,r=this.chart;for(n=0,i=(r.data.datasets||[]).length;n=Math.PI?-1:g<-Math.PI?1:0))+f,v={x:Math.cos(g),y:Math.sin(g)},m={x:Math.cos(p),y:Math.sin(p)},b=g<=0&&p>=0||g<=2*Math.PI&&2*Math.PI<=p,x=g<=.5*Math.PI&&.5*Math.PI<=p||g<=2.5*Math.PI&&2.5*Math.PI<=p,y=g<=-Math.PI&&-Math.PI<=p||g<=Math.PI&&Math.PI<=p,k=g<=.5*-Math.PI&&.5*-Math.PI<=p||g<=1.5*Math.PI&&1.5*Math.PI<=p,w=h/100,M={x:y?-1:Math.min(v.x*(v.x<0?1:w),m.x*(m.x<0?1:w)),y:k?-1:Math.min(v.y*(v.y<0?1:w),m.y*(m.y<0?1:w))},S={x:b?1:Math.max(v.x*(v.x>0?1:w),m.x*(m.x>0?1:w)),y:x?1:Math.max(v.y*(v.y>0?1:w),m.y*(m.y>0?1:w))},C={width:.5*(S.x-M.x),height:.5*(S.y-M.y)};u=Math.min(l/C.width,s/C.height),d={x:-.5*(S.x+M.x),y:-.5*(S.y+M.y)}}n.borderWidth=e.getMaxBorderWidth(c.data),n.outerRadius=Math.max((u-n.borderWidth)/2,0),n.innerRadius=Math.max(h?n.outerRadius/100*h:0,0),n.radiusLength=(n.outerRadius-n.innerRadius)/n.getVisibleDatasetCount(),n.offsetX=d.x*n.outerRadius,n.offsetY=d.y*n.outerRadius,c.total=e.calculateTotal(),e.outerRadius=n.outerRadius-n.radiusLength*e.getRingIndex(e.index),e.innerRadius=Math.max(e.outerRadius-n.radiusLength,0),o.each(c.data,function(n,i){e.updateElement(n,i,t)})},updateElement:function(t,e,n){var i=this,a=i.chart,r=a.chartArea,l=a.options,s=l.animation,u=(r.left+r.right)/2,d=(r.top+r.bottom)/2,c=l.rotation,h=l.rotation,f=i.getDataset(),g=n&&s.animateRotate?0:t.hidden?0:i.calculateCircumference(f.data[e])*(l.circumference/(2*Math.PI)),p=n&&s.animateScale?0:i.innerRadius,v=n&&s.animateScale?0:i.outerRadius,m=o.valueAtIndexOrDefault;o.extend(t,{_datasetIndex:i.index,_index:e,_model:{x:u+a.offsetX,y:d+a.offsetY,startAngle:c,endAngle:h,circumference:g,outerRadius:v,innerRadius:p,label:m(f.label,e,a.data.labels[e])}});var b=t._model;this.removeHoverStyle(t),n&&s.animateRotate||(b.startAngle=0===e?l.rotation:i.getMeta().data[e-1]._model.endAngle,b.endAngle=b.startAngle+b.circumference),t.pivot()},removeHoverStyle:function(e){t.DatasetController.prototype.removeHoverStyle.call(this,e,this.chart.options.elements.arc)},calculateTotal:function(){var t,e=this.getDataset(),n=this.getMeta(),i=0;return o.each(n.data,function(n,a){t=e.data[a],isNaN(t)||n.hidden||(i+=Math.abs(t))}),i},calculateCircumference:function(t){var e=this.getMeta().total;return e>0&&!isNaN(t)?2*Math.PI*(t/e):0},getMaxBorderWidth:function(t){for(var e,n,i=0,a=this.index,o=t.length,r=0;r(i=e>i?e:i)?n:i;return i}})}},{25:25,40:40,45:45}],18:[function(t,e,n){"use strict";var i=t(25),a=t(40),o=t(45);i._set("line",{showLines:!0,spanGaps:!1,hover:{mode:"label"},scales:{xAxes:[{type:"category",id:"x-axis-0"}],yAxes:[{type:"linear",id:"y-axis-0"}]}}),e.exports=function(t){function e(t,e){return o.valueOrDefault(t.showLine,e.showLines)}t.controllers.line=t.DatasetController.extend({datasetElementType:a.Line,dataElementType:a.Point,update:function(t){var n,i,a,r=this,l=r.getMeta(),s=l.dataset,u=l.data||[],d=r.chart.options,c=d.elements.line,h=r.getScaleForId(l.yAxisID),f=r.getDataset(),g=e(f,d);for(g&&(a=s.custom||{},void 0!==f.tension&&void 0===f.lineTension&&(f.lineTension=f.tension),s._scale=h,s._datasetIndex=r.index,s._children=u,s._model={spanGaps:f.spanGaps?f.spanGaps:d.spanGaps,tension:a.tension?a.tension:o.valueOrDefault(f.lineTension,c.tension),backgroundColor:a.backgroundColor?a.backgroundColor:f.backgroundColor||c.backgroundColor,borderWidth:a.borderWidth?a.borderWidth:f.borderWidth||c.borderWidth,borderColor:a.borderColor?a.borderColor:f.borderColor||c.borderColor,borderCapStyle:a.borderCapStyle?a.borderCapStyle:f.borderCapStyle||c.borderCapStyle,borderDash:a.borderDash?a.borderDash:f.borderDash||c.borderDash,borderDashOffset:a.borderDashOffset?a.borderDashOffset:f.borderDashOffset||c.borderDashOffset,borderJoinStyle:a.borderJoinStyle?a.borderJoinStyle:f.borderJoinStyle||c.borderJoinStyle,fill:a.fill?a.fill:void 0!==f.fill?f.fill:c.fill,steppedLine:a.steppedLine?a.steppedLine:o.valueOrDefault(f.steppedLine,c.stepped),cubicInterpolationMode:a.cubicInterpolationMode?a.cubicInterpolationMode:o.valueOrDefault(f.cubicInterpolationMode,c.cubicInterpolationMode)},s.pivot()),n=0,i=u.length;n');var n=t.data,i=n.datasets,a=n.labels;if(i.length)for(var o=0;o'),a[o]&&e.push(a[o]),e.push("");return e.push(""),e.join("")},legend:{labels:{generateLabels:function(t){var e=t.data;return e.labels.length&&e.datasets.length?e.labels.map(function(n,i){var a=t.getDatasetMeta(0),r=e.datasets[0],l=a.data[i].custom||{},s=o.valueAtIndexOrDefault,u=t.options.elements.arc;return{text:n,fillStyle:l.backgroundColor?l.backgroundColor:s(r.backgroundColor,i,u.backgroundColor),strokeStyle:l.borderColor?l.borderColor:s(r.borderColor,i,u.borderColor),lineWidth:l.borderWidth?l.borderWidth:s(r.borderWidth,i,u.borderWidth),hidden:isNaN(r.data[i])||a.data[i].hidden,index:i}}):[]}},onClick:function(t,e){var n,i,a,o=e.index,r=this.chart;for(n=0,i=(r.data.datasets||[]).length;n0&&!isNaN(t)?2*Math.PI/e:0}})}},{25:25,40:40,45:45}],20:[function(t,e,n){"use strict";var i=t(25),a=t(40),o=t(45);i._set("radar",{scale:{type:"radialLinear"},elements:{line:{tension:0}}}),e.exports=function(t){t.controllers.radar=t.DatasetController.extend({datasetElementType:a.Line,dataElementType:a.Point,linkScales:o.noop,update:function(t){var e=this,n=e.getMeta(),i=n.dataset,a=n.data,r=i.custom||{},l=e.getDataset(),s=e.chart.options.elements.line,u=e.chart.scale;void 0!==l.tension&&void 0===l.lineTension&&(l.lineTension=l.tension),o.extend(n.dataset,{_datasetIndex:e.index,_scale:u,_children:a,_loop:!0,_model:{tension:r.tension?r.tension:o.valueOrDefault(l.lineTension,s.tension),backgroundColor:r.backgroundColor?r.backgroundColor:l.backgroundColor||s.backgroundColor,borderWidth:r.borderWidth?r.borderWidth:l.borderWidth||s.borderWidth,borderColor:r.borderColor?r.borderColor:l.borderColor||s.borderColor,fill:r.fill?r.fill:void 0!==l.fill?l.fill:s.fill,borderCapStyle:r.borderCapStyle?r.borderCapStyle:l.borderCapStyle||s.borderCapStyle,borderDash:r.borderDash?r.borderDash:l.borderDash||s.borderDash,borderDashOffset:r.borderDashOffset?r.borderDashOffset:l.borderDashOffset||s.borderDashOffset,borderJoinStyle:r.borderJoinStyle?r.borderJoinStyle:l.borderJoinStyle||s.borderJoinStyle}}),n.dataset.pivot(),o.each(a,function(n,i){e.updateElement(n,i,t)},e),e.updateBezierControlPoints()},updateElement:function(t,e,n){var i=this,a=t.custom||{},r=i.getDataset(),l=i.chart.scale,s=i.chart.options.elements.point,u=l.getPointPositionForValue(e,r.data[e]);void 0!==r.radius&&void 0===r.pointRadius&&(r.pointRadius=r.radius),void 0!==r.hitRadius&&void 0===r.pointHitRadius&&(r.pointHitRadius=r.hitRadius),o.extend(t,{_datasetIndex:i.index,_index:e,_scale:l,_model:{x:n?l.xCenter:u.x,y:n?l.yCenter:u.y,tension:a.tension?a.tension:o.valueOrDefault(r.lineTension,i.chart.options.elements.line.tension),radius:a.radius?a.radius:o.valueAtIndexOrDefault(r.pointRadius,e,s.radius),backgroundColor:a.backgroundColor?a.backgroundColor:o.valueAtIndexOrDefault(r.pointBackgroundColor,e,s.backgroundColor),borderColor:a.borderColor?a.borderColor:o.valueAtIndexOrDefault(r.pointBorderColor,e,s.borderColor),borderWidth:a.borderWidth?a.borderWidth:o.valueAtIndexOrDefault(r.pointBorderWidth,e,s.borderWidth),pointStyle:a.pointStyle?a.pointStyle:o.valueAtIndexOrDefault(r.pointStyle,e,s.pointStyle),hitRadius:a.hitRadius?a.hitRadius:o.valueAtIndexOrDefault(r.pointHitRadius,e,s.hitRadius)}}),t._model.skip=a.skip?a.skip:isNaN(t._model.x)||isNaN(t._model.y)},updateBezierControlPoints:function(){var t=this.chart.chartArea,e=this.getMeta();o.each(e.data,function(n,i){var a=n._model,r=o.splineCurve(o.previousItem(e.data,i,!0)._model,a,o.nextItem(e.data,i,!0)._model,a.tension);a.controlPointPreviousX=Math.max(Math.min(r.previous.x,t.right),t.left),a.controlPointPreviousY=Math.max(Math.min(r.previous.y,t.bottom),t.top),a.controlPointNextX=Math.max(Math.min(r.next.x,t.right),t.left),a.controlPointNextY=Math.max(Math.min(r.next.y,t.bottom),t.top),n.pivot()})},setHoverStyle:function(t){var e=this.chart.data.datasets[t._datasetIndex],n=t.custom||{},i=t._index,a=t._model;a.radius=n.hoverRadius?n.hoverRadius:o.valueAtIndexOrDefault(e.pointHoverRadius,i,this.chart.options.elements.point.hoverRadius),a.backgroundColor=n.hoverBackgroundColor?n.hoverBackgroundColor:o.valueAtIndexOrDefault(e.pointHoverBackgroundColor,i,o.getHoverColor(a.backgroundColor)),a.borderColor=n.hoverBorderColor?n.hoverBorderColor:o.valueAtIndexOrDefault(e.pointHoverBorderColor,i,o.getHoverColor(a.borderColor)),a.borderWidth=n.hoverBorderWidth?n.hoverBorderWidth:o.valueAtIndexOrDefault(e.pointHoverBorderWidth,i,a.borderWidth)},removeHoverStyle:function(t){var e=this.chart.data.datasets[t._datasetIndex],n=t.custom||{},i=t._index,a=t._model,r=this.chart.options.elements.point;a.radius=n.radius?n.radius:o.valueAtIndexOrDefault(e.pointRadius,i,r.radius),a.backgroundColor=n.backgroundColor?n.backgroundColor:o.valueAtIndexOrDefault(e.pointBackgroundColor,i,r.backgroundColor),a.borderColor=n.borderColor?n.borderColor:o.valueAtIndexOrDefault(e.pointBorderColor,i,r.borderColor),a.borderWidth=n.borderWidth?n.borderWidth:o.valueAtIndexOrDefault(e.pointBorderWidth,i,r.borderWidth)}})}},{25:25,40:40,45:45}],21:[function(t,e,n){"use strict";t(25)._set("scatter",{hover:{mode:"single"},scales:{xAxes:[{id:"x-axis-1",type:"linear",position:"bottom"}],yAxes:[{id:"y-axis-1",type:"linear",position:"left"}]},showLines:!1,tooltips:{callbacks:{title:function(){return""},label:function(t){return"("+t.xLabel+", "+t.yLabel+")"}}}}),e.exports=function(t){t.controllers.scatter=t.controllers.line}},{25:25}],22:[function(t,e,n){"use strict";var i=t(25),a=t(26),o=t(45);i._set("global",{animation:{duration:1e3,easing:"easeOutQuart",onProgress:o.noop,onComplete:o.noop}}),e.exports=function(t){t.Animation=a.extend({chart:null,currentStep:0,numSteps:60,easing:"",render:null,onAnimationProgress:null,onAnimationComplete:null}),t.animationService={frameDuration:17,animations:[],dropFrames:0,request:null,addAnimation:function(t,e,n,i){var a,o,r=this.animations;for(e.chart=t,i||(t.animating=!0),a=0,o=r.length;a1&&(n=Math.floor(t.dropFrames),t.dropFrames=t.dropFrames%1),t.advance(1+n);var i=Date.now();t.dropFrames+=(i-e)/t.frameDuration,t.animations.length>0&&t.requestAnimationFrame()},advance:function(t){for(var e,n,i=this.animations,a=0;a=e.numSteps?(o.callback(e.onAnimationComplete,[e],n),n.animating=!1,i.splice(a,1)):++a}},Object.defineProperty(t.Animation.prototype,"animationObject",{get:function(){return this}}),Object.defineProperty(t.Animation.prototype,"chartInstance",{get:function(){return this.chart},set:function(t){this.chart=t}})}},{25:25,26:26,45:45}],23:[function(t,e,n){"use strict";var i=t(25),a=t(45),o=t(28),r=t(48);e.exports=function(t){function e(t){var e=(t=t||{}).data=t.data||{};return e.datasets=e.datasets||[],e.labels=e.labels||[],t.options=a.configMerge(i.global,i[t.type],t.options||{}),t}function n(t){var e=t.options;e.scale?t.scale.options=e.scale:e.scales&&e.scales.xAxes.concat(e.scales.yAxes).forEach(function(e){t.scales[e.id].options=e}),t.tooltip._options=e.tooltips}function l(t){return"top"===t||"bottom"===t}var s=t.plugins;t.types={},t.instances={},t.controllers={},a.extend(t.prototype,{construct:function(n,i){var o=this;i=e(i);var l=r.acquireContext(n,i),s=l&&l.canvas,u=s&&s.height,d=s&&s.width;o.id=a.uid(),o.ctx=l,o.canvas=s,o.config=i,o.width=d,o.height=u,o.aspectRatio=u?d/u:null,o.options=i.options,o._bufferedRender=!1,o.chart=o,o.controller=o,t.instances[o.id]=o,Object.defineProperty(o,"data",{get:function(){return o.config.data},set:function(t){o.config.data=t}}),l&&s?(o.initialize(),o.update()):console.error("Failed to create chart: can't acquire context from the given item")},initialize:function(){var t=this;return s.notify(t,"beforeInit"),a.retinaScale(t,t.options.devicePixelRatio),t.bindEvents(),t.options.responsive&&t.resize(!0),t.ensureScalesHaveIDs(),t.buildScales(),t.initToolTip(),s.notify(t,"afterInit"),t},clear:function(){return a.canvas.clear(this),this},stop:function(){return t.animationService.cancelAnimation(this),this},resize:function(t){var e=this,n=e.options,i=e.canvas,o=n.maintainAspectRatio&&e.aspectRatio||null,r=Math.max(0,Math.floor(a.getMaximumWidth(i))),l=Math.max(0,Math.floor(o?r/o:a.getMaximumHeight(i)));if((e.width!==r||e.height!==l)&&(i.width=e.width=r,i.height=e.height=l,i.style.width=r+"px",i.style.height=l+"px",a.retinaScale(e,n.devicePixelRatio),!t)){var u={width:r,height:l};s.notify(e,"resize",[u]),e.options.onResize&&e.options.onResize(e,u),e.stop(),e.update(e.options.responsiveAnimationDuration)}},ensureScalesHaveIDs:function(){var t=this.options,e=t.scales||{},n=t.scale;a.each(e.xAxes,function(t,e){t.id=t.id||"x-axis-"+e}),a.each(e.yAxes,function(t,e){t.id=t.id||"y-axis-"+e}),n&&(n.id=n.id||"scale")},buildScales:function(){var e=this,n=e.options,i=e.scales={},o=[];n.scales&&(o=o.concat((n.scales.xAxes||[]).map(function(t){return{options:t,dtype:"category",dposition:"bottom"}}),(n.scales.yAxes||[]).map(function(t){return{options:t,dtype:"linear",dposition:"left"}}))),n.scale&&o.push({options:n.scale,dtype:"radialLinear",isDefault:!0,dposition:"chartArea"}),a.each(o,function(n){var o=n.options,r=a.valueOrDefault(o.type,n.dtype),s=t.scaleService.getScaleConstructor(r);if(s){l(o.position)!==l(n.dposition)&&(o.position=n.dposition);var u=new s({id:o.id,options:o,ctx:e.ctx,chart:e});i[u.id]=u,u.mergeTicksOptions(),n.isDefault&&(e.scale=u)}}),t.scaleService.addScalesToLayout(this)},buildOrUpdateControllers:function(){var e=this,n=[],i=[];return a.each(e.data.datasets,function(a,o){var r=e.getDatasetMeta(o),l=a.type||e.config.type;if(r.type&&r.type!==l&&(e.destroyDatasetMeta(o),r=e.getDatasetMeta(o)),r.type=l,n.push(r.type),r.controller)r.controller.updateIndex(o);else{var s=t.controllers[r.type];if(void 0===s)throw new Error('"'+r.type+'" is not a chart type.');r.controller=new s(e,o),i.push(r.controller)}},e),i},resetElements:function(){var t=this;a.each(t.data.datasets,function(e,n){t.getDatasetMeta(n).controller.reset()},t)},reset:function(){this.resetElements(),this.tooltip.initialize()},update:function(t){var e=this;if(t&&"object"==typeof t||(t={duration:t,lazy:arguments[1]}),n(e),!1!==s.notify(e,"beforeUpdate")){e.tooltip._data=e.data;var i=e.buildOrUpdateControllers();a.each(e.data.datasets,function(t,n){e.getDatasetMeta(n).controller.buildOrUpdateElements()},e),e.updateLayout(),a.each(i,function(t){t.reset()}),e.updateDatasets(),e.tooltip.initialize(),e.lastActive=[],s.notify(e,"afterUpdate"),e._bufferedRender?e._bufferedRequest={duration:t.duration,easing:t.easing,lazy:t.lazy}:e.render(t)}},updateLayout:function(){var e=this;!1!==s.notify(e,"beforeLayout")&&(t.layoutService.update(this,this.width,this.height),s.notify(e,"afterScaleUpdate"),s.notify(e,"afterLayout"))},updateDatasets:function(){var t=this;if(!1!==s.notify(t,"beforeDatasetsUpdate")){for(var e=0,n=t.data.datasets.length;e=0;--n)e.isDatasetVisible(n)&&e.drawDataset(n,t);s.notify(e,"afterDatasetsDraw",[t])}},drawDataset:function(t,e){var n=this,i=n.getDatasetMeta(t),a={meta:i,index:t,easingValue:e};!1!==s.notify(n,"beforeDatasetDraw",[a])&&(i.controller.draw(e),s.notify(n,"afterDatasetDraw",[a]))},_drawTooltip:function(t){var e=this,n=e.tooltip,i={tooltip:n,easingValue:t};!1!==s.notify(e,"beforeTooltipDraw",[i])&&(n.draw(),s.notify(e,"afterTooltipDraw",[i]))},getElementAtEvent:function(t){return o.modes.single(this,t)},getElementsAtEvent:function(t){return o.modes.label(this,t,{intersect:!0})},getElementsAtXAxis:function(t){return o.modes["x-axis"](this,t,{intersect:!0})},getElementsAtEventForMode:function(t,e,n){var i=o.modes[e];return"function"==typeof i?i(this,t,n):[]},getDatasetAtEvent:function(t){return o.modes.dataset(this,t,{intersect:!0})},getDatasetMeta:function(t){var e=this,n=e.data.datasets[t];n._meta||(n._meta={});var i=n._meta[e.id];return i||(i=n._meta[e.id]={type:null,data:[],dataset:null,controller:null,hidden:null,xAxisID:null,yAxisID:null}),i},getVisibleDatasetCount:function(){for(var t=0,e=0,n=this.data.datasets.length;e0||(a.forEach(function(e){delete t[e]}),delete t._chartjs)}}var a=["push","pop","shift","splice","unshift"];t.DatasetController=function(t,e){this.initialize(t,e)},i.extend(t.DatasetController.prototype,{datasetElementType:null,dataElementType:null,initialize:function(t,e){var n=this;n.chart=t,n.index=e,n.linkScales(),n.addElements()},updateIndex:function(t){this.index=t},linkScales:function(){var t=this,e=t.getMeta(),n=t.getDataset();null===e.xAxisID&&(e.xAxisID=n.xAxisID||t.chart.options.scales.xAxes[0].id),null===e.yAxisID&&(e.yAxisID=n.yAxisID||t.chart.options.scales.yAxes[0].id)},getDataset:function(){return this.chart.data.datasets[this.index]},getMeta:function(){return this.chart.getDatasetMeta(this.index)},getScaleForId:function(t){return this.chart.scales[t]},reset:function(){this.update(!0)},destroy:function(){this._data&&n(this._data,this)},createMetaDataset:function(){var t=this,e=t.datasetElementType;return e&&new e({_chart:t.chart,_datasetIndex:t.index})},createMetaData:function(t){var e=this,n=e.dataElementType;return n&&new n({_chart:e.chart,_datasetIndex:e.index,_index:t})},addElements:function(){var t,e,n=this,i=n.getMeta(),a=n.getDataset().data||[],o=i.data;for(t=0,e=a.length;ti&&t.insertElements(i,a-i)},insertElements:function(t,e){for(var n=0;n=n[e].length&&n[e].push({}),!n[e][r].type||s.type&&s.type!==n[e][r].type?o.merge(n[e][r],[t.scaleService.getScaleDefaults(l),s]):o.merge(n[e][r],s)}else o._merger(e,n,i,a)}})},o.where=function(t,e){if(o.isArray(t)&&Array.prototype.filter)return t.filter(e);var n=[];return o.each(t,function(t){e(t)&&n.push(t)}),n},o.findIndex=Array.prototype.findIndex?function(t,e,n){return t.findIndex(e,n)}:function(t,e,n){n=void 0===n?t:n;for(var i=0,a=t.length;i=0;i--){var a=t[i];if(e(a))return a}},o.isNumber=function(t){return!isNaN(parseFloat(t))&&isFinite(t)},o.almostEquals=function(t,e,n){return Math.abs(t-e)t},o.max=function(t){return t.reduce(function(t,e){return isNaN(e)?t:Math.max(t,e)},Number.NEGATIVE_INFINITY)},o.min=function(t){return t.reduce(function(t,e){return isNaN(e)?t:Math.min(t,e)},Number.POSITIVE_INFINITY)},o.sign=Math.sign?function(t){return Math.sign(t)}:function(t){return 0==(t=+t)||isNaN(t)?t:t>0?1:-1},o.log10=Math.log10?function(t){return Math.log10(t)}:function(t){return Math.log(t)/Math.LN10},o.toRadians=function(t){return t*(Math.PI/180)},o.toDegrees=function(t){return t*(180/Math.PI)},o.getAngleFromPoint=function(t,e){var n=e.x-t.x,i=e.y-t.y,a=Math.sqrt(n*n+i*i),o=Math.atan2(i,n);return o<-.5*Math.PI&&(o+=2*Math.PI),{angle:o,distance:a}},o.distanceBetweenPoints=function(t,e){return Math.sqrt(Math.pow(e.x-t.x,2)+Math.pow(e.y-t.y,2))},o.aliasPixel=function(t){return t%2==0?0:.5},o.splineCurve=function(t,e,n,i){var a=t.skip?e:t,o=e,r=n.skip?e:n,l=Math.sqrt(Math.pow(o.x-a.x,2)+Math.pow(o.y-a.y,2)),s=Math.sqrt(Math.pow(r.x-o.x,2)+Math.pow(r.y-o.y,2)),u=l/(l+s),d=s/(l+s),c=i*(u=isNaN(u)?0:u),h=i*(d=isNaN(d)?0:d);return{previous:{x:o.x-c*(r.x-a.x),y:o.y-c*(r.y-a.y)},next:{x:o.x+h*(r.x-a.x),y:o.y+h*(r.y-a.y)}}},o.EPSILON=Number.EPSILON||1e-14,o.splineCurveMonotone=function(t){var e,n,i,a,r=(t||[]).map(function(t){return{model:t._model,deltaK:0,mK:0}}),l=r.length;for(e=0;e0?r[e-1]:null,(a=e0?r[e-1]:null,a=e=t.length-1?t[0]:t[e+1]:e>=t.length-1?t[t.length-1]:t[e+1]},o.previousItem=function(t,e,n){return n?e<=0?t[t.length-1]:t[e-1]:e<=0?t[0]:t[e-1]},o.niceNum=function(t,e){var n=Math.floor(o.log10(t)),i=t/Math.pow(10,n);return(e?i<1.5?1:i<3?2:i<7?5:10:i<=1?1:i<=2?2:i<=5?5:10)*Math.pow(10,n)},o.requestAnimFrame="undefined"==typeof window?function(t){t()}:window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(t){return window.setTimeout(t,1e3/60)},o.getRelativePosition=function(t,e){var n,i,a=t.originalEvent||t,r=t.currentTarget||t.srcElement,l=r.getBoundingClientRect(),s=a.touches;s&&s.length>0?(n=s[0].clientX,i=s[0].clientY):(n=a.clientX,i=a.clientY);var u=parseFloat(o.getStyle(r,"padding-left")),d=parseFloat(o.getStyle(r,"padding-top")),c=parseFloat(o.getStyle(r,"padding-right")),h=parseFloat(o.getStyle(r,"padding-bottom")),f=l.right-l.left-u-c,g=l.bottom-l.top-d-h;return n=Math.round((n-l.left-u)/f*r.width/e.currentDevicePixelRatio),i=Math.round((i-l.top-d)/g*r.height/e.currentDevicePixelRatio),{x:n,y:i}},o.getConstraintWidth=function(t){return r(t,"max-width","clientWidth")},o.getConstraintHeight=function(t){return r(t,"max-height","clientHeight")},o.getMaximumWidth=function(t){var e=t.parentNode;if(!e)return t.clientWidth;var n=parseInt(o.getStyle(e,"padding-left"),10),i=parseInt(o.getStyle(e,"padding-right"),10),a=e.clientWidth-n-i,r=o.getConstraintWidth(t);return isNaN(r)?a:Math.min(a,r)},o.getMaximumHeight=function(t){var e=t.parentNode;if(!e)return t.clientHeight;var n=parseInt(o.getStyle(e,"padding-top"),10),i=parseInt(o.getStyle(e,"padding-bottom"),10),a=e.clientHeight-n-i,r=o.getConstraintHeight(t);return isNaN(r)?a:Math.min(a,r)},o.getStyle=function(t,e){return t.currentStyle?t.currentStyle[e]:document.defaultView.getComputedStyle(t,null).getPropertyValue(e)},o.retinaScale=function(t,e){var n=t.currentDevicePixelRatio=e||window.devicePixelRatio||1;if(1!==n){var i=t.canvas,a=t.height,o=t.width;i.height=a*n,i.width=o*n,t.ctx.scale(n,n),i.style.height=a+"px",i.style.width=o+"px"}},o.fontString=function(t,e,n){return e+" "+t+"px "+n},o.longestText=function(t,e,n,i){var a=(i=i||{}).data=i.data||{},r=i.garbageCollect=i.garbageCollect||[];i.font!==e&&(a=i.data={},r=i.garbageCollect=[],i.font=e),t.font=e;var l=0;o.each(n,function(e){void 0!==e&&null!==e&&!0!==o.isArray(e)?l=o.measureText(t,a,r,l,e):o.isArray(e)&&o.each(e,function(e){void 0===e||null===e||o.isArray(e)||(l=o.measureText(t,a,r,l,e))})});var s=r.length/2;if(s>n.length){for(var u=0;ui&&(i=o),i},o.numberOfLabelLines=function(t){var e=1;return o.each(t,function(t){o.isArray(t)&&t.length>e&&(e=t.length)}),e},o.color=i?function(t){return t instanceof CanvasGradient&&(t=a.global.defaultColor),i(t)}:function(t){return console.error("Color.js not found!"),t},o.getHoverColor=function(t){return t instanceof CanvasPattern?t:o.color(t).saturate(.5).darken(.1).rgbString()}}},{25:25,3:3,45:45}],28:[function(t,e,n){"use strict";function i(t,e){return t.native?{x:t.x,y:t.y}:u.getRelativePosition(t,e)}function a(t,e){var n,i,a,o,r;for(i=0,o=t.data.datasets.length;i0&&(u=t.getDatasetMeta(u[0]._datasetIndex).data),u},"x-axis":function(t,e){return s(t,e,{intersect:!1})},point:function(t,e){return o(t,i(e,t))},nearest:function(t,e,n){var a=i(e,t);n.axis=n.axis||"xy";var o=l(n.axis),s=r(t,a,n.intersect,o);return s.length>1&&s.sort(function(t,e){var n=t.getArea()-e.getArea();return 0===n&&(n=t._datasetIndex-e._datasetIndex),n}),s.slice(0,1)},x:function(t,e,n){var o=i(e,t),r=[],l=!1;return a(t,function(t){t.inXRange(o.x)&&r.push(t),t.inRange(o.x,o.y)&&(l=!0)}),n.intersect&&!l&&(r=[]),r},y:function(t,e,n){var o=i(e,t),r=[],l=!1;return a(t,function(t){t.inYRange(o.y)&&r.push(t),t.inRange(o.x,o.y)&&(l=!0)}),n.intersect&&!l&&(r=[]),r}}}},{45:45}],29:[function(t,e,n){"use strict";t(25)._set("global",{responsive:!0,responsiveAnimationDuration:0,maintainAspectRatio:!0,events:["mousemove","mouseout","click","touchstart","touchmove"],hover:{onHover:null,mode:"nearest",intersect:!0,animationDuration:400},onClick:null,defaultColor:"rgba(0,0,0,0.1)",defaultFontColor:"#666",defaultFontFamily:"'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",defaultFontSize:12,defaultFontStyle:"normal",showLines:!0,elements:{},layout:{padding:{top:0,right:0,bottom:0,left:0}}}),e.exports=function(){var t=function(t,e){return this.construct(t,e),this};return t.Chart=t,t}},{25:25}],30:[function(t,e,n){"use strict";var i=t(45);e.exports=function(t){function e(t,e){return i.where(t,function(t){return t.position===e})}function n(t,e){t.forEach(function(t,e){return t._tmpIndex_=e,t}),t.sort(function(t,n){var i=e?n:t,a=e?t:n;return i.weight===a.weight?i._tmpIndex_-a._tmpIndex_:i.weight-a.weight}),t.forEach(function(t){delete t._tmpIndex_})}t.layoutService={defaults:{},addBox:function(t,e){t.boxes||(t.boxes=[]),e.fullWidth=e.fullWidth||!1,e.position=e.position||"top",e.weight=e.weight||0,t.boxes.push(e)},removeBox:function(t,e){var n=t.boxes?t.boxes.indexOf(e):-1;-1!==n&&t.boxes.splice(n,1)},configure:function(t,e,n){for(var i,a=["fullWidth","position","weight"],o=a.length,r=0;rh&&st.maxHeight){s--;break}s++,c=u*d}t.labelRotation=s},afterCalculateTickRotation:function(){l.callback(this.options.afterCalculateTickRotation,[this])},beforeFit:function(){l.callback(this.options.beforeFit,[this])},fit:function(){var t=this,a=t.minSize={width:0,height:0},o=i(t._ticks),r=t.options,u=r.ticks,d=r.scaleLabel,c=r.gridLines,h=r.display,f=t.isHorizontal(),g=n(u),p=r.gridLines.tickMarkLength;if(a.width=f?t.isFullWidth()?t.maxWidth-t.margins.left-t.margins.right:t.maxWidth:h&&c.drawTicks?p:0,a.height=f?h&&c.drawTicks?p:0:t.maxHeight,d.display&&h){var v=s(d)+l.options.toPadding(d.padding).height;f?a.height+=v:a.width+=v}if(u.display&&h){var m=l.longestText(t.ctx,g.font,o,t.longestTextCache),b=l.numberOfLabelLines(o),x=.5*g.size,y=t.options.ticks.padding;if(f){t.longestLabelWidth=m;var k=l.toRadians(t.labelRotation),w=Math.cos(k),M=Math.sin(k)*m+g.size*b+x*(b-1)+x;a.height=Math.min(t.maxHeight,a.height+M+y),t.ctx.font=g.font;var S=e(t.ctx,o[0],g.font),C=e(t.ctx,o[o.length-1],g.font);0!==t.labelRotation?(t.paddingLeft="bottom"===r.position?w*S+3:w*x+3,t.paddingRight="bottom"===r.position?w*x+3:w*C+3):(t.paddingLeft=S/2+3,t.paddingRight=C/2+3)}else u.mirror?m=0:m+=y+x,a.width=Math.min(t.maxWidth,a.width+m),t.paddingTop=g.size/2,t.paddingBottom=g.size/2}t.handleMargins(),t.width=a.width,t.height=a.height},handleMargins:function(){var t=this;t.margins&&(t.paddingLeft=Math.max(t.paddingLeft-t.margins.left,0),t.paddingTop=Math.max(t.paddingTop-t.margins.top,0),t.paddingRight=Math.max(t.paddingRight-t.margins.right,0),t.paddingBottom=Math.max(t.paddingBottom-t.margins.bottom,0))},afterFit:function(){l.callback(this.options.afterFit,[this])},isHorizontal:function(){return"top"===this.options.position||"bottom"===this.options.position},isFullWidth:function(){return this.options.fullWidth},getRightValue:function(t){if(l.isNullOrUndef(t))return NaN;if("number"==typeof t&&!isFinite(t))return NaN;if(t)if(this.isHorizontal()){if(void 0!==t.x)return this.getRightValue(t.x)}else if(void 0!==t.y)return this.getRightValue(t.y);return t},getLabelForIndex:l.noop,getPixelForValue:l.noop,getValueForPixel:l.noop,getPixelForTick:function(t){var e=this,n=e.options.offset;if(e.isHorizontal()){var i=(e.width-(e.paddingLeft+e.paddingRight))/Math.max(e._ticks.length-(n?0:1),1),a=i*t+e.paddingLeft;n&&(a+=i/2);var o=e.left+Math.round(a);return o+=e.isFullWidth()?e.margins.left:0}var r=e.height-(e.paddingTop+e.paddingBottom);return e.top+t*(r/(e._ticks.length-1))},getPixelForDecimal:function(t){var e=this;if(e.isHorizontal()){var n=(e.width-(e.paddingLeft+e.paddingRight))*t+e.paddingLeft,i=e.left+Math.round(n);return i+=e.isFullWidth()?e.margins.left:0}return e.top+t*e.height},getBasePixel:function(){return this.getPixelForValue(this.getBaseValue())},getBaseValue:function(){var t=this,e=t.min,n=t.max;return t.beginAtZero?0:e<0&&n<0?n:e>0&&n>0?e:0},_autoSkip:function(t){var e,n,i,a,o=this,r=o.isHorizontal(),s=o.options.ticks.minor,u=t.length,d=l.toRadians(o.labelRotation),c=Math.cos(d),h=o.longestLabelWidth*c,f=[];for(s.maxTicksLimit&&(a=s.maxTicksLimit),r&&(e=!1,(h+s.autoSkipPadding)*u>o.width-(o.paddingLeft+o.paddingRight)&&(e=1+Math.floor((h+s.autoSkipPadding)*u/(o.width-(o.paddingLeft+o.paddingRight)))),a&&u>a&&(e=Math.max(e,Math.floor(u/a)))),n=0;n1&&n%e>0||n%e==0&&n+e>=u)&&n!==u-1&&delete i.label,f.push(i);return f},draw:function(t){var e=this,i=e.options;if(i.display){var r=e.ctx,u=o.global,d=i.ticks.minor,c=i.ticks.major||d,h=i.gridLines,f=i.scaleLabel,g=0!==e.labelRotation,p=e.isHorizontal(),v=d.autoSkip?e._autoSkip(e.getTicks()):e.getTicks(),m=l.valueOrDefault(d.fontColor,u.defaultFontColor),b=n(d),x=l.valueOrDefault(c.fontColor,u.defaultFontColor),y=n(c),k=h.drawTicks?h.tickMarkLength:0,w=l.valueOrDefault(f.fontColor,u.defaultFontColor),M=n(f),S=l.options.toPadding(f.padding),C=l.toRadians(e.labelRotation),_=[],D="right"===i.position?e.left:e.right-k,I="right"===i.position?e.left+k:e.right,P="bottom"===i.position?e.top:e.bottom-k,A="bottom"===i.position?e.top+k:e.bottom;if(l.each(v,function(n,o){if(!l.isNullOrUndef(n.label)){var r,s,c,f,m=n.label;o===e.zeroLineIndex&&i.offset===h.offsetGridLines?(r=h.zeroLineWidth,s=h.zeroLineColor,c=h.zeroLineBorderDash,f=h.zeroLineBorderDashOffset):(r=l.valueAtIndexOrDefault(h.lineWidth,o),s=l.valueAtIndexOrDefault(h.color,o),c=l.valueOrDefault(h.borderDash,u.borderDash),f=l.valueOrDefault(h.borderDashOffset,u.borderDashOffset));var b,x,y,w,M,S,T,F,O,R,L="middle",z="middle",B=d.padding;if(p){var W=k+B;"bottom"===i.position?(z=g?"middle":"top",L=g?"right":"center",R=e.top+W):(z=g?"middle":"bottom",L=g?"left":"center",R=e.bottom-W);var N=a(e,o,h.offsetGridLines&&v.length>1);N1);H0)n=t.stepSize;else{var o=i.niceNum(e.max-e.min,!1);n=i.niceNum(o/(t.maxTicks-1),!0)}var r=Math.floor(e.min/n)*n,l=Math.ceil(e.max/n)*n;t.min&&t.max&&t.stepSize&&i.almostWhole((t.max-t.min)/t.stepSize,n/1e3)&&(r=t.min,l=t.max);var s=(l-r)/n;s=i.almostEquals(s,Math.round(s),n/1e3)?Math.round(s):Math.ceil(s),a.push(void 0!==t.min?t.min:r);for(var u=1;u3?n[2]-n[1]:n[1]-n[0];Math.abs(a)>1&&t!==Math.floor(t)&&(a=t-Math.floor(t));var o=i.log10(Math.abs(a)),r="";if(0!==t){var l=-1*Math.floor(o);l=Math.max(Math.min(l,20),0),r=t.toFixed(l)}else r="0";return r},logarithmic:function(t,e,n){var a=t/Math.pow(10,Math.floor(i.log10(t)));return 0===t?"0":1===a||2===a||5===a||0===e||e===n.length-1?t.toExponential():""}}}},{45:45}],35:[function(t,e,n){"use strict";var i=t(25),a=t(26),o=t(45);i._set("global",{tooltips:{enabled:!0,custom:null,mode:"nearest",position:"average",intersect:!0,backgroundColor:"rgba(0,0,0,0.8)",titleFontStyle:"bold",titleSpacing:2,titleMarginBottom:6,titleFontColor:"#fff",titleAlign:"left",bodySpacing:2,bodyFontColor:"#fff",bodyAlign:"left",footerFontStyle:"bold",footerSpacing:2,footerMarginTop:6,footerFontColor:"#fff",footerAlign:"left",yPadding:6,xPadding:6,caretPadding:2,caretSize:5,cornerRadius:6,multiKeyBackground:"#fff",displayColors:!0,borderColor:"rgba(0,0,0,0)",borderWidth:0,callbacks:{beforeTitle:o.noop,title:function(t,e){var n="",i=e.labels,a=i?i.length:0;if(t.length>0){var o=t[0];o.xLabel?n=o.xLabel:a>0&&o.indexi.height-e.height&&(r="bottom");var l,s,u,d,c,h=(a.left+a.right)/2,f=(a.top+a.bottom)/2;"center"===r?(l=function(t){return t<=h},s=function(t){return t>h}):(l=function(t){return t<=e.width/2},s=function(t){return t>=i.width-e.width/2}),u=function(t){return t+e.width>i.width},d=function(t){return t-e.width<0},c=function(t){return t<=f?"top":"bottom"},l(n.x)?(o="left",u(n.x)&&(o="center",r=c(n.y))):s(n.x)&&(o="right",d(n.x)&&(o="center",r=c(n.y)));var g=t._options;return{xAlign:g.xAlign?g.xAlign:o,yAlign:g.yAlign?g.yAlign:r}}function d(t,e,n){var i=t.x,a=t.y,o=t.caretSize,r=t.caretPadding,l=t.cornerRadius,s=n.xAlign,u=n.yAlign,d=o+r,c=l+r;return"right"===s?i-=e.width:"center"===s&&(i-=e.width/2),"top"===u?a+=d:a-="bottom"===u?e.height+d:e.height/2,"center"===u?"left"===s?i+=d:"right"===s&&(i-=d):"left"===s?i-=c:"right"===s&&(i+=c),{x:i,y:a}}t.Tooltip=a.extend({initialize:function(){this._model=l(this._options),this._lastActive=[]},getTitle:function(){var t=this,e=t._options.callbacks,i=e.beforeTitle.apply(t,arguments),a=e.title.apply(t,arguments),o=e.afterTitle.apply(t,arguments),r=[];return r=n(r,i),r=n(r,a),r=n(r,o)},getBeforeBody:function(){var t=this._options.callbacks.beforeBody.apply(this,arguments);return o.isArray(t)?t:void 0!==t?[t]:[]},getBody:function(t,e){var i=this,a=i._options.callbacks,r=[];return o.each(t,function(t){var o={before:[],lines:[],after:[]};n(o.before,a.beforeLabel.call(i,t,e)),n(o.lines,a.label.call(i,t,e)),n(o.after,a.afterLabel.call(i,t,e)),r.push(o)}),r},getAfterBody:function(){var t=this._options.callbacks.afterBody.apply(this,arguments);return o.isArray(t)?t:void 0!==t?[t]:[]},getFooter:function(){var t=this,e=t._options.callbacks,i=e.beforeFooter.apply(t,arguments),a=e.footer.apply(t,arguments),o=e.afterFooter.apply(t,arguments),r=[];return r=n(r,i),r=n(r,a),r=n(r,o)},update:function(e){var n,i,a=this,c=a._options,h=a._model,f=a._model=l(c),g=a._active,p=a._data,v={xAlign:h.xAlign,yAlign:h.yAlign},m={x:h.x,y:h.y},b={width:h.width,height:h.height},x={x:h.caretX,y:h.caretY};if(g.length){f.opacity=1;var y=[],k=[];x=t.Tooltip.positioners[c.position].call(a,g,a._eventPosition);var w=[];for(n=0,i=g.length;n0&&i.stroke()},draw:function(){var t=this._chart.ctx,e=this._view;if(0!==e.opacity){var n={width:e.width,height:e.height},i={x:e.x,y:e.y},a=Math.abs(e.opacity<.001)?0:e.opacity,o=e.title.length||e.beforeBody.length||e.body.length||e.afterBody.length||e.footer.length;this._options.enabled&&o&&(this.drawBackground(i,e,t,n,a),i.x+=e.xPadding,i.y+=e.yPadding,this.drawTitle(i,e,t,a),this.drawBody(i,e,t,a),this.drawFooter(i,e,t,a))}},handleEvent:function(t){var e=this,n=e._options,i=!1;if(e._lastActive=e._lastActive||[],"mouseout"===t.type?e._active=[]:e._active=e._chart.getElementsAtEventForMode(t,n.mode,n),!(i=!o.arrayEquals(e._active,e._lastActive)))return!1;if(e._lastActive=e._active,n.enabled||n.custom){e._eventPosition={x:t.x,y:t.y};var a=e._model;e.update(!0),e.pivot(),i|=a.x!==e._model.x||a.y!==e._model.y}return i}}),t.Tooltip.positioners={average:function(t){if(!t.length)return!1;var e,n,i=0,a=0,o=0;for(e=0,n=t.length;es;)a-=2*Math.PI;for(;a=l&&a<=s,d=r>=n.innerRadius&&r<=n.outerRadius;return u&&d}return!1},getCenterPoint:function(){var t=this._view,e=(t.startAngle+t.endAngle)/2,n=(t.innerRadius+t.outerRadius)/2;return{x:t.x+Math.cos(e)*n,y:t.y+Math.sin(e)*n}},getArea:function(){var t=this._view;return Math.PI*((t.endAngle-t.startAngle)/(2*Math.PI))*(Math.pow(t.outerRadius,2)-Math.pow(t.innerRadius,2))},tooltipPosition:function(){var t=this._view,e=t.startAngle+(t.endAngle-t.startAngle)/2,n=(t.outerRadius-t.innerRadius)/2+t.innerRadius;return{x:t.x+Math.cos(e)*n,y:t.y+Math.sin(e)*n}},draw:function(){var t=this._chart.ctx,e=this._view,n=e.startAngle,i=e.endAngle;t.beginPath(),t.arc(e.x,e.y,e.outerRadius,n,i),t.arc(e.x,e.y,e.innerRadius,i,n,!0),t.closePath(),t.strokeStyle=e.borderColor,t.lineWidth=e.borderWidth,t.fillStyle=e.backgroundColor,t.fill(),t.lineJoin="bevel",e.borderWidth&&t.stroke()}})},{25:25,26:26,45:45}],37:[function(t,e,n){"use strict";var i=t(25),a=t(26),o=t(45),r=i.global;i._set("global",{elements:{line:{tension:.4,backgroundColor:r.defaultColor,borderWidth:3,borderColor:r.defaultColor,borderCapStyle:"butt",borderDash:[],borderDashOffset:0,borderJoinStyle:"miter",capBezierPoints:!0,fill:!0}}}),e.exports=a.extend({draw:function(){var t,e,n,i,a=this,l=a._view,s=a._chart.ctx,u=l.spanGaps,d=a._children.slice(),c=r.elements.line,h=-1;for(a._loop&&d.length&&d.push(d[0]),s.save(),s.lineCap=l.borderCapStyle||c.borderCapStyle,s.setLineDash&&s.setLineDash(l.borderDash||c.borderDash),s.lineDashOffset=l.borderDashOffset||c.borderDashOffset,s.lineJoin=l.borderJoinStyle||c.borderJoinStyle,s.lineWidth=l.borderWidth||c.borderWidth,s.strokeStyle=l.borderColor||r.defaultColor,s.beginPath(),h=-1,t=0;te?1:-1,r=1,l=u.borderSkipped||"left"):(e=u.x-u.width/2,n=u.x+u.width/2,i=u.y,o=1,r=(a=u.base)>i?1:-1,l=u.borderSkipped||"bottom"),d){var c=Math.min(Math.abs(e-n),Math.abs(i-a)),h=(d=d>c?c:d)/2,f=e+("left"!==l?h*o:0),g=n+("right"!==l?-h*o:0),p=i+("top"!==l?h*r:0),v=a+("bottom"!==l?-h*r:0);f!==g&&(i=p,a=v),p!==v&&(e=f,n=g)}s.beginPath(),s.fillStyle=u.backgroundColor,s.strokeStyle=u.borderColor,s.lineWidth=d;var m=[[e,a],[e,i],[n,i],[n,a]],b=["bottom","left","top","right"].indexOf(l,0);-1===b&&(b=0);var x=t(0);s.moveTo(x[0],x[1]);for(var y=1;y<4;y++)x=t(y),s.lineTo(x[0],x[1]);s.fill(),d&&s.stroke()},height:function(){var t=this._view;return t.base-t.y},inRange:function(t,e){var n=!1;if(this._view){var i=a(this);n=t>=i.left&&t<=i.right&&e>=i.top&&e<=i.bottom}return n},inLabelRange:function(t,e){var n=this;if(!n._view)return!1;var o=a(n);return i(n)?t>=o.left&&t<=o.right:e>=o.top&&e<=o.bottom},inXRange:function(t){var e=a(this);return t>=e.left&&t<=e.right},inYRange:function(t){var e=a(this);return t>=e.top&&t<=e.bottom},getCenterPoint:function(){var t,e,n=this._view;return i(this)?(t=n.x,e=(n.y+n.base)/2):(t=(n.x+n.base)/2,e=n.y),{x:t,y:e}},getArea:function(){var t=this._view;return t.width*Math.abs(t.y-t.base)},tooltipPosition:function(){var t=this._view;return{x:t.x,y:t.y}}})},{25:25,26:26}],40:[function(t,e,n){"use strict";e.exports={},e.exports.Arc=t(36),e.exports.Line=t(37),e.exports.Point=t(38),e.exports.Rectangle=t(39)},{36:36,37:37,38:38,39:39}],41:[function(t,e,n){"use strict";var i=t(42),n=e.exports={clear:function(t){t.ctx.clearRect(0,0,t.width,t.height)},roundedRect:function(t,e,n,i,a,o){if(o){var r=Math.min(o,i/2),l=Math.min(o,a/2);t.moveTo(e+r,n),t.lineTo(e+i-r,n),t.quadraticCurveTo(e+i,n,e+i,n+l),t.lineTo(e+i,n+a-l),t.quadraticCurveTo(e+i,n+a,e+i-r,n+a),t.lineTo(e+r,n+a),t.quadraticCurveTo(e,n+a,e,n+a-l),t.lineTo(e,n+l),t.quadraticCurveTo(e,n,e+r,n)}else t.rect(e,n,i,a)},drawPoint:function(t,e,n,i,a){var o,r,l,s,u,d;if(!e||"object"!=typeof e||"[object HTMLImageElement]"!==(o=e.toString())&&"[object HTMLCanvasElement]"!==o){if(!(isNaN(n)||n<=0)){switch(e){default:t.beginPath(),t.arc(i,a,n,0,2*Math.PI),t.closePath(),t.fill();break;case"triangle":t.beginPath(),u=(r=3*n/Math.sqrt(3))*Math.sqrt(3)/2,t.moveTo(i-r/2,a+u/3),t.lineTo(i+r/2,a+u/3),t.lineTo(i,a-2*u/3),t.closePath(),t.fill();break;case"rect":d=1/Math.SQRT2*n,t.beginPath(),t.fillRect(i-d,a-d,2*d,2*d),t.strokeRect(i-d,a-d,2*d,2*d);break;case"rectRounded":var c=n/Math.SQRT2,h=i-c,f=a-c,g=Math.SQRT2*n;t.beginPath(),this.roundedRect(t,h,f,g,g,n/2),t.closePath(),t.fill();break;case"rectRot":d=1/Math.SQRT2*n,t.beginPath(),t.moveTo(i-d,a),t.lineTo(i,a+d),t.lineTo(i+d,a),t.lineTo(i,a-d),t.closePath(),t.fill();break;case"cross":t.beginPath(),t.moveTo(i,a+n),t.lineTo(i,a-n),t.moveTo(i-n,a),t.lineTo(i+n,a),t.closePath();break;case"crossRot":t.beginPath(),l=Math.cos(Math.PI/4)*n,s=Math.sin(Math.PI/4)*n,t.moveTo(i-l,a-s),t.lineTo(i+l,a+s),t.moveTo(i-l,a+s),t.lineTo(i+l,a-s),t.closePath();break;case"star":t.beginPath(),t.moveTo(i,a+n),t.lineTo(i,a-n),t.moveTo(i-n,a),t.lineTo(i+n,a),l=Math.cos(Math.PI/4)*n,s=Math.sin(Math.PI/4)*n,t.moveTo(i-l,a-s),t.lineTo(i+l,a+s),t.moveTo(i-l,a+s),t.lineTo(i+l,a-s),t.closePath();break;case"line":t.beginPath(),t.moveTo(i-n,a),t.lineTo(i+n,a),t.closePath();break;case"dash":t.beginPath(),t.moveTo(i,a),t.lineTo(i+n,a),t.closePath()}t.stroke()}}else t.drawImage(e,i-e.width/2,a-e.height/2,e.width,e.height)},clipArea:function(t,e){t.save(),t.beginPath(),t.rect(e.left,e.top,e.right-e.left,e.bottom-e.top),t.clip()},unclipArea:function(t){t.restore()},lineTo:function(t,e,n,i){if(n.steppedLine)return"after"===n.steppedLine&&!i||"after"!==n.steppedLine&&i?t.lineTo(e.x,n.y):t.lineTo(n.x,e.y),void t.lineTo(n.x,n.y);n.tension?t.bezierCurveTo(i?e.controlPointPreviousX:e.controlPointNextX,i?e.controlPointPreviousY:e.controlPointNextY,i?n.controlPointNextX:n.controlPointPreviousX,i?n.controlPointNextY:n.controlPointPreviousY,n.x,n.y):t.lineTo(n.x,n.y)}};i.clear=n.clear,i.drawRoundedRectangle=function(t){t.beginPath(),n.roundedRect.apply(n,arguments),t.closePath()}},{42:42}],42:[function(t,e,n){"use strict";var i={noop:function(){},uid:function(){var t=0;return function(){return t++}}(),isNullOrUndef:function(t){return null===t||void 0===t},isArray:Array.isArray?Array.isArray:function(t){return"[object Array]"===Object.prototype.toString.call(t)},isObject:function(t){return null!==t&&"[object Object]"===Object.prototype.toString.call(t)},valueOrDefault:function(t,e){return void 0===t?e:t},valueAtIndexOrDefault:function(t,e,n){return i.valueOrDefault(i.isArray(t)?t[e]:t,n)},callback:function(t,e,n){if(t&&"function"==typeof t.call)return t.apply(n,e)},each:function(t,e,n,a){var o,r,l;if(i.isArray(t))if(r=t.length,a)for(o=r-1;o>=0;o--)e.call(n,t[o],o);else for(o=0;o=1?t:-(Math.sqrt(1-t*t)-1)},easeOutCirc:function(t){return Math.sqrt(1-(t-=1)*t)},easeInOutCirc:function(t){return(t/=.5)<1?-.5*(Math.sqrt(1-t*t)-1):.5*(Math.sqrt(1-(t-=2)*t)+1)},easeInElastic:function(t){var e=1.70158,n=0,i=1;return 0===t?0:1===t?1:(n||(n=.3),i<1?(i=1,e=n/4):e=n/(2*Math.PI)*Math.asin(1/i),-i*Math.pow(2,10*(t-=1))*Math.sin((t-e)*(2*Math.PI)/n))},easeOutElastic:function(t){var e=1.70158,n=0,i=1;return 0===t?0:1===t?1:(n||(n=.3),i<1?(i=1,e=n/4):e=n/(2*Math.PI)*Math.asin(1/i),i*Math.pow(2,-10*t)*Math.sin((t-e)*(2*Math.PI)/n)+1)},easeInOutElastic:function(t){var e=1.70158,n=0,i=1;return 0===t?0:2==(t/=.5)?1:(n||(n=.45),i<1?(i=1,e=n/4):e=n/(2*Math.PI)*Math.asin(1/i),t<1?i*Math.pow(2,10*(t-=1))*Math.sin((t-e)*(2*Math.PI)/n)*-.5:i*Math.pow(2,-10*(t-=1))*Math.sin((t-e)*(2*Math.PI)/n)*.5+1)},easeInBack:function(t){var e=1.70158;return t*t*((e+1)*t-e)},easeOutBack:function(t){var e=1.70158;return(t-=1)*t*((e+1)*t+e)+1},easeInOutBack:function(t){var e=1.70158;return(t/=.5)<1?t*t*((1+(e*=1.525))*t-e)*.5:.5*((t-=2)*t*((1+(e*=1.525))*t+e)+2)},easeInBounce:function(t){return 1-a.easeOutBounce(1-t)},easeOutBounce:function(t){return t<1/2.75?7.5625*t*t:t<2/2.75?7.5625*(t-=1.5/2.75)*t+.75:t<2.5/2.75?7.5625*(t-=2.25/2.75)*t+.9375:7.5625*(t-=2.625/2.75)*t+.984375},easeInOutBounce:function(t){return t<.5?.5*a.easeInBounce(2*t):.5*a.easeOutBounce(2*t-1)+.5}};e.exports={effects:a},i.easingEffects=a},{42:42}],44:[function(t,e,n){"use strict";var i=t(42);e.exports={toLineHeight:function(t,e){var n=(""+t).match(/^(normal|(\d+(?:\.\d+)?)(px|em|%)?)$/);if(!n||"normal"===n[1])return 1.2*e;switch(t=+n[2],n[3]){case"px":return t;case"%":t/=100}return e*t},toPadding:function(t){var e,n,a,o;return i.isObject(t)?(e=+t.top||0,n=+t.right||0,a=+t.bottom||0,o=+t.left||0):e=n=a=o=+t||0,{top:e,right:n,bottom:a,left:o,height:e+a,width:o+n}},resolve:function(t,e,n){var a,o,r;for(a=0,o=t.length;a
      ';var a=e.childNodes[0],r=e.childNodes[1];e._reset=function(){a.scrollLeft=1e6,a.scrollTop=1e6,r.scrollLeft=1e6,r.scrollTop=1e6};var l=function(){e._reset(),t()};return o(a,"scroll",l.bind(a,"expand")),o(r,"scroll",l.bind(r,"shrink")),e}function c(t,e){var n=t[m]||(t[m]={}),i=n.renderProxy=function(t){t.animationName===y&&e()};v.each(k,function(e){o(t,e,i)}),n.reflow=!!t.offsetParent,t.classList.add(x)}function h(t){var e=t[m]||{},n=e.renderProxy;n&&(v.each(k,function(e){r(t,e,n)}),delete e.renderProxy),t.classList.remove(x)}function f(t,e,n){var i=t[m]||(t[m]={}),a=i.resizer=d(u(function(){if(i.resizer)return e(l("resize",n))}));c(t,function(){if(i.resizer){var e=t.parentNode;e&&e!==a.parentNode&&e.insertBefore(a,e.firstChild),a._reset()}})}function g(t){var e=t[m]||{},n=e.resizer;delete e.resizer,h(t),n&&n.parentNode&&n.parentNode.removeChild(n)}function p(t,e){var n=t._style||document.createElement("style");t._style||(t._style=n,e="/* Chart.js */\n"+e,n.setAttribute("type","text/css"),document.getElementsByTagName("head")[0].appendChild(n)),n.appendChild(document.createTextNode(e))}var v=t(45),m="$chartjs",b="chartjs-",x=b+"render-monitor",y=b+"render-animation",k=["animationstart","webkitAnimationStart"],w={touchstart:"mousedown",touchmove:"mousemove",touchend:"mouseup",pointerenter:"mouseenter",pointerdown:"mousedown",pointermove:"mousemove",pointerup:"mouseup",pointerleave:"mouseout",pointerout:"mouseout"},M=!!function(){var t=!1;try{var e=Object.defineProperty({},"passive",{get:function(){t=!0}});window.addEventListener("e",null,e)}catch(t){}return t}()&&{passive:!0};e.exports={_enabled:"undefined"!=typeof window&&"undefined"!=typeof document,initialize:function(){var t="from{opacity:0.99}to{opacity:1}";p(this,"@-webkit-keyframes "+y+"{"+t+"}@keyframes "+y+"{"+t+"}."+x+"{-webkit-animation:"+y+" 0.001s;animation:"+y+" 0.001s;}")},acquireContext:function(t,e){"string"==typeof t?t=document.getElementById(t):t.length&&(t=t[0]),t&&t.canvas&&(t=t.canvas);var n=t&&t.getContext&&t.getContext("2d");return n&&n.canvas===t?(a(t,e),n):null},releaseContext:function(t){var e=t.canvas;if(e[m]){var n=e[m].initial;["height","width"].forEach(function(t){var i=n[t];v.isNullOrUndef(i)?e.removeAttribute(t):e.setAttribute(t,i)}),v.each(n.style||{},function(t,n){e.style[n]=t}),e.width=e.width,delete e[m]}},addEventListener:function(t,e,n){var i=t.canvas;if("resize"!==e){var a=n[m]||(n[m]={});o(i,e,(a.proxies||(a.proxies={}))[t.id+"_"+e]=function(e){n(s(e,t))})}else f(i,n,t)},removeEventListener:function(t,e,n){var i=t.canvas;if("resize"!==e){var a=((n[m]||{}).proxies||{})[t.id+"_"+e];a&&r(i,e,a)}else g(i)}},v.addEvent=o,v.removeEvent=r},{45:45}],48:[function(t,e,n){"use strict";var i=t(45),a=t(46),o=t(47),r=o._enabled?o:a;e.exports=i.extend({initialize:function(){},acquireContext:function(){},releaseContext:function(){},addEventListener:function(){},removeEventListener:function(){}},r)},{45:45,46:46,47:47}],49:[function(t,e,n){"use strict";var i=t(25),a=t(40),o=t(45);i._set("global",{plugins:{filler:{propagate:!0}}}),e.exports=function(){function t(t,e,n){var i,a=t._model||{},o=a.fill;if(void 0===o&&(o=!!a.backgroundColor),!1===o||null===o)return!1;if(!0===o)return"origin";if(i=parseFloat(o,10),isFinite(i)&&Math.floor(i)===i)return"-"!==o[0]&&"+"!==o[0]||(i=e+i),!(i===e||i<0||i>=n)&&i;switch(o){case"bottom":return"start";case"top":return"end";case"zero":return"origin";case"origin":case"start":case"end":return o;default:return!1}}function e(t){var e,n=t.el._model||{},i=t.el._scale||{},a=t.fill,o=null;if(isFinite(a))return null;if("start"===a?o=void 0===n.scaleBottom?i.bottom:n.scaleBottom:"end"===a?o=void 0===n.scaleTop?i.top:n.scaleTop:void 0!==n.scaleZero?o=n.scaleZero:i.getBasePosition?o=i.getBasePosition():i.getBasePixel&&(o=i.getBasePixel()),void 0!==o&&null!==o){if(void 0!==o.x&&void 0!==o.y)return o;if("number"==typeof o&&isFinite(o))return e=i.isHorizontal(),{x:e?o:null,y:e?null:o}}return null}function n(t,e,n){var i,a=t[e].fill,o=[e];if(!n)return a;for(;!1!==a&&-1===o.indexOf(a);){if(!isFinite(a))return a;if(!(i=t[a]))return!1;if(i.visible)return a;o.push(a),a=i.fill}return!1}function r(t){var e=t.fill,n="dataset";return!1===e?null:(isFinite(e)||(n="boundary"),d[n](t))}function l(t){return t&&!t.skip}function s(t,e,n,i,a){var r;if(i&&a){for(t.moveTo(e[0].x,e[0].y),r=1;r0;--r)o.canvas.lineTo(t,n[r],n[r-1],!0)}}function u(t,e,n,i,a,o){var r,u,d,c,h,f,g,p=e.length,v=i.spanGaps,m=[],b=[],x=0,y=0;for(t.beginPath(),r=0,u=p+!!o;r');for(var n=0;n'),t.data.datasets[n].label&&e.push(t.data.datasets[n].label),e.push("");return e.push(""),e.join("")}}),e.exports=function(t){function e(t,e){return t.usePointStyle?e*Math.SQRT2:t.boxWidth}function n(e,n){var i=new t.Legend({ctx:e.ctx,options:n,chart:e});r.configure(e,i,n),r.addBox(e,i),e.legend=i}var r=t.layoutService,l=o.noop;return t.Legend=a.extend({initialize:function(t){o.extend(this,t),this.legendHitBoxes=[],this.doughnutMode=!1},beforeUpdate:l,update:function(t,e,n){var i=this;return i.beforeUpdate(),i.maxWidth=t,i.maxHeight=e,i.margins=n,i.beforeSetDimensions(),i.setDimensions(),i.afterSetDimensions(),i.beforeBuildLabels(),i.buildLabels(),i.afterBuildLabels(),i.beforeFit(),i.fit(),i.afterFit(),i.afterUpdate(),i.minSize},afterUpdate:l,beforeSetDimensions:l,setDimensions:function(){var t=this;t.isHorizontal()?(t.width=t.maxWidth,t.left=0,t.right=t.width):(t.height=t.maxHeight,t.top=0,t.bottom=t.height),t.paddingLeft=0,t.paddingTop=0,t.paddingRight=0,t.paddingBottom=0,t.minSize={width:0,height:0}},afterSetDimensions:l,beforeBuildLabels:l,buildLabels:function(){var t=this,e=t.options.labels||{},n=o.callback(e.generateLabels,[t.chart],t)||[];e.filter&&(n=n.filter(function(n){return e.filter(n,t.chart.data)})),t.options.reverse&&n.reverse(),t.legendItems=n},afterBuildLabels:l,beforeFit:l,fit:function(){var t=this,n=t.options,a=n.labels,r=n.display,l=t.ctx,s=i.global,u=o.valueOrDefault,d=u(a.fontSize,s.defaultFontSize),c=u(a.fontStyle,s.defaultFontStyle),h=u(a.fontFamily,s.defaultFontFamily),f=o.fontString(d,c,h),g=t.legendHitBoxes=[],p=t.minSize,v=t.isHorizontal();if(v?(p.width=t.maxWidth,p.height=r?10:0):(p.width=r?10:0,p.height=t.maxHeight),r)if(l.font=f,v){var m=t.lineWidths=[0],b=t.legendItems.length?d+a.padding:0;l.textAlign="left",l.textBaseline="top",o.each(t.legendItems,function(n,i){var o=e(a,d)+d/2+l.measureText(n.text).width;m[m.length-1]+o+a.padding>=t.width&&(b+=d+a.padding,m[m.length]=t.left),g[i]={left:0,top:0,width:o,height:d},m[m.length-1]+=o+a.padding}),p.height+=b}else{var x=a.padding,y=t.columnWidths=[],k=a.padding,w=0,M=0,S=d+x;o.each(t.legendItems,function(t,n){var i=e(a,d)+d/2+l.measureText(t.text).width;M+S>p.height&&(k+=w+a.padding,y.push(w),w=0,M=0),w=Math.max(w,i),M+=S,g[n]={left:0,top:0,width:i,height:d}}),k+=w,y.push(w),p.width+=k}t.width=p.width,t.height=p.height},afterFit:l,isHorizontal:function(){return"top"===this.options.position||"bottom"===this.options.position},draw:function(){var t=this,n=t.options,a=n.labels,r=i.global,l=r.elements.line,s=t.width,u=t.lineWidths;if(n.display){var d,c=t.ctx,h=o.valueOrDefault,f=h(a.fontColor,r.defaultFontColor),g=h(a.fontSize,r.defaultFontSize),p=h(a.fontStyle,r.defaultFontStyle),v=h(a.fontFamily,r.defaultFontFamily),m=o.fontString(g,p,v);c.textAlign="left",c.textBaseline="middle",c.lineWidth=.5,c.strokeStyle=f,c.fillStyle=f,c.font=m;var b=e(a,g),x=t.legendHitBoxes,y=function(t,e,i){if(!(isNaN(b)||b<=0)){c.save(),c.fillStyle=h(i.fillStyle,r.defaultColor),c.lineCap=h(i.lineCap,l.borderCapStyle),c.lineDashOffset=h(i.lineDashOffset,l.borderDashOffset),c.lineJoin=h(i.lineJoin,l.borderJoinStyle),c.lineWidth=h(i.lineWidth,l.borderWidth),c.strokeStyle=h(i.strokeStyle,r.defaultColor);var a=0===h(i.lineWidth,l.borderWidth);if(c.setLineDash&&c.setLineDash(h(i.lineDash,l.borderDash)),n.labels&&n.labels.usePointStyle){var s=g*Math.SQRT2/2,u=s/Math.SQRT2,d=t+u,f=e+u;o.canvas.drawPoint(c,i.pointStyle,s,d,f)}else a||c.strokeRect(t,e,b,g),c.fillRect(t,e,b,g);c.restore()}},k=function(t,e,n,i){var a=g/2,o=b+a+t,r=e+a;c.fillText(n.text,o,r),n.hidden&&(c.beginPath(),c.lineWidth=2,c.moveTo(o,r),c.lineTo(o+i,r),c.stroke())},w=t.isHorizontal();d=w?{x:t.left+(s-u[0])/2,y:t.top+a.padding,line:0}:{x:t.left+a.padding,y:t.top+a.padding,line:0};var M=g+a.padding;o.each(t.legendItems,function(e,n){var i=c.measureText(e.text).width,o=b+g/2+i,r=d.x,l=d.y;w?r+o>=s&&(l=d.y+=M,d.line++,r=d.x=t.left+(s-u[d.line])/2):l+M>t.bottom&&(r=d.x=r+t.columnWidths[d.line]+a.padding,l=d.y=t.top+a.padding,d.line++),y(r,l,e),x[n].left=r,x[n].top=l,k(r,l,e,i),w?d.x+=o+a.padding:d.y+=M})}},handleEvent:function(t){var e=this,n=e.options,i="mouseup"===t.type?"click":t.type,a=!1;if("mousemove"===i){if(!n.onHover)return}else{if("click"!==i)return;if(!n.onClick)return}var o=t.x,r=t.y;if(o>=e.left&&o<=e.right&&r>=e.top&&r<=e.bottom)for(var l=e.legendHitBoxes,s=0;s=u.left&&o<=u.left+u.width&&r>=u.top&&r<=u.top+u.height){if("click"===i){n.onClick.call(e,t.native,e.legendItems[s]),a=!0;break}if("mousemove"===i){n.onHover.call(e,t.native,e.legendItems[s]),a=!0;break}}}return a}}),{id:"legend",beforeInit:function(t){var e=t.options.legend;e&&n(t,e)},beforeUpdate:function(t){var e=t.options.legend,a=t.legend;e?(o.mergeIf(e,i.global.legend),a?(r.configure(t,a,e),a.options=e):n(t,e)):a&&(r.removeBox(t,a),delete t.legend)},afterEvent:function(t,e){var n=t.legend;n&&n.handleEvent(e)}}}},{25:25,26:26,45:45}],51:[function(t,e,n){"use strict";var i=t(25),a=t(26),o=t(45);i._set("global",{title:{display:!1,fontStyle:"bold",fullWidth:!0,lineHeight:1.2,padding:10,position:"top",text:"",weight:2e3}}),e.exports=function(t){function e(e,i){var a=new t.Title({ctx:e.ctx,options:i,chart:e});n.configure(e,a,i),n.addBox(e,a),e.titleBlock=a}var n=t.layoutService,r=o.noop;return t.Title=a.extend({initialize:function(t){var e=this;o.extend(e,t),e.legendHitBoxes=[]},beforeUpdate:r,update:function(t,e,n){var i=this;return i.beforeUpdate(),i.maxWidth=t,i.maxHeight=e,i.margins=n,i.beforeSetDimensions(),i.setDimensions(),i.afterSetDimensions(),i.beforeBuildLabels(),i.buildLabels(),i.afterBuildLabels(),i.beforeFit(),i.fit(),i.afterFit(),i.afterUpdate(),i.minSize},afterUpdate:r,beforeSetDimensions:r,setDimensions:function(){var t=this;t.isHorizontal()?(t.width=t.maxWidth,t.left=0,t.right=t.width):(t.height=t.maxHeight,t.top=0,t.bottom=t.height),t.paddingLeft=0,t.paddingTop=0,t.paddingRight=0,t.paddingBottom=0,t.minSize={width:0,height:0}},afterSetDimensions:r,beforeBuildLabels:r,buildLabels:r,afterBuildLabels:r,beforeFit:r,fit:function(){var t=this,e=o.valueOrDefault,n=t.options,a=n.display,r=e(n.fontSize,i.global.defaultFontSize),l=t.minSize,s=o.isArray(n.text)?n.text.length:1,u=o.options.toLineHeight(n.lineHeight,r),d=a?s*u+2*n.padding:0;t.isHorizontal()?(l.width=t.maxWidth,l.height=d):(l.width=d,l.height=t.maxHeight),t.width=l.width,t.height=l.height},afterFit:r,isHorizontal:function(){var t=this.options.position;return"top"===t||"bottom"===t},draw:function(){var t=this,e=t.ctx,n=o.valueOrDefault,a=t.options,r=i.global;if(a.display){var l,s,u,d=n(a.fontSize,r.defaultFontSize),c=n(a.fontStyle,r.defaultFontStyle),h=n(a.fontFamily,r.defaultFontFamily),f=o.fontString(d,c,h),g=o.options.toLineHeight(a.lineHeight,d),p=g/2+a.padding,v=0,m=t.top,b=t.left,x=t.bottom,y=t.right;e.fillStyle=n(a.fontColor,r.defaultFontColor),e.font=f,t.isHorizontal()?(s=b+(y-b)/2,u=m+p,l=y-b):(s="left"===a.position?b+p:y-p,u=m+(x-m)/2,l=x-m,v=Math.PI*("left"===a.position?-.5:.5)),e.save(),e.translate(s,u),e.rotate(v),e.textAlign="center",e.textBaseline="middle";var k=a.text;if(o.isArray(k))for(var w=0,M=0;Me.max&&(e.max=i))})});e.min=isFinite(e.min)&&!isNaN(e.min)?e.min:0,e.max=isFinite(e.max)&&!isNaN(e.max)?e.max:1,this.handleTickRangeOptions()},getTickLimit:function(){var t,e=this,n=e.options.ticks;if(e.isHorizontal())t=Math.min(n.maxTicksLimit?n.maxTicksLimit:11,Math.ceil(e.width/50));else{var o=a.valueOrDefault(n.fontSize,i.global.defaultFontSize);t=Math.min(n.maxTicksLimit?n.maxTicksLimit:11,Math.ceil(e.height/(2*o)))}return t},handleDirectionalChanges:function(){this.isHorizontal()||this.ticks.reverse()},getLabelForIndex:function(t,e){return+this.getRightValue(this.chart.data.datasets[e].data[t])},getPixelForValue:function(t){var e,n=this,i=n.start,a=+n.getRightValue(t),o=n.end-i;return n.isHorizontal()?(e=n.left+n.width/o*(a-i),Math.round(e)):(e=n.bottom-n.height/o*(a-i),Math.round(e))},getValueForPixel:function(t){var e=this,n=e.isHorizontal(),i=n?e.width:e.height,a=(n?t-e.left:e.bottom-t)/i;return e.start+(e.end-e.start)*a},getPixelForTick:function(t){return this.getPixelForValue(this.ticksAsNumbers[t])}});t.scaleService.registerScaleType("linear",n,e)}},{25:25,34:34,45:45}],54:[function(t,e,n){"use strict";var i=t(45),a=t(34);e.exports=function(t){var e=i.noop;t.LinearScaleBase=t.Scale.extend({getRightValue:function(e){return"string"==typeof e?+e:t.Scale.prototype.getRightValue.call(this,e)},handleTickRangeOptions:function(){var t=this,e=t.options.ticks;if(e.beginAtZero){var n=i.sign(t.min),a=i.sign(t.max);n<0&&a<0?t.max=0:n>0&&a>0&&(t.min=0)}var o=void 0!==e.min||void 0!==e.suggestedMin,r=void 0!==e.max||void 0!==e.suggestedMax;void 0!==e.min?t.min=e.min:void 0!==e.suggestedMin&&(null===t.min?t.min=e.suggestedMin:t.min=Math.min(t.min,e.suggestedMin)),void 0!==e.max?t.max=e.max:void 0!==e.suggestedMax&&(null===t.max?t.max=e.suggestedMax:t.max=Math.max(t.max,e.suggestedMax)),o!==r&&t.min>=t.max&&(o?t.max=t.min+1:t.min=t.max-1),t.min===t.max&&(t.max++,e.beginAtZero||t.min--)},getTickLimit:e,handleDirectionalChanges:e,buildTicks:function(){var t=this,e=t.options.ticks,n=t.getTickLimit(),o={maxTicks:n=Math.max(2,n),min:e.min,max:e.max,stepSize:i.valueOrDefault(e.fixedStepSize,e.stepSize)},r=t.ticks=a.generators.linear(o,t);t.handleDirectionalChanges(),t.max=i.max(r),t.min=i.min(r),e.reverse?(r.reverse(),t.start=t.max,t.end=t.min):(t.start=t.min,t.end=t.max)},convertTicksToLabels:function(){var e=this;e.ticksAsNumbers=e.ticks.slice(),e.zeroLineIndex=e.ticks.indexOf(0),t.Scale.prototype.convertTicksToLabels.call(e)}})}},{34:34,45:45}],55:[function(t,e,n){"use strict";var i=t(45),a=t(34);e.exports=function(t){var e={position:"left",ticks:{callback:a.formatters.logarithmic}},n=t.Scale.extend({determineDataLimits:function(){function t(t){return s?t.xAxisID===e.id:t.yAxisID===e.id}var e=this,n=e.options,a=n.ticks,o=e.chart,r=o.data.datasets,l=i.valueOrDefault,s=e.isHorizontal();e.min=null,e.max=null,e.minNotZero=null;var u=n.stacked;if(void 0===u&&i.each(r,function(e,n){if(!u){var i=o.getDatasetMeta(n);o.isDatasetVisible(n)&&t(i)&&void 0!==i.stack&&(u=!0)}}),n.stacked||u){var d={};i.each(r,function(a,r){var l=o.getDatasetMeta(r),s=[l.type,void 0===n.stacked&&void 0===l.stack?r:"",l.stack].join(".");o.isDatasetVisible(r)&&t(l)&&(void 0===d[s]&&(d[s]=[]),i.each(a.data,function(t,i){var a=d[s],o=+e.getRightValue(t);isNaN(o)||l.data[i].hidden||(a[i]=a[i]||0,n.relativePoints?a[i]=100:a[i]+=o)}))}),i.each(d,function(t){var n=i.min(t),a=i.max(t);e.min=null===e.min?n:Math.min(e.min,n),e.max=null===e.max?a:Math.max(e.max,a)})}else i.each(r,function(n,a){var r=o.getDatasetMeta(a);o.isDatasetVisible(a)&&t(r)&&i.each(n.data,function(t,n){var i=+e.getRightValue(t);isNaN(i)||r.data[n].hidden||(null===e.min?e.min=i:ie.max&&(e.max=i),0!==i&&(null===e.minNotZero||ia?{start:e-n-5,end:e}:{start:e,end:e+n+5}}function s(t){var i,o,s,u=n(t),d=Math.min(t.height/2,t.width/2),c={r:t.width,l:0,t:t.height,b:0},h={};t.ctx.font=u.font,t._pointLabelSizes=[];var f=e(t);for(i=0;ic.r&&(c.r=v.end,h.r=g),m.startc.b&&(c.b=m.end,h.b=g)}t.setReductions(d,c,h)}function u(t){var e=Math.min(t.height/2,t.width/2);t.drawingArea=Math.round(e),t.setCenterPoint(0,0,0,0)}function d(t){return 0===t||180===t?"center":t<180?"left":"right"}function c(t,e,n,i){if(a.isArray(e))for(var o=n.y,r=1.5*i,l=0;l270||t<90)&&(n.y-=e.h)}function f(t){var i=t.ctx,o=a.valueOrDefault,r=t.options,l=r.angleLines,s=r.pointLabels;i.lineWidth=l.lineWidth,i.strokeStyle=l.color;var u=t.getDistanceFromCenterForValue(r.ticks.reverse?t.min:t.max),f=n(t);i.textBaseline="top";for(var g=e(t)-1;g>=0;g--){if(l.display){var p=t.getPointPosition(g,u);i.beginPath(),i.moveTo(t.xCenter,t.yCenter),i.lineTo(p.x,p.y),i.stroke(),i.closePath()}if(s.display){var m=t.getPointPosition(g,u+5),b=o(s.fontColor,v.defaultFontColor);i.font=f.font,i.fillStyle=b;var x=t.getIndexAngle(g),y=a.toDegrees(x);i.textAlign=d(y),h(y,t._pointLabelSizes[g],m),c(i,t.pointLabels[g]||"",m,f.size)}}}function g(t,n,i,o){var r=t.ctx;if(r.strokeStyle=a.valueAtIndexOrDefault(n.color,o-1),r.lineWidth=a.valueAtIndexOrDefault(n.lineWidth,o-1),t.options.gridLines.circular)r.beginPath(),r.arc(t.xCenter,t.yCenter,i,0,2*Math.PI),r.closePath(),r.stroke();else{var l=e(t);if(0===l)return;r.beginPath();var s=t.getPointPosition(0,i);r.moveTo(s.x,s.y);for(var u=1;u0&&n>0?e:0)},draw:function(){var t=this,e=t.options,n=e.gridLines,i=e.ticks,o=a.valueOrDefault;if(e.display){var r=t.ctx,l=this.getIndexAngle(0),s=o(i.fontSize,v.defaultFontSize),u=o(i.fontStyle,v.defaultFontStyle),d=o(i.fontFamily,v.defaultFontFamily),c=a.fontString(s,u,d);a.each(t.ticks,function(e,a){if(a>0||i.reverse){var u=t.getDistanceFromCenterForValue(t.ticksAsNumbers[a]);if(n.display&&0!==a&&g(t,n,u,a),i.display){var d=o(i.fontColor,v.defaultFontColor);if(r.font=c,r.save(),r.translate(t.xCenter,t.yCenter),r.rotate(l),i.showLabelBackdrop){var h=r.measureText(e).width;r.fillStyle=i.backdropColor,r.fillRect(-h/2-i.backdropPaddingX,-u-s/2-i.backdropPaddingY,h+2*i.backdropPaddingX,s+2*i.backdropPaddingY)}r.textAlign="center",r.textBaseline="middle",r.fillStyle=d,r.fillText(e,0,-u),r.restore()}}}),(e.angleLines.display||e.pointLabels.display)&&f(t)}}});t.scaleService.registerScaleType("radialLinear",b,m)}},{25:25,34:34,45:45}],57:[function(t,e,n){"use strict";function i(t,e){return t-e}function a(t){var e,n,i,a={},o=[];for(e=0,n=t.length;ee&&l=0&&r<=l;){if(i=r+l>>1,a=t[i-1]||null,o=t[i],!a)return{lo:null,hi:o};if(o[e]n))return{lo:a,hi:o};l=i-1}}return{lo:o,hi:null}}function l(t,e,n,i){var a=r(t,e,n),o=a.lo?a.hi?a.lo:t[t.length-2]:t[0],l=a.lo?a.hi?a.hi:t[t.length-1]:t[1],s=l[e]-o[e],u=s?(n-o[e])/s:0,d=(l[i]-o[i])*u;return o[i]+d}function s(t,e){var n=e.parser,i=e.parser||e.format;return"function"==typeof n?n(t):"string"==typeof t&&"string"==typeof i?m(t,i):(t instanceof m||(t=m(t)),t.isValid()?t:"function"==typeof i?i(t):t)}function u(t,e){if(x.isNullOrUndef(t))return null;var n=e.options.time,i=s(e.getRightValue(t),n);return i.isValid()?(n.round&&i.startOf(n.round),i.valueOf()):null}function d(t,e,n,i){var a,o,r,l=e-t,s=w[n],u=s.size,d=s.steps;if(!d)return Math.ceil(l/((i||1)*u));for(a=0,o=d.length;a=M.indexOf(e);a--)if(o=M[a],w[o].common&&r.as(o)>=t.length)return o;return M[e?M.indexOf(e):0]}function f(t){for(var e=M.indexOf(t)+1,n=M.length;e1?e[1]:i,r=e[0],s=(l(t,"time",o,"pos")-l(t,"time",r,"pos"))/2),a.time.max||(o=e[e.length-1],r=e.length>1?e[e.length-2]:n,u=(l(t,"time",o,"pos")-l(t,"time",r,"pos"))/2)),{left:s,right:u}}function v(t,e){var n,i,a,o,r=[];for(n=0,i=t.length;n=a&&n<=r&&c.push(n);return i.min=a,i.max=r,i._unit=s.unit||h(c,s.minUnit,i.min,i.max),i._majorUnit=f(i._unit),i._table=o(i._timestamps.data,a,r,l.distribution),i._offsets=p(i._table,c,a,r,l),v(c,i._majorUnit)},getLabelForIndex:function(t,e){var n=this,i=n.chart.data,a=n.options.time,o=i.labels&&t=0&&t>>0,s=0;sDe(e)?(r=e+1,a=o-De(e)):(r=e,a=o),{year:r,dayOfYear:a}}function Ie(e,t,n){var s,i,r=Ve(e.year(),t,n),a=Math.floor((e.dayOfYear()-r-1)/7)+1;return a<1?s=a+Ae(i=e.year()-1,t,n):a>Ae(e.year(),t,n)?(s=a-Ae(e.year(),t,n),i=e.year()+1):(i=e.year(),s=a),{week:s,year:i}}function Ae(e,t,n){var s=Ve(e,t,n),i=Ve(e+1,t,n);return(De(e)-s+i)/7}I("w",["ww",2],"wo","week"),I("W",["WW",2],"Wo","isoWeek"),H("week","w"),H("isoWeek","W"),L("week",5),L("isoWeek",5),ue("w",B),ue("ww",B,z),ue("W",B),ue("WW",B,z),fe(["w","ww","W","WW"],function(e,t,n,s){t[s.substr(0,1)]=k(e)});I("d",0,"do","day"),I("dd",0,0,function(e){return this.localeData().weekdaysMin(this,e)}),I("ddd",0,0,function(e){return this.localeData().weekdaysShort(this,e)}),I("dddd",0,0,function(e){return this.localeData().weekdays(this,e)}),I("e",0,0,"weekday"),I("E",0,0,"isoWeekday"),H("day","d"),H("weekday","e"),H("isoWeekday","E"),L("day",11),L("weekday",11),L("isoWeekday",11),ue("d",B),ue("e",B),ue("E",B),ue("dd",function(e,t){return t.weekdaysMinRegex(e)}),ue("ddd",function(e,t){return t.weekdaysShortRegex(e)}),ue("dddd",function(e,t){return t.weekdaysRegex(e)}),fe(["dd","ddd","dddd"],function(e,t,n,s){var i=n._locale.weekdaysParse(e,s,n._strict);null!=i?t.d=i:g(n).invalidWeekday=e}),fe(["d","e","E"],function(e,t,n,s){t[s]=k(e)});var je="Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_");var Ze="Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_");var ze="Su_Mo_Tu_We_Th_Fr_Sa".split("_");var $e=ae;var qe=ae;var Je=ae;function Be(){function e(e,t){return t.length-e.length}var t,n,s,i,r,a=[],o=[],u=[],l=[];for(t=0;t<7;t++)n=y([2e3,1]).day(t),s=this.weekdaysMin(n,""),i=this.weekdaysShort(n,""),r=this.weekdays(n,""),a.push(s),o.push(i),u.push(r),l.push(s),l.push(i),l.push(r);for(a.sort(e),o.sort(e),u.sort(e),l.sort(e),t=0;t<7;t++)o[t]=de(o[t]),u[t]=de(u[t]),l[t]=de(l[t]);this._weekdaysRegex=new RegExp("^("+l.join("|")+")","i"),this._weekdaysShortRegex=this._weekdaysRegex,this._weekdaysMinRegex=this._weekdaysRegex,this._weekdaysStrictRegex=new RegExp("^("+u.join("|")+")","i"),this._weekdaysShortStrictRegex=new RegExp("^("+o.join("|")+")","i"),this._weekdaysMinStrictRegex=new RegExp("^("+a.join("|")+")","i")}function Qe(){return this.hours()%12||12}function Xe(e,t){I(e,0,0,function(){return this.localeData().meridiem(this.hours(),this.minutes(),t)})}function Ke(e,t){return t._meridiemParse}I("H",["HH",2],0,"hour"),I("h",["hh",2],0,Qe),I("k",["kk",2],0,function(){return this.hours()||24}),I("hmm",0,0,function(){return""+Qe.apply(this)+U(this.minutes(),2)}),I("hmmss",0,0,function(){return""+Qe.apply(this)+U(this.minutes(),2)+U(this.seconds(),2)}),I("Hmm",0,0,function(){return""+this.hours()+U(this.minutes(),2)}),I("Hmmss",0,0,function(){return""+this.hours()+U(this.minutes(),2)+U(this.seconds(),2)}),Xe("a",!0),Xe("A",!1),H("hour","h"),L("hour",13),ue("a",Ke),ue("A",Ke),ue("H",B),ue("h",B),ue("k",B),ue("HH",B,z),ue("hh",B,z),ue("kk",B,z),ue("hmm",Q),ue("hmmss",X),ue("Hmm",Q),ue("Hmmss",X),ce(["H","HH"],ge),ce(["k","kk"],function(e,t,n){var s=k(e);t[ge]=24===s?0:s}),ce(["a","A"],function(e,t,n){n._isPm=n._locale.isPM(e),n._meridiem=e}),ce(["h","hh"],function(e,t,n){t[ge]=k(e),g(n).bigHour=!0}),ce("hmm",function(e,t,n){var s=e.length-2;t[ge]=k(e.substr(0,s)),t[pe]=k(e.substr(s)),g(n).bigHour=!0}),ce("hmmss",function(e,t,n){var s=e.length-4,i=e.length-2;t[ge]=k(e.substr(0,s)),t[pe]=k(e.substr(s,2)),t[ve]=k(e.substr(i)),g(n).bigHour=!0}),ce("Hmm",function(e,t,n){var s=e.length-2;t[ge]=k(e.substr(0,s)),t[pe]=k(e.substr(s))}),ce("Hmmss",function(e,t,n){var s=e.length-4,i=e.length-2;t[ge]=k(e.substr(0,s)),t[pe]=k(e.substr(s,2)),t[ve]=k(e.substr(i))});var et,tt=Te("Hours",!0),nt={calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},longDateFormat:{LTS:"h:mm:ss A",LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY h:mm A",LLLL:"dddd, MMMM D, YYYY h:mm A"},invalidDate:"Invalid date",ordinal:"%d",dayOfMonthOrdinalParse:/\d{1,2}/,relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",ss:"%d seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},months:He,monthsShort:Re,week:{dow:0,doy:6},weekdays:je,weekdaysMin:ze,weekdaysShort:Ze,meridiemParse:/[ap]\.?m?\.?/i},st={},it={};function rt(e){return e?e.toLowerCase().replace("_","-"):e}function at(e){var t=null;if(!st[e]&&"undefined"!=typeof module&&module&&module.exports)try{t=et._abbr,require("./locale/"+e),ot(t)}catch(e){}return st[e]}function ot(e,t){var n;return e&&((n=l(t)?lt(e):ut(e,t))?et=n:"undefined"!=typeof console&&console.warn&&console.warn("Locale "+e+" not found. Did you forget to load it?")),et._abbr}function ut(e,t){if(null!==t){var n,s=nt;if(t.abbr=e,null!=st[e])T("defineLocaleOverride","use moment.updateLocale(localeName, config) to change an existing locale. moment.defineLocale(localeName, config) should only be used for creating a new locale See http://momentjs.com/guides/#/warnings/define-locale/ for more info."),s=st[e]._config;else if(null!=t.parentLocale)if(null!=st[t.parentLocale])s=st[t.parentLocale]._config;else{if(null==(n=at(t.parentLocale)))return it[t.parentLocale]||(it[t.parentLocale]=[]),it[t.parentLocale].push({name:e,config:t}),null;s=n._config}return st[e]=new P(b(s,t)),it[e]&&it[e].forEach(function(e){ut(e.name,e.config)}),ot(e),st[e]}return delete st[e],null}function lt(e){var t;if(e&&e._locale&&e._locale._abbr&&(e=e._locale._abbr),!e)return et;if(!o(e)){if(t=at(e))return t;e=[e]}return function(e){for(var t,n,s,i,r=0;r=t&&a(i,n,!0)>=t-1)break;t--}r++}return et}(e)}function dt(e){var t,n=e._a;return n&&-2===g(e).overflow&&(t=n[_e]<0||11Pe(n[me],n[_e])?ye:n[ge]<0||24Ae(n,r,a)?g(e)._overflowWeeks=!0:null!=u?g(e)._overflowWeekday=!0:(o=Ee(n,s,i,r,a),e._a[me]=o.year,e._dayOfYear=o.dayOfYear)}(e),null!=e._dayOfYear&&(r=ht(e._a[me],s[me]),(e._dayOfYear>De(r)||0===e._dayOfYear)&&(g(e)._overflowDayOfYear=!0),n=Ge(r,0,e._dayOfYear),e._a[_e]=n.getUTCMonth(),e._a[ye]=n.getUTCDate()),t=0;t<3&&null==e._a[t];++t)e._a[t]=a[t]=s[t];for(;t<7;t++)e._a[t]=a[t]=null==e._a[t]?2===t?1:0:e._a[t];24===e._a[ge]&&0===e._a[pe]&&0===e._a[ve]&&0===e._a[we]&&(e._nextDay=!0,e._a[ge]=0),e._d=(e._useUTC?Ge:function(e,t,n,s,i,r,a){var o=new Date(e,t,n,s,i,r,a);return e<100&&0<=e&&isFinite(o.getFullYear())&&o.setFullYear(e),o}).apply(null,a),i=e._useUTC?e._d.getUTCDay():e._d.getDay(),null!=e._tzm&&e._d.setUTCMinutes(e._d.getUTCMinutes()-e._tzm),e._nextDay&&(e._a[ge]=24),e._w&&void 0!==e._w.d&&e._w.d!==i&&(g(e).weekdayMismatch=!0)}}var ft=/^\s*((?:[+-]\d{6}|\d{4})-(?:\d\d-\d\d|W\d\d-\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?::\d\d(?::\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,mt=/^\s*((?:[+-]\d{6}|\d{4})(?:\d\d\d\d|W\d\d\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?:\d\d(?:\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,_t=/Z|[+-]\d\d(?::?\d\d)?/,yt=[["YYYYYY-MM-DD",/[+-]\d{6}-\d\d-\d\d/],["YYYY-MM-DD",/\d{4}-\d\d-\d\d/],["GGGG-[W]WW-E",/\d{4}-W\d\d-\d/],["GGGG-[W]WW",/\d{4}-W\d\d/,!1],["YYYY-DDD",/\d{4}-\d{3}/],["YYYY-MM",/\d{4}-\d\d/,!1],["YYYYYYMMDD",/[+-]\d{10}/],["YYYYMMDD",/\d{8}/],["GGGG[W]WWE",/\d{4}W\d{3}/],["GGGG[W]WW",/\d{4}W\d{2}/,!1],["YYYYDDD",/\d{7}/]],gt=[["HH:mm:ss.SSSS",/\d\d:\d\d:\d\d\.\d+/],["HH:mm:ss,SSSS",/\d\d:\d\d:\d\d,\d+/],["HH:mm:ss",/\d\d:\d\d:\d\d/],["HH:mm",/\d\d:\d\d/],["HHmmss.SSSS",/\d\d\d\d\d\d\.\d+/],["HHmmss,SSSS",/\d\d\d\d\d\d,\d+/],["HHmmss",/\d\d\d\d\d\d/],["HHmm",/\d\d\d\d/],["HH",/\d\d/]],pt=/^\/?Date\((\-?\d+)/i;function vt(e){var t,n,s,i,r,a,o=e._i,u=ft.exec(o)||mt.exec(o);if(u){for(g(e).iso=!0,t=0,n=yt.length;tn.valueOf():n.valueOf()this.clone().month(0).utcOffset()||this.utcOffset()>this.clone().month(5).utcOffset()},ln.isLocal=function(){return!!this.isValid()&&!this._isUTC},ln.isUtcOffset=function(){return!!this.isValid()&&this._isUTC},ln.isUtc=Vt,ln.isUTC=Vt,ln.zoneAbbr=function(){return this._isUTC?"UTC":""},ln.zoneName=function(){return this._isUTC?"Coordinated Universal Time":""},ln.dates=n("dates accessor is deprecated. Use date instead.",nn),ln.months=n("months accessor is deprecated. Use month instead",Fe),ln.years=n("years accessor is deprecated. Use year instead",Oe),ln.zone=n("moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/",function(e,t){return null!=e?("string"!=typeof e&&(e=-e),this.utcOffset(e,t),this):-this.utcOffset()}),ln.isDSTShifted=n("isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information",function(){if(!l(this._isDSTShifted))return this._isDSTShifted;var e={};if(w(e,this),(e=Yt(e))._a){var t=e._isUTC?y(e._a):Tt(e._a);this._isDSTShifted=this.isValid()&&0',$(div).appendTo('body').click(function(){$('html').removeClass('nav-open'),nowuiDashboard.misc.navbar_menu_visible=0,setTimeout(function(){$toggle.removeClass('toggled'),$('#bodyClick').remove()},550)}),$('html').addClass('nav-open'),nowuiDashboard.misc.navbar_menu_visible=1)}),$(window).resize(function(){seq=seq2=0,0==$('.full-screen-map').length&&0==$('.bd-docs').length&&($navbar=$('.navbar'),isExpanded=$('.navbar').find('[data-toggle="collapse"]').attr('aria-expanded'),$navbar.hasClass('bg-white')&&991<$(window).width()?$navbar.removeClass('bg-white').addClass('navbar-transparent'):$navbar.hasClass('navbar-transparent')&&991>$(window).width()&&'false'!=isExpanded&&$navbar.addClass('bg-white').removeClass('navbar-transparent'))}),nowuiDashboard={misc:{navbar_menu_visible:0},initMinimizeSidebar:function(){0!=$('.sidebar-mini').length&&(sidebar_mini_active=!0),$('#minimizeSidebar').click(function(){$(this);!0==sidebar_mini_active?($('body').removeClass('sidebar-mini'),sidebar_mini_active=!1,nowuiDashboard.showSidebarMessage('Sidebar mini deactivated...')):($('body').addClass('sidebar-mini'),sidebar_mini_active=!0,nowuiDashboard.showSidebarMessage('Sidebar mini activated...'));var a=setInterval(function(){window.dispatchEvent(new Event('resize'))},180);setTimeout(function(){clearInterval(a)},1e3)})},showSidebarMessage:function(a){try{$.notify({icon:'now-ui-icons ui-1_bell-53',message:a},{type:'info',timer:4e3,placement:{from:'top',align:'right'}})}catch(a){console.log('Notify library is missing, please make sure you have the notifications library added.')}}},hexToRGB=function(a,c){var d=parseInt(a.slice(1,3),16),e=parseInt(a.slice(3,5),16),f=parseInt(a.slice(5,7),16);return c?'rgba('+d+', '+e+', '+f+', '+c+')':'rgb('+d+', '+e+', '+f+')'}; \ No newline at end of file diff --git a/web/templates/boilerplate/assets/js/perfect-scrollbar.jquery.min.js b/web/templates/boilerplate/assets/js/perfect-scrollbar.jquery.min.js deleted file mode 100644 index 108e725..0000000 --- a/web/templates/boilerplate/assets/js/perfect-scrollbar.jquery.min.js +++ /dev/null @@ -1,2 +0,0 @@ -/* perfect-scrollbar v0.6.13 */ -!function t(e,n,r){function o(i,s){if(!n[i]){if(!e[i]){var a="function"==typeof require&&require;if(!s&&a)return a(i,!0);if(l)return l(i,!0);var c=new Error("Cannot find module '"+i+"'");throw c.code="MODULE_NOT_FOUND",c}var u=n[i]={exports:{}};e[i][0].call(u.exports,function(t){var n=e[i][1][t];return o(n?n:t)},u,u.exports,t,e,n,r)}return n[i].exports}for(var l="function"==typeof require&&require,i=0;i=0&&n.splice(r,1),t.className=n.join(" ")}n.add=function(t,e){t.classList?t.classList.add(e):r(t,e)},n.remove=function(t,e){t.classList?t.classList.remove(e):o(t,e)},n.list=function(t){return t.classList?Array.prototype.slice.apply(t.classList):t.className.split(" ")}},{}],3:[function(t,e,n){"use strict";function r(t,e){return window.getComputedStyle(t)[e]}function o(t,e,n){return"number"==typeof n&&(n=n.toString()+"px"),t.style[e]=n,t}function l(t,e){for(var n in e){var r=e[n];"number"==typeof r&&(r=r.toString()+"px"),t.style[n]=r}return t}var i={};i.e=function(t,e){var n=document.createElement(t);return n.className=e,n},i.appendTo=function(t,e){return e.appendChild(t),t},i.css=function(t,e,n){return"object"==typeof e?l(t,e):"undefined"==typeof n?r(t,e):o(t,e,n)},i.matches=function(t,e){return"undefined"!=typeof t.matches?t.matches(e):"undefined"!=typeof t.matchesSelector?t.matchesSelector(e):"undefined"!=typeof t.webkitMatchesSelector?t.webkitMatchesSelector(e):"undefined"!=typeof t.mozMatchesSelector?t.mozMatchesSelector(e):"undefined"!=typeof t.msMatchesSelector?t.msMatchesSelector(e):void 0},i.remove=function(t){"undefined"!=typeof t.remove?t.remove():t.parentNode&&t.parentNode.removeChild(t)},i.queryChildren=function(t,e){return Array.prototype.filter.call(t.childNodes,function(t){return i.matches(t,e)})},e.exports=i},{}],4:[function(t,e,n){"use strict";var r=function(t){this.element=t,this.events={}};r.prototype.bind=function(t,e){"undefined"==typeof this.events[t]&&(this.events[t]=[]),this.events[t].push(e),this.element.addEventListener(t,e,!1)},r.prototype.unbind=function(t,e){var n="undefined"!=typeof e;this.events[t]=this.events[t].filter(function(r){return!(!n||r===e)||(this.element.removeEventListener(t,r,!1),!1)},this)},r.prototype.unbindAll=function(){for(var t in this.events)this.unbind(t)};var o=function(){this.eventElements=[]};o.prototype.eventElement=function(t){var e=this.eventElements.filter(function(e){return e.element===t})[0];return"undefined"==typeof e&&(e=new r(t),this.eventElements.push(e)),e},o.prototype.bind=function(t,e,n){this.eventElement(t).bind(e,n)},o.prototype.unbind=function(t,e,n){this.eventElement(t).unbind(e,n)},o.prototype.unbindAll=function(){for(var t=0;te.scrollbarYTop?1:-1;i(t,"top",t.scrollTop+s*e.containerHeight),l(t),r.stopPropagation()}),e.event.bind(e.scrollbarX,"click",r),e.event.bind(e.scrollbarXRail,"click",function(r){var o=r.pageX-window.pageXOffset-n(e.scrollbarXRail).left,s=o>e.scrollbarXLeft?1:-1;i(t,"left",t.scrollLeft+s*e.containerWidth),l(t),r.stopPropagation()})}var o=t("../instances"),l=t("../update-geometry"),i=t("../update-scroll");e.exports=function(t){var e=o.get(t);r(t,e)}},{"../instances":18,"../update-geometry":19,"../update-scroll":20}],11:[function(t,e,n){"use strict";function r(t,e){function n(n){var o=r+n*e.railXRatio,i=Math.max(0,e.scrollbarXRail.getBoundingClientRect().left)+e.railXRatio*(e.railXWidth-e.scrollbarXWidth);o<0?e.scrollbarXLeft=0:o>i?e.scrollbarXLeft=i:e.scrollbarXLeft=o;var s=l.toInt(e.scrollbarXLeft*(e.contentWidth-e.containerWidth)/(e.containerWidth-e.railXRatio*e.scrollbarXWidth))-e.negativeScrollAdjustment;c(t,"left",s)}var r=null,o=null,s=function(e){n(e.pageX-o),a(t),e.stopPropagation(),e.preventDefault()},u=function(){l.stopScrolling(t,"x"),e.event.unbind(e.ownerDocument,"mousemove",s)};e.event.bind(e.scrollbarX,"mousedown",function(n){o=n.pageX,r=l.toInt(i.css(e.scrollbarX,"left"))*e.railXRatio,l.startScrolling(t,"x"),e.event.bind(e.ownerDocument,"mousemove",s),e.event.once(e.ownerDocument,"mouseup",u),n.stopPropagation(),n.preventDefault()})}function o(t,e){function n(n){var o=r+n*e.railYRatio,i=Math.max(0,e.scrollbarYRail.getBoundingClientRect().top)+e.railYRatio*(e.railYHeight-e.scrollbarYHeight);o<0?e.scrollbarYTop=0:o>i?e.scrollbarYTop=i:e.scrollbarYTop=o;var s=l.toInt(e.scrollbarYTop*(e.contentHeight-e.containerHeight)/(e.containerHeight-e.railYRatio*e.scrollbarYHeight));c(t,"top",s)}var r=null,o=null,s=function(e){n(e.pageY-o),a(t),e.stopPropagation(),e.preventDefault()},u=function(){l.stopScrolling(t,"y"),e.event.unbind(e.ownerDocument,"mousemove",s)};e.event.bind(e.scrollbarY,"mousedown",function(n){o=n.pageY,r=l.toInt(i.css(e.scrollbarY,"top"))*e.railYRatio,l.startScrolling(t,"y"),e.event.bind(e.ownerDocument,"mousemove",s),e.event.once(e.ownerDocument,"mouseup",u),n.stopPropagation(),n.preventDefault()})}var l=t("../../lib/helper"),i=t("../../lib/dom"),s=t("../instances"),a=t("../update-geometry"),c=t("../update-scroll");e.exports=function(t){var e=s.get(t);r(t,e),o(t,e)}},{"../../lib/dom":3,"../../lib/helper":6,"../instances":18,"../update-geometry":19,"../update-scroll":20}],12:[function(t,e,n){"use strict";function r(t,e){function n(n,r){var o=t.scrollTop;if(0===n){if(!e.scrollbarYActive)return!1;if(0===o&&r>0||o>=e.contentHeight-e.containerHeight&&r<0)return!e.settings.wheelPropagation}var l=t.scrollLeft;if(0===r){if(!e.scrollbarXActive)return!1;if(0===l&&n<0||l>=e.contentWidth-e.containerWidth&&n>0)return!e.settings.wheelPropagation}return!0}var r=!1;e.event.bind(t,"mouseenter",function(){r=!0}),e.event.bind(t,"mouseleave",function(){r=!1});var i=!1;e.event.bind(e.ownerDocument,"keydown",function(c){if(!(c.isDefaultPrevented&&c.isDefaultPrevented()||c.defaultPrevented)){var u=l.matches(e.scrollbarX,":focus")||l.matches(e.scrollbarY,":focus");if(r||u){var d=document.activeElement?document.activeElement:e.ownerDocument.activeElement;if(d){if("IFRAME"===d.tagName)d=d.contentDocument.activeElement;else for(;d.shadowRoot;)d=d.shadowRoot.activeElement;if(o.isEditable(d))return}var p=0,f=0;switch(c.which){case 37:p=c.metaKey?-e.contentWidth:c.altKey?-e.containerWidth:-30;break;case 38:f=c.metaKey?e.contentHeight:c.altKey?e.containerHeight:30;break;case 39:p=c.metaKey?e.contentWidth:c.altKey?e.containerWidth:30;break;case 40:f=c.metaKey?-e.contentHeight:c.altKey?-e.containerHeight:-30;break;case 33:f=90;break;case 32:f=c.shiftKey?90:-90;break;case 34:f=-90;break;case 35:f=c.ctrlKey?-e.contentHeight:-e.containerHeight;break;case 36:f=c.ctrlKey?t.scrollTop:e.containerHeight;break;default:return}a(t,"top",t.scrollTop-f),a(t,"left",t.scrollLeft+p),s(t),i=n(p,f),i&&c.preventDefault()}}})}var o=t("../../lib/helper"),l=t("../../lib/dom"),i=t("../instances"),s=t("../update-geometry"),a=t("../update-scroll");e.exports=function(t){var e=i.get(t);r(t,e)}},{"../../lib/dom":3,"../../lib/helper":6,"../instances":18,"../update-geometry":19,"../update-scroll":20}],13:[function(t,e,n){"use strict";function r(t,e){function n(n,r){var o=t.scrollTop;if(0===n){if(!e.scrollbarYActive)return!1;if(0===o&&r>0||o>=e.contentHeight-e.containerHeight&&r<0)return!e.settings.wheelPropagation}var l=t.scrollLeft;if(0===r){if(!e.scrollbarXActive)return!1;if(0===l&&n<0||l>=e.contentWidth-e.containerWidth&&n>0)return!e.settings.wheelPropagation}return!0}function r(t){var e=t.deltaX,n=-1*t.deltaY;return"undefined"!=typeof e&&"undefined"!=typeof n||(e=-1*t.wheelDeltaX/6,n=t.wheelDeltaY/6),t.deltaMode&&1===t.deltaMode&&(e*=10,n*=10),e!==e&&n!==n&&(e=0,n=t.wheelDelta),t.shiftKey?[-n,-e]:[e,n]}function o(e,n){var r=t.querySelector("textarea:hover, select[multiple]:hover, .ps-child:hover");if(r){if(!window.getComputedStyle(r).overflow.match(/(scroll|auto)/))return!1;var o=r.scrollHeight-r.clientHeight;if(o>0&&!(0===r.scrollTop&&n>0||r.scrollTop===o&&n<0))return!0;var l=r.scrollLeft-r.clientWidth;if(l>0&&!(0===r.scrollLeft&&e<0||r.scrollLeft===l&&e>0))return!0}return!1}function s(s){var c=r(s),u=c[0],d=c[1];o(u,d)||(a=!1,e.settings.useBothWheelAxes?e.scrollbarYActive&&!e.scrollbarXActive?(d?i(t,"top",t.scrollTop-d*e.settings.wheelSpeed):i(t,"top",t.scrollTop+u*e.settings.wheelSpeed),a=!0):e.scrollbarXActive&&!e.scrollbarYActive&&(u?i(t,"left",t.scrollLeft+u*e.settings.wheelSpeed):i(t,"left",t.scrollLeft-d*e.settings.wheelSpeed),a=!0):(i(t,"top",t.scrollTop-d*e.settings.wheelSpeed),i(t,"left",t.scrollLeft+u*e.settings.wheelSpeed)),l(t),a=a||n(u,d),a&&(s.stopPropagation(),s.preventDefault()))}var a=!1;"undefined"!=typeof window.onwheel?e.event.bind(t,"wheel",s):"undefined"!=typeof window.onmousewheel&&e.event.bind(t,"mousewheel",s)}var o=t("../instances"),l=t("../update-geometry"),i=t("../update-scroll");e.exports=function(t){var e=o.get(t);r(t,e)}},{"../instances":18,"../update-geometry":19,"../update-scroll":20}],14:[function(t,e,n){"use strict";function r(t,e){e.event.bind(t,"scroll",function(){l(t)})}var o=t("../instances"),l=t("../update-geometry");e.exports=function(t){var e=o.get(t);r(t,e)}},{"../instances":18,"../update-geometry":19}],15:[function(t,e,n){"use strict";function r(t,e){function n(){var t=window.getSelection?window.getSelection():document.getSelection?document.getSelection():"";return 0===t.toString().length?null:t.getRangeAt(0).commonAncestorContainer}function r(){c||(c=setInterval(function(){return l.get(t)?(s(t,"top",t.scrollTop+u.top),s(t,"left",t.scrollLeft+u.left),void i(t)):void clearInterval(c)},50))}function a(){c&&(clearInterval(c),c=null),o.stopScrolling(t)}var c=null,u={top:0,left:0},d=!1;e.event.bind(e.ownerDocument,"selectionchange",function(){t.contains(n())?d=!0:(d=!1,a())}),e.event.bind(window,"mouseup",function(){d&&(d=!1,a())}),e.event.bind(window,"keyup",function(){d&&(d=!1,a())}),e.event.bind(window,"mousemove",function(e){if(d){var n={x:e.pageX,y:e.pageY},l={left:t.offsetLeft,right:t.offsetLeft+t.offsetWidth,top:t.offsetTop,bottom:t.offsetTop+t.offsetHeight};n.xl.right-3?(u.left=5,o.startScrolling(t,"x")):u.left=0,n.yl.bottom-3?(n.y-l.bottom+3<5?u.top=5:u.top=20,o.startScrolling(t,"y")):u.top=0,0===u.top&&0===u.left?a():r()}})}var o=t("../../lib/helper"),l=t("../instances"),i=t("../update-geometry"),s=t("../update-scroll");e.exports=function(t){var e=l.get(t);r(t,e)}},{"../../lib/helper":6,"../instances":18,"../update-geometry":19,"../update-scroll":20}],16:[function(t,e,n){"use strict";function r(t,e,n,r){function o(n,r){var o=t.scrollTop,l=t.scrollLeft,i=Math.abs(n),s=Math.abs(r);if(s>i){if(r<0&&o===e.contentHeight-e.containerHeight||r>0&&0===o)return!e.settings.swipePropagation}else if(i>s&&(n<0&&l===e.contentWidth-e.containerWidth||n>0&&0===l))return!e.settings.swipePropagation;return!0}function a(e,n){s(t,"top",t.scrollTop-n),s(t,"left",t.scrollLeft-e),i(t)}function c(){w=!0}function u(){w=!1}function d(t){return t.targetTouches?t.targetTouches[0]:t}function p(t){return!(!t.targetTouches||1!==t.targetTouches.length)||!(!t.pointerType||"mouse"===t.pointerType||t.pointerType===t.MSPOINTER_TYPE_MOUSE)}function f(t){if(p(t)){Y=!0;var e=d(t);g.pageX=e.pageX,g.pageY=e.pageY,v=(new Date).getTime(),null!==y&&clearInterval(y),t.stopPropagation()}}function h(t){if(!Y&&e.settings.swipePropagation&&f(t),!w&&Y&&p(t)){var n=d(t),r={pageX:n.pageX,pageY:n.pageY},l=r.pageX-g.pageX,i=r.pageY-g.pageY;a(l,i),g=r;var s=(new Date).getTime(),c=s-v;c>0&&(m.x=l/c,m.y=i/c,v=s),o(l,i)&&(t.stopPropagation(),t.preventDefault())}}function b(){!w&&Y&&(Y=!1,clearInterval(y),y=setInterval(function(){return l.get(t)&&(m.x||m.y)?Math.abs(m.x)<.01&&Math.abs(m.y)<.01?void clearInterval(y):(a(30*m.x,30*m.y),m.x*=.8,void(m.y*=.8)):void clearInterval(y)},10))}var g={},v=0,m={},y=null,w=!1,Y=!1;n&&(e.event.bind(window,"touchstart",c),e.event.bind(window,"touchend",u),e.event.bind(t,"touchstart",f),e.event.bind(t,"touchmove",h),e.event.bind(t,"touchend",b)),r&&(window.PointerEvent?(e.event.bind(window,"pointerdown",c),e.event.bind(window,"pointerup",u),e.event.bind(t,"pointerdown",f),e.event.bind(t,"pointermove",h),e.event.bind(t,"pointerup",b)):window.MSPointerEvent&&(e.event.bind(window,"MSPointerDown",c),e.event.bind(window,"MSPointerUp",u),e.event.bind(t,"MSPointerDown",f),e.event.bind(t,"MSPointerMove",h),e.event.bind(t,"MSPointerUp",b)))}var o=t("../../lib/helper"),l=t("../instances"),i=t("../update-geometry"),s=t("../update-scroll");e.exports=function(t){if(o.env.supportsTouch||o.env.supportsIePointer){var e=l.get(t);r(t,e,o.env.supportsTouch,o.env.supportsIePointer)}}},{"../../lib/helper":6,"../instances":18,"../update-geometry":19,"../update-scroll":20}],17:[function(t,e,n){"use strict";var r=t("../lib/helper"),o=t("../lib/class"),l=t("./instances"),i=t("./update-geometry"),s={"click-rail":t("./handler/click-rail"),"drag-scrollbar":t("./handler/drag-scrollbar"),keyboard:t("./handler/keyboard"),wheel:t("./handler/mouse-wheel"),touch:t("./handler/touch"),selection:t("./handler/selection")},a=t("./handler/native-scroll");e.exports=function(t,e){e="object"==typeof e?e:{},o.add(t,"ps-container");var n=l.add(t);n.settings=r.extend(n.settings,e),o.add(t,"ps-theme-"+n.settings.theme),n.settings.handlers.forEach(function(e){s[e](t)}),a(t),i(t)}},{"../lib/class":2,"../lib/helper":6,"./handler/click-rail":10,"./handler/drag-scrollbar":11,"./handler/keyboard":12,"./handler/mouse-wheel":13,"./handler/native-scroll":14,"./handler/selection":15,"./handler/touch":16,"./instances":18,"./update-geometry":19}],18:[function(t,e,n){"use strict";function r(t){function e(){a.add(t,"ps-focus")}function n(){a.remove(t,"ps-focus")}var r=this;r.settings=s.clone(c),r.containerWidth=null,r.containerHeight=null,r.contentWidth=null,r.contentHeight=null,r.isRtl="rtl"===u.css(t,"direction"),r.isNegativeScroll=function(){var e=t.scrollLeft,n=null;return t.scrollLeft=-1,n=t.scrollLeft<0,t.scrollLeft=e,n}(),r.negativeScrollAdjustment=r.isNegativeScroll?t.scrollWidth-t.clientWidth:0,r.event=new d,r.ownerDocument=t.ownerDocument||document,r.scrollbarXRail=u.appendTo(u.e("div","ps-scrollbar-x-rail"),t),r.scrollbarX=u.appendTo(u.e("div","ps-scrollbar-x"),r.scrollbarXRail),r.scrollbarX.setAttribute("tabindex",0),r.event.bind(r.scrollbarX,"focus",e),r.event.bind(r.scrollbarX,"blur",n),r.scrollbarXActive=null,r.scrollbarXWidth=null,r.scrollbarXLeft=null,r.scrollbarXBottom=s.toInt(u.css(r.scrollbarXRail,"bottom")),r.isScrollbarXUsingBottom=r.scrollbarXBottom===r.scrollbarXBottom,r.scrollbarXTop=r.isScrollbarXUsingBottom?null:s.toInt(u.css(r.scrollbarXRail,"top")),r.railBorderXWidth=s.toInt(u.css(r.scrollbarXRail,"borderLeftWidth"))+s.toInt(u.css(r.scrollbarXRail,"borderRightWidth")),u.css(r.scrollbarXRail,"display","block"),r.railXMarginWidth=s.toInt(u.css(r.scrollbarXRail,"marginLeft"))+s.toInt(u.css(r.scrollbarXRail,"marginRight")),u.css(r.scrollbarXRail,"display",""),r.railXWidth=null,r.railXRatio=null,r.scrollbarYRail=u.appendTo(u.e("div","ps-scrollbar-y-rail"),t),r.scrollbarY=u.appendTo(u.e("div","ps-scrollbar-y"),r.scrollbarYRail),r.scrollbarY.setAttribute("tabindex",0),r.event.bind(r.scrollbarY,"focus",e),r.event.bind(r.scrollbarY,"blur",n),r.scrollbarYActive=null,r.scrollbarYHeight=null,r.scrollbarYTop=null,r.scrollbarYRight=s.toInt(u.css(r.scrollbarYRail,"right")),r.isScrollbarYUsingRight=r.scrollbarYRight===r.scrollbarYRight,r.scrollbarYLeft=r.isScrollbarYUsingRight?null:s.toInt(u.css(r.scrollbarYRail,"left")),r.scrollbarYOuterWidth=r.isRtl?s.outerWidth(r.scrollbarY):null,r.railBorderYWidth=s.toInt(u.css(r.scrollbarYRail,"borderTopWidth"))+s.toInt(u.css(r.scrollbarYRail,"borderBottomWidth")),u.css(r.scrollbarYRail,"display","block"),r.railYMarginHeight=s.toInt(u.css(r.scrollbarYRail,"marginTop"))+s.toInt(u.css(r.scrollbarYRail,"marginBottom")),u.css(r.scrollbarYRail,"display",""),r.railYHeight=null,r.railYRatio=null}function o(t){return t.getAttribute("data-ps-id")}function l(t,e){t.setAttribute("data-ps-id",e)}function i(t){t.removeAttribute("data-ps-id")}var s=t("../lib/helper"),a=t("../lib/class"),c=t("./default-setting"),u=t("../lib/dom"),d=t("../lib/event-manager"),p=t("../lib/guid"),f={};n.add=function(t){var e=p();return l(t,e),f[e]=new r(t),f[e]},n.remove=function(t){delete f[o(t)],i(t)},n.get=function(t){return f[o(t)]}},{"../lib/class":2,"../lib/dom":3,"../lib/event-manager":4,"../lib/guid":5,"../lib/helper":6,"./default-setting":8}],19:[function(t,e,n){"use strict";function r(t,e){return t.settings.minScrollbarLength&&(e=Math.max(e,t.settings.minScrollbarLength)),t.settings.maxScrollbarLength&&(e=Math.min(e,t.settings.maxScrollbarLength)),e}function o(t,e){var n={width:e.railXWidth};e.isRtl?n.left=e.negativeScrollAdjustment+t.scrollLeft+e.containerWidth-e.contentWidth:n.left=t.scrollLeft,e.isScrollbarXUsingBottom?n.bottom=e.scrollbarXBottom-t.scrollTop:n.top=e.scrollbarXTop+t.scrollTop,s.css(e.scrollbarXRail,n);var r={top:t.scrollTop,height:e.railYHeight};e.isScrollbarYUsingRight?e.isRtl?r.right=e.contentWidth-(e.negativeScrollAdjustment+t.scrollLeft)-e.scrollbarYRight-e.scrollbarYOuterWidth:r.right=e.scrollbarYRight-t.scrollLeft:e.isRtl?r.left=e.negativeScrollAdjustment+t.scrollLeft+2*e.containerWidth-e.contentWidth-e.scrollbarYLeft-e.scrollbarYOuterWidth:r.left=e.scrollbarYLeft+t.scrollLeft,s.css(e.scrollbarYRail,r),s.css(e.scrollbarX,{left:e.scrollbarXLeft,width:e.scrollbarXWidth-e.railBorderXWidth}),s.css(e.scrollbarY,{top:e.scrollbarYTop,height:e.scrollbarYHeight-e.railBorderYWidth})}var l=t("../lib/helper"),i=t("../lib/class"),s=t("../lib/dom"),a=t("./instances"),c=t("./update-scroll");e.exports=function(t){var e=a.get(t);e.containerWidth=t.clientWidth,e.containerHeight=t.clientHeight,e.contentWidth=t.scrollWidth,e.contentHeight=t.scrollHeight;var n;t.contains(e.scrollbarXRail)||(n=s.queryChildren(t,".ps-scrollbar-x-rail"),n.length>0&&n.forEach(function(t){s.remove(t)}),s.appendTo(e.scrollbarXRail,t)),t.contains(e.scrollbarYRail)||(n=s.queryChildren(t,".ps-scrollbar-y-rail"),n.length>0&&n.forEach(function(t){s.remove(t)}),s.appendTo(e.scrollbarYRail,t)),!e.settings.suppressScrollX&&e.containerWidth+e.settings.scrollXMarginOffset=e.railXWidth-e.scrollbarXWidth&&(e.scrollbarXLeft=e.railXWidth-e.scrollbarXWidth),e.scrollbarYTop>=e.railYHeight-e.scrollbarYHeight&&(e.scrollbarYTop=e.railYHeight-e.scrollbarYHeight),o(t,e),e.scrollbarXActive?i.add(t,"ps-active-x"):(i.remove(t,"ps-active-x"),e.scrollbarXWidth=0,e.scrollbarXLeft=0,c(t,"left",0)),e.scrollbarYActive?i.add(t,"ps-active-y"):(i.remove(t,"ps-active-y"),e.scrollbarYHeight=0,e.scrollbarYTop=0,c(t,"top",0))}},{"../lib/class":2,"../lib/dom":3,"../lib/helper":6,"./instances":18,"./update-scroll":20}],20:[function(t,e,n){"use strict";var r,o,l=t("./instances"),i=function(t){var e=document.createEvent("Event");return e.initEvent(t,!0,!0),e};e.exports=function(t,e,n){if("undefined"==typeof t)throw"You must provide an element to the update-scroll function";if("undefined"==typeof e)throw"You must provide an axis to the update-scroll function";if("undefined"==typeof n)throw"You must provide a value to the update-scroll function";"top"===e&&n<=0&&(t.scrollTop=n=0,t.dispatchEvent(i("ps-y-reach-start"))),"left"===e&&n<=0&&(t.scrollLeft=n=0,t.dispatchEvent(i("ps-x-reach-start")));var s=l.get(t);"top"===e&&n>=s.contentHeight-s.containerHeight&&(n=s.contentHeight-s.containerHeight,n-t.scrollTop<=1?n=t.scrollTop:t.scrollTop=n,t.dispatchEvent(i("ps-y-reach-end"))),"left"===e&&n>=s.contentWidth-s.containerWidth&&(n=s.contentWidth-s.containerWidth,n-t.scrollLeft<=1?n=t.scrollLeft:t.scrollLeft=n,t.dispatchEvent(i("ps-x-reach-end"))),r||(r=t.scrollTop),o||(o=t.scrollLeft),"top"===e&&nr&&t.dispatchEvent(i("ps-scroll-down")),"left"===e&&no&&t.dispatchEvent(i("ps-scroll-right")),"top"===e&&(t.scrollTop=r=n,t.dispatchEvent(i("ps-scroll-y"))),"left"===e&&(t.scrollLeft=o=n,t.dispatchEvent(i("ps-scroll-x")))}},{"./instances":18}],21:[function(t,e,n){"use strict";var r=t("../lib/helper"),o=t("../lib/dom"),l=t("./instances"),i=t("./update-geometry"),s=t("./update-scroll");e.exports=function(t){var e=l.get(t);e&&(e.negativeScrollAdjustment=e.isNegativeScroll?t.scrollWidth-t.clientWidth:0,o.css(e.scrollbarXRail,"display","block"),o.css(e.scrollbarYRail,"display","block"),e.railXMarginWidth=r.toInt(o.css(e.scrollbarXRail,"marginLeft"))+r.toInt(o.css(e.scrollbarXRail,"marginRight")),e.railYMarginHeight=r.toInt(o.css(e.scrollbarYRail,"marginTop"))+r.toInt(o.css(e.scrollbarYRail,"marginBottom")),o.css(e.scrollbarXRail,"display","none"),o.css(e.scrollbarYRail,"display","none"),i(t),s(t,"top",t.scrollTop),s(t,"left",t.scrollLeft),o.css(e.scrollbarXRail,"display",""),o.css(e.scrollbarYRail,"display",""))}},{"../lib/dom":3,"../lib/helper":6,"./instances":18,"./update-geometry":19,"./update-scroll":20}]},{},[1]); diff --git a/web/templates/boilerplate/assets/js/popper.min.js b/web/templates/boilerplate/assets/js/popper.min.js deleted file mode 100644 index ce33a86..0000000 --- a/web/templates/boilerplate/assets/js/popper.min.js +++ /dev/null @@ -1,4 +0,0 @@ -/* - Copyright (C) Federico Zivolo 2017 - Distributed under the MIT License (license terms are at http://opensource.org/licenses/MIT). - */(function(e,t){'object'==typeof exports&&'undefined'!=typeof module?module.exports=t():'function'==typeof define&&define.amd?define(t):e.Popper=t()})(this,function(){'use strict';function e(e){return e&&'[object Function]'==={}.toString.call(e)}function t(e,t){if(1!==e.nodeType)return[];var o=window.getComputedStyle(e,null);return t?o[t]:o}function o(e){return'HTML'===e.nodeName?e:e.parentNode||e.host}function n(e){if(!e||-1!==['HTML','BODY','#document'].indexOf(e.nodeName))return window.document.body;var i=t(e),r=i.overflow,p=i.overflowX,s=i.overflowY;return /(auto|scroll)/.test(r+s+p)?e:n(o(e))}function r(e){var o=e&&e.offsetParent,i=o&&o.nodeName;return i&&'BODY'!==i&&'HTML'!==i?-1!==['TD','TABLE'].indexOf(o.nodeName)&&'static'===t(o,'position')?r(o):o:window.document.documentElement}function p(e){var t=e.nodeName;return'BODY'!==t&&('HTML'===t||r(e.firstElementChild)===e)}function s(e){return null===e.parentNode?e:s(e.parentNode)}function d(e,t){if(!e||!e.nodeType||!t||!t.nodeType)return window.document.documentElement;var o=e.compareDocumentPosition(t)&Node.DOCUMENT_POSITION_FOLLOWING,i=o?e:t,n=o?t:e,a=document.createRange();a.setStart(i,0),a.setEnd(n,0);var f=a.commonAncestorContainer;if(e!==f&&t!==f||i.contains(n))return p(f)?f:r(f);var l=s(e);return l.host?d(l.host,t):d(e,s(t).host)}function a(e){var t=1=o.clientWidth&&i>=o.clientHeight}),f=0i[e]&&!t.escapeWithReference&&(n=z(p[o],i[e]-('right'===e?p.width:p.height))),pe({},o,n)}};return n.forEach(function(e){var t=-1===['left','top'].indexOf(e)?'secondary':'primary';p=se({},p,s[t](e))}),e.offsets.popper=p,e},priority:['left','right','top','bottom'],padding:5,boundariesElement:'scrollParent'},keepTogether:{order:400,enabled:!0,fn:function(e){var t=e.offsets,o=t.popper,i=t.reference,n=e.placement.split('-')[0],r=V,p=-1!==['top','bottom'].indexOf(n),s=p?'right':'bottom',d=p?'left':'top',a=p?'width':'height';return o[s]r(i[s])&&(e.offsets.popper[d]=r(i[s])),e}},arrow:{order:500,enabled:!0,fn:function(e,t){if(!F(e.instance.modifiers,'arrow','keepTogether'))return e;var o=t.element;if('string'==typeof o){if(o=e.instance.popper.querySelector(o),!o)return e;}else if(!e.instance.popper.contains(o))return console.warn('WARNING: `arrow.element` must be child of its popper element!'),e;var i=e.placement.split('-')[0],n=e.offsets,r=n.popper,p=n.reference,s=-1!==['left','right'].indexOf(i),d=s?'height':'width',a=s?'top':'left',f=s?'left':'top',l=s?'bottom':'right',m=O(o)[d];p[l]-mr[l]&&(e.offsets.popper[a]+=p[a]+m-r[l]);var h=p[a]+p[d]/2-m/2,g=h-c(e.offsets.popper)[a];return g=_(z(r[d]-m,g),0),e.arrowElement=o,e.offsets.arrow={},e.offsets.arrow[a]=Math.round(g),e.offsets.arrow[f]='',e},element:'[x-arrow]'},flip:{order:600,enabled:!0,fn:function(e,t){if(W(e.instance.modifiers,'inner'))return e;if(e.flipped&&e.placement===e.originalPlacement)return e;var o=w(e.instance.popper,e.instance.reference,t.padding,t.boundariesElement),i=e.placement.split('-')[0],n=L(i),r=e.placement.split('-')[1]||'',p=[];switch(t.behavior){case fe.FLIP:p=[i,n];break;case fe.CLOCKWISE:p=K(i);break;case fe.COUNTERCLOCKWISE:p=K(i,!0);break;default:p=t.behavior;}return p.forEach(function(s,d){if(i!==s||p.length===d+1)return e;i=e.placement.split('-')[0],n=L(i);var a=e.offsets.popper,f=e.offsets.reference,l=V,m='left'===i&&l(a.right)>l(f.left)||'right'===i&&l(a.left)l(f.top)||'bottom'===i&&l(a.top)l(o.right),g=l(a.top)l(o.bottom),b='left'===i&&h||'right'===i&&c||'top'===i&&g||'bottom'===i&&u,y=-1!==['top','bottom'].indexOf(i),w=!!t.flipVariations&&(y&&'start'===r&&h||y&&'end'===r&&c||!y&&'start'===r&&g||!y&&'end'===r&&u);(m||b||w)&&(e.flipped=!0,(m||b)&&(i=p[d+1]),w&&(r=j(r)),e.placement=i+(r?'-'+r:''),e.offsets.popper=se({},e.offsets.popper,S(e.instance.popper,e.offsets.reference,e.placement)),e=N(e.instance.modifiers,e,'flip'))}),e},behavior:'flip',padding:5,boundariesElement:'viewport'},inner:{order:700,enabled:!1,fn:function(e){var t=e.placement,o=t.split('-')[0],i=e.offsets,n=i.popper,r=i.reference,p=-1!==['left','right'].indexOf(o),s=-1===['top','left'].indexOf(o);return n[p?'left':'top']=r[t]-(s?n[p?'width':'height']:0),e.placement=L(t),e.offsets.popper=c(n),e}},hide:{order:800,enabled:!0,fn:function(e){if(!F(e.instance.modifiers,'hide','preventOverflow'))return e;var t=e.offsets.reference,o=T(e.instance.modifiers,function(e){return'preventOverflow'===e.name}).boundaries;if(t.bottomo.right||t.top>o.bottom||t.right - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/web/templates/boilerplate/views/blocks/header.ejs b/web/templates/boilerplate/views/blocks/header.ejs deleted file mode 100644 index 9b8d9b1..0000000 --- a/web/templates/boilerplate/views/blocks/header.ejs +++ /dev/null @@ -1,48 +0,0 @@ - - - - <%-pageTitle%> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/web/templates/boilerplate/views/blocks/home.ejs b/web/templates/boilerplate/views/blocks/home.ejs deleted file mode 100644 index cb065ab..0000000 --- a/web/templates/boilerplate/views/blocks/home.ejs +++ /dev/null @@ -1,132 +0,0 @@ - -
      - -
      - - - -
      - -
      -
      -
      - -
      -
      -
      -
      - \ No newline at end of file diff --git a/web/templates/boilerplate/views/index.ejs b/web/templates/boilerplate/views/index.ejs deleted file mode 100644 index 2ce2791..0000000 --- a/web/templates/boilerplate/views/index.ejs +++ /dev/null @@ -1,7 +0,0 @@ -<% var pageTitle = 'Shinobi Boilerplate Template' %> - -<% include blocks/header.ejs %> - -<% include blocks/home.ejs %> - -<% include blocks/footer.ejs %> \ No newline at end of file