Merge remote-tracking branch 'upstream/dev' into developer_documentation
commit
85b75aca76
|
|
@ -0,0 +1,19 @@
|
|||
Feature Request
|
||||
===============
|
||||
Summary
|
||||
-------
|
||||
[//]: # (Please write a concise description of the feature you would like implemented.)
|
||||
|
||||
Prerequisites
|
||||
-------------
|
||||
[//]: # (Include links to other feature requests or problems that would need to be handled before implementing this.)
|
||||
|
||||
Proposed Implementation
|
||||
-----------------------
|
||||
[//]: # (If you have an idea of how the feature should be implemented please write it down here.)
|
||||
|
||||
References
|
||||
----------
|
||||
[//]: # (Please provide links to projects which implement something similar, or projects that could be used to implement this feature.)
|
||||
|
||||
/label ~feature
|
||||
|
|
@ -44,7 +44,7 @@ if [ "$ffmpeginstall" = "y" ] || [ "$ffmpeginstall" = "Y" ]; then
|
|||
sudo rpm -Uvh http://li.nux.ro/download/nux/dextop/el7/x86_64/nux-dextop-release-0-1.el7.nux.noarch.rpm
|
||||
sudo yum install ffmpeg ffmpeg-devel -y
|
||||
else
|
||||
sudo npm install ffmpeg-static
|
||||
sudo npm install ffmpeg-static@2.2.1
|
||||
fi
|
||||
fi
|
||||
echo "Shinobi - Do you want to Install Node.js?"
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ if [ "$ffmpeginstall" = "y" ] || [ "$ffmpeginstall" = "Y" ]; then
|
|||
echo "============="
|
||||
fi
|
||||
else
|
||||
sudo npm install ffmpeg-static
|
||||
sudo npm install ffmpeg-static@2.2.1
|
||||
fi
|
||||
fi
|
||||
echo "============="
|
||||
|
|
|
|||
76
LICENSE
76
LICENSE
|
|
@ -1,76 +0,0 @@
|
|||
SHINOBI OPEN SOURCE SOFTWARE LICENSE AGREEMENT
|
||||
Version 1, 04 June 2018
|
||||
|
||||
Copyright (C) 2018 Shinobi Systems <https://shinobi.systems>
|
||||
|
||||
We'll try to keep it simple. Thanks for using Shinobi Software!
|
||||
|
||||
Defintions.
|
||||
|
||||
In this End User Licence Agreement,
|
||||
"EULA" shall mean this End User Licence Agreement
|
||||
"Licenser" shall mean SHINOBI SYSTEMS
|
||||
"Licensee" shall mean YOU, or the organisation (if any) on whose behalf YOU are taking the EULA.
|
||||
|
||||
"SOFTWARE PRODUCTS" or "SOFTWARE" or "PRODUCTS" shall mean the Software Product this License is included with and any additional modules or add-ons delivered by Shinobi Systems. The term "SOFTWARE" includes, to the extent provided by SHINOBI SYSTEMS: 1) any revisions, updates and/or upgrades thereto; 2) any data, image or executable files, databases, data engines, computer software, or similar items customarily used or distributed with computer software products; 3) anything in any form whatsoever intended to be used with or in conjunction with the SOFTWARE; and 4) any associated media, documentation (including physical, electronic and on-line) and printed materials (the "Documentation").
|
||||
|
||||
Purpose of the Agreement.
|
||||
|
||||
The Short : Protect the rights of this Software Product and the Licenser.
|
||||
|
||||
The Long : The LICENSER grants the LICENSEE a non-exclusive, non-transferable and perpetual licence to use the SOFTWARE PRODUCTS listed therein and under the terms thereof. By accepting the terms and conditions established in this agreement, the LICENSEE does not acquire any ownership of copyright or other intellectual property rights in any part of the SOFTWARE PRODUCTS. The LICENSEE is only entitled to use the SOFTWARE PRODUCTS in accordance with the terms and conditions set forth by Shinobi Systems. By using the SOFTWARE PRODUCTS, the LICENSEE agrees to accept the terms and conditions presented.
|
||||
|
||||
LICENSEE must purchase the applicable subscription in any other use case unless otherwise granted. If the use case does not have a subscription applicable please contact a representative at support@shinobi.systems.
|
||||
|
||||
Conditions for Free (Unpaid) use.
|
||||
|
||||
- Use in a non commercial area for non commercial purposes
|
||||
- Educational use
|
||||
- Testing Purposes
|
||||
- Use in a School like a elementary school, college, or university
|
||||
|
||||
Support Services.
|
||||
|
||||
The Maintenance and Support Service shall be contracted and provided as per selected plan agreement, taxes will be included in all prices for Support Services.
|
||||
|
||||
Support Services will only provide support services as per the selected agreement.
|
||||
|
||||
This is not the entire agreement on support services. You must also review all agreements provided with subscription plans provided.
|
||||
|
||||
Software Product Ownership.
|
||||
|
||||
This software is property of Shinobi Systems. LICENSEE must keep all copyright notices unchanged.
|
||||
|
||||
Modification of this Software Product.
|
||||
|
||||
LICENSEE may modify the code but LICENSEE must provide the source code if asked by law enforcement or an authorized Shinobi representative. LICENSEE must keep all copyright notices unchanged.
|
||||
|
||||
Software Product Rebranding or "White-Labelling".
|
||||
|
||||
LICENSEE can remove the Shinobi branding from the front end but all copyright notices must remain unchanged.
|
||||
|
||||
Software Product Contributions.
|
||||
|
||||
All contributed code becomes the property of Shinobi Systems. All contributors give permission to Shinobi and Shinobi developers to use the code however it is seen fit.
|
||||
|
||||
Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
Limitation of Liability.
|
||||
|
||||
LIMITATION ON AND EXCLUSION OF REMEDIES AND DAMAGES. YOU CAN RECOVER FROM SHINOBI SYSTEMS AND ITS SUPPLIERS ONLY DIRECT DAMAGES UP TO $5.00 CAD. YOU CANNOT RECOVER ANY OTHER DAMAGES, INCLUDING CONSEQUENTIAL, LOST PROFITS, SPECIAL, INDIRECT OR INCIDENTAL DAMAGES.
|
||||
This limitation applies to:
|
||||
|
||||
- anything related to the software, services, content (including code) on third-party Internet sites, or third-party programs; and
|
||||
- claims for breach of contract, breach of warranty, guarantee or condition, strict liability, negligence, or other tort to the extent permitted by applicable law.
|
||||
|
||||
It also applies even if Shinobi Systems knew or should have known about the possibility of the damages. The above limitation or exclusion may not apply to you because your country may not allow the exclusion or limitation of incidental, consequential or other damages.
|
||||
|
||||
Changes to the Agreement.
|
||||
|
||||
Shinobi Systems reserves the right to change the license and set of terms at any time. Continued use is agreement to those possible changes. Changes to this license will be provided in the commit history of the repository it is located in.
|
||||
|
||||
Legal Proceedings
|
||||
|
||||
All lawsuits must be filed in the city in which the current headquarters is based at the time of the filing.
|
||||
|
|
@ -0,0 +1,138 @@
|
|||
SHINOBI OPEN SOURCE SOFTWARE LICENSE AGREEMENT
|
||||
==============================================
|
||||
Version 1, 04 June 2018
|
||||
|
||||
Copyright (C) 2018 [Shinobi Systems](https://shinobi.systems)
|
||||
|
||||
*We'll try to keep it simple. Thanks for using Shinobi Software!*
|
||||
|
||||
Defintions.
|
||||
-----------
|
||||
This license, which also serves as a general End User License Agreement [EULA], the following terms shall be interpreted by these definitions:
|
||||
* "EULA" shall mean this End User Licence Agreement
|
||||
* "Licensor" shall mean SHINOBI SYSTEMS
|
||||
* "Licensee" shall mean YOU, or the organisation (if any) on whose behalf YOU are taking the EULA.
|
||||
|
||||
"SOFTWARE PRODUCTS" or "SOFTWARE" or "PRODUCTS" shall mean the Software Product this License is
|
||||
included with and any additional modules or add-ons delivered by Shinobi Systems. The term
|
||||
"SOFTWARE" includes, to the extent provided by SHINOBI SYSTEMS:
|
||||
1) any revisions, updates and/or upgrades thereto;
|
||||
2) any data, image or executable files, databases, data engines, computer software, or similar
|
||||
items customarily used or distributed with computer software products;
|
||||
3) anything in any form whatsoever intended to be used with or in conjunction with the SOFTWARE;
|
||||
4) any associated media, documentation (including physical, electronic and on-line) and printed
|
||||
materials (the "Documentation").
|
||||
|
||||
Purpose of the Agreement.
|
||||
-------------------------
|
||||
**The Short**: Protect the rights of this Software Product and the Licensor.
|
||||
|
||||
**The Long**: The Licensor grants the LICENSEE a non-exclusive, non-transferable and perpetual
|
||||
licence to use the SOFTWARE PRODUCTS listed therein and under the terms thereof. By accepting
|
||||
the terms and conditions established in this agreement, the LICENSEE does not acquire any
|
||||
ownership of copyright or other intellectual property rights in any part of the SOFTWARE
|
||||
PRODUCTS. The LICENSEE is only entitled to use the SOFTWARE PRODUCTS in accordance with the
|
||||
terms and conditions set forth by Shinobi Systems. By using the SOFTWARE PRODUCTS, the
|
||||
LICENSEE agrees to accept the terms and conditions presented.
|
||||
|
||||
LICENSEE must purchase the applicable subscription in any other use case unless otherwise
|
||||
granted. If the use case does not have a subscription applicable please contact a
|
||||
representative at support@shinobi.systems.
|
||||
|
||||
#### Commercial Uses
|
||||
- Selling usage of the software
|
||||
- Using the software in locations that engage in the buying and selling of goods and services
|
||||
|
||||
#### Conditions for Free (Unpaid) use.
|
||||
- Use in a non commercial area
|
||||
- Used for non commercial purposes
|
||||
- When used for research or educational purposes
|
||||
- Testing Purposes
|
||||
- Usage by Educational institutions
|
||||
- Use for Emergency Services and facilties associated like Search and Rescue Services or Ambulance Services
|
||||
- Use in Health Care facility like a hospital or walk-in clinic
|
||||
|
||||
#### Support Services.
|
||||
The Maintenance and Support Service shall be contracted and provided as per selected plan
|
||||
agreement, taxes will be included in all prices for Support Services.
|
||||
|
||||
Support Services will only provide support services as per the selected agreement.
|
||||
|
||||
This is not the entire agreement on support services. You must also review all agreements
|
||||
provided with subscription plans provided.
|
||||
|
||||
#### Software Product Ownership.
|
||||
This software is property of Shinobi Systems. LICENSEE must keep all copyright notices
|
||||
unchanged.
|
||||
|
||||
#### Modification of this Software Product.
|
||||
LICENSEE may modify code for personal use but must provide these changes upon request from Shinobi Systems or an authorized Shinobi representative. LICENSEE may not alter or change copyright notices. All code changes by LICENSEE shall fall under the copyright of Shinobi Systems in the case code modified by LICENSEE is integrated into the official Shinobi code base.
|
||||
|
||||
#### Software Product Rebranding or "White-Labelling".
|
||||
LICENSEE can remove the Shinobi branding from the front end but all copyright notices must
|
||||
remain unchanged.
|
||||
|
||||
#### Software Product Contributions.
|
||||
All contributed code becomes the property of Shinobi Systems. All contributors give permission
|
||||
to Shinobi and Shinobi developers to use the code however it is seen fit.
|
||||
|
||||
#### Disclaimer of Warranty.
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM
|
||||
"AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK
|
||||
AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE,
|
||||
YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
#### Changes to the Agreement.
|
||||
Shinobi Systems reserves the right to change the license and set of terms at any time.
|
||||
Continued use is agreement to those possible changes. Changes to this license will be provided
|
||||
in the commit history of the repository it is located in.
|
||||
|
||||
#### Legal Proceedings.
|
||||
All lawsuits must be filed at the Vancouver Court House.
|
||||
|
||||
Courthouse Vancouver Robson Square
|
||||
800 Hornby St, Vancouver, BC V6Z 2C5
|
||||
|
||||
#### List of Included Software
|
||||
|
||||
This list is completed to best of our knowledge.
|
||||
|
||||
Node.js - https://nodejs.org/en/
|
||||
MariaDB - https://mariadb.org/
|
||||
FFmpeg - https://www.ffmpeg.org/
|
||||
Express (npm) - https://expressjs.com/ https://www.npmjs.com/package/express
|
||||
EJS (npm) - http://ejs.co/ https://www.npmjs.com/package/ejs
|
||||
pam-diff (npm) (Motion Detector) - https://github.com/kevinGodell/pam-diff
|
||||
pipe2pam (npm) (for pam-diff) - https://github.com/kevinGodell/pipe2pam
|
||||
mp4frag (npm) (Poseidon's main engine) - https://github.com/kevinGodell/mp4frag
|
||||
mse-live-player (for mp4frag) - https://github.com/kevinGodell/mse-live-player
|
||||
pipe2jpeg (npm) - https://github.com/kevinGodell/pipe2jpeg
|
||||
webdav (npm) - https://www.npmjs.com/package/webdav
|
||||
jsonfile (npm) - https://www.npmjs.com/package/jsonfile
|
||||
connectionTester (npm) - https://www.npmjs.com/package/connectionTester
|
||||
node-onvif (npm) - https://www.npmjs.com/package/node-onvif
|
||||
knex (npm) - https://www.npmjs.com/package/knex
|
||||
nodemailer (npm) - https://www.npmjs.com/package/nodemailer
|
||||
mysql (npm) - https://www.npmjs.com/package/mysql
|
||||
sqlite3 (npm) - https://www.npmjs.com/package/sqlite3
|
||||
ldapauth-fork (npm) - https://www.npmjs.com/package/ldapauth-fork
|
||||
http-proxy (npm) - https://www.npmjs.com/package/http-proxy
|
||||
hls.js - https://github.com/video-dev/hls.js/
|
||||
flv.js - https://github.com/Bilibili/flv.js/
|
||||
Material Design Lite - https://getmdl.io/
|
||||
socket.io - https://socket.io/
|
||||
fullcalendar - https://fullcalendar.io/
|
||||
jQuery & jQuery UI - http://jquery.com
|
||||
Bootstrap - https://getbootstrap.com/
|
||||
PNotify - https://sciactive.com/pnotify/
|
||||
Font Awesome - https://fontawesome.com/
|
||||
Gridstack.js - http://gridstackjs.com/
|
||||
Date Range Picker (daterangepicker.js) - http://www.daterangepicker.com/
|
||||
Hero Pattern CSS Backgrounds - http://www.heropatterns.com/
|
||||
Bootstrap Table - https://github.com/wenzhixin/bootstrap-table
|
||||
placeholder.js - https://jamesallardice.github.io/Placeholders.js/
|
||||
Moment.js - https://momentjs.com/
|
||||
Livestamp.js - https://mattbradley.github.io/livestampjs/
|
||||
Lodash - https://lodash.com/
|
||||
95
UPDATE.sh
95
UPDATE.sh
|
|
@ -1,24 +1,83 @@
|
|||
#!/bin/bash
|
||||
distro=$1
|
||||
repo=$2
|
||||
if [ -z "$distro" ]; then
|
||||
distro='master'
|
||||
fi
|
||||
if [ -z "$repo" ]; then
|
||||
repo='ShinobiCCTV'
|
||||
fi
|
||||
if [ "$repo" = "ShinobiCCTV" ]; then
|
||||
productName="Shinobi Professional (Pro)"
|
||||
|
||||
gitURL="$(git remote get-url origin)"
|
||||
branch="$(git name-rev --name-only HEAD)"
|
||||
productName="Shinobi Pro"
|
||||
reqsubstr="Not a git repository"
|
||||
if [ -z "${gitURL##*$reqsubstr*}" ]; then
|
||||
echo "This is not a Git folder"
|
||||
gitURL="https://gitlab.com/Shinobi-Systems/Shinobi"
|
||||
branch='master'
|
||||
else
|
||||
productName="Shinobi Community Editon (CE)"
|
||||
echo "This is a Git folder"
|
||||
fi
|
||||
git reset --hard
|
||||
git pull
|
||||
gitURL="https://github.com/$repo/Shinobi"
|
||||
reqsubstr="/ShinobiCE"
|
||||
if [ -z "${gitURL##*$reqsubstr*}" ]; then
|
||||
echo "This is Shinobi CE"
|
||||
productName="Shinobi CE"
|
||||
gitURL="https://gitlab.com/Shinobi-Systems/ShinobiCE"
|
||||
else
|
||||
echo "This is Shinobi Pro"
|
||||
fi
|
||||
echo $branch
|
||||
echo $gitURL
|
||||
echo "Shinobi - Stopping All Processes"
|
||||
pm2 stop all
|
||||
|
||||
# open working directory (default is /home)
|
||||
cd ..
|
||||
|
||||
# delete the old backup
|
||||
if [ -e "./ShinobiOld" ]; then
|
||||
echo "Remove old backup"
|
||||
rm -rf ShinobiOld
|
||||
fi
|
||||
|
||||
# back up old install
|
||||
echo "Shinobi - Backup old files"
|
||||
mv Shinobi ShinobiOld
|
||||
|
||||
# clone the new files
|
||||
echo "Shinobi - Download new files"
|
||||
git clone $gitURL -b $branch Shinobi
|
||||
|
||||
# set permissions
|
||||
chmod -R 777 Shinobi
|
||||
|
||||
# move videos, videos2, conf.json, and super.json
|
||||
echo "Shinobi - Move videos, videos2, conf.json, and super.json"
|
||||
mv ShinobiOld/videos Shinobi/videos
|
||||
mv ShinobiOld/videos2 Shinobi/videos2
|
||||
cp ShinobiOld/conf.json Shinobi/conf.json
|
||||
if [ -e "./ShinobiOld/super.json" ]; then
|
||||
cp ShinobiOld/super.json Shinobi/super.json
|
||||
fi
|
||||
|
||||
# merge new plugin files but keep configs (added files)
|
||||
echo "Shinobi - merge new plugin files but keep configs (added files)"
|
||||
cp -R Shinobi/plugins Shinobi/pluginsTemp
|
||||
rm -rf Shinobi/plugins
|
||||
cp -R ShinobiOld/plugins Shinobi/plugins
|
||||
rm -rf ShinobiOld/plugins
|
||||
cp -R Shinobi/pluginsTemp/* Shinobi/plugins/
|
||||
rm -rf Shinobi/pluginsTemp
|
||||
|
||||
# move node modules and install updates
|
||||
echo "Shinobi - Move node modules and install updates"
|
||||
mv ShinobiOld/node_modules Shinobi/node_modules
|
||||
cd Shinobi
|
||||
chmod -R 777 node_modules
|
||||
npm install
|
||||
|
||||
# write version info
|
||||
gitVersionNumber=$(git rev-parse HEAD)
|
||||
theDateRightNow=$(date)
|
||||
rm version.json
|
||||
touch version.json
|
||||
chmod 755 version.json
|
||||
echo '{"Product" : "'"$productName"'" , "Branch" : "'"$distro"'" , "Version" : "'"$gitVersionNumber"'" , "Date" : "'"$theDateRightNow"'" , "Repository" : "'"$gitURL"'"}' > version.json
|
||||
echo "Restart Shinobi for updates to take effect."
|
||||
chmod 666 version.json
|
||||
versionJson='{"Product" : "'"$productName"'" , "Branch" : "'"$branch"'" , "Version" : "'"$gitVersionNumber"'" , "Date" : "'"$theDateRightNow"'" , "Repository" : "'"$gitURL"'"}'
|
||||
echo $versionJson > version.json
|
||||
echo $versionJson
|
||||
|
||||
# start processes
|
||||
echo "Shinobi - Starting All Processes"
|
||||
pm2 start all
|
||||
326
camera.js
326
camera.js
|
|
@ -116,6 +116,7 @@ if(config.databaseType===undefined){config.databaseType='mysql'}
|
|||
if(config.pluginKeys===undefined)config.pluginKeys={};
|
||||
if(config.databaseLogs===undefined){config.databaseLogs=false}
|
||||
if(config.useUTC===undefined){config.useUTC=false}
|
||||
if(config.strictDatabase===undefined){config.strictDatabase=false}
|
||||
if(config.pipeAddition===undefined){config.pipeAddition=7}else{config.pipeAddition=parseInt(config.pipeAddition)}
|
||||
//Web Paths
|
||||
if(config.webPaths===undefined){config.webPaths={}}
|
||||
|
|
@ -326,8 +327,13 @@ s.ocvTx=function(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);}
|
||||
s.txWithSubPermissions=function(z,y,permissionChoices){
|
||||
s.tx = function(z,y,x){if(x){return x.broadcast.to(y).emit('f',z)};io.to(y).emit('f',z);}
|
||||
s.txToDashcamUsers = function(data,groupKey){
|
||||
Object.keys(s.group[groupKey].dashcamUsers).forEach(function(auth){
|
||||
s.tx(data,s.group[groupKey].dashcamUsers[auth].cnid)
|
||||
})
|
||||
}
|
||||
s.txWithSubPermissions = function(z,y,permissionChoices){
|
||||
if(typeof permissionChoices==='string'){
|
||||
permissionChoices=[permissionChoices]
|
||||
}
|
||||
|
|
@ -488,6 +494,12 @@ s.getRequest = function(url,callback){
|
|||
s.kill=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){
|
||||
if(s.group[e.ke].mon[e.id].spawn){
|
||||
s.group[e.ke].mon[e.mid].allowStdinWrite = false
|
||||
s.txToDashcamUsers({
|
||||
f : 'disable_stream',
|
||||
ke : e.ke,
|
||||
mid : e.id
|
||||
},e.ke)
|
||||
s.group[e.ke].mon[e.id].spawn.stdio[3].unpipe();
|
||||
// if(s.group[e.ke].mon[e.id].p2pStream){s.group[e.ke].mon[e.id].p2pStream.unpipe();}
|
||||
if(s.group[e.ke].mon[e.id].p2p){s.group[e.ke].mon[e.id].p2p.unpipe();}
|
||||
|
|
@ -517,7 +529,7 @@ s.kill=function(x,e,p){
|
|||
if(!x||x===1){return};
|
||||
p=x.pid;
|
||||
if(s.group[e.ke].mon_conf[e.id].type===('dashcam'||'socket'||'jpeg'||'pipe')){
|
||||
x.stdin.pause();setTimeout(function(){x.kill('SIGTERM');delete(x);},500)
|
||||
x.stdin.pause();setTimeout(function(){x.kill('SIGTERM');},500)
|
||||
}else{
|
||||
try{
|
||||
x.stdin.setEncoding('utf8');x.stdin.write('q');
|
||||
|
|
@ -592,7 +604,7 @@ s.ffmpegVersion=execSync(config.ffmpegDir+" -version").toString().split('Copyrig
|
|||
console.log('FFMPEG version : '+s.ffmpegVersion)
|
||||
if(s.ffmpegVersion.indexOf(': 2.')>-1){
|
||||
s.systemLog('FFMPEG is too old : '+s.ffmpegVersion+', Needed : 3.2+',err)
|
||||
return
|
||||
throw (new Error())
|
||||
}
|
||||
//directories
|
||||
s.group={};
|
||||
|
|
@ -652,6 +664,7 @@ s.init=function(x,e,k,fn){
|
|||
if(!s.group[e.ke].sizeChangeQueue){s.group[e.ke].sizeChangeQueue=[]}
|
||||
if(!s.group[e.ke].sizePurgeQueue){s.group[e.ke].sizePurgeQueue=[]}
|
||||
if(!s.group[e.ke].users){s.group[e.ke].users={}}
|
||||
if(!s.group[e.ke].dashcamUsers){s.group[e.ke].dashcamUsers={}}
|
||||
if(!s.group[e.ke].mon[e.mid]){s.group[e.ke].mon[e.mid]={}}
|
||||
if(!s.group[e.ke].mon[e.mid].streamIn){s.group[e.ke].mon[e.mid].streamIn={}};
|
||||
if(!s.group[e.ke].mon[e.mid].emitterChannel){s.group[e.ke].mon[e.mid].emitterChannel={}};
|
||||
|
|
@ -791,6 +804,10 @@ s.init=function(x,e,k,fn){
|
|||
checkQueue()
|
||||
}
|
||||
break;
|
||||
case'monitorStatus':
|
||||
s.group[e.ke].mon[e.id].monitorStatus = e.status
|
||||
s.tx(Object.assign(e,{f:'monitor_status'}),'GRP_'+e.ke)
|
||||
break;
|
||||
}
|
||||
if(typeof e.callback==='function'){setTimeout(function(){e.callback()},500);}
|
||||
}
|
||||
|
|
@ -884,30 +901,32 @@ s.video=function(x,e,k){
|
|||
})
|
||||
});
|
||||
break;
|
||||
case'archive':
|
||||
if(!e.filename&&e.time){e.filename=s.formattedTime(e.time)}
|
||||
if(!e.status){e.status=0}
|
||||
e.details.archived="1"
|
||||
e.save=[JSON.stringify(e.details),e.id,e.ke,s.nameToTime(e.filename)];
|
||||
s.sqlQuery('UPDATE Videos SET details=? WHERE `mid`=? AND `ke`=? AND `time`=?',e.save,function(err,r){
|
||||
s.tx({f:'video_edit',status:3,filename:e.filename+'.'+e.ext,mid:e.mid,ke:e.ke,time:s.nameToTime(e.filename)},'GRP_'+e.ke);
|
||||
});
|
||||
break;
|
||||
case'delete':
|
||||
if(!e.filename&&e.time){e.filename=s.formattedTime(e.time)}
|
||||
var filename
|
||||
if(!e.filename && e.time){
|
||||
e.filename = s.formattedTime(e.time)
|
||||
}
|
||||
var filename,
|
||||
time
|
||||
if(e.filename.indexOf('.')>-1){
|
||||
filename = e.filename
|
||||
}else{
|
||||
filename = e.filename+'.'+e.ext
|
||||
}
|
||||
if(!e.status){e.status=0}
|
||||
e.save=[e.id,e.ke,s.nameToTime(filename)];
|
||||
s.sqlQuery('SELECT * FROM Videos WHERE `mid`=? AND `ke`=? AND `time`=?',e.save,function(err,r){
|
||||
if(e.filename && !e.time){
|
||||
time = s.nameToTime(filename)
|
||||
}else{
|
||||
time = e.time
|
||||
}
|
||||
time = new Date(time)
|
||||
if(config.databaseType !== 'sqlite'){
|
||||
time = moment(time).format('YYYY-MM-DD HH:mm:ss')
|
||||
}
|
||||
e.save=[e.id,e.ke,time];
|
||||
s.sqlQuery('SELECT * FROM Videos WHERE `mid`=? AND `ke`=? AND `time`=? LIMIT 1',e.save,function(err,r){
|
||||
if(r&&r[0]){
|
||||
r=r[0]
|
||||
var dir=s.video('getDir',r)
|
||||
s.sqlQuery('DELETE FROM Videos WHERE `mid`=? AND `ke`=? AND `time`=?',e.save,function(){
|
||||
s.sqlQuery('DELETE FROM Videos WHERE `mid`=? AND `ke`=? AND `time`=? LIMIT 1',e.save,function(){
|
||||
fs.stat(dir+filename,function(err,file){
|
||||
if(err){
|
||||
s.systemLog('File Delete Error : '+e.ke+' : '+' : '+e.mid,err)
|
||||
|
|
@ -917,6 +936,9 @@ s.video=function(x,e,k){
|
|||
s.tx({f:'video_delete',filename:filename,mid:e.mid,ke:e.ke,time:s.nameToTime(filename),end:s.formattedTime(new Date,'YYYY-MM-DD HH:mm:ss')},'GRP_'+e.ke);
|
||||
s.file('delete',dir+filename)
|
||||
})
|
||||
}else{
|
||||
// console.log('Delete Failed',e)
|
||||
// console.error(err)
|
||||
}
|
||||
})
|
||||
break;
|
||||
|
|
@ -1028,7 +1050,8 @@ s.video=function(x,e,k){
|
|||
}else{
|
||||
queryString = ''
|
||||
}
|
||||
v.href = '/'+k+'/videos/'+v.ke+'/'+v.mid+'/'+s.formattedTime(v.time)+'.'+v.ext;
|
||||
v.filename = s.formattedTime(v.time)+'.'+v.ext;
|
||||
v.href = '/'+k+'/videos/'+v.ke+'/'+v.mid+'/'+v.filename;
|
||||
v.links = {
|
||||
deleteVideo : v.href+'/delete' + queryString,
|
||||
changeToUnread : v.href+'/status/1' + queryString,
|
||||
|
|
@ -1067,6 +1090,7 @@ s.video=function(x,e,k){
|
|||
if(s.group[e.ke].usedSpace>(s.group[e.ke].sizeLimit*config.cron.deleteOverMaxOffset)){
|
||||
s.sqlQuery('SELECT * FROM Videos WHERE status != 0 AND details NOT LIKE \'%"archived":"1"%\' AND ke=? ORDER BY `time` ASC LIMIT 2',[e.ke],function(err,evs){
|
||||
k.del=[];k.ar=[e.ke];
|
||||
if(!evs)return console.log(err)
|
||||
evs.forEach(function(ev){
|
||||
ev.dir=s.video('getDir',ev)+s.formattedTime(ev.time)+'.'+ev.ext;
|
||||
k.del.push('(mid=? AND time=?)');
|
||||
|
|
@ -1130,8 +1154,8 @@ s.video=function(x,e,k){
|
|||
});
|
||||
k.filename = s.formattedTime(e.startTime)+'.'+e.ext
|
||||
}else{
|
||||
e.startTime = s.utcToLocal(e.startTime)
|
||||
e.endTime = s.utcToLocal(e.endTime)
|
||||
// e.startTime = s.utcToLocal(e.startTime)
|
||||
// e.endTime = s.utcToLocal(e.endTime)
|
||||
k.filename = k.file
|
||||
}
|
||||
if(!e.ext){e.ext = k.filename.split('.')[1]}
|
||||
|
|
@ -1174,9 +1198,9 @@ s.video=function(x,e,k){
|
|||
filename:k.filename,
|
||||
mid:e.mid,
|
||||
ke:e.ke,
|
||||
time:s.timeObject(e.startTime).format(),
|
||||
time:e.startTime,
|
||||
size:e.filesize,
|
||||
end:s.timeObject(e.endTime).format()
|
||||
end:e.endTime
|
||||
},'GRP_'+e.ke,'video_view');
|
||||
}
|
||||
//cloud auto savers
|
||||
|
|
@ -1213,7 +1237,11 @@ s.video=function(x,e,k){
|
|||
if(e.details&&e.details.dir&&e.details.dir!==''){
|
||||
k.details.dir = e.details.dir
|
||||
}
|
||||
if(config.useUTC)k.details.isUTC = config.useUTC;
|
||||
if(config.useUTC === true)k.details.isUTC = config.useUTC;
|
||||
if(config.strictDatabase === true){
|
||||
e.startTime = s.formattedTime(e.startTime)
|
||||
e.endTime = s.formattedTime(e.endTime)
|
||||
}
|
||||
var save = [
|
||||
e.mid,
|
||||
e.ke,
|
||||
|
|
@ -1515,11 +1543,11 @@ s.ffmpeg=function(e){
|
|||
//input - stream loop (good for static files/lists)
|
||||
if(e.details.stream_loop==='1'){x.cust_input+=' -stream_loop -1'};
|
||||
//input
|
||||
if(e.details.cust_input.indexOf('-fflags') === -1){x.cust_input+=' -fflags +igndts'}
|
||||
switch(e.type){
|
||||
case'h264':
|
||||
switch(e.protocol){
|
||||
case'rtsp':
|
||||
if(e.details.cust_input.indexOf('-fflags') === -1){x.cust_input+=' -fflags +igndts'}
|
||||
if(e.details.rtsp_transport&&e.details.rtsp_transport!==''&&e.details.rtsp_transport!=='no'){x.cust_input+=' -rtsp_transport '+e.details.rtsp_transport;}
|
||||
break;
|
||||
}
|
||||
|
|
@ -1908,19 +1936,19 @@ s.ffmpeg=function(e){
|
|||
}
|
||||
switch(e.type){
|
||||
case'dashcam':
|
||||
x.ffmpegCommandString += ' -i -';
|
||||
x.ffmpegCommandString += x.cust_input+x.hwaccel+' -i -';
|
||||
break;
|
||||
case'socket':case'jpeg':case'pipe':
|
||||
x.ffmpegCommandString += ' -pattern_type glob -f image2pipe'+x.record_fps+' -vcodec mjpeg'+x.cust_input+' -i -';
|
||||
x.ffmpegCommandString += ' -pattern_type glob -f image2pipe'+x.record_fps+' -vcodec mjpeg'+x.cust_input+x.hwaccel+' -i -';
|
||||
break;
|
||||
case'mjpeg':
|
||||
x.ffmpegCommandString += ' -reconnect 1 -f mjpeg'+x.cust_input+' -i "'+e.url+'"';
|
||||
x.ffmpegCommandString += ' -reconnect 1 -f mjpeg'+x.cust_input+x.hwaccel+' -i "'+e.url+'"';
|
||||
break;
|
||||
case'h264':case'hls':case'mp4':
|
||||
x.ffmpegCommandString += x.cust_input+x.hwaccel+' -i "'+e.url+'"';
|
||||
break;
|
||||
case'local':
|
||||
x.ffmpegCommandString += x.cust_input+' -i "'+e.path+'"';
|
||||
x.ffmpegCommandString += x.cust_input+x.hwaccel+' -i "'+e.path+'"';
|
||||
break;
|
||||
}
|
||||
//add extra input maps
|
||||
|
|
@ -2281,6 +2309,7 @@ s.camera=function(x,e,cn,tx){
|
|||
s.tx({viewers:e.ob,ke:e.ke,id:e.id},'MON_'+e.id);
|
||||
break;
|
||||
case'restart'://restart monitor
|
||||
s.init('monitorStatus',{id:e.id,ke:e.ke,status:'Restarting'});
|
||||
s.camera('stop',e)
|
||||
setTimeout(function(){
|
||||
s.camera(e.mode,e)
|
||||
|
|
@ -2335,6 +2364,11 @@ s.camera=function(x,e,cn,tx){
|
|||
s.log(e,{type:lang['Monitor Idling'],msg:lang.MonitorIdlingText});
|
||||
}
|
||||
}
|
||||
var wantedStatus = lang.Stopped
|
||||
if(x==='idle'){
|
||||
var wantedStatus = lang.Idle
|
||||
}
|
||||
s.init('monitorStatus',{id:e.id,ke:e.ke,status:wantedStatus});
|
||||
break;
|
||||
case'start':case'record'://watch or record monitor url
|
||||
s.init(0,{ke:e.ke,mid:e.id})
|
||||
|
|
@ -2345,6 +2379,7 @@ s.camera=function(x,e,cn,tx){
|
|||
return
|
||||
}
|
||||
//lock this function
|
||||
s.init('monitorStatus',{id:e.id,ke:e.ke,status:lang.Starting});
|
||||
s.group[e.ke].mon[e.id].started = 1;
|
||||
//create host string without username and password
|
||||
e.hosty = e.host.split('@');
|
||||
|
|
@ -2356,7 +2391,9 @@ s.camera=function(x,e,cn,tx){
|
|||
e.hosty = e.hosty[0]
|
||||
}
|
||||
//set recording status
|
||||
var wantedStatus = lang.Watching
|
||||
if(x==='record'){
|
||||
var wantedStatus = lang.Recording
|
||||
s.group[e.ke].mon[e.id].record.yes=1;
|
||||
}else{
|
||||
s.group[e.ke].mon[e.mid].record.yes=0;
|
||||
|
|
@ -2421,19 +2458,26 @@ s.camera=function(x,e,cn,tx){
|
|||
}else{
|
||||
s.kill(s.group[e.ke].mon[e.id].spawn,e);
|
||||
}
|
||||
s.init('monitorStatus',{id:e.id,ke:e.ke,status:lang.Died});
|
||||
}
|
||||
errorFatalCount = 0;
|
||||
var errorFatalCount = 0;
|
||||
//cutoff time and recording check interval
|
||||
if(!e.details.cutoff||e.details.cutoff===''){e.cutoff=15}else{e.cutoff=parseFloat(e.details.cutoff)};
|
||||
if(isNaN(e.cutoff)===true){e.cutoff=15}
|
||||
//set master based process launcher
|
||||
launchMonitorProcesses = function(){
|
||||
var launchMonitorProcesses = function(){
|
||||
s.group[e.ke].mon[e.id].allowStdinWrite = false
|
||||
s.txToDashcamUsers({
|
||||
f : 'disable_stream',
|
||||
ke : e.ke,
|
||||
mid : e.id
|
||||
},e.ke)
|
||||
if(e.details.detector_trigger=='1'){
|
||||
s.group[e.ke].mon[e.id].motion_lock=setTimeout(function(){
|
||||
clearTimeout(s.group[e.ke].mon[e.id].motion_lock);
|
||||
delete(s.group[e.ke].mon[e.id].motion_lock);
|
||||
},30000)
|
||||
}
|
||||
//cutoff time and recording check interval
|
||||
if(!e.details.cutoff||e.details.cutoff===''){e.cutoff=15}else{e.cutoff=parseFloat(e.details.cutoff)};
|
||||
if(isNaN(e.cutoff)===true){e.cutoff=15}
|
||||
//start "no motion" checker
|
||||
if(e.details.detector=='1'&&e.details.detector_notrigger=='1'){
|
||||
if(!e.details.detector_notrigger_timeout||e.details.detector_notrigger_timeout===''){
|
||||
|
|
@ -2466,9 +2510,24 @@ s.camera=function(x,e,cn,tx){
|
|||
s.group[e.ke].mon[e.id].detector_notrigger_timeout=setInterval(s.group[e.ke].mon[e.id].detector_notrigger_timeout_function,s.group[e.ke].mon[e.id].detector_notrigger_timeout)
|
||||
})
|
||||
}
|
||||
var resetRecordingCheck = function(){
|
||||
clearTimeout(s.group[e.ke].mon[e.id].checker)
|
||||
clearTimeout(s.group[e.ke].mon[e.id].checkStream)
|
||||
var cutoff = e.cutoff + 0
|
||||
if(e.type === 'dashcam'){
|
||||
cutoff *= 100
|
||||
}
|
||||
s.group[e.ke].mon[e.id].checker=setTimeout(function(){
|
||||
if(s.group[e.ke].mon[e.id].started === 1){
|
||||
launchMonitorProcesses();
|
||||
s.init('monitorStatus',{id:e.id,ke:e.ke,status:lang.Restarting});
|
||||
s.log(e,{type:lang['Camera is not recording'],msg:{msg:lang['Restarting Process']}});
|
||||
}
|
||||
},60000 * cutoff * 1.1);
|
||||
}
|
||||
var resetStreamCheck=function(){
|
||||
clearTimeout(s.group[e.ke].mon[e.id].checkStream)
|
||||
s.group[e.ke].mon[e.id].checkStream=setTimeout(function(){
|
||||
s.group[e.ke].mon[e.id].checkStream = setTimeout(function(){
|
||||
if(s.group[e.ke].mon[e.id].started===1){
|
||||
launchMonitorProcesses();
|
||||
s.log(e,{type:lang['Camera is not streaming'],msg:{msg:lang['Restarting Process']}});
|
||||
|
|
@ -2483,14 +2542,7 @@ s.camera=function(x,e,cn,tx){
|
|||
s.group[e.ke].mon[e.id].open = filename.split('.')[0]
|
||||
break;
|
||||
case'change':
|
||||
clearTimeout(s.group[e.ke].mon[e.id].checker)
|
||||
clearTimeout(s.group[e.ke].mon[e.id].checkStream)
|
||||
s.group[e.ke].mon[e.id].checker=setTimeout(function(){
|
||||
if(s.group[e.ke].mon[e.id].started===1){
|
||||
launchMonitorProcesses();
|
||||
s.log(e,{type:lang['Camera is not recording'],msg:{msg:lang['Restarting Process']}});
|
||||
}
|
||||
},60000 * e.cutoff * 1.1);
|
||||
resetRecordingCheck()
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
|
@ -2521,6 +2573,17 @@ s.camera=function(x,e,cn,tx){
|
|||
if(!s.group[e.ke].mon[e.id].record){s.group[e.ke].mon[e.id].record={yes:1}};
|
||||
//launch ffmpeg (main)
|
||||
s.group[e.ke].mon[e.id].spawn = s.ffmpeg(e);
|
||||
if(e.type === 'dashcam'){
|
||||
setTimeout(function(){
|
||||
s.group[e.ke].mon[e.id].allowStdinWrite = true
|
||||
s.txToDashcamUsers({
|
||||
f : 'enable_stream',
|
||||
ke : e.ke,
|
||||
mid : e.id
|
||||
},e.ke)
|
||||
},30000)
|
||||
}
|
||||
s.init('monitorStatus',{id:e.id,ke:e.ke,status:wantedStatus});
|
||||
//on unexpected exit restart
|
||||
s.group[e.ke].mon[e.id].spawn_exit=function(){
|
||||
if(s.group[e.ke].mon[e.id].started===1){
|
||||
|
|
@ -2836,6 +2899,12 @@ s.camera=function(x,e,cn,tx){
|
|||
d=d.toString();
|
||||
e.chk=function(x){return d.indexOf(x)>-1;}
|
||||
switch(true){
|
||||
case e.chk('Non-monotonous DTS'):
|
||||
case e.chk('NULL @'):
|
||||
case e.chk('RTP: missed'):
|
||||
case e.chk('deprecated pixel format used, make sure you did set range correctly'):
|
||||
return
|
||||
break;
|
||||
//mp4 output with webm encoder chosen
|
||||
case e.chk('Could not find tag for vp8'):
|
||||
case e.chk('Only VP8 or VP9 Video'):
|
||||
|
|
@ -2857,11 +2926,6 @@ s.camera=function(x,e,cn,tx){
|
|||
// s.camera('restart',e)
|
||||
return s.log(e,{type:lang['Incorrect Settings Chosen'],msg:{msg:d}})
|
||||
break;
|
||||
case e.chk('NULL @'):
|
||||
case e.chk('RTP: missed'):
|
||||
case e.chk('deprecated pixel format used, make sure you did set range correctly'):
|
||||
return
|
||||
break;
|
||||
// case e.chk('av_interleaved_write_frame'):
|
||||
case e.chk('Connection refused'):
|
||||
case e.chk('Connection timed out'):
|
||||
|
|
@ -2875,14 +2939,14 @@ s.camera=function(x,e,cn,tx){
|
|||
// case e.chk('Unable to open RTSP for listening'):
|
||||
// case e.chk('timed out'):
|
||||
// case e.chk('Invalid data found when processing input'):
|
||||
// case e.chk('Immediate exit requested'):
|
||||
// case e.chk('reset by peer'):
|
||||
// if(e.frames===0&&x==='record'){s.video('delete',e)};
|
||||
// setTimeout(function(){
|
||||
// if(!s.group[e.ke].mon[e.id].spawn){launchMonitorProcesses()}
|
||||
// },2000)
|
||||
// break;
|
||||
case e.chk('mjpeg_decode_dc'):
|
||||
case e.chk('Immediate exit requested'):
|
||||
case e.chk('mjpeg_decode_dc'):
|
||||
case e.chk('bad vlc'):
|
||||
case e.chk('error dc'):
|
||||
launchMonitorProcesses()
|
||||
|
|
@ -2911,6 +2975,7 @@ s.camera=function(x,e,cn,tx){
|
|||
})
|
||||
}
|
||||
s.group[e.ke].mon[e.id].detector_motion_count = 0
|
||||
resetRecordingCheck()
|
||||
return;
|
||||
break;
|
||||
}
|
||||
|
|
@ -4193,8 +4258,11 @@ var tx;
|
|||
switch(d.ff){
|
||||
case'update':
|
||||
s.ffmpegKill()
|
||||
s.systemLog('Shinobi ordered to update',{by:cn.mail,ip:cn.ip,distro:d.distro})
|
||||
var updateProcess = spawn('sh',(__dirname+'/UPDATE.sh '+d.distro).split(' '),{detached: true})
|
||||
s.systemLog('Shinobi ordered to update',{
|
||||
by:cn.mail,
|
||||
ip:cn.ip
|
||||
})
|
||||
var updateProcess = spawn('sh',(__dirname+'/UPDATE.sh').split(' '),{detached: true})
|
||||
updateProcess.stderr.on('data',function(data){
|
||||
s.systemLog('Update Info',data.toString())
|
||||
})
|
||||
|
|
@ -4360,21 +4428,59 @@ var tx;
|
|||
cn.ke=d.ke,cn.uid=d.uid,cn.auth=d.auth;
|
||||
if(!s.group[d.ke])s.group[d.ke]={};
|
||||
if(!s.group[d.ke].users)s.group[d.ke].users={};
|
||||
s.group[d.ke].users[d.auth]={cnid:cn.id,uid:r.uid,mail:r.mail,details:JSON.parse(r.details),logged_in_at:s.timeObject(new Date).format(),login_type:'Streamer'}
|
||||
if(!s.group[d.ke].dashcamUsers)s.group[d.ke].dashcamUsers={};
|
||||
s.group[d.ke].users[d.auth]={
|
||||
cnid:cn.id,
|
||||
ke : d.ke,
|
||||
uid:r.uid,
|
||||
mail:r.mail,
|
||||
details:JSON.parse(r.details),
|
||||
logged_in_at:s.timeObject(new Date).format(),
|
||||
login_type:'Streamer'
|
||||
}
|
||||
s.group[d.ke].dashcamUsers[d.auth] = s.group[d.ke].users[d.auth]
|
||||
if(s.group[d.ke].mon){
|
||||
Object.keys(s.group[d.ke].mon).forEach(function(monitorId){
|
||||
var dataToClient = {
|
||||
f : 'disable_stream',
|
||||
mid : monitorId,
|
||||
ke : d.ke
|
||||
}
|
||||
var mon = s.group[d.ke].mon[monitorId]
|
||||
if(s.group[d.ke].mon_conf[monitorId].type === 'dashcam'){
|
||||
if(mon.allowStdinWrite === true){
|
||||
dataToClient.f = 'enable_stream'
|
||||
}
|
||||
s.tx(dataToClient,cn.id)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
}else{
|
||||
switch(d.f){
|
||||
case'monitor_chunk':
|
||||
if(!s.group[d.ke]||!s.group[d.ke].mon[d.mid]){return}
|
||||
if(s.group[d.ke].mon[d.mid].started!==1){s.tx({error:'Not Started'},cn.id);return false};
|
||||
s.group[d.ke].mon[d.mid].spawn.stdin.write(new Buffer(d.chunk, "binary"));
|
||||
break;
|
||||
case'monitor_frame':
|
||||
if(!s.group[d.ke]||!s.group[d.ke].mon[d.mid]){return}
|
||||
if(s.group[d.ke].mon[d.mid].started!==1){s.tx({error:'Not Started'},cn.id);return false};
|
||||
s.group[d.ke].mon[d.mid].spawn.stdin.write(d.frame);
|
||||
break;
|
||||
if(s.group[d.ke] && s.group[d.ke].mon[d.mid]){
|
||||
if(s.group[d.ke].mon[d.mid].allowStdinWrite === true){
|
||||
switch(d.f){
|
||||
case'monitor_chunk':
|
||||
if(s.group[d.ke].mon[d.mid].started!==1 || !s.group[d.ke].mon[d.mid].spawn || !s.group[d.ke].mon[d.mid].spawn.stdin){
|
||||
s.tx({error:'Not Started'},cn.id);
|
||||
return false
|
||||
};
|
||||
s.group[d.ke].mon[d.mid].spawn.stdin.write(new Buffer(d.chunk, "binary"));
|
||||
break;
|
||||
case'monitor_frame':
|
||||
if(s.group[d.ke].mon[d.mid].started!==1){
|
||||
s.tx({error:'Not Started'},cn.id);
|
||||
return false
|
||||
};
|
||||
s.group[d.ke].mon[d.mid].spawn.stdin.write(d.frame);
|
||||
break;
|
||||
}
|
||||
}else{
|
||||
s.tx({error:'Cannot Write Yet'},cn.id)
|
||||
}
|
||||
}else{
|
||||
s.tx({error:'Non Existant Monitor'},cn.id)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
@ -4407,6 +4513,43 @@ var tx;
|
|||
break;
|
||||
}
|
||||
})
|
||||
//functions for retrieving cron announcements
|
||||
cn.on('cron',function(d){
|
||||
if(d.f==='init'){
|
||||
if(config.cron.key){
|
||||
if(config.cron.key===d.cronKey){
|
||||
s.cron={started:moment(),last_run:moment(),id:cn.id};
|
||||
}else{
|
||||
cn.disconnect()
|
||||
}
|
||||
}else{
|
||||
s.cron={started:moment(),last_run:moment(),id:cn.id};
|
||||
}
|
||||
}else{
|
||||
if(s.cron&&cn.id===s.cron.id){
|
||||
delete(d.cronKey)
|
||||
switch(d.f){
|
||||
case'filters':
|
||||
s.filterEvents(d.ff,d);
|
||||
break;
|
||||
case's.tx':
|
||||
s.tx(d.data,d.to)
|
||||
break;
|
||||
case's.video':
|
||||
s.video(d.data,d.file)
|
||||
break;
|
||||
case'start':case'end':
|
||||
d.mid='_cron';s.log(d,{type:'cron',msg:d.msg})
|
||||
break;
|
||||
default:
|
||||
s.systemLog('CRON : ',d)
|
||||
break;
|
||||
}
|
||||
}else{
|
||||
cn.disconnect()
|
||||
}
|
||||
}
|
||||
})
|
||||
cn.on('disconnect', function () {
|
||||
if(cn.socketVideoStream){
|
||||
cn.closeSocketVideoStream()
|
||||
|
|
@ -4426,6 +4569,7 @@ var tx;
|
|||
}
|
||||
s.log({ke:cn.ke,mid:'$USER'},{type:lang['Websocket Disconnected'],msg:{mail:s.group[cn.ke].users[cn.auth].mail,id:cn.uid,ip:cn.ip}})
|
||||
delete(s.group[cn.ke].users[cn.auth]);
|
||||
delete(s.group[cn.ke].dashcamUsers[cn.auth]);
|
||||
}
|
||||
}
|
||||
if(cn.pluginEngine){
|
||||
|
|
@ -4433,6 +4577,9 @@ var tx;
|
|||
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);
|
||||
|
|
@ -5049,7 +5196,7 @@ app.get('/:auth/jpeg/:ke/:id/s.jpg', function(req,res){
|
|||
'Cache-Control': 'no-cache',
|
||||
'Pragma': 'no-cache'
|
||||
});
|
||||
res.on('finish',function(){res.end();delete(res)});
|
||||
res.on('finish',function(){res.end();});
|
||||
if (fs.existsSync(req.dir)){
|
||||
fs.createReadStream(req.dir).pipe(res);
|
||||
}else{
|
||||
|
|
@ -5432,6 +5579,9 @@ app.get(['/:auth/monitor/:ke','/:auth/monitor/:ke/:id'], function (req,res){
|
|||
if(s.group[v.ke]&&s.group[v.ke].mon[v.mid]&&s.group[v.ke].mon[v.mid].watch){
|
||||
r[n].currentlyWatching=Object.keys(s.group[v.ke].mon[v.mid].watch).length
|
||||
}
|
||||
if(s.group[v.ke]&&s.group[v.ke].mon[v.mid]&&s.group[v.ke].mon[v.mid].watch){
|
||||
r[n].status = s.group[v.ke].mon[v.mid].monitorStatus
|
||||
}
|
||||
var buildStreamURL = function(type,channelNumber){
|
||||
var streamURL
|
||||
if(channelNumber){channelNumber = '/'+channelNumber}else{channelNumber=''}
|
||||
|
|
@ -5660,6 +5810,25 @@ app.get(['/:auth/logs/:ke','/:auth/logs/:ke/:id'], function (req,res){
|
|||
return;
|
||||
}
|
||||
}
|
||||
if(req.query.start||req.query.end){
|
||||
if(!req.query.startOperator||req.query.startOperator==''){
|
||||
req.query.startOperator='>='
|
||||
}
|
||||
if(!req.query.endOperator||req.query.endOperator==''){
|
||||
req.query.endOperator='<='
|
||||
}
|
||||
if(req.query.start && req.query.start !== '' && req.query.end && req.query.end !== ''){
|
||||
req.query.start=req.query.start.replace('T',' ')
|
||||
req.query.end=req.query.end.replace('T',' ')
|
||||
req.sql+=' AND `time` '+req.query.startOperator+' ? AND `time` '+req.query.endOperator+' ?';
|
||||
req.ar.push(req.query.start)
|
||||
req.ar.push(req.query.end)
|
||||
}else if(req.query.start && req.query.start !== ''){
|
||||
req.query.start=req.query.start.replace('T',' ')
|
||||
req.sql+=' AND `time` '+req.query.startOperator+' ?';
|
||||
req.ar.push(req.query.start)
|
||||
}
|
||||
}
|
||||
if(!req.query.limit||req.query.limit==''){req.query.limit=50}
|
||||
req.sql+=' ORDER BY `time` DESC LIMIT '+req.query.limit+'';
|
||||
s.sqlQuery(req.sql,req.ar,function(err,r){
|
||||
|
|
@ -5986,11 +6155,12 @@ app.get('/:auth/videos/:ke/:id/:file', function (req,res){
|
|||
res.end(user.lang['Not Permitted'])
|
||||
return
|
||||
}
|
||||
var filename = s.nameToTime(req.params.file)
|
||||
var time = s.nameToTime(req.params.file)
|
||||
if(req.query.isUTC === 'true'){
|
||||
filename = s.utcToLocal(filename)
|
||||
time = s.utcToLocal(time)
|
||||
}
|
||||
s.sqlQuery('SELECT * FROM Videos WHERE ke=? AND mid=? AND time=?',[req.params.ke,req.params.id,filename],function(err,r){
|
||||
time = new Date(time)
|
||||
s.sqlQuery('SELECT * FROM Videos WHERE ke=? AND mid=? AND time=?',[req.params.ke,req.params.id,time],function(err,r){
|
||||
if(r&&r[0]){
|
||||
req.dir=s.video('getDir',r[0])+req.params.file
|
||||
if (fs.existsSync(req.dir)){
|
||||
|
|
@ -6081,12 +6251,13 @@ app.get(['/:auth/videos/:ke/:id/:file/:mode','/:auth/videos/:ke/:id/:file/:mode/
|
|||
res.end(user.lang['Not Permitted'])
|
||||
return
|
||||
}
|
||||
var filename = s.nameToTime(req.params.file)
|
||||
var time = s.nameToTime(req.params.file)
|
||||
if(req.query.isUTC === 'true'){
|
||||
filename = s.utcToLocal(filename)
|
||||
time = s.utcToLocal(time)
|
||||
}
|
||||
time = new Date(time)
|
||||
req.sql='SELECT * FROM Videos WHERE ke=? AND mid=? AND time=?';
|
||||
req.ar=[req.params.ke,req.params.id,filename];
|
||||
req.ar=[req.params.ke,req.params.id,time];
|
||||
s.sqlQuery(req.sql,req.ar,function(err,r){
|
||||
if(r&&r[0]){
|
||||
r=r[0];r.filename=s.formattedTime(r.time)+'.'+r.ext;
|
||||
|
|
@ -6096,13 +6267,14 @@ app.get(['/:auth/videos/:ke/:id/:file/:mode','/:auth/videos/:ke/:id/:file/:mode/
|
|||
s.video('fix',r)
|
||||
break;
|
||||
case'status':
|
||||
req.params.f=parseInt(req.params.f)
|
||||
r.f = 'video_edit'
|
||||
r.status = parseInt(req.params.f)
|
||||
if(isNaN(req.params.f)||req.params.f===0){
|
||||
req.ret.msg='Not a valid value.';
|
||||
}else{
|
||||
req.ret.ok=true;
|
||||
s.sqlQuery('UPDATE Videos SET status=? WHERE ke=? AND mid=? AND time=?',[req.params.f,req.params.ke,req.params.id,filename])
|
||||
s.tx({f:'video_edit',status:req.params.f,filename:r.filename,mid:r.mid,ke:r.ke,time:s.nameToTime(r.filename),end:s.formattedTime(new Date,'YYYY-MM-DD HH:mm:ss')},'GRP_'+r.ke);
|
||||
s.sqlQuery('UPDATE Videos SET status=? WHERE ke=? AND mid=? AND time=?',[req.params.f,req.params.ke,req.params.id,time])
|
||||
s.tx(r,'GRP_'+r.ke);
|
||||
}
|
||||
break;
|
||||
case'delete':
|
||||
|
|
@ -6541,9 +6713,9 @@ if(config.childNodes.enabled === true && config.childNodes.mode === 'master'){
|
|||
filename:d.filename,
|
||||
mid:d.mid,
|
||||
ke:d.ke,
|
||||
time:s.timeObject(d.startTime).format(),
|
||||
time:d.startTime,
|
||||
size:d.filesize,
|
||||
end:s.timeObject(d.endTime).format()
|
||||
end:d.endTime
|
||||
},'GRP_'+d.ke,'video_view');
|
||||
clearTimeout(s.group[d.ke].mon[d.mid].checker)
|
||||
clearTimeout(s.group[d.ke].mon[d.mid].checkStream)
|
||||
|
|
|
|||
79
cron.js
79
cron.js
|
|
@ -64,6 +64,7 @@ s.sqlDate = function(value){
|
|||
return dateQueryFunction
|
||||
}
|
||||
s.sqlQuery = function(query,values,onMoveOn,hideLog){
|
||||
s.debugLog(query,values)
|
||||
if(!values){values=[]}
|
||||
var valuesNotFunction = true;
|
||||
if(typeof values === 'function'){
|
||||
|
|
@ -176,9 +177,9 @@ s.checkFilterRules=function(v,callback){
|
|||
}
|
||||
//delete old videos with filter
|
||||
if(config.cron.deleteOld===true){
|
||||
v.d.filters.deleteOldByCron={
|
||||
"id":"deleteOldByCron",
|
||||
"name":"deleteOldByCron",
|
||||
v.d.filters.deleteOldVideosByCron={
|
||||
"id":"deleteOldVideosByCron",
|
||||
"name":"deleteOldVideosByCron",
|
||||
"sort_by":"time",
|
||||
"sort_by_direction":"ASC",
|
||||
"limit":"",
|
||||
|
|
@ -195,10 +196,13 @@ s.checkFilterRules=function(v,callback){
|
|||
}]
|
||||
};
|
||||
}
|
||||
s.debugLog('Filters')
|
||||
var keys = Object.keys(v.d.filters)
|
||||
if(keys.length>0){
|
||||
keys.forEach(function(m,current){
|
||||
var b=v.d.filters[m];
|
||||
// b = filter
|
||||
var b = v.d.filters[m];
|
||||
s.debugLog(b)
|
||||
if(b.enabled==="1"){
|
||||
b.ar=[v.ke];
|
||||
b.sql=[];
|
||||
|
|
@ -223,6 +227,9 @@ s.checkFilterRules=function(v,callback){
|
|||
}
|
||||
s.sqlQuery('SELECT * FROM Videos '+b.sql,b.ar,function(err,r){
|
||||
if(r&&r[0]){
|
||||
if(r.length > 0 || config.debugLog === true){
|
||||
s.cx({f:'filterMatch',msg:r.length+' SQL rows match "'+m+'"',ke:v.ke,time:moment()})
|
||||
}
|
||||
b.cx={
|
||||
f:'filters',
|
||||
name:b.name,
|
||||
|
|
@ -233,10 +240,8 @@ s.checkFilterRules=function(v,callback){
|
|||
};
|
||||
if(b.archive==="1"){
|
||||
s.cx({f:'filters',ff:'archive',videos:r,time:moment(),ke:v.ke,id:b.id});
|
||||
}else{
|
||||
if(b.delete==="1"){
|
||||
s.cx({f:'filters',ff:'delete',videos:r,time:moment(),ke:v.ke,id:b.id});
|
||||
}
|
||||
}else if(b.delete==="1"){
|
||||
s.cx({f:'filters',ff:'delete',videos:r,time:moment(),ke:v.ke,id:b.id});
|
||||
}
|
||||
if(b.email==="1"){
|
||||
b.cx.ff='email';
|
||||
|
|
@ -277,21 +282,30 @@ s.deleteRowsWithNoVideo=function(v,callback){
|
|||
if(evs&&evs[0]){
|
||||
es.del=[];es.ar=[v.ke];
|
||||
evs.forEach(function(ev){
|
||||
var details = JSON.parse(ev.details)
|
||||
var filename = ev.time
|
||||
var dir = s.getVideoDirectory(ev)+s.moment(filename)+'.'+ev.ext;
|
||||
var fileExists = fs.existsSync(dir)
|
||||
if(details.isUTC === true){
|
||||
filename = s.localToUtc(filename).format('YYYY-MM-DDTHH-mm-ss')
|
||||
dir = s.getVideoDirectory(ev)+filename+'.'+ev.ext;
|
||||
fileExists = fs.existsSync(dir)
|
||||
var filename
|
||||
var details
|
||||
try{
|
||||
details = JSON.parse(ev.details)
|
||||
}catch(err){
|
||||
if(details instanceof Object){
|
||||
details = ev.details
|
||||
}else{
|
||||
details = {}
|
||||
}
|
||||
}
|
||||
var dir = s.getVideoDirectory(ev)
|
||||
if(details.isUTC === true){
|
||||
filename = s.localToUtc(ev.time).format('YYYY-MM-DDTHH-mm-ss')+'.'+ev.ext
|
||||
}else{
|
||||
filename = s.moment(ev.time)+'.'+ev.ext
|
||||
}
|
||||
fileExists = fs.existsSync(dir+filename)
|
||||
if(fileExists !== true){
|
||||
s.video('delete',ev)
|
||||
s.tx({f:'video_delete',filename:filename+'.'+ev.ext,mid:ev.mid,ke:ev.ke,time:ev.time,end:s.moment(new Date,'YYYY-MM-DD HH:mm:ss')},'GRP_'+ev.ke);
|
||||
}
|
||||
});
|
||||
if(es.del.length>0){
|
||||
if(es.del.length>0 || config.debugLog === true){
|
||||
s.cx({f:'deleteNoVideo',msg:es.del.length+' SQL rows with no file deleted',ke:v.ke,time:moment()})
|
||||
}
|
||||
}
|
||||
|
|
@ -310,8 +324,8 @@ s.deleteOldLogs=function(v,callback){
|
|||
s.sqlQuery("DELETE FROM Logs WHERE ke=? AND `time` < "+s.sqlDate('? DAYS'),[v.ke,v.d.log_days],function(err,rrr){
|
||||
callback()
|
||||
if(err)return console.error(err);
|
||||
if(rrr.affectedRows && rrr.affectedRows.length>0){
|
||||
s.cx({f:'deleteLogs',msg:rrr.affectedRows+' SQL rows older than '+v.d.log_days+' days deleted',ke:v.ke,time:moment()})
|
||||
if(rrr.affectedRows && rrr.affectedRows.length>0 || config.debugLog === true){
|
||||
s.cx({f:'deleteLogs',msg:(rrr.affectedRows || 0)+' SQL rows older than '+v.d.log_days+' days deleted',ke:v.ke,time:moment()})
|
||||
}
|
||||
})
|
||||
}else{
|
||||
|
|
@ -325,8 +339,8 @@ s.deleteOldEvents=function(v,callback){
|
|||
s.sqlQuery("DELETE FROM Events WHERE ke=? AND `time` < "+s.sqlDate('? DAYS'),[v.ke,v.d.event_days],function(err,rrr){
|
||||
callback()
|
||||
if(err)return console.error(err);
|
||||
if(rrr.affectedRows && rrr.affectedRows.length>0){
|
||||
s.cx({f:'deleteEvents',msg:rrr.affectedRows+' SQL rows older than '+v.d.event_days+' days deleted',ke:v.ke,time:moment()})
|
||||
if(rrr.affectedRows && rrr.affectedRows.length>0 || config.debugLog === true){
|
||||
s.cx({f:'deleteEvents',msg:(rrr.affectedRows || 0)+' SQL rows older than '+v.d.event_days+' days deleted',ke:v.ke,time:moment()})
|
||||
}
|
||||
})
|
||||
}else{
|
||||
|
|
@ -350,8 +364,8 @@ s.deleteOldFileBins=function(v,callback){
|
|||
s.sqlQuery("DELETE"+fileBinQuery,[v.ke,v.d.fileBin_days],function(err,rrr){
|
||||
callback()
|
||||
if(err)return console.error(err);
|
||||
if(rrr.affectedRows && rrr.affectedRows.length>0){
|
||||
s.cx({f:'deleteFileBins',msg:rrr.affectedRows+' files older than '+v.d.fileBin_days+' days deleted',ke:v.ke,time:moment()})
|
||||
if(rrr.affectedRows && rrr.affectedRows.length>0 || config.debugLog === true){
|
||||
s.cx({f:'deleteFileBins',msg:(rrr.affectedRows || 0)+' files older than '+v.d.fileBin_days+' days deleted',ke:v.ke,time:moment()})
|
||||
}
|
||||
})
|
||||
}else{
|
||||
|
|
@ -366,7 +380,7 @@ s.deleteOldFileBins=function(v,callback){
|
|||
s.checkForOrphanedFiles=function(v,callback){
|
||||
if(config.cron.deleteOrphans===true){
|
||||
var finish=function(count){
|
||||
if(count>0){
|
||||
if(count>0 || config.debugLog === true){
|
||||
s.cx({f:'deleteOrphanedFiles',msg:count+' SQL rows with no database row deleted',ke:v.ke,time:moment()})
|
||||
}
|
||||
callback()
|
||||
|
|
@ -445,9 +459,9 @@ s.processUser = function(number,rows){
|
|||
rr.forEach(function(b,m){
|
||||
b.details=JSON.parse(b.details);
|
||||
if(b.details.max_keep_days&&b.details.max_keep_days!==''){
|
||||
v.d.filters['deleteOldByCron'+b.mid]={
|
||||
"id":'deleteOldByCron'+b.mid,
|
||||
"name":'deleteOldByCron'+b.mid,
|
||||
v.d.filters['deleteOldVideosByCron'+b.mid]={
|
||||
"id":'deleteOldVideosByCron'+b.mid,
|
||||
"name":'deleteOldVideosByCron'+b.mid,
|
||||
"sort_by":"time",
|
||||
"sort_by_direction":"ASC",
|
||||
"limit":"",
|
||||
|
|
@ -470,16 +484,17 @@ s.processUser = function(number,rows){
|
|||
}
|
||||
})
|
||||
s.deleteOldLogs(v,function(){
|
||||
s.debugLog('deleteOldLogs')
|
||||
s.debugLog('--- deleteOldLogs Complete')
|
||||
s.deleteOldFileBins(v,function(){
|
||||
s.debugLog('deleteOldFileBins')
|
||||
s.debugLog('--- deleteOldFileBins Complete')
|
||||
s.deleteOldEvents(v,function(){
|
||||
s.debugLog('deleteOldEvents')
|
||||
s.debugLog('--- deleteOldEvents Complete')
|
||||
s.checkFilterRules(v,function(){
|
||||
s.debugLog('checkFilterRules')
|
||||
s.debugLog('--- checkFilterRules Complete')
|
||||
s.deleteRowsWithNoVideo(v,function(){
|
||||
s.debugLog('deleteRowsWithNoVideo')
|
||||
s.debugLog('--- deleteRowsWithNoVideo Complete')
|
||||
s.checkForOrphanedFiles(v,function(){
|
||||
s.debugLog('--- checkForOrphanedFiles Complete')
|
||||
//done user, unlock current, and do next
|
||||
s.overlapLock[v.ke]=false;
|
||||
s.processUser(number+1,rows)
|
||||
|
|
|
|||
|
|
@ -185,6 +185,7 @@
|
|||
"Force Monitors Per Row": "Force Monitors Per Row",
|
||||
"Monitors per row": "Monitors per row <small>for Montage</small>",
|
||||
"Browser Console Log": "Browser Console Log",
|
||||
"Log Stream": "Log Stream",
|
||||
"All Monitors and Privileges": "All Monitors and Privileges",
|
||||
"Permissions": "Permissions",
|
||||
"Time-lapse Tool": "Time-lapse Tool",
|
||||
|
|
@ -493,6 +494,12 @@
|
|||
"Camera is not recording": "Camera is not recording",
|
||||
"Camera is not streaming": "Camera is not streaming",
|
||||
"Restarting Process": "Restarting Process",
|
||||
"Restarting": "Restarting",
|
||||
"Starting": "Starting",
|
||||
"Watching": "Watching",
|
||||
"Recording": "Recording",
|
||||
"Stopped": "Stopped",
|
||||
"Died": "Died",
|
||||
"Restart": "Restart",
|
||||
"Monitor Stopped": "Monitor Stopped",
|
||||
"MonitorStoppedText": "Monitor session has been ordered to stop.",
|
||||
|
|
|
|||
|
|
@ -0,0 +1,2 @@
|
|||
conf.json
|
||||
data
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
#!/bin/bash
|
||||
mkdir data
|
||||
chmod -R 777 data
|
||||
wget https://cdn.shinobi.video/weights/dnnCocoData.zip -O dnnCocoData.zip
|
||||
unzip dnnCocoData.zip -d data
|
||||
if [ $(dpkg-query -W -f='${Status}' opencv_version 2>/dev/null | grep -c "ok installed") -eq 0 ]; then
|
||||
echo "Shinobi - Do ypu want to let the `opencv4nodejs` npm package install OpenCV? "
|
||||
echo "Only do this if you do not have OpenCV already or will not use a GPU (Hardware Acceleration)."
|
||||
echo "(y)es or (N)o"
|
||||
read nodejsinstall
|
||||
if [ "$nodejsinstall" = "y" ] || [ "$nodejsinstall" = "Y" ]; then
|
||||
export OPENCV4NODEJS_DISABLE_AUTOBUILD=0
|
||||
else
|
||||
export OPENCV4NODEJS_DISABLE_AUTOBUILD=1
|
||||
fi
|
||||
else
|
||||
export OPENCV4NODEJS_DISABLE_AUTOBUILD=1
|
||||
fi
|
||||
npm install opencv4nodejs moment express canvas@1.6 --unsafe-perm
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"plug":"Coco",
|
||||
"host":"localhost",
|
||||
"port":8080,
|
||||
"hostPort":8082,
|
||||
"key":"change_this_to_something_very_random____make_sure_to_match__/plugins/opencv/conf.json",
|
||||
"mode":"client",
|
||||
"type":"detector"
|
||||
}
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
module.exports = [
|
||||
'background',
|
||||
'person',
|
||||
'bicycle',
|
||||
'car',
|
||||
'motorcycle',
|
||||
'airplane',
|
||||
'bus',
|
||||
'train',
|
||||
'truck',
|
||||
'boat',
|
||||
'traffic light',
|
||||
'fire hydrant',
|
||||
'stop sign',
|
||||
'parking meter',
|
||||
'bench',
|
||||
'bird',
|
||||
'cat',
|
||||
'dog',
|
||||
'horse',
|
||||
'sheep',
|
||||
'cow',
|
||||
'elephant',
|
||||
'bear',
|
||||
'zebra',
|
||||
'giraffe',
|
||||
'backpack',
|
||||
'umbrella',
|
||||
'handbag',
|
||||
'tie',
|
||||
'suitcase',
|
||||
'frisbee',
|
||||
'skis',
|
||||
'snowboard',
|
||||
'sports ball',
|
||||
'kite',
|
||||
'baseball bat',
|
||||
'baseball glove',
|
||||
'skateboard',
|
||||
'surfboard',
|
||||
'tennis racket',
|
||||
'bottle',
|
||||
'wine glass',
|
||||
'cup',
|
||||
'fork',
|
||||
'knife',
|
||||
'spoon',
|
||||
'bowl',
|
||||
'banana',
|
||||
'apple',
|
||||
'sandwich',
|
||||
'orange',
|
||||
'broccoli',
|
||||
'carrot',
|
||||
'hot dog',
|
||||
'pizza',
|
||||
'donut',
|
||||
'cake',
|
||||
'chair',
|
||||
'couch',
|
||||
'potted plant',
|
||||
'bed',
|
||||
'dining table',
|
||||
'toilet',
|
||||
'tv',
|
||||
'laptop',
|
||||
'mouse',
|
||||
'remote',
|
||||
'keyboard',
|
||||
'cell phone',
|
||||
'microwave',
|
||||
'oven',
|
||||
'toaster',
|
||||
'sink',
|
||||
'refrigerator',
|
||||
'book',
|
||||
'clock',
|
||||
'vase',
|
||||
'scissors',
|
||||
'teddy bear',
|
||||
'hair drier',
|
||||
'toothbrush'
|
||||
];
|
||||
|
|
@ -0,0 +1,94 @@
|
|||
|
||||
; Specify the path to the runtime data directory
|
||||
runtime_dir = ${CMAKE_INSTALL_PREFIX}/share/openalpr/runtime_data
|
||||
|
||||
|
||||
ocr_img_size_percent = 1.33333333
|
||||
state_id_img_size_percent = 2.0
|
||||
|
||||
; Calibrating your camera improves detection accuracy in cases where vehicle plates are captured at a steep angle
|
||||
; Use the openalpr-utils-calibrate utility to calibrate your fixed camera to adjust for an angle
|
||||
; Once done, update the prewarp config with the values obtained from the tool
|
||||
prewarp =
|
||||
|
||||
; detection will ignore plates that are too large. This is a good efficiency technique to use if the
|
||||
; plates are going to be a fixed distance away from the camera (e.g., you will never see plates that fill
|
||||
; up the entire image
|
||||
max_plate_width_percent = 100
|
||||
max_plate_height_percent = 100
|
||||
|
||||
; detection_iteration_increase is the percentage that the LBP frame increases each iteration.
|
||||
; It must be greater than 1.0. A value of 1.01 means increase by 1%, 1.10 increases it by 10% each time.
|
||||
; So a 1% increase would be ~10x slower than 10% to process, but it has a higher chance of landing
|
||||
; directly on the plate and getting a strong detection
|
||||
detection_iteration_increase = 1.1
|
||||
|
||||
; The minimum detection strength determines how sure the detection algorithm must be before signaling that
|
||||
; a plate region exists. Technically this corresponds to LBP nearest neighbors (e.g., how many detections
|
||||
; are clustered around the same area). For example, 2 = very lenient, 9 = very strict.
|
||||
detection_strictness = 3
|
||||
|
||||
; The detection doesn't necessarily need an extremely high resolution image in order to detect plates
|
||||
; Using a smaller input image should still find the plates and will do it faster
|
||||
; Tweaking the max_detection_input values will resize the input image if it is larger than these sizes
|
||||
; max_detection_input_width/height are specified in pixels
|
||||
max_detection_input_width = 1280
|
||||
max_detection_input_height = 720
|
||||
|
||||
; detector is the technique used to find license plate regions in an image. Value can be set to
|
||||
; lbpcpu - default LBP-based detector uses the system CPU
|
||||
; lbpgpu - LBP-based detector that uses Nvidia GPU to increase recognition speed.
|
||||
; lbpopencl - LBP-based detector that uses OpenCL GPU to increase recognition speed. Requires OpenCV 3.0
|
||||
; morphcpu - Experimental detector that detects white rectangles in an image. Does not require training.
|
||||
detector = lbpgpu
|
||||
|
||||
; If set to true, all results must match a postprocess text pattern if a pattern is available.
|
||||
; If not, the result is disqualified.
|
||||
must_match_pattern = 0
|
||||
|
||||
; Bypasses plate detection. If this is set to 1, the library assumes that each region provided is a likely plate area.
|
||||
skip_detection = 0
|
||||
|
||||
; Specifies the full path to an image file that constrains the detection area. Only the plate regions allowed through the mask
|
||||
; will be analyzed. The mask image must match the resolution of your image to be analyzed. The mask is black and white.
|
||||
; Black areas will be ignored, white areas will be searched. An empty value means no mask (scan the entire image)
|
||||
detection_mask_image =
|
||||
|
||||
; OpenALPR can scan the same image multiple times with different randomization. Setting this to a value larger than
|
||||
; 1 may increase accuracy, but will increase processing time linearly (e.g., analysis_count = 3 is 3x slower)
|
||||
analysis_count = 1
|
||||
|
||||
; OpenALPR detects high-contrast plate crops and uses an alternative edge detection technique. Setting this to 0.0
|
||||
; would classify ALL images as high-contrast, setting it to 1.0 would classify no images as high-contrast.
|
||||
contrast_detection_threshold = 0.3
|
||||
|
||||
max_plate_angle_degrees = 15
|
||||
|
||||
ocr_min_font_point = 6
|
||||
|
||||
; Minimum OCR confidence percent to consider.
|
||||
postprocess_min_confidence = 65
|
||||
|
||||
; Any OCR character lower than this will also add an equally likely
|
||||
; chance that the character is incorrect and will be skipped. Value is a confidence percent
|
||||
postprocess_confidence_skip_level = 80
|
||||
|
||||
|
||||
debug_general = 0
|
||||
debug_timing = 0
|
||||
debug_detector = 0
|
||||
debug_prewarp = 0
|
||||
debug_state_id = 0
|
||||
debug_plate_lines = 0
|
||||
debug_plate_corners = 0
|
||||
debug_char_segment = 0
|
||||
debug_char_analysis = 0
|
||||
debug_color_filter = 0
|
||||
debug_ocr = 0
|
||||
debug_postprocess = 0
|
||||
debug_show_images = 0
|
||||
debug_pause_on_frame = 0
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,525 @@
|
|||
//
|
||||
// Shinobi - OpenCV 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);
|
||||
});
|
||||
var fs=require('fs');
|
||||
var cv=require('opencv4nodejs');
|
||||
var exec = require('child_process').exec;
|
||||
var moment = require('moment');
|
||||
var Canvas = require('canvas');
|
||||
var express = require('express');
|
||||
const path = require('path');
|
||||
var http = require('http'),
|
||||
app = express(),
|
||||
server = http.createServer(app);
|
||||
var config=require('./conf.json');
|
||||
if(!config.port){config.port=8080}
|
||||
if(!config.hostPort){config.hostPort=8082}
|
||||
if(config.systemLog===undefined){config.systemLog=true}
|
||||
if(config.cascadesDir===undefined){config.cascadesDir=__dirname+'/cascades/'}
|
||||
if(config.alprConfig===undefined){config.alprConfig=__dirname+'/openalpr.conf'}
|
||||
|
||||
|
||||
const classNames = require(__dirname+'/dnnCocoClassNames.js');
|
||||
const extractResults = function (outputBlob, imgDimensions) {
|
||||
return Array(outputBlob.rows).fill(0)
|
||||
.map((res, i) => {
|
||||
const classLabel = outputBlob.at(i, 1);
|
||||
const confidence = outputBlob.at(i, 2);
|
||||
const bottomLeft = new cv.Point(
|
||||
outputBlob.at(i, 3) * imgDimensions.cols,
|
||||
outputBlob.at(i, 6) * imgDimensions.rows
|
||||
);
|
||||
const topRight = new cv.Point(
|
||||
outputBlob.at(i, 5) * imgDimensions.cols,
|
||||
outputBlob.at(i, 4) * imgDimensions.rows
|
||||
);
|
||||
const rect = new cv.Rect(
|
||||
bottomLeft.x,
|
||||
topRight.y,
|
||||
topRight.x - bottomLeft.x,
|
||||
bottomLeft.y - topRight.y
|
||||
);
|
||||
|
||||
return ({
|
||||
classLabel,
|
||||
confidence,
|
||||
rect
|
||||
});
|
||||
});
|
||||
};
|
||||
// replace with path where you unzipped inception model
|
||||
const ssdcocoModelPath = __dirname+'/data';
|
||||
|
||||
const prototxt = path.resolve(ssdcocoModelPath, 'deploy.prototxt');
|
||||
const modelFile = path.resolve(ssdcocoModelPath, 'VGG_coco_SSD_300x300_iter_400000.caffemodel');
|
||||
|
||||
if (!fs.existsSync(prototxt) || !fs.existsSync(modelFile)) {
|
||||
console.log('could not find ssdcoco model');
|
||||
console.log('download the model from: https://cdn.shinobi.video/weights/dnnCocoData.zip');
|
||||
throw new Error('exiting: could not find ssdcoco model');
|
||||
}
|
||||
|
||||
// initialize ssdcoco model from prototxt and modelFile
|
||||
const net = cv.readNetFromCaffe(prototxt, modelFile);
|
||||
|
||||
function classifyImg(img) {
|
||||
// ssdcoco model works with 300 x 300 images
|
||||
const imgResized = img.resize(300, 300);
|
||||
|
||||
// network accepts blobs as input
|
||||
const inputBlob = cv.blobFromImage(imgResized);
|
||||
net.setInput(inputBlob);
|
||||
|
||||
// forward pass input through entire network, will return
|
||||
// classification result as 1x1xNxM Mat
|
||||
let outputBlob = net.forward();
|
||||
// extract NxM Mat
|
||||
outputBlob = outputBlob.flattenFloat(outputBlob.sizes[2], outputBlob.sizes[3]);
|
||||
|
||||
return extractResults(outputBlob, img)
|
||||
.map(r => Object.assign({}, r.rect, { confidence : r.confidence, tag: classNames[r.classLabel] }));
|
||||
}
|
||||
|
||||
const makeDrawClassDetections = predictions => (drawImg, className, getColor, thickness = 2) => {
|
||||
predictions
|
||||
.filter(p => classNames[p.classLabel] === className)
|
||||
.forEach(p => console.log(p));
|
||||
};
|
||||
|
||||
|
||||
s={
|
||||
group:{},
|
||||
dir:{
|
||||
cascades : config.cascadesDir
|
||||
},
|
||||
isWin:(process.platform==='win32'),
|
||||
foundCascades : {
|
||||
|
||||
}
|
||||
}
|
||||
//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);
|
||||
}
|
||||
//streams dir
|
||||
if(!fs.existsSync(s.dir.cascades)){
|
||||
fs.mkdirSync(s.dir.cascades);
|
||||
}
|
||||
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.findCascades=function(callback){
|
||||
var tmp={};
|
||||
tmp.foundCascades=[];
|
||||
fs.readdir(s.dir.cascades,function(err,files){
|
||||
files.forEach(function(cascade,n){
|
||||
if(cascade.indexOf('.xml')>-1){
|
||||
tmp.foundCascades.push(cascade.replace('.xml',''))
|
||||
}
|
||||
})
|
||||
s.cascadesInDir=tmp.foundCascades;
|
||||
callback(tmp.foundCascades)
|
||||
})
|
||||
}
|
||||
s.findCascades(function(){
|
||||
//get cascades
|
||||
})
|
||||
s.detectLicensePlate=function(buffer,d,tx){
|
||||
if(!d.mon.detector_lisence_plate_country||d.mon.detector_lisence_plate_country===''){
|
||||
d.mon.detector_lisence_plate_country='us'
|
||||
}
|
||||
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);
|
||||
exec('alpr -j --config '+config.alprConfig+' -c '+d.mon.detector_lisence_plate_country+' '+d.dir+d.tmpFile,{encoding:'utf8'},(err, scan, stderr) => {
|
||||
if(err){
|
||||
s.systemLog(err);
|
||||
}else{
|
||||
try{
|
||||
scan=JSON.parse(scan.replace('--(!)Loaded CUDA classifier','').trim())
|
||||
}catch(err){
|
||||
if(!scan||!scan.results){
|
||||
return s.systemLog(scan,err);
|
||||
}
|
||||
}
|
||||
if(scan.results.length>0){
|
||||
scan.plates=[]
|
||||
scan.mats=[]
|
||||
scan.results.forEach(function(v){
|
||||
v.candidates.forEach(function(g,n){
|
||||
if(v.candidates[n].matches_template)
|
||||
delete(v.candidates[n].matches_template)
|
||||
})
|
||||
scan.plates.push({coordinates:v.coordinates,candidates:v.candidates,confidence:v.confidence,plate:v.plate})
|
||||
var width = Math.sqrt( Math.pow(v.coordinates[1].x - v.coordinates[0].x, 2) + Math.pow(v.coordinates[1].y - v.coordinates[0].y, 2));
|
||||
var height = Math.sqrt( Math.pow(v.coordinates[2].x - v.coordinates[1].x, 2) + Math.pow(v.coordinates[2].y - v.coordinates[1].y, 2))
|
||||
scan.mats.push({
|
||||
x:v.coordinates[0].x,
|
||||
y:v.coordinates[0].y,
|
||||
width:width,
|
||||
height:height,
|
||||
tag:v.plate
|
||||
})
|
||||
})
|
||||
tx({f:'trigger',id:d.id,ke:d.ke,details:{split:true,plug:config.plug,name:'licensePlate',reason:'object',matrices:scan.mats,imgHeight:d.mon.detector_scale_y,imgWidth:d.mon.detector_scale_x,frame:d.base64}})
|
||||
}
|
||||
}
|
||||
exec('rm -rf '+d.dir+d.tmpFile,{encoding:'utf8'})
|
||||
})
|
||||
})
|
||||
}
|
||||
s.detectObject=function(buffer,d,tx){
|
||||
//detect license plate?
|
||||
if(d.mon.detector_lisence_plate==="1"){
|
||||
s.detectLicensePlate(buffer,d,tx)
|
||||
}
|
||||
cv.imdecodeAsync(buffer,(err,im) => {
|
||||
if(err){
|
||||
console.log(err)
|
||||
return
|
||||
}
|
||||
|
||||
if (!cv.xmodules.dnn) {
|
||||
throw new Error('exiting: opencv4nodejs compiled without dnn module');
|
||||
}
|
||||
|
||||
|
||||
const minConfidence = 0.5;
|
||||
|
||||
const predictions = classifyImg(im).filter(res => res.confidence > minConfidence);
|
||||
// console.log(predictions)
|
||||
if(predictions.length > 0) {
|
||||
s.cx({
|
||||
f:'trigger',
|
||||
id:d.id,
|
||||
ke:d.ke,
|
||||
name:'coco',
|
||||
details:{
|
||||
plug:'coco',
|
||||
name:'coco',
|
||||
reason:'object',
|
||||
matrices : predictions
|
||||
// confidence:d.average
|
||||
},
|
||||
imgHeight:d.mon.detector_scale_y,
|
||||
imgWidth:d.mon.detector_scale_x
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
s.systemLog=function(q,w,e){
|
||||
if(!w){w=''}
|
||||
if(!e){e=''}
|
||||
if(config.systemLog===true){
|
||||
return console.log(moment().format(),q,w,e)
|
||||
}
|
||||
}
|
||||
|
||||
s.blenderRegion=function(d,cord,tx){
|
||||
d.width = d.image.width;
|
||||
d.height = d.image.height;
|
||||
if(!s.group[d.ke][d.id].canvas[cord.name]){
|
||||
if(!cord.sensitivity||isNaN(cord.sensitivity)){
|
||||
cord.sensitivity=d.mon.detector_sensitivity;
|
||||
}
|
||||
s.group[d.ke][d.id].canvas[cord.name] = new Canvas(d.width,d.height);
|
||||
s.group[d.ke][d.id].canvasContext[cord.name] = s.group[d.ke][d.id].canvas[cord.name].getContext('2d');
|
||||
s.group[d.ke][d.id].canvasContext[cord.name].fillStyle = '#000';
|
||||
s.group[d.ke][d.id].canvasContext[cord.name].fillRect( 0, 0,d.width,d.height);
|
||||
if(cord.points&&cord.points.length>0){
|
||||
s.group[d.ke][d.id].canvasContext[cord.name].beginPath();
|
||||
for (var b = 0; b < cord.points.length; b++){
|
||||
cord.points[b][0]=parseFloat(cord.points[b][0]);
|
||||
cord.points[b][1]=parseFloat(cord.points[b][1]);
|
||||
if(b===0){
|
||||
s.group[d.ke][d.id].canvasContext[cord.name].moveTo(cord.points[b][0],cord.points[b][1]);
|
||||
}else{
|
||||
s.group[d.ke][d.id].canvasContext[cord.name].lineTo(cord.points[b][0],cord.points[b][1]);
|
||||
}
|
||||
}
|
||||
s.group[d.ke][d.id].canvasContext[cord.name].clip();
|
||||
}
|
||||
}
|
||||
if(!s.group[d.ke][d.id].canvasContext[cord.name]){
|
||||
return
|
||||
}
|
||||
s.group[d.ke][d.id].canvasContext[cord.name].drawImage(d.image, 0, 0, d.width, d.height);
|
||||
if(!s.group[d.ke][d.id].blendRegion[cord.name]){
|
||||
s.group[d.ke][d.id].blendRegion[cord.name] = new Canvas(d.width, d.height);
|
||||
s.group[d.ke][d.id].blendRegionContext[cord.name] = s.group[d.ke][d.id].blendRegion[cord.name].getContext('2d');
|
||||
}
|
||||
var sourceData = s.group[d.ke][d.id].canvasContext[cord.name].getImageData(0, 0, d.width, d.height);
|
||||
// create an image if the previous image doesn<73>t exist
|
||||
if (!s.group[d.ke][d.id].lastRegionImageData[cord.name]) s.group[d.ke][d.id].lastRegionImageData[cord.name] = s.group[d.ke][d.id].canvasContext[cord.name].getImageData(0, 0, d.width, d.height);
|
||||
// create a ImageData instance to receive the blended result
|
||||
var blendedData = s.group[d.ke][d.id].canvasContext[cord.name].createImageData(d.width, d.height);
|
||||
// blend the 2 images
|
||||
s.differenceAccuracy(blendedData.data,sourceData.data,s.group[d.ke][d.id].lastRegionImageData[cord.name].data);
|
||||
// draw the result in a canvas
|
||||
s.group[d.ke][d.id].blendRegionContext[cord.name].putImageData(blendedData, 0, 0);
|
||||
// store the current webcam image
|
||||
s.group[d.ke][d.id].lastRegionImageData[cord.name] = sourceData;
|
||||
blendedData = s.group[d.ke][d.id].blendRegionContext[cord.name].getImageData(0, 0, d.width, d.height);
|
||||
var i = 0;
|
||||
d.average = 0;
|
||||
while (i < (blendedData.data.length * 0.25)) {
|
||||
d.average += (blendedData.data[i * 4] + blendedData.data[i * 4 + 1] + blendedData.data[i * 4 + 2]);
|
||||
++i;
|
||||
}
|
||||
d.average = (d.average / (blendedData.data.length * 0.25))*10;
|
||||
if (d.average > parseFloat(cord.sensitivity)){
|
||||
if(d.mon.detector_use_detect_object==="1"&&d.mon.detector_second!=='1'){
|
||||
var buffer=s.group[d.ke][d.id].canvas[cord.name].toBuffer();
|
||||
s.detectObject(buffer,d,tx)
|
||||
}else{
|
||||
tx({f:'trigger',id:d.id,ke:d.ke,details:{split:true,plug:config.plug,name:cord.name,reason:'motion',confidence:d.average,frame:d.base64}})
|
||||
}
|
||||
}
|
||||
s.group[d.ke][d.id].canvasContext[cord.name].clearRect(0, 0, d.width, d.height);
|
||||
s.group[d.ke][d.id].blendRegionContext[cord.name].clearRect(0, 0, d.width, d.height);
|
||||
}
|
||||
function blobToBuffer (blob, cb) {
|
||||
if (typeof Blob === 'undefined' || !(blob instanceof Blob)) {
|
||||
throw new Error('first argument must be a Blob')
|
||||
}
|
||||
if (typeof cb !== 'function') {
|
||||
throw new Error('second argument must be a function')
|
||||
}
|
||||
|
||||
var reader = new FileReader()
|
||||
|
||||
function onLoadEnd (e) {
|
||||
reader.removeEventListener('loadend', onLoadEnd, false)
|
||||
if (e.error) cb(e.error)
|
||||
else cb(null, Buffer.from(reader.result))
|
||||
}
|
||||
|
||||
reader.addEventListener('loadend', onLoadEnd, false)
|
||||
reader.readAsArrayBuffer(blob)
|
||||
}
|
||||
function fastAbs(value) {
|
||||
return (value ^ (value >> 31)) - (value >> 31);
|
||||
}
|
||||
|
||||
function threshold(value) {
|
||||
return (value > 0x15) ? 0xFF : 0;
|
||||
}
|
||||
s.differenceAccuracy=function(target, data1, data2) {
|
||||
if (data1.length != data2.length) return null;
|
||||
var i = 0;
|
||||
while (i < (data1.length * 0.25)) {
|
||||
var average1 = (data1[4 * i] + data1[4 * i + 1] + data1[4 * i + 2]) / 3;
|
||||
var average2 = (data2[4 * i] + data2[4 * i + 1] + data2[4 * i + 2]) / 3;
|
||||
var diff = threshold(fastAbs(average1 - average2));
|
||||
target[4 * i] = diff;
|
||||
target[4 * i + 1] = diff;
|
||||
target[4 * i + 2] = diff;
|
||||
target[4 * i + 3] = 0xFF;
|
||||
++i;
|
||||
}
|
||||
}
|
||||
s.checkAreas=function(d,tx){
|
||||
if(!s.group[d.ke][d.id].cords){
|
||||
if(!d.mon.cords){d.mon.cords={}}
|
||||
s.group[d.ke][d.id].cords=Object.values(d.mon.cords);
|
||||
}
|
||||
if(d.mon.detector_frame==='1'){
|
||||
d.mon.cords.frame={name:'FULL_FRAME',s:d.mon.detector_sensitivity,points:[[0,0],[0,d.image.height],[d.image.width,d.image.height],[d.image.width,0]]};
|
||||
s.group[d.ke][d.id].cords.push(d.mon.cords.frame);
|
||||
}
|
||||
for (var b = 0; b < s.group[d.ke][d.id].cords.length; b++){
|
||||
if(!s.group[d.ke][d.id].cords[b]){return}
|
||||
s.blenderRegion(d,s.group[d.ke][d.id].cords[b],tx)
|
||||
}
|
||||
delete(d.image)
|
||||
}
|
||||
|
||||
s.MainEventController=function(d,cn,tx){
|
||||
switch(d.f){
|
||||
case'refreshPlugins':
|
||||
s.findCascades(function(cascades){
|
||||
s.cx({f:'s.tx',data:{f:'detector_cascade_list',cascades:cascades},to:'GRP_'+d.ke})
|
||||
})
|
||||
break;
|
||||
case'readPlugins':
|
||||
s.cx({f:'s.tx',data:{f:'detector_cascade_list',cascades:s.cascadesInDir},to:'GRP_'+d.ke})
|
||||
break;
|
||||
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]){
|
||||
s.group[d.ke][d.id].canvas={}
|
||||
s.group[d.ke][d.id].canvasContext={}
|
||||
s.group[d.ke][d.id].blendRegion={}
|
||||
s.group[d.ke][d.id].blendRegionContext={}
|
||||
s.group[d.ke][d.id].lastRegionImageData={}
|
||||
s.group[d.ke][d.id].numberOfTriggers=0
|
||||
delete(s.group[d.ke][d.id].cords)
|
||||
delete(s.group[d.ke][d.id].buffer)
|
||||
}
|
||||
break;
|
||||
case'init_aws_push':
|
||||
// console.log('init_aws')
|
||||
s.group[d.ke][d.id].aws={links:[],complete:0,total:d.total,videos:[],tx:tx}
|
||||
break;
|
||||
case'frame':
|
||||
try{
|
||||
if(!s.group[d.ke]){
|
||||
s.group[d.ke]={}
|
||||
}
|
||||
if(!s.group[d.ke][d.id]){
|
||||
s.group[d.ke][d.id]={
|
||||
canvas:{},
|
||||
canvasContext:{},
|
||||
lastRegionImageData:{},
|
||||
blendRegion:{},
|
||||
blendRegionContext:{},
|
||||
}
|
||||
}
|
||||
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.group[d.ke][d.id].buffer=Buffer.concat(s.group[d.ke][d.id].buffer);
|
||||
try{
|
||||
d.mon.detector_cascades=JSON.parse(d.mon.detector_cascades)
|
||||
}catch(err){
|
||||
|
||||
}
|
||||
if(d.mon.detector_frame_save==="1"){
|
||||
d.base64=s.group[d.ke][d.id].buffer.toString('base64')
|
||||
}
|
||||
if(d.mon.detector_second==='1'&&d.objectOnly===true){
|
||||
s.detectObject(s.group[d.ke][d.id].buffer,d,tx)
|
||||
}else{
|
||||
if((d.mon.detector_pam !== '1' && d.mon.detector_use_motion === "1") || d.mon.detector_use_detect_object !== "1"){
|
||||
if((typeof d.mon.cords ==='string')&&d.mon.cords.trim()===''){
|
||||
d.mon.cords=[]
|
||||
}else{
|
||||
try{
|
||||
d.mon.cords=JSON.parse(d.mon.cords)
|
||||
}catch(err){
|
||||
// console.log('d.mon.cords',err,d)
|
||||
}
|
||||
}
|
||||
s.group[d.ke][d.id].cords=Object.values(d.mon.cords);
|
||||
d.mon.cords=d.mon.cords;
|
||||
d.image = new Canvas.Image;
|
||||
if(d.mon.detector_scale_x===''||d.mon.detector_scale_y===''){
|
||||
s.systemLog('Must set detector image size')
|
||||
return
|
||||
}else{
|
||||
d.image.width=d.mon.detector_scale_x;
|
||||
d.image.height=d.mon.detector_scale_y;
|
||||
}
|
||||
d.width=d.image.width;
|
||||
d.height=d.image.height;
|
||||
d.image.onload = function() {
|
||||
s.checkAreas(d,tx);
|
||||
}
|
||||
d.image.src = s.group[d.ke][d.id].buffer;
|
||||
}else{
|
||||
s.detectObject(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('<b>'+config.plug+'</b> 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 = require('socket.io-client')('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)
|
||||
})
|
||||
}
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
{
|
||||
"plug":"ComputerVision",
|
||||
"host":"localhost",
|
||||
"port":8080,
|
||||
"key":"UNIQUE KEY HERE",
|
||||
"computerVision":{
|
||||
"apiKey":"YOUR_KEY",
|
||||
"endpoint":"http://YOUR_ENDPOINT/analyze",
|
||||
"params":{
|
||||
"visualFeatures": "Categories,Description,Color",
|
||||
"details": "",
|
||||
"language": "en"
|
||||
}
|
||||
},
|
||||
"EmotionAPI":{
|
||||
"apiKey":"YOUR_KEY",
|
||||
"endpoint":"http://YOUR_ENDPOINT/recognize",
|
||||
"params":{}
|
||||
},
|
||||
"FaceAPI":{
|
||||
"apiKey":"YOUR_KEY",
|
||||
"endpoint":"http://YOUR_ENDPOINT/detect",
|
||||
"params":{
|
||||
"returnFaceId": "true",
|
||||
"returnFaceLandmarks": "false",
|
||||
"returnFaceAttributes": "age,gender,headPose,smile,facialHair,glasses,emotion,hair,makeup,occlusion,accessories,blur,exposure,noise"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,170 +0,0 @@
|
|||
//
|
||||
// Shinobi - Microsoft Computer Vision Plugin
|
||||
// Copyright (C) 2016-2025 Moe Alam, moeiscool
|
||||
//
|
||||
process.on('uncaughtException', function (err) {
|
||||
console.error('uncaughtException',err);
|
||||
});
|
||||
var fs=require('fs');
|
||||
var exec = require('child_process').exec;
|
||||
//var http = require('http');
|
||||
var request = require('request');
|
||||
var moment = require('moment');
|
||||
var cognitive = require('cognitive-services');
|
||||
var config=require('./conf.json');
|
||||
if(config.systemLog===undefined){config.systemLog=true}
|
||||
s={
|
||||
group:{},
|
||||
dir:{
|
||||
cascades:__dirname+'/cascades/'
|
||||
},
|
||||
isWin:(process.platform==='win32')
|
||||
}
|
||||
//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.systemLog=function(q,w,e){
|
||||
if(!w){w=''}
|
||||
if(!e){e=''}
|
||||
if(config.systemLog===true){
|
||||
return console.log(moment().format(),q,w,e)
|
||||
}
|
||||
}
|
||||
s.objectToParameter = function(obj){
|
||||
return Object.keys(obj).map(function(key) {
|
||||
return key + '=' + encodeURIComponent(obj[key]);
|
||||
}).join('&');
|
||||
}
|
||||
s.sendImageToMS=function(sourceImageUrl,API,callback){
|
||||
var URL = API.endpoint+'?'+s.objectToParameter(API.params)
|
||||
request(URL,{
|
||||
method: 'POST',
|
||||
headers:{
|
||||
"Ocp-Apim-Subscription-Key":API.apiKey
|
||||
},
|
||||
json: {
|
||||
url:sourceImageUrl
|
||||
}
|
||||
}, callback)
|
||||
}
|
||||
s.detectObject=function(buffer,d){
|
||||
var sourceImageUrl = 'http://184.105.6.43/'+s.api_key+'/jpeg/'+d.ke+'/'+d.id+'/s.jpg'
|
||||
// const client = new cognitive.computerVision({
|
||||
// apiKey: config.computerVision.apiKey,
|
||||
// endpoint: config.computerVision.endpoint
|
||||
// });
|
||||
// const parameters = {
|
||||
// "visualFeatures": "Categories,Tags,Description",
|
||||
// "details": "Celebrities,Landmarks"
|
||||
// };
|
||||
// const headers = {
|
||||
// 'Content-type': 'application/json'
|
||||
// };
|
||||
// const body = {
|
||||
// "url": sourceImageUrl
|
||||
// };
|
||||
//
|
||||
// client.analyzeImage({
|
||||
// parameters,
|
||||
// headers,
|
||||
// body
|
||||
// }).then((response) => {
|
||||
//// should(response).not.be.undefined();
|
||||
//// should(response).have.properties(["categories", "metadata", "requestId"]);
|
||||
// console.log(response)
|
||||
// }).catch((err) => {
|
||||
// console.log('Error',err)
|
||||
// });
|
||||
var responses = {}
|
||||
s.sendImageToMS(sourceImageUrl,config.computerVision,function(err,resp,body1){
|
||||
responses.computerVisionURL = body1
|
||||
s.sendImageToMS(sourceImageUrl,config.FaceAPI,function(err,resp,body2){
|
||||
responses.faceApiURL = body2
|
||||
s.sendImageToMS(sourceImageUrl,config.EmotionAPI,function(err,resp,body3){
|
||||
responses.EmotionAPI = body3
|
||||
console.log('responses',JSON.stringify(responses,null,3))
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
s.makeMonitorObject=function(d){
|
||||
if(!s.group[d.ke]){
|
||||
s.group[d.ke]={}
|
||||
}
|
||||
if(!s.group[d.ke][d.id]){
|
||||
s.group[d.ke][d.id]={
|
||||
port:null,
|
||||
countStarted:new Date()
|
||||
}
|
||||
}
|
||||
}
|
||||
io = require('socket.io-client')('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});
|
||||
})
|
||||
io.on('disconnect',function(d){
|
||||
io.connect()
|
||||
})
|
||||
io.on('f',function(d){
|
||||
switch(d.f){
|
||||
case'api_key':
|
||||
s.api_key=d.key
|
||||
break;
|
||||
case'init_monitor':
|
||||
if(s.group[d.ke]&&s.group[d.ke][d.id]){
|
||||
s.group[d.ke][d.id].buffer=null
|
||||
s.group[d.ke][d.id].countStarted=new Date()
|
||||
}
|
||||
s.makeMonitorObject(d)
|
||||
break;
|
||||
case'frame':
|
||||
d.details={}
|
||||
try{
|
||||
s.makeMonitorObject(d)
|
||||
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){
|
||||
if(d.mon.detector_frame_save==="1"){
|
||||
d.base64=s.group[d.ke][d.id].buffer.toString('base64')
|
||||
}
|
||||
if(d.mon.detector_scale_x&&d.mon.detector_scale_x!==''&&d.mon.detector_scale_y&&d.mon.detector_scale_y!==''){
|
||||
d.width=d.mon.detector_scale_x;
|
||||
d.height=d.mon.detector_scale_y;
|
||||
}else{
|
||||
d.width=640
|
||||
d.height=480
|
||||
}
|
||||
s.detectObject(Buffer.concat(s.group[d.ke][d.id].buffer),d)
|
||||
s.group[d.ke][d.id].buffer=null;
|
||||
}
|
||||
} catch(err){
|
||||
console.error(err)
|
||||
}
|
||||
break;
|
||||
}
|
||||
})
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
conf.json
|
||||
cascades
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
#!/bin/bash
|
||||
mkdir data
|
||||
mkdir data/inception
|
||||
chmod -R 777 data
|
||||
wget https://cdn.shinobi.video/weights/inception5h.zip -O inception5h.zip
|
||||
unzip inception5h.zip -d data/inception
|
||||
if [ $(dpkg-query -W -f='${Status}' opencv_version 2>/dev/null | grep -c "ok installed") -eq 0 ]; then
|
||||
echo "Shinobi - Do ypu want to let the `opencv4nodejs` npm package install OpenCV? "
|
||||
echo "Only do this if you do not have OpenCV already or will not use a GPU (Hardware Acceleration)."
|
||||
echo "(y)es or (N)o"
|
||||
read nodejsinstall
|
||||
if [ "$nodejsinstall" = "y" ] || [ "$nodejsinstall" = "Y" ]; then
|
||||
export OPENCV4NODEJS_DISABLE_AUTOBUILD=0
|
||||
else
|
||||
export OPENCV4NODEJS_DISABLE_AUTOBUILD=1
|
||||
fi
|
||||
else
|
||||
export OPENCV4NODEJS_DISABLE_AUTOBUILD=1
|
||||
fi
|
||||
npm install opencv4nodejs moment express canvas@1.6 --unsafe-perm
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"plug":"Tensorflow",
|
||||
"host":"localhost",
|
||||
"port":8080,
|
||||
"hostPort":8082,
|
||||
"key":"change_this_to_something_very_random____make_sure_to_match__/plugins/opencv/conf.json",
|
||||
"mode":"client",
|
||||
"type":"detector"
|
||||
}
|
||||
|
|
@ -0,0 +1,94 @@
|
|||
|
||||
; Specify the path to the runtime data directory
|
||||
runtime_dir = ${CMAKE_INSTALL_PREFIX}/share/openalpr/runtime_data
|
||||
|
||||
|
||||
ocr_img_size_percent = 1.33333333
|
||||
state_id_img_size_percent = 2.0
|
||||
|
||||
; Calibrating your camera improves detection accuracy in cases where vehicle plates are captured at a steep angle
|
||||
; Use the openalpr-utils-calibrate utility to calibrate your fixed camera to adjust for an angle
|
||||
; Once done, update the prewarp config with the values obtained from the tool
|
||||
prewarp =
|
||||
|
||||
; detection will ignore plates that are too large. This is a good efficiency technique to use if the
|
||||
; plates are going to be a fixed distance away from the camera (e.g., you will never see plates that fill
|
||||
; up the entire image
|
||||
max_plate_width_percent = 100
|
||||
max_plate_height_percent = 100
|
||||
|
||||
; detection_iteration_increase is the percentage that the LBP frame increases each iteration.
|
||||
; It must be greater than 1.0. A value of 1.01 means increase by 1%, 1.10 increases it by 10% each time.
|
||||
; So a 1% increase would be ~10x slower than 10% to process, but it has a higher chance of landing
|
||||
; directly on the plate and getting a strong detection
|
||||
detection_iteration_increase = 1.1
|
||||
|
||||
; The minimum detection strength determines how sure the detection algorithm must be before signaling that
|
||||
; a plate region exists. Technically this corresponds to LBP nearest neighbors (e.g., how many detections
|
||||
; are clustered around the same area). For example, 2 = very lenient, 9 = very strict.
|
||||
detection_strictness = 3
|
||||
|
||||
; The detection doesn't necessarily need an extremely high resolution image in order to detect plates
|
||||
; Using a smaller input image should still find the plates and will do it faster
|
||||
; Tweaking the max_detection_input values will resize the input image if it is larger than these sizes
|
||||
; max_detection_input_width/height are specified in pixels
|
||||
max_detection_input_width = 1280
|
||||
max_detection_input_height = 720
|
||||
|
||||
; detector is the technique used to find license plate regions in an image. Value can be set to
|
||||
; lbpcpu - default LBP-based detector uses the system CPU
|
||||
; lbpgpu - LBP-based detector that uses Nvidia GPU to increase recognition speed.
|
||||
; lbpopencl - LBP-based detector that uses OpenCL GPU to increase recognition speed. Requires OpenCV 3.0
|
||||
; morphcpu - Experimental detector that detects white rectangles in an image. Does not require training.
|
||||
detector = lbpgpu
|
||||
|
||||
; If set to true, all results must match a postprocess text pattern if a pattern is available.
|
||||
; If not, the result is disqualified.
|
||||
must_match_pattern = 0
|
||||
|
||||
; Bypasses plate detection. If this is set to 1, the library assumes that each region provided is a likely plate area.
|
||||
skip_detection = 0
|
||||
|
||||
; Specifies the full path to an image file that constrains the detection area. Only the plate regions allowed through the mask
|
||||
; will be analyzed. The mask image must match the resolution of your image to be analyzed. The mask is black and white.
|
||||
; Black areas will be ignored, white areas will be searched. An empty value means no mask (scan the entire image)
|
||||
detection_mask_image =
|
||||
|
||||
; OpenALPR can scan the same image multiple times with different randomization. Setting this to a value larger than
|
||||
; 1 may increase accuracy, but will increase processing time linearly (e.g., analysis_count = 3 is 3x slower)
|
||||
analysis_count = 1
|
||||
|
||||
; OpenALPR detects high-contrast plate crops and uses an alternative edge detection technique. Setting this to 0.0
|
||||
; would classify ALL images as high-contrast, setting it to 1.0 would classify no images as high-contrast.
|
||||
contrast_detection_threshold = 0.3
|
||||
|
||||
max_plate_angle_degrees = 15
|
||||
|
||||
ocr_min_font_point = 6
|
||||
|
||||
; Minimum OCR confidence percent to consider.
|
||||
postprocess_min_confidence = 65
|
||||
|
||||
; Any OCR character lower than this will also add an equally likely
|
||||
; chance that the character is incorrect and will be skipped. Value is a confidence percent
|
||||
postprocess_confidence_skip_level = 80
|
||||
|
||||
|
||||
debug_general = 0
|
||||
debug_timing = 0
|
||||
debug_detector = 0
|
||||
debug_prewarp = 0
|
||||
debug_state_id = 0
|
||||
debug_plate_lines = 0
|
||||
debug_plate_corners = 0
|
||||
debug_char_segment = 0
|
||||
debug_char_analysis = 0
|
||||
debug_color_filter = 0
|
||||
debug_ocr = 0
|
||||
debug_postprocess = 0
|
||||
debug_show_images = 0
|
||||
debug_pause_on_frame = 0
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,502 @@
|
|||
//
|
||||
// Shinobi - OpenCV 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);
|
||||
});
|
||||
var fs=require('fs');
|
||||
var cv=require('opencv4nodejs');
|
||||
var exec = require('child_process').exec;
|
||||
var moment = require('moment');
|
||||
var Canvas = require('canvas');
|
||||
var express = require('express');
|
||||
const path = require('path');
|
||||
var http = require('http'),
|
||||
app = express(),
|
||||
server = http.createServer(app);
|
||||
var config=require('./conf.json');
|
||||
if(!config.port){config.port=8080}
|
||||
if(!config.hostPort){config.hostPort=8082}
|
||||
if(config.systemLog===undefined){config.systemLog=true}
|
||||
if(config.cascadesDir===undefined){config.cascadesDir=__dirname+'/cascades/'}
|
||||
if(config.alprConfig===undefined){config.alprConfig=__dirname+'/openalpr.conf'}
|
||||
s={
|
||||
group:{},
|
||||
dir:{
|
||||
cascades : config.cascadesDir
|
||||
},
|
||||
isWin:(process.platform==='win32'),
|
||||
foundCascades : {
|
||||
|
||||
}
|
||||
}
|
||||
//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);
|
||||
}
|
||||
//streams dir
|
||||
if(!fs.existsSync(s.dir.cascades)){
|
||||
fs.mkdirSync(s.dir.cascades);
|
||||
}
|
||||
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.findCascades=function(callback){
|
||||
var tmp={};
|
||||
tmp.foundCascades=[];
|
||||
fs.readdir(s.dir.cascades,function(err,files){
|
||||
files.forEach(function(cascade,n){
|
||||
if(cascade.indexOf('.xml')>-1){
|
||||
tmp.foundCascades.push(cascade.replace('.xml',''))
|
||||
}
|
||||
})
|
||||
s.cascadesInDir=tmp.foundCascades;
|
||||
callback(tmp.foundCascades)
|
||||
})
|
||||
}
|
||||
s.findCascades(function(){
|
||||
//get cascades
|
||||
})
|
||||
s.detectLicensePlate=function(buffer,d,tx){
|
||||
if(!d.mon.detector_lisence_plate_country||d.mon.detector_lisence_plate_country===''){
|
||||
d.mon.detector_lisence_plate_country='us'
|
||||
}
|
||||
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);
|
||||
exec('alpr -j --config '+config.alprConfig+' -c '+d.mon.detector_lisence_plate_country+' '+d.dir+d.tmpFile,{encoding:'utf8'},(err, scan, stderr) => {
|
||||
if(err){
|
||||
s.systemLog(err);
|
||||
}else{
|
||||
try{
|
||||
scan=JSON.parse(scan.replace('--(!)Loaded CUDA classifier','').trim())
|
||||
}catch(err){
|
||||
if(!scan||!scan.results){
|
||||
return s.systemLog(scan,err);
|
||||
}
|
||||
}
|
||||
if(scan.results.length>0){
|
||||
scan.plates=[]
|
||||
scan.mats=[]
|
||||
scan.results.forEach(function(v){
|
||||
v.candidates.forEach(function(g,n){
|
||||
if(v.candidates[n].matches_template)
|
||||
delete(v.candidates[n].matches_template)
|
||||
})
|
||||
scan.plates.push({coordinates:v.coordinates,candidates:v.candidates,confidence:v.confidence,plate:v.plate})
|
||||
var width = Math.sqrt( Math.pow(v.coordinates[1].x - v.coordinates[0].x, 2) + Math.pow(v.coordinates[1].y - v.coordinates[0].y, 2));
|
||||
var height = Math.sqrt( Math.pow(v.coordinates[2].x - v.coordinates[1].x, 2) + Math.pow(v.coordinates[2].y - v.coordinates[1].y, 2))
|
||||
scan.mats.push({
|
||||
x:v.coordinates[0].x,
|
||||
y:v.coordinates[0].y,
|
||||
width:width,
|
||||
height:height,
|
||||
tag:v.plate
|
||||
})
|
||||
})
|
||||
tx({f:'trigger',id:d.id,ke:d.ke,details:{split:true,plug:config.plug,name:'licensePlate',reason:'object',matrices:scan.mats,imgHeight:d.mon.detector_scale_y,imgWidth:d.mon.detector_scale_x,frame:d.base64}})
|
||||
}
|
||||
}
|
||||
exec('rm -rf '+d.dir+d.tmpFile,{encoding:'utf8'})
|
||||
})
|
||||
})
|
||||
}
|
||||
s.detectObject=function(buffer,d,tx){
|
||||
//detect license plate?
|
||||
if(d.mon.detector_lisence_plate==="1"){
|
||||
s.detectLicensePlate(buffer,d,tx)
|
||||
}
|
||||
cv.imdecodeAsync(buffer,(err,im) => {
|
||||
if(err){
|
||||
console.log(err)
|
||||
return
|
||||
}
|
||||
|
||||
if (!cv.xmodules.dnn) {
|
||||
throw new Error('exiting: opencv4nodejs compiled without dnn module');
|
||||
}
|
||||
|
||||
// replace with path where you unzipped inception model
|
||||
const inceptionModelPath = __dirname+'/data/inception';
|
||||
|
||||
|
||||
const modelFile = path.resolve(inceptionModelPath, 'tensorflow_inception_graph.pb');
|
||||
const classNamesFile = path.resolve(inceptionModelPath, 'imagenet_comp_graph_label_strings.txt');
|
||||
if (!fs.existsSync(modelFile) || !fs.existsSync(classNamesFile)) {
|
||||
console.log('could not find inception model');
|
||||
console.log('download the model from: https://cdn.shinobi.video/weights/inception5h.zip');
|
||||
throw new Error('exiting');
|
||||
}
|
||||
|
||||
// read classNames and store them in an array
|
||||
const classNames = fs.readFileSync(classNamesFile).toString().split('\n');
|
||||
|
||||
// initialize tensorflow inception model from modelFile
|
||||
const net = cv.readNetFromTensorflow(modelFile);
|
||||
|
||||
// inception model works with 224 x 224 images, so we resize
|
||||
// our input images and pad the image with white pixels to
|
||||
// make the images have the same width and height
|
||||
const maxImgDim = 224;
|
||||
const white = new cv.Vec(255, 255, 255);
|
||||
const imgResized = im.resizeToMax(maxImgDim).padToSquare(white);
|
||||
|
||||
// network accepts blobs as input
|
||||
const inputBlob = cv.blobFromImage(imgResized);
|
||||
net.setInput(inputBlob);
|
||||
|
||||
// forward pass input through entire network, will return
|
||||
// classification result as 1xN Mat with confidences of each class
|
||||
const outputBlob = net.forward();
|
||||
|
||||
// find all labels with a minimum confidence
|
||||
const minConfidence = 0.05;
|
||||
const locations =
|
||||
outputBlob
|
||||
.threshold(minConfidence, 1, cv.THRESH_BINARY)
|
||||
.convertTo(cv.CV_8U)
|
||||
.findNonZero();
|
||||
// locations.forEach(function(v){
|
||||
// console.log(v)
|
||||
// })
|
||||
const result =
|
||||
locations.map(pt => ({
|
||||
confidence: parseInt(outputBlob.at(0, pt.x) * 100) / 100,
|
||||
className: classNames[pt.x]
|
||||
}))
|
||||
// sort result by confidence
|
||||
.sort((r0, r1) => r1.confidence - r0.confidence)
|
||||
.map(res => `${res.className} (${res.confidence})`);
|
||||
console.log(result)
|
||||
if(result.length > 0) {
|
||||
s.cx({
|
||||
f:'trigger',
|
||||
id:d.id,
|
||||
ke:d.ke,
|
||||
name:'tensorflow',
|
||||
details:{
|
||||
plug:'tensorflow',
|
||||
name:'tensorflow',
|
||||
reason:'object',
|
||||
matrices : result
|
||||
// confidence:d.average
|
||||
},
|
||||
imgHeight:d.mon.detector_scale_y,
|
||||
imgWidth:d.mon.detector_scale_x
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
s.systemLog=function(q,w,e){
|
||||
if(!w){w=''}
|
||||
if(!e){e=''}
|
||||
if(config.systemLog===true){
|
||||
return console.log(moment().format(),q,w,e)
|
||||
}
|
||||
}
|
||||
|
||||
s.blenderRegion=function(d,cord,tx){
|
||||
d.width = d.image.width;
|
||||
d.height = d.image.height;
|
||||
if(!s.group[d.ke][d.id].canvas[cord.name]){
|
||||
if(!cord.sensitivity||isNaN(cord.sensitivity)){
|
||||
cord.sensitivity=d.mon.detector_sensitivity;
|
||||
}
|
||||
s.group[d.ke][d.id].canvas[cord.name] = new Canvas(d.width,d.height);
|
||||
s.group[d.ke][d.id].canvasContext[cord.name] = s.group[d.ke][d.id].canvas[cord.name].getContext('2d');
|
||||
s.group[d.ke][d.id].canvasContext[cord.name].fillStyle = '#000';
|
||||
s.group[d.ke][d.id].canvasContext[cord.name].fillRect( 0, 0,d.width,d.height);
|
||||
if(cord.points&&cord.points.length>0){
|
||||
s.group[d.ke][d.id].canvasContext[cord.name].beginPath();
|
||||
for (var b = 0; b < cord.points.length; b++){
|
||||
cord.points[b][0]=parseFloat(cord.points[b][0]);
|
||||
cord.points[b][1]=parseFloat(cord.points[b][1]);
|
||||
if(b===0){
|
||||
s.group[d.ke][d.id].canvasContext[cord.name].moveTo(cord.points[b][0],cord.points[b][1]);
|
||||
}else{
|
||||
s.group[d.ke][d.id].canvasContext[cord.name].lineTo(cord.points[b][0],cord.points[b][1]);
|
||||
}
|
||||
}
|
||||
s.group[d.ke][d.id].canvasContext[cord.name].clip();
|
||||
}
|
||||
}
|
||||
if(!s.group[d.ke][d.id].canvasContext[cord.name]){
|
||||
return
|
||||
}
|
||||
s.group[d.ke][d.id].canvasContext[cord.name].drawImage(d.image, 0, 0, d.width, d.height);
|
||||
if(!s.group[d.ke][d.id].blendRegion[cord.name]){
|
||||
s.group[d.ke][d.id].blendRegion[cord.name] = new Canvas(d.width, d.height);
|
||||
s.group[d.ke][d.id].blendRegionContext[cord.name] = s.group[d.ke][d.id].blendRegion[cord.name].getContext('2d');
|
||||
}
|
||||
var sourceData = s.group[d.ke][d.id].canvasContext[cord.name].getImageData(0, 0, d.width, d.height);
|
||||
// create an image if the previous image doesn<73>t exist
|
||||
if (!s.group[d.ke][d.id].lastRegionImageData[cord.name]) s.group[d.ke][d.id].lastRegionImageData[cord.name] = s.group[d.ke][d.id].canvasContext[cord.name].getImageData(0, 0, d.width, d.height);
|
||||
// create a ImageData instance to receive the blended result
|
||||
var blendedData = s.group[d.ke][d.id].canvasContext[cord.name].createImageData(d.width, d.height);
|
||||
// blend the 2 images
|
||||
s.differenceAccuracy(blendedData.data,sourceData.data,s.group[d.ke][d.id].lastRegionImageData[cord.name].data);
|
||||
// draw the result in a canvas
|
||||
s.group[d.ke][d.id].blendRegionContext[cord.name].putImageData(blendedData, 0, 0);
|
||||
// store the current webcam image
|
||||
s.group[d.ke][d.id].lastRegionImageData[cord.name] = sourceData;
|
||||
blendedData = s.group[d.ke][d.id].blendRegionContext[cord.name].getImageData(0, 0, d.width, d.height);
|
||||
var i = 0;
|
||||
d.average = 0;
|
||||
while (i < (blendedData.data.length * 0.25)) {
|
||||
d.average += (blendedData.data[i * 4] + blendedData.data[i * 4 + 1] + blendedData.data[i * 4 + 2]);
|
||||
++i;
|
||||
}
|
||||
d.average = (d.average / (blendedData.data.length * 0.25))*10;
|
||||
if (d.average > parseFloat(cord.sensitivity)){
|
||||
if(d.mon.detector_use_detect_object==="1"&&d.mon.detector_second!=='1'){
|
||||
var buffer=s.group[d.ke][d.id].canvas[cord.name].toBuffer();
|
||||
s.detectObject(buffer,d,tx)
|
||||
}else{
|
||||
tx({f:'trigger',id:d.id,ke:d.ke,details:{split:true,plug:config.plug,name:cord.name,reason:'motion',confidence:d.average,frame:d.base64}})
|
||||
}
|
||||
}
|
||||
s.group[d.ke][d.id].canvasContext[cord.name].clearRect(0, 0, d.width, d.height);
|
||||
s.group[d.ke][d.id].blendRegionContext[cord.name].clearRect(0, 0, d.width, d.height);
|
||||
}
|
||||
function blobToBuffer (blob, cb) {
|
||||
if (typeof Blob === 'undefined' || !(blob instanceof Blob)) {
|
||||
throw new Error('first argument must be a Blob')
|
||||
}
|
||||
if (typeof cb !== 'function') {
|
||||
throw new Error('second argument must be a function')
|
||||
}
|
||||
|
||||
var reader = new FileReader()
|
||||
|
||||
function onLoadEnd (e) {
|
||||
reader.removeEventListener('loadend', onLoadEnd, false)
|
||||
if (e.error) cb(e.error)
|
||||
else cb(null, Buffer.from(reader.result))
|
||||
}
|
||||
|
||||
reader.addEventListener('loadend', onLoadEnd, false)
|
||||
reader.readAsArrayBuffer(blob)
|
||||
}
|
||||
function fastAbs(value) {
|
||||
return (value ^ (value >> 31)) - (value >> 31);
|
||||
}
|
||||
|
||||
function threshold(value) {
|
||||
return (value > 0x15) ? 0xFF : 0;
|
||||
}
|
||||
s.differenceAccuracy=function(target, data1, data2) {
|
||||
if (data1.length != data2.length) return null;
|
||||
var i = 0;
|
||||
while (i < (data1.length * 0.25)) {
|
||||
var average1 = (data1[4 * i] + data1[4 * i + 1] + data1[4 * i + 2]) / 3;
|
||||
var average2 = (data2[4 * i] + data2[4 * i + 1] + data2[4 * i + 2]) / 3;
|
||||
var diff = threshold(fastAbs(average1 - average2));
|
||||
target[4 * i] = diff;
|
||||
target[4 * i + 1] = diff;
|
||||
target[4 * i + 2] = diff;
|
||||
target[4 * i + 3] = 0xFF;
|
||||
++i;
|
||||
}
|
||||
}
|
||||
s.checkAreas=function(d,tx){
|
||||
if(!s.group[d.ke][d.id].cords){
|
||||
if(!d.mon.cords){d.mon.cords={}}
|
||||
s.group[d.ke][d.id].cords=Object.values(d.mon.cords);
|
||||
}
|
||||
if(d.mon.detector_frame==='1'){
|
||||
d.mon.cords.frame={name:'FULL_FRAME',s:d.mon.detector_sensitivity,points:[[0,0],[0,d.image.height],[d.image.width,d.image.height],[d.image.width,0]]};
|
||||
s.group[d.ke][d.id].cords.push(d.mon.cords.frame);
|
||||
}
|
||||
for (var b = 0; b < s.group[d.ke][d.id].cords.length; b++){
|
||||
if(!s.group[d.ke][d.id].cords[b]){return}
|
||||
s.blenderRegion(d,s.group[d.ke][d.id].cords[b],tx)
|
||||
}
|
||||
delete(d.image)
|
||||
}
|
||||
|
||||
s.MainEventController=function(d,cn,tx){
|
||||
switch(d.f){
|
||||
case'refreshPlugins':
|
||||
s.findCascades(function(cascades){
|
||||
s.cx({f:'s.tx',data:{f:'detector_cascade_list',cascades:cascades},to:'GRP_'+d.ke})
|
||||
})
|
||||
break;
|
||||
case'readPlugins':
|
||||
s.cx({f:'s.tx',data:{f:'detector_cascade_list',cascades:s.cascadesInDir},to:'GRP_'+d.ke})
|
||||
break;
|
||||
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]){
|
||||
s.group[d.ke][d.id].canvas={}
|
||||
s.group[d.ke][d.id].canvasContext={}
|
||||
s.group[d.ke][d.id].blendRegion={}
|
||||
s.group[d.ke][d.id].blendRegionContext={}
|
||||
s.group[d.ke][d.id].lastRegionImageData={}
|
||||
s.group[d.ke][d.id].numberOfTriggers=0
|
||||
delete(s.group[d.ke][d.id].cords)
|
||||
delete(s.group[d.ke][d.id].buffer)
|
||||
}
|
||||
break;
|
||||
case'init_aws_push':
|
||||
// console.log('init_aws')
|
||||
s.group[d.ke][d.id].aws={links:[],complete:0,total:d.total,videos:[],tx:tx}
|
||||
break;
|
||||
case'frame':
|
||||
try{
|
||||
if(!s.group[d.ke]){
|
||||
s.group[d.ke]={}
|
||||
}
|
||||
if(!s.group[d.ke][d.id]){
|
||||
s.group[d.ke][d.id]={
|
||||
canvas:{},
|
||||
canvasContext:{},
|
||||
lastRegionImageData:{},
|
||||
blendRegion:{},
|
||||
blendRegionContext:{},
|
||||
}
|
||||
}
|
||||
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.group[d.ke][d.id].buffer=Buffer.concat(s.group[d.ke][d.id].buffer);
|
||||
try{
|
||||
d.mon.detector_cascades=JSON.parse(d.mon.detector_cascades)
|
||||
}catch(err){
|
||||
|
||||
}
|
||||
if(d.mon.detector_frame_save==="1"){
|
||||
d.base64=s.group[d.ke][d.id].buffer.toString('base64')
|
||||
}
|
||||
if(d.mon.detector_second==='1'&&d.objectOnly===true){
|
||||
s.detectObject(s.group[d.ke][d.id].buffer,d,tx)
|
||||
}else{
|
||||
if((d.mon.detector_pam !== '1' && d.mon.detector_use_motion === "1") || d.mon.detector_use_detect_object !== "1"){
|
||||
if((typeof d.mon.cords ==='string')&&d.mon.cords.trim()===''){
|
||||
d.mon.cords=[]
|
||||
}else{
|
||||
try{
|
||||
d.mon.cords=JSON.parse(d.mon.cords)
|
||||
}catch(err){
|
||||
// console.log('d.mon.cords',err,d)
|
||||
}
|
||||
}
|
||||
s.group[d.ke][d.id].cords=Object.values(d.mon.cords);
|
||||
d.mon.cords=d.mon.cords;
|
||||
d.image = new Canvas.Image;
|
||||
if(d.mon.detector_scale_x===''||d.mon.detector_scale_y===''){
|
||||
s.systemLog('Must set detector image size')
|
||||
return
|
||||
}else{
|
||||
d.image.width=d.mon.detector_scale_x;
|
||||
d.image.height=d.mon.detector_scale_y;
|
||||
}
|
||||
d.width=d.image.width;
|
||||
d.height=d.image.height;
|
||||
d.image.onload = function() {
|
||||
s.checkAreas(d,tx);
|
||||
}
|
||||
d.image.src = s.group[d.ke][d.id].buffer;
|
||||
}else{
|
||||
s.detectObject(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('<b>'+config.plug+'</b> 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 = require('socket.io-client')('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)
|
||||
})
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -65,11 +65,13 @@ nav h4{cursor:default;font-size:95%;padding:16px 40px;font-weight:100;text-trans
|
|||
.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;}
|
||||
|
|
@ -90,9 +92,9 @@ img{max-width:100%}
|
|||
.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}
|
||||
/*.monitor_item .data-menu{max-height:700px}*/
|
||||
.monitor_item .data-menu:not(:last-child){border-right:1px solid #fff;}
|
||||
.monitor_item .data-menu.logs{list-style:none;}
|
||||
/*.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;right:0}
|
||||
|
|
@ -713,4 +715,10 @@ ul.msg_list li .message {
|
|||
|
||||
.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");
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
|
|
@ -12,15 +12,26 @@ $.ccio={
|
|||
fr:$('#files_recent'),
|
||||
mon:{}
|
||||
};
|
||||
<% if(config.useUTC){ %>
|
||||
$.ccio.timeObject = function(date){
|
||||
return moment.utc(date).local()
|
||||
$.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('<a></a>')
|
||||
.find('a')
|
||||
.attr('href',dataStr)
|
||||
.attr('download',filename)
|
||||
[0].click()
|
||||
}
|
||||
<% }else{ %>
|
||||
$.ccio.timeObject = function(date){
|
||||
return moment(date)
|
||||
$.ccio.timeObject = function(time,isUTC){
|
||||
if(isUTC === true){
|
||||
return moment(time).utc()
|
||||
}
|
||||
return moment(time)
|
||||
}
|
||||
<% } %>
|
||||
if(!$user.details.lang||$user.details.lang==''){
|
||||
$user.details.lang="<%-config.language%>"
|
||||
}
|
||||
|
|
@ -158,10 +169,40 @@ switch($user.details.lang){
|
|||
url=url+'/'
|
||||
}
|
||||
}else{
|
||||
url=''
|
||||
url = ''
|
||||
}
|
||||
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;
|
||||
|
|
@ -369,6 +410,7 @@ switch($user.details.lang){
|
|||
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;
|
||||
|
|
@ -463,6 +505,19 @@ switch($user.details.lang){
|
|||
})
|
||||
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);
|
||||
|
|
@ -492,15 +547,6 @@ switch($user.details.lang){
|
|||
$.ccio.init('jpegMode',v,user)
|
||||
});
|
||||
break;
|
||||
case'dragWindows':
|
||||
console.log('Deprecated : dragWindows')
|
||||
// k.e=$("#monitors_live");
|
||||
// if(k.e.disableSelection){k.e.disableSelection()};
|
||||
// k.e.sortable({
|
||||
// handle: ".mdl-card__supporting-text",
|
||||
// placeholder: "ui-state-highlight col-md-6"
|
||||
// });
|
||||
break;
|
||||
case'getLocation':
|
||||
var l = document.createElement("a");
|
||||
l.href = d;
|
||||
|
|
@ -834,25 +880,18 @@ switch($user.details.lang){
|
|||
if(d.id&&!d.mid){d.mid=d.id;}
|
||||
switch(x){
|
||||
case 0://video
|
||||
var href
|
||||
if(d.href){
|
||||
href = d.href
|
||||
}else if(!d.href && d.hrefNoAuth){
|
||||
href = $.ccio.init('location',user)+user.auth_token+d.hrefNoAuth
|
||||
}
|
||||
if(user!==$user&&href.charAt(0)==='/'){
|
||||
href = $.ccio.init('location',user)+d.href.substring(1)
|
||||
}
|
||||
href = 'href="'+href+'"'
|
||||
if(!d.filename){d.filename=$.ccio.init('tf',d.time)+'.'+d.ext;}
|
||||
var url = $.ccio.init('videoUrlBuild',d)
|
||||
href = 'href="'+url+'"'
|
||||
// if(!d.filename){d.filename=$.ccio.init('tf',d.time)+'.'+d.ext;}
|
||||
d.dlname=d.mid+'-'+d.filename;
|
||||
d.mom=$.ccio.timeObject(d.time),
|
||||
d.hr=parseInt(d.mom.format('HH')),
|
||||
d.startMoment=$.ccio.timeObject(d.time),
|
||||
d.endMoment=$.ccio.timeObject(d.end),
|
||||
d.hr=parseInt(d.startMoment.format('HH')),
|
||||
d.per=parseInt(d.hr/24*100);
|
||||
d.circle='<div title="at '+d.hr+' hours of '+d.mom.format('MMMM DD')+'" '+href+' video="launch" class="progress-circle progress-'+d.per+'"><span>'+d.hr+'</span></div>'
|
||||
tmp+='<li class="video-item glM'+d.mid+user.auth_token+'" auth="'+user.auth_token+'" mid="'+d.mid+'" ke="'+d.ke+'" status="'+d.status+'" status="'+d.status+'" file="'+d.filename+'">'+d.circle+'<div><span title="'+d.end+'" class="livestamp"></span></div><div><div class="small"><b><%-cleanLang(lang.Start)%></b> : '+$.ccio.timeObject(d.time).format('h:mm:ss , MMMM Do YYYY')+'</div><div class="small"><b><%-cleanLang(lang.End)%></b> : '+$.ccio.timeObject(d.end).format('h:mm:ss , MMMM Do YYYY')+'</div></div><div><span class="pull-right">'+(parseInt(d.size)/1000000).toFixed(2)+'mb</span><div class="controls btn-group"><a class="btn btn-sm btn-primary" video="launch" '+href+'><i class="fa fa-play-circle"></i></a> <a download="'+d.dlname+'" '+href+' class="btn btn-sm btn-default"><i class="fa fa-download"></i></a>'
|
||||
d.circle='<div title="at '+d.hr+' hours of '+d.startMoment.format('MMMM DD')+'" '+href+' video="launch" class="progress-circle progress-'+d.per+'"><span>'+d.hr+'</span></div>'
|
||||
tmp+='<li class="video-item glM'+d.mid+user.auth_token+'" auth="'+user.auth_token+'" mid="'+d.mid+'" ke="'+d.ke+'" status="'+d.status+'" status="'+d.status+'" file="'+d.filename+'">'+d.circle+'<div><span title="'+d.endMoment.format()+'" class="livestamp"></span></div><div><div class="small"><b><%-cleanLang(lang.Start)%></b> : '+d.startMoment.format('h:mm:ss , MMMM Do YYYY')+'</div><div class="small"><b><%-cleanLang(lang.End)%></b> : '+d.endMoment.format('h:mm:ss , MMMM Do YYYY')+'</div></div><div><span class="pull-right">'+(parseInt(d.size)/1000000).toFixed(2)+'mb</span><div class="controls btn-group"><a class="btn btn-sm btn-primary" video="launch" '+href+'><i class="fa fa-play-circle"></i></a> <a download="'+d.dlname+'" '+href+' class="btn btn-sm btn-default"><i class="fa fa-download"></i></a>'
|
||||
<% if(config.DropboxAppKey){ %> tmp+='<a video="download" host="dropbox" download="'+d.dlname+'" '+href+' class="btn btn-sm btn-default"><i class="fa fa-dropbox"></i></a>' <% } %>
|
||||
tmp+='<a title="<%-cleanLang(lang['Delete Video'])%>" video="delete" class="btn btn-sm btn-danger permission_video_delete"><i class="fa fa-trash"></i></a></div></div></li>';
|
||||
tmp+='<a title="<%-cleanLang(lang['Delete Video'])%>" video="delete" href="'+$.ccio.init('videoHrefToDelete',url)+'" class="btn btn-sm btn-danger permission_video_delete"><i class="fa fa-trash"></i></a></div></div></li>';
|
||||
$(z).each(function(n,v){
|
||||
v=$(v);
|
||||
if(v.find('.video-item').length>10){v.find('.video-item:last').remove()}
|
||||
|
|
@ -860,7 +899,7 @@ switch($user.details.lang){
|
|||
break;
|
||||
case 1://monitor icon
|
||||
d.src=placeholder.getData(placeholder.plcimg({bgcolor:'#b57d00',text:'...'}));
|
||||
tmp+='<div auth="'+user.auth_token+'" mid="'+d.mid+'" ke="'+d.ke+'" title="'+d.mid+' : '+d.name+'" class="monitor_block glM'+d.mid+user.auth_token+' col-md-4"><img monitor="watch" class="snapshot" src="'+d.src+'"><div class="box"><div class="title monitor_name truncate">'+d.name+'</div><div class="list-data"><div class="monitor_mid">'+d.mid+'</div><div><b><%-cleanLang(lang['Save as'])%> :</b> <span class="monitor_ext">'+d.ext+'</span></div><div><b>Mode :</b> <span class="monitor_mode">'+d.mode+'</span></div></div><div class="icons text-center"><div class="btn-group"><a class="btn btn-xs btn-default permission_monitor_edit" monitor="edit"><i class="fa fa-wrench"></i></a> <a monitor="videos_table" class="btn btn-xs btn-default"><i class="fa fa-film"></i></a> <a monitor="pop" class="btn btn-xs btn-success"><i class="fa fa-external-link"></i></a></div></div></div></div>';
|
||||
tmp+='<div auth="'+user.auth_token+'" mid="'+d.mid+'" ke="'+d.ke+'" title="'+d.mid+' : '+d.name+'" class="monitor_block glM'+d.mid+user.auth_token+' col-md-4"><img monitor="watch" class="snapshot" src="'+d.src+'"><div class="box"><div class="title monitor_name truncate">'+d.name+'</div><div class="list-data"><div class="monitor_mid">'+d.mid+'</div><div><b><%-cleanLang(lang['Save as'])%> :</b> <span class="monitor_ext">'+d.ext+'</span></div><div><b>Status :</b> <span class="monitor_status">'+d.status+'</span></div></div><div class="icons text-center"><div class="btn-group"><a class="btn btn-xs btn-default permission_monitor_edit" monitor="edit"><i class="fa fa-wrench"></i></a> <a monitor="videos_table" class="btn btn-xs btn-default"><i class="fa fa-film"></i></a> <a monitor="pop" class="btn btn-xs btn-success"><i class="fa fa-external-link"></i></a></div></div></div></div>';
|
||||
delete(d.src);
|
||||
break;
|
||||
case 2://monitor stream
|
||||
|
|
@ -876,7 +915,7 @@ switch($user.details.lang){
|
|||
],function(n,v){
|
||||
tmp+='<div>'+v.label+' : <span class="'+v.tag+'"></span></div>'
|
||||
})
|
||||
tmp+='</div></div></div></div>';
|
||||
tmp+='</div></div></div></div>'
|
||||
tmp+='<div class="mdl-card__supporting-text text-center">';
|
||||
tmp+='<div class="indifference detector-fade"><div class="progress"><div class="progress-bar progress-bar-danger" role="progressbar"><span></span></div></div></div>';
|
||||
tmp+='<div class="monitor_details">';
|
||||
|
|
@ -1597,7 +1636,11 @@ $.ccio.globalWebsocket=function(d,user){
|
|||
}
|
||||
switch(d.f){
|
||||
case'note':
|
||||
$.ccio.init('note',d.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+'"]')
|
||||
|
|
@ -1705,7 +1748,8 @@ $.ccio.globalWebsocket=function(d,user){
|
|||
$.ccio.pm(0,d,null,user)
|
||||
break;
|
||||
case'log':
|
||||
$.ccio.tm(4,d,'#logs,.monitor_item[mid="'+d.mid+'"][ke="'+d.ke+'"][auth="'+user.auth_token+'"] .logs',user)
|
||||
var attr = '[mid="'+d.mid+'"][ke="'+d.ke+'"][auth="'+user.auth_token+'"]'
|
||||
$.ccio.tm(4,d,'#logs,'+attr+'.monitor_item .logs:visible,'+attr+'#add_monitor:visible .logs',user)
|
||||
break;
|
||||
case'os'://indicator
|
||||
//cpu
|
||||
|
|
@ -1741,8 +1785,10 @@ $.ccio.globalWebsocket=function(d,user){
|
|||
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+'"]');
|
||||
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')}
|
||||
|
|
@ -1794,8 +1840,9 @@ $.ccio.globalWebsocket=function(d,user){
|
|||
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);
|
||||
if($.ccio.mon[d.ke+d.id+user.auth_token]){
|
||||
$.ccio.init('jpegModeStop',{mid:d.id,ke:d.ke});
|
||||
$.ccio.init('clearTimers',d)
|
||||
$.ccio.init('closeVideo',{mid:d.id,ke:d.ke},user);
|
||||
$.ccio.init('jpegModeStop',{mid:d.id,ke:d.ke},user);
|
||||
$.ccio.init('clearTimers',d,user)
|
||||
clearInterval($.ccio.mon[d.ke+d.id+user.auth_token].signal);delete($.ccio.mon[d.ke+d.id+user.auth_token].signal);
|
||||
$.ccio.mon[d.ke+d.id+user.auth_token].watch=0;
|
||||
if($.ccio.mon[d.ke+d.id+user.auth_token].hls){$.ccio.mon[d.ke+d.id+user.auth_token].hls.destroy()}
|
||||
|
|
@ -1817,9 +1864,11 @@ $.ccio.globalWebsocket=function(d,user){
|
|||
d.e=$('#monitor_live_'+d.id+user.auth_token);
|
||||
d.e.find('.stream-detected-object').remove()
|
||||
$.ccio.init('clearTimers',d)
|
||||
if(d.e.length==0){
|
||||
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);
|
||||
$.ccio.init('dragWindows')
|
||||
}
|
||||
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);
|
||||
|
|
@ -1903,30 +1952,35 @@ $.ccio.globalWebsocket=function(d,user){
|
|||
})
|
||||
break;
|
||||
case'mp4':
|
||||
var stream = d.e.find('.stream-element');
|
||||
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.destroy()
|
||||
setTimeout(function(){
|
||||
var stream = d.e.find('.stream-element');
|
||||
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.destroy()
|
||||
}
|
||||
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: url
|
||||
});
|
||||
$.ccio.mon[d.ke+d.id+user.auth_token].Poseidon.start();
|
||||
}catch(err){
|
||||
setTimeout(function(){
|
||||
$.ccio.cx({f:'monitor',ff:'watch_on',id:d.id},user)
|
||||
},5000)
|
||||
console.log(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)
|
||||
}
|
||||
}
|
||||
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: url
|
||||
});
|
||||
$.ccio.mon[d.ke+d.id+user.auth_token].Poseidon.start();
|
||||
}catch(err){
|
||||
setTimeout(function(){
|
||||
$.ccio.cx({f:'monitor',ff:'watch_on',id:d.id},user)
|
||||
},3000)
|
||||
console.log(err)
|
||||
}
|
||||
}else{
|
||||
stream.attr('src',$.ccio.init('location',user)+user.auth_token+'/mp4/'+d.ke+'/'+d.id+'/s.mp4')
|
||||
}
|
||||
},2000)
|
||||
break;
|
||||
case'flv':
|
||||
if (flvjs.isSupported()) {
|
||||
|
|
@ -2153,7 +2207,7 @@ $.ccio.globalWebsocket=function(d,user){
|
|||
$.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;
|
||||
// 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]={
|
||||
|
|
@ -2801,27 +2855,67 @@ $.pB.e.find('.stop').click(function(e){
|
|||
// $.ccio.cx({f:'ffprobe',ff:'stop'})
|
||||
});
|
||||
//log viewer
|
||||
$.log={e:$('#logs_modal'),lm:$('#log_monitors')};$.log.o=$.log.e.find('table tbody');
|
||||
$.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,
|
||||
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;
|
||||
v.id = v.mid
|
||||
$.ccio.tm('option',v,'#log_monitors')
|
||||
})
|
||||
$.log.lm.change()
|
||||
});
|
||||
$.log.lm.change(function(e){
|
||||
e.v=$(this).val();
|
||||
if(e.v==='all'){e.v=''}
|
||||
$.get($.ccio.init('location',$user)+$user.auth_token+'/logs/'+$user.ke+'/'+e.v,function(d){
|
||||
})
|
||||
$.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='';
|
||||
$.each(d,function(n,v){
|
||||
e.tmp+='<tr class="search-row"><td title="'+v.time+'" class="livestamp"></td><td>'+v.time+'</td><td>'+v.name+'</td><td>'+v.mid+'</td><td>'+$.ccio.init('jsontoblock',v.info)+'</td></tr>'
|
||||
})
|
||||
$.log.o.html(e.tmp)
|
||||
if(d.length === 0){
|
||||
e.tmp = '<tr class="text-center"><td><%-cleanLang(lang.NoLogsFoundForDateRange)%></td></tr>'
|
||||
}else{
|
||||
$.each(d,function(n,v){
|
||||
e.tmp+='<tr class="search-row"><td title="'+v.time+'" class="livestamp"></td><td>'+v.time+'</td><td>'+v.mid+'</td><td>'+$.ccio.init('jsontoblock',v.info)+'</td></tr>'
|
||||
})
|
||||
}
|
||||
$.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.',
|
||||
})
|
||||
})
|
||||
//multi monitor manager
|
||||
$.multimon={e:$('#multi_mon')};
|
||||
$.multimon.table=$.multimon.e.find('.tableData tbody');
|
||||
|
|
@ -2988,7 +3082,7 @@ $.multimon.e.on('shown.bs.modal',function() {
|
|||
var img = $('#left_menu [mid="'+v.mid+'"][auth="'+v.user.auth_token+'"] [monitor="watch"]').attr('src')
|
||||
tmp+='<tr mid="'+v.mid+'" ke="'+v.ke+'" auth="'+v.user.auth_token+'">'
|
||||
tmp+='<td><div class="checkbox"><input id="multimonCheck_'+v.ke+v.mid+v.user.auth_token+'" type="checkbox" name="'+v.ke+v.mid+v.user.auth_token+'" value="1"><label for="multimonCheck_'+v.ke+v.mid+v.user.auth_token+'"></label></div></td>'
|
||||
tmp+='<td><a monitor="watch"><img class="small-square-img" src="'+img+'"></a></td><td>'+v.name+'<br><small>'+v.mid+'</small></td><td class="monitor_mode">'+$.ccio.init('humanReadMode',v.mode)+'</td><td>'+streamURL+'</td>'
|
||||
tmp+='<td><a monitor="watch"><img class="small-square-img" src="'+img+'"></a></td><td>'+v.name+'<br><small>'+v.mid+'</small></td><td class="monitor_status">'+v.status+'</td><td>'+streamURL+'</td>'
|
||||
//buttons
|
||||
tmp+='<td class="text-right"><a title="<%-cleanLang(lang.Pop)%>" monitor="pop" class="btn btn-primary"><i class="fa fa-external-link"></i></a> <a title="<%-cleanLang(lang.Calendar)%>" monitor="calendar" class="btn btn-default"><i class="fa fa-calendar"></i></a> <a title="<%-cleanLang(lang['Power Viewer'])%>" class="btn btn-default" monitor="powerview"><i class="fa fa-map-marker"></i></a> <a title="<%-cleanLang(lang['Time-lapse'])%>" class="btn btn-default" monitor="timelapse"><i class="fa fa-angle-double-right"></i></a> <a title="<%-cleanLang(lang['Videos List'])%>" monitor="videos_table" class="btn btn-default"><i class="fa fa-film"></i></a> <a title="<%-cleanLang(lang['Monitor Settings'])%>" class="btn btn-default permission_monitor_edit" monitor="edit"><i class="fa fa-wrench"></i></a></td>'
|
||||
tmp+='</tr>'
|
||||
|
|
@ -4062,7 +4156,7 @@ $.timelapse.drawTimeline=function(getData){
|
|||
e.tmp=''
|
||||
$.each(videos.videos,function(n,v){
|
||||
if(!v||!v.time){return}
|
||||
v.filename=$.ccio.init('tf',v.time)+'.'+v.ext;
|
||||
// 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)==='/'){
|
||||
|
|
@ -4075,7 +4169,7 @@ $.timelapse.drawTimeline=function(getData){
|
|||
e.tmp+='<div class="flex-block">'
|
||||
e.tmp+='<div class="flex-unit-3"><div class="frame" style="background-image:url('+$.timelapse.placeholder+')"></div></div>'
|
||||
e.tmp+='<div class="flex-unit-3"><div><span title="'+v.time+'" class="livestamp"></span></div><div>'+v.filename+'</div></div>'
|
||||
e.tmp+='<div class="flex-unit-3 text-right"><a class="btn btn-default" download="'+v.mid+'-'+v.filename+'" href="'+v.href+'"> <i class="fa fa-download"></i> </a> <a class="btn btn-danger" video="delete"> <i class="fa fa-trash-o"></i> </a></div>'
|
||||
e.tmp+='<div class="flex-unit-3 text-right"><a class="btn btn-default" download="'+v.mid+'-'+v.filename+'" href="'+v.href+'"> <i class="fa fa-download"></i> </a> <a class="btn btn-danger" video="delete" href="'+$.ccio.init('videoHrefToDelete',v.href)+'"> <i class="fa fa-trash-o"></i> </a></div>'
|
||||
e.tmp+='</div>'
|
||||
e.tmp+='<div class="flex-block">'
|
||||
e.tmp+='<div class="flex-unit-3"><div class="progress"><div class="progress-bar progress-bar-primary" role="progressbar" style="width:0%"></div></div></div>'
|
||||
|
|
@ -4449,7 +4543,8 @@ $.pwrvid.e.on('click','[preview]',function(e){
|
|||
$.pwrvid.vp.find('.stream-objects .stream-detected-object').remove()
|
||||
})
|
||||
if(e.status==1){
|
||||
$.get(e.href.split('?')[0]+'/status/2',function(d){
|
||||
$.get($.ccio.init('videoHrefToRead',e.href),function(d){
|
||||
|
||||
})
|
||||
}
|
||||
var labels=[]
|
||||
|
|
@ -4778,22 +4873,28 @@ $('body')
|
|||
.attr('auth',e.auth)
|
||||
.attr('file',e.file);
|
||||
if(e.status==1){
|
||||
$.get(e.href.split('?')[0]+'/status/2',function(d){
|
||||
$.get($.ccio.init('videoHrefToRead',e.href),function(d){
|
||||
if(d.ok !== true)console.log(d,new Error())
|
||||
})
|
||||
}
|
||||
break;
|
||||
case'delete':
|
||||
e.href=e.p.find('[download]').attr('href')
|
||||
if(!e.href||e.href===''){
|
||||
e.href=e.p.attr('href')
|
||||
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('<%-cleanLang(lang['Delete Video'])%> : '+e.file)
|
||||
e.html='<%-cleanLang(lang.DeleteVideoMsg)%>'
|
||||
e.html+='<video class="video_video" autoplay loop controls><source src="'+e.href+'" type="video/'+e.mon.ext+'"></video>';
|
||||
e.html+='<video class="video_video" autoplay loop controls><source src="'+videoLink+'" type="video/'+e.mon.ext+'"></video>';
|
||||
$.confirm.body.html(e.html)
|
||||
$.confirm.click({title:'Delete Video',class:'btn-danger'},function(){
|
||||
$.getJSON($.ccio.init('location',$.users[e.auth])+e.auth+'/videos/'+e.ke+'/'+e.mid+'/'+e.file+'/delete',function(d){
|
||||
$.getJSON(href,function(d){
|
||||
$.ccio.log(d)
|
||||
})
|
||||
});
|
||||
|
|
@ -5072,7 +5173,7 @@ $('body')
|
|||
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;
|
||||
// v.filename=$.ccio.init('tf',v.time)+'.'+v.ext;
|
||||
e.ar.push(v);
|
||||
}
|
||||
})
|
||||
|
|
@ -5089,7 +5190,7 @@ $('body')
|
|||
eventLimit: true,
|
||||
events:e.ar,
|
||||
eventClick:function(f){
|
||||
$('#temp').html('<div mid="'+f.mid+'" ke="'+f.ke+'" auth="'+user.auth_token+'" file="'+f.filename+'"><div video="launch" href="'+f.href+'"></div></div>').find('[video="launch"]').click();
|
||||
$('#temp').html('<div mid="'+f.mid+'" ke="'+f.ke+'" auth="'+user.auth_token+'" file="'+f.filename+'"><div video="launch" href="'+$.ccio.init('videoUrlBuild',f)+'"></div></div>').find('[video="launch"]').click();
|
||||
$(this).css('border-color', 'red');
|
||||
}
|
||||
});
|
||||
|
|
@ -5120,10 +5221,10 @@ $('body')
|
|||
e.tmp+='<tbody>';
|
||||
$.each(d.videos,function(n,v){
|
||||
if(v.status!==0){
|
||||
var href = $.ccio.init('location',user)+v.href
|
||||
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;
|
||||
// v.filename=$.ccio.init('tf',v.time)+'.'+v.ext;
|
||||
e.tmp+='<tr data-ke="'+v.ke+'" data-status="'+v.status+'" data-mid="'+v.mid+'" data-file="'+v.filename+'" data-auth="'+v.mon.user.auth_token+'">';
|
||||
e.tmp+='<td><div class="checkbox"><input id="'+v.ke+'_'+v.filename+'" name="'+v.filename+'" value="'+v.mid+'" type="checkbox"><label for="'+v.ke+'_'+v.filename+'"></label></div></td>';
|
||||
e.tmp+='<td><span class="livestamp" title="'+v.end+'"></span></td>';
|
||||
|
|
@ -5135,7 +5236,7 @@ $('body')
|
|||
e.tmp+='<td><a class="btn btn-sm btn-default preview" href="'+href+'"> <i class="fa fa-play-circle"></i> </a></td>';
|
||||
e.tmp+='<td><a class="btn btn-sm btn-primary" video="launch" href="'+href+'"> <i class="fa fa-play-circle"></i> </a></td>';
|
||||
e.tmp+='<td><a class="btn btn-sm btn-success" download="'+v.mid+'-'+v.filename+'" href="'+href+'"> <i class="fa fa-download"></i> </a></td>';
|
||||
e.tmp+='<td class="permission_video_delete"><a class="btn btn-sm btn-danger" video="delete"> <i class="fa fa-trash"></i> </a></td>';
|
||||
e.tmp+='<td class="permission_video_delete"><a class="btn btn-sm btn-danger" video="delete" href="'+$.ccio.init('videoHrefToDelete',href)+'"> <i class="fa fa-trash"></i> </a></td>';
|
||||
// e.tmp+='<td class="permission_video_delete"><a class="btn btn-sm btn-warning" video="fix"> <i class="fa fa-wrench"></i> </a></td>';
|
||||
e.tmp+='</tr>';
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,220 @@
|
|||
/*!
|
||||
|
||||
=========================================================
|
||||
* Now-ui-kit - v1.1.0
|
||||
=========================================================
|
||||
|
||||
* Product Page: https://www.creative-tim.com/product/now-ui-kit
|
||||
* Copyright 2017 Creative Tim (http://www.creative-tim.com)
|
||||
* Licensed under MIT (https://github.com/creativetimofficial/now-ui-kit/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.
|
||||
|
||||
*/
|
||||
|
||||
var transparent = true;
|
||||
|
||||
var transparentDemo = true;
|
||||
var fixedTop = false;
|
||||
|
||||
var navbar_initialized,
|
||||
backgroundOrange = false,
|
||||
toggle_initialized = false;
|
||||
|
||||
$(document).ready(function() {
|
||||
try{
|
||||
// Activate the Tooltips
|
||||
$('[data-toggle="tooltip"], [rel="tooltip"]').tooltip();
|
||||
|
||||
// Activate Popovers and set color for popovers
|
||||
$('[data-toggle="popover"]').each(function() {
|
||||
color_class = $(this).data('color');
|
||||
$(this).popover({
|
||||
template: '<div class="popover popover-' + color_class + '" role="tooltip"><div class="arrow"></div><h3 class="popover-header"></h3><div class="popover-body"></div></div>'
|
||||
});
|
||||
});
|
||||
}catch(err){
|
||||
|
||||
}
|
||||
|
||||
// Activate the image for the navbar-collapse
|
||||
nowuiKit.initNavbarImage();
|
||||
|
||||
$navbar = $('.navbar[color-on-scroll]');
|
||||
scroll_distance = $navbar.attr('color-on-scroll') || 500;
|
||||
|
||||
// Check if we have the class "navbar-color-on-scroll" then add the function to remove the class "navbar-transparent" so it will transform to a plain color.
|
||||
|
||||
// if ($('.navbar[color-on-scroll]').length != 0) {
|
||||
// nowuiKit.checkScrollForTransparentNavbar();
|
||||
// $(window).on('scroll', nowuiKit.checkScrollForTransparentNavbar)
|
||||
// }
|
||||
|
||||
$('.form-control').on("focus", function() {
|
||||
$(this).parent('.input-group').addClass("input-group-focus");
|
||||
}).on("blur", function() {
|
||||
$(this).parent(".input-group").removeClass("input-group-focus");
|
||||
});
|
||||
|
||||
// Activate bootstrapSwitch
|
||||
$('.bootstrap-switch').each(function() {
|
||||
$this = $(this);
|
||||
data_on_label = $this.data('on-label') || '';
|
||||
data_off_label = $this.data('off-label') || '';
|
||||
|
||||
$this.bootstrapSwitch({
|
||||
onText: data_on_label,
|
||||
offText: data_off_label
|
||||
});
|
||||
});
|
||||
|
||||
if ($(window).width() >= 992) {
|
||||
big_image = $('.page-header-image[data-parallax="true"]');
|
||||
|
||||
$(window).on('scroll', nowuiKitDemo.checkScrollForParallax);
|
||||
}
|
||||
|
||||
// Activate Carousel
|
||||
$('.carousel').carousel({
|
||||
interval: 4000
|
||||
});
|
||||
|
||||
$('.date-picker').each(function() {
|
||||
$(this).datepicker({
|
||||
templates: {
|
||||
leftArrow: '<i class="now-ui-icons arrows-1_minimal-left"></i>',
|
||||
rightArrow: '<i class="now-ui-icons arrows-1_minimal-right"></i>'
|
||||
}
|
||||
}).on('show', function() {
|
||||
$('.datepicker').addClass('open');
|
||||
|
||||
datepicker_color = $(this).data('datepicker-color');
|
||||
if (datepicker_color.length != 0) {
|
||||
$('.datepicker').addClass('datepicker-' + datepicker_color + '');
|
||||
}
|
||||
}).on('hide', function() {
|
||||
$('.datepicker').removeClass('open');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
|
||||
$(window).on('resize', function() {
|
||||
nowuiKit.initNavbarImage();
|
||||
});
|
||||
|
||||
$(document).on('click', '.navbar-toggler', function() {
|
||||
$toggle = $(this);
|
||||
|
||||
if (nowuiKit.misc.navbar_menu_visible == 1) {
|
||||
$('html').removeClass('nav-open');
|
||||
nowuiKit.misc.navbar_menu_visible = 0;
|
||||
$('#bodyClick').remove();
|
||||
setTimeout(function() {
|
||||
$toggle.removeClass('toggled');
|
||||
}, 550);
|
||||
} else {
|
||||
setTimeout(function() {
|
||||
$toggle.addClass('toggled');
|
||||
}, 580);
|
||||
div = '<div id="bodyClick"></div>';
|
||||
$(div).appendTo('body').click(function() {
|
||||
$('html').removeClass('nav-open');
|
||||
nowuiKit.misc.navbar_menu_visible = 0;
|
||||
setTimeout(function() {
|
||||
$toggle.removeClass('toggled');
|
||||
$('#bodyClick').remove();
|
||||
}, 550);
|
||||
});
|
||||
|
||||
$('html').addClass('nav-open');
|
||||
nowuiKit.misc.navbar_menu_visible = 1;
|
||||
}
|
||||
});
|
||||
|
||||
nowuiKit = {
|
||||
misc: {
|
||||
navbar_menu_visible: 0
|
||||
},
|
||||
|
||||
checkScrollForTransparentNavbar: debounce(function() {
|
||||
if ($(document).scrollTop() > scroll_distance) {
|
||||
if (transparent) {
|
||||
transparent = false;
|
||||
$('.navbar[color-on-scroll]').removeClass('navbar-transparent');
|
||||
}
|
||||
} else {
|
||||
if (!transparent) {
|
||||
transparent = true;
|
||||
$('.navbar[color-on-scroll]').addClass('navbar-transparent');
|
||||
}
|
||||
}
|
||||
}, 17),
|
||||
|
||||
initNavbarImage: function() {
|
||||
var $navbar = $('.navbar').find('.navbar-translate').siblings('.navbar-collapse');
|
||||
var background_image = $navbar.data('nav-image');
|
||||
|
||||
if ($(window).width() < 991 || $('body').hasClass('burger-menu')) {
|
||||
if (background_image != undefined) {
|
||||
$navbar.css('background', "url('" + background_image + "')")
|
||||
.removeAttr('data-nav-image')
|
||||
.css('background-size', "cover")
|
||||
.addClass('has-image');
|
||||
}
|
||||
} else if (background_image != undefined) {
|
||||
$navbar.css('background', "")
|
||||
.attr('data-nav-image', '' + background_image + '')
|
||||
.css('background-size', "")
|
||||
.removeClass('has-image');
|
||||
}
|
||||
},
|
||||
|
||||
initSliders: function() {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var big_image;
|
||||
|
||||
// Javascript just for Demo purpose, remove it from your project
|
||||
nowuiKitDemo = {
|
||||
checkScrollForParallax: debounce(function() {
|
||||
var current_scroll = $(this).scrollTop();
|
||||
|
||||
oVal = ($(window).scrollTop() / 3);
|
||||
big_image.css({
|
||||
'transform': 'translate3d(0,' + oVal + 'px,0)',
|
||||
'-webkit-transform': 'translate3d(0,' + oVal + 'px,0)',
|
||||
'-ms-transform': 'translate3d(0,' + oVal + 'px,0)',
|
||||
'-o-transform': 'translate3d(0,' + oVal + 'px,0)'
|
||||
});
|
||||
|
||||
}, 6)
|
||||
|
||||
}
|
||||
|
||||
// Returns a function, that, as long as it continues to be invoked, will not
|
||||
// be triggered. The function will be called after it stops being called for
|
||||
// N milliseconds. If `immediate` is passed, trigger the function on the
|
||||
// leading edge, instead of the trailing.
|
||||
|
||||
function debounce(func, wait, immediate) {
|
||||
var timeout;
|
||||
return function() {
|
||||
var context = this,
|
||||
args = arguments;
|
||||
clearTimeout(timeout);
|
||||
timeout = setTimeout(function() {
|
||||
timeout = null;
|
||||
if (!immediate) func.apply(context, args);
|
||||
}, wait);
|
||||
if (immediate && !timeout) func.apply(context, args);
|
||||
};
|
||||
};
|
||||
|
|
@ -0,0 +1,834 @@
|
|||
/*
|
||||
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 < arguments.length && void 0 !== arguments[1] ? arguments[1] : 'top',
|
||||
o = 'top' === t ? 'scrollTop' : 'scrollLeft',
|
||||
i = e.nodeName;
|
||||
if ('BODY' === i || 'HTML' === i) {
|
||||
var n = window.document.documentElement,
|
||||
r = window.document.scrollingElement || n;
|
||||
return r[o]
|
||||
}
|
||||
return e[o]
|
||||
}
|
||||
|
||||
function f(e, t) {
|
||||
var o = 2 < arguments.length && void 0 !== arguments[2] && arguments[2],
|
||||
i = a(t, 'top'),
|
||||
n = a(t, 'left'),
|
||||
r = o ? -1 : 1;
|
||||
return e.top += i * r, e.bottom += i * r, e.left += n * r, e.right += n * r, e
|
||||
}
|
||||
|
||||
function l(e, t) {
|
||||
var o = 'x' === t ? 'Left' : 'Top',
|
||||
i = 'Left' == o ? 'Right' : 'Bottom';
|
||||
return +e['border' + o + 'Width'].split('px')[0] + +e['border' + i + 'Width'].split('px')[0]
|
||||
}
|
||||
|
||||
function m(e, t, o, i) {
|
||||
return _(t['offset' + e], o['client' + e], o['offset' + e], ie() ? o['offset' + e] + i['margin' + ('Height' === e ? 'Top' : 'Left')] + i['margin' + ('Height' === e ? 'Bottom' : 'Right')] : 0)
|
||||
}
|
||||
|
||||
function h() {
|
||||
var e = window.document.body,
|
||||
t = window.document.documentElement,
|
||||
o = ie() && window.getComputedStyle(t);
|
||||
return {
|
||||
height: m('Height', e, t, o),
|
||||
width: m('Width', e, t, o)
|
||||
}
|
||||
}
|
||||
|
||||
function c(e) {
|
||||
return se({}, e, {
|
||||
right: e.left + e.width,
|
||||
bottom: e.top + e.height
|
||||
})
|
||||
}
|
||||
|
||||
function g(e) {
|
||||
var o = {};
|
||||
if (ie()) try {
|
||||
o = e.getBoundingClientRect();
|
||||
var i = a(e, 'top'),
|
||||
n = a(e, 'left');
|
||||
o.top += i, o.left += n, o.bottom += i, o.right += n
|
||||
} catch (e) {} else o = e.getBoundingClientRect();
|
||||
var r = {
|
||||
left: o.left,
|
||||
top: o.top,
|
||||
width: o.right - o.left,
|
||||
height: o.bottom - o.top
|
||||
},
|
||||
p = 'HTML' === e.nodeName ? h() : {},
|
||||
s = p.width || e.clientWidth || r.right - r.left,
|
||||
d = p.height || e.clientHeight || r.bottom - r.top,
|
||||
f = e.offsetWidth - s,
|
||||
m = e.offsetHeight - d;
|
||||
if (f || m) {
|
||||
var g = t(e);
|
||||
f -= l(g, 'x'), m -= l(g, 'y'), r.width -= f, r.height -= m
|
||||
}
|
||||
return c(r)
|
||||
}
|
||||
|
||||
function u(e, o) {
|
||||
var i = ie(),
|
||||
r = 'HTML' === o.nodeName,
|
||||
p = g(e),
|
||||
s = g(o),
|
||||
d = n(e),
|
||||
a = t(o),
|
||||
l = +a.borderTopWidth.split('px')[0],
|
||||
m = +a.borderLeftWidth.split('px')[0],
|
||||
h = c({
|
||||
top: p.top - s.top - l,
|
||||
left: p.left - s.left - m,
|
||||
width: p.width,
|
||||
height: p.height
|
||||
});
|
||||
if (h.marginTop = 0, h.marginLeft = 0, !i && r) {
|
||||
var u = +a.marginTop.split('px')[0],
|
||||
b = +a.marginLeft.split('px')[0];
|
||||
h.top -= l - u, h.bottom -= l - u, h.left -= m - b, h.right -= m - b, h.marginTop = u, h.marginLeft = b
|
||||
}
|
||||
return (i ? o.contains(d) : o === d && 'BODY' !== d.nodeName) && (h = f(h, o)), h
|
||||
}
|
||||
|
||||
function b(e) {
|
||||
var t = window.document.documentElement,
|
||||
o = u(e, t),
|
||||
i = _(t.clientWidth, window.innerWidth || 0),
|
||||
n = _(t.clientHeight, window.innerHeight || 0),
|
||||
r = a(t),
|
||||
p = a(t, 'left'),
|
||||
s = {
|
||||
top: r - o.top + o.marginTop,
|
||||
left: p - o.left + o.marginLeft,
|
||||
width: i,
|
||||
height: n
|
||||
};
|
||||
return c(s)
|
||||
}
|
||||
|
||||
function y(e) {
|
||||
var i = e.nodeName;
|
||||
return 'BODY' === i || 'HTML' === i ? !1 : 'fixed' === t(e, 'position') || y(o(e))
|
||||
}
|
||||
|
||||
function w(e, t, i, r) {
|
||||
var p = {
|
||||
top: 0,
|
||||
left: 0
|
||||
},
|
||||
s = d(e, t);
|
||||
if ('viewport' === r) p = b(s);
|
||||
else {
|
||||
var a;
|
||||
'scrollParent' === r ? (a = n(o(e)), 'BODY' === a.nodeName && (a = window.document.documentElement)) : 'window' === r ? a = window.document.documentElement : a = r;
|
||||
var f = u(a, s);
|
||||
if ('HTML' === a.nodeName && !y(s)) {
|
||||
var l = h(),
|
||||
m = l.height,
|
||||
c = l.width;
|
||||
p.top += f.top - f.marginTop, p.bottom = m + f.top, p.left += f.left - f.marginLeft, p.right = c + f.left
|
||||
} else p = f
|
||||
}
|
||||
return p.left += i, p.top += i, p.right -= i, p.bottom -= i, p
|
||||
}
|
||||
|
||||
function v(e) {
|
||||
var t = e.width,
|
||||
o = e.height;
|
||||
return t * o
|
||||
}
|
||||
|
||||
function E(e, t, o, i, n) {
|
||||
var r = 5 < arguments.length && void 0 !== arguments[5] ? arguments[5] : 0;
|
||||
if (-1 === e.indexOf('auto')) return e;
|
||||
var p = w(o, i, r, n),
|
||||
s = {
|
||||
top: {
|
||||
width: p.width,
|
||||
height: t.top - p.top
|
||||
},
|
||||
right: {
|
||||
width: p.right - t.right,
|
||||
height: p.height
|
||||
},
|
||||
bottom: {
|
||||
width: p.width,
|
||||
height: p.bottom - t.bottom
|
||||
},
|
||||
left: {
|
||||
width: t.left - p.left,
|
||||
height: p.height
|
||||
}
|
||||
},
|
||||
d = Object.keys(s).map(function(e) {
|
||||
return se({
|
||||
key: e
|
||||
}, s[e], {
|
||||
area: v(s[e])
|
||||
})
|
||||
}).sort(function(e, t) {
|
||||
return t.area - e.area
|
||||
}),
|
||||
a = d.filter(function(e) {
|
||||
var t = e.width,
|
||||
i = e.height;
|
||||
return t >= o.clientWidth && i >= o.clientHeight
|
||||
}),
|
||||
f = 0 < a.length ? a[0].key : d[0].key,
|
||||
l = e.split('-')[1];
|
||||
return f + (l ? '-' + l : '')
|
||||
}
|
||||
|
||||
function x(e, t, o) {
|
||||
var i = d(t, o);
|
||||
return u(o, i)
|
||||
}
|
||||
|
||||
function O(e) {
|
||||
var t = window.getComputedStyle(e),
|
||||
o = parseFloat(t.marginTop) + parseFloat(t.marginBottom),
|
||||
i = parseFloat(t.marginLeft) + parseFloat(t.marginRight),
|
||||
n = {
|
||||
width: e.offsetWidth + i,
|
||||
height: e.offsetHeight + o
|
||||
};
|
||||
return n
|
||||
}
|
||||
|
||||
function L(e) {
|
||||
var t = {
|
||||
left: 'right',
|
||||
right: 'left',
|
||||
bottom: 'top',
|
||||
top: 'bottom'
|
||||
};
|
||||
return e.replace(/left|right|bottom|top/g, function(e) {
|
||||
return t[e]
|
||||
})
|
||||
}
|
||||
|
||||
function S(e, t, o) {
|
||||
o = o.split('-')[0];
|
||||
var i = O(e),
|
||||
n = {
|
||||
width: i.width,
|
||||
height: i.height
|
||||
},
|
||||
r = -1 !== ['right', 'left'].indexOf(o),
|
||||
p = r ? 'top' : 'left',
|
||||
s = r ? 'left' : 'top',
|
||||
d = r ? 'height' : 'width',
|
||||
a = r ? 'width' : 'height';
|
||||
return n[p] = t[p] + t[d] / 2 - i[d] / 2, n[s] = o === s ? t[s] - i[a] : t[L(s)], n
|
||||
}
|
||||
|
||||
function T(e, t) {
|
||||
return Array.prototype.find ? e.find(t) : e.filter(t)[0]
|
||||
}
|
||||
|
||||
function C(e, t, o) {
|
||||
if (Array.prototype.findIndex) return e.findIndex(function(e) {
|
||||
return e[t] === o
|
||||
});
|
||||
var i = T(e, function(e) {
|
||||
return e[t] === o
|
||||
});
|
||||
return e.indexOf(i)
|
||||
}
|
||||
|
||||
function N(t, o, i) {
|
||||
var n = void 0 === i ? t : t.slice(0, C(t, 'name', i));
|
||||
return n.forEach(function(t) {
|
||||
t.function && console.warn('`modifier.function` is deprecated, use `modifier.fn`!');
|
||||
var i = t.function || t.fn;
|
||||
t.enabled && e(i) && (o.offsets.popper = c(o.offsets.popper), o.offsets.reference = c(o.offsets.reference), o = i(o, t))
|
||||
}), o
|
||||
}
|
||||
|
||||
function k() {
|
||||
if (!this.state.isDestroyed) {
|
||||
var e = {
|
||||
instance: this,
|
||||
styles: {},
|
||||
attributes: {},
|
||||
flipped: !1,
|
||||
offsets: {}
|
||||
};
|
||||
e.offsets.reference = x(this.state, this.popper, this.reference), e.placement = E(this.options.placement, e.offsets.reference, this.popper, this.reference, this.options.modifiers.flip.boundariesElement, this.options.modifiers.flip.padding), e.originalPlacement = e.placement, e.offsets.popper = S(this.popper, e.offsets.reference, e.placement), e.offsets.popper.position = 'absolute', e = N(this.modifiers, e), this.state.isCreated ? this.options.onUpdate(e) : (this.state.isCreated = !0, this.options.onCreate(e))
|
||||
}
|
||||
}
|
||||
|
||||
function W(e, t) {
|
||||
return e.some(function(e) {
|
||||
var o = e.name,
|
||||
i = e.enabled;
|
||||
return i && o === t
|
||||
})
|
||||
}
|
||||
|
||||
function B(e) {
|
||||
for (var t = [!1, 'ms', 'Webkit', 'Moz', 'O'], o = e.charAt(0).toUpperCase() + e.slice(1), n = 0; n < t.length - 1; n++) {
|
||||
var i = t[n],
|
||||
r = i ? '' + i + o : e;
|
||||
if ('undefined' != typeof window.document.body.style[r]) return r
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
function D() {
|
||||
return this.state.isDestroyed = !0, W(this.modifiers, 'applyStyle') && (this.popper.removeAttribute('x-placement'), this.popper.style.left = '', this.popper.style.position = '', this.popper.style.top = '', this.popper.style[B('transform')] = ''), this.disableEventListeners(), this.options.removeOnDestroy && this.popper.parentNode.removeChild(this.popper), this
|
||||
}
|
||||
|
||||
function H(e, t, o, i) {
|
||||
var r = 'BODY' === e.nodeName,
|
||||
p = r ? window : e;
|
||||
p.addEventListener(t, o, {
|
||||
passive: !0
|
||||
}), r || H(n(p.parentNode), t, o, i), i.push(p)
|
||||
}
|
||||
|
||||
function P(e, t, o, i) {
|
||||
o.updateBound = i, window.addEventListener('resize', o.updateBound, {
|
||||
passive: !0
|
||||
});
|
||||
var r = n(e);
|
||||
return H(r, 'scroll', o.updateBound, o.scrollParents), o.scrollElement = r, o.eventsEnabled = !0, o
|
||||
}
|
||||
|
||||
function A() {
|
||||
this.state.eventsEnabled || (this.state = P(this.reference, this.options, this.state, this.scheduleUpdate))
|
||||
}
|
||||
|
||||
function M(e, t) {
|
||||
return window.removeEventListener('resize', t.updateBound), t.scrollParents.forEach(function(e) {
|
||||
e.removeEventListener('scroll', t.updateBound)
|
||||
}), t.updateBound = null, t.scrollParents = [], t.scrollElement = null, t.eventsEnabled = !1, t
|
||||
}
|
||||
|
||||
function I() {
|
||||
this.state.eventsEnabled && (window.cancelAnimationFrame(this.scheduleUpdate), this.state = M(this.reference, this.state))
|
||||
}
|
||||
|
||||
function R(e) {
|
||||
return '' !== e && !isNaN(parseFloat(e)) && isFinite(e)
|
||||
}
|
||||
|
||||
function U(e, t) {
|
||||
Object.keys(t).forEach(function(o) {
|
||||
var i = ''; - 1 !== ['width', 'height', 'top', 'right', 'bottom', 'left'].indexOf(o) && R(t[o]) && (i = 'px'), e.style[o] = t[o] + i
|
||||
})
|
||||
}
|
||||
|
||||
function Y(e, t) {
|
||||
Object.keys(t).forEach(function(o) {
|
||||
var i = t[o];
|
||||
!1 === i ? e.removeAttribute(o) : e.setAttribute(o, t[o])
|
||||
})
|
||||
}
|
||||
|
||||
function F(e, t, o) {
|
||||
var i = T(e, function(e) {
|
||||
var o = e.name;
|
||||
return o === t
|
||||
}),
|
||||
n = !!i && e.some(function(e) {
|
||||
return e.name === o && e.enabled && e.order < i.order
|
||||
});
|
||||
if (!n) {
|
||||
var r = '`' + t + '`';
|
||||
console.warn('`' + o + '`' + ' modifier is required by ' + r + ' modifier in order to work, be sure to include it before ' + r + '!')
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
function j(e) {
|
||||
return 'end' === e ? 'start' : 'start' === e ? 'end' : e
|
||||
}
|
||||
|
||||
function K(e) {
|
||||
var t = 1 < arguments.length && void 0 !== arguments[1] && arguments[1],
|
||||
o = ae.indexOf(e),
|
||||
i = ae.slice(o + 1).concat(ae.slice(0, o));
|
||||
return t ? i.reverse() : i
|
||||
}
|
||||
|
||||
function q(e, t, o, i) {
|
||||
var n = e.match(/((?:\-|\+)?\d*\.?\d*)(.*)/),
|
||||
r = +n[1],
|
||||
p = n[2];
|
||||
if (!r) return e;
|
||||
if (0 === p.indexOf('%')) {
|
||||
var s;
|
||||
switch (p) {
|
||||
case '%p':
|
||||
s = o;
|
||||
break;
|
||||
case '%':
|
||||
case '%r':
|
||||
default:
|
||||
s = i;
|
||||
}
|
||||
var d = c(s);
|
||||
return d[t] / 100 * r
|
||||
}
|
||||
if ('vh' === p || 'vw' === p) {
|
||||
var a;
|
||||
return a = 'vh' === p ? _(document.documentElement.clientHeight, window.innerHeight || 0) : _(document.documentElement.clientWidth, window.innerWidth || 0), a / 100 * r
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
function G(e, t, o, i) {
|
||||
var n = [0, 0],
|
||||
r = -1 !== ['right', 'left'].indexOf(i),
|
||||
p = e.split(/(\+|\-)/).map(function(e) {
|
||||
return e.trim()
|
||||
}),
|
||||
s = p.indexOf(T(p, function(e) {
|
||||
return -1 !== e.search(/,|\s/)
|
||||
}));
|
||||
p[s] && -1 === p[s].indexOf(',') && console.warn('Offsets separated by white space(s) are deprecated, use a comma (,) instead.');
|
||||
var d = /\s*,\s*|\s+/,
|
||||
a = -1 === s ? [p] : [p.slice(0, s).concat([p[s].split(d)[0]]), [p[s].split(d)[1]].concat(p.slice(s + 1))];
|
||||
return a = a.map(function(e, i) {
|
||||
var n = (1 === i ? !r : r) ? 'height' : 'width',
|
||||
p = !1;
|
||||
return e.reduce(function(e, t) {
|
||||
return '' === e[e.length - 1] && -1 !== ['+', '-'].indexOf(t) ? (e[e.length - 1] = t, p = !0, e) : p ? (e[e.length - 1] += t, p = !1, e) : e.concat(t)
|
||||
}, []).map(function(e) {
|
||||
return q(e, n, t, o)
|
||||
})
|
||||
}), a.forEach(function(e, t) {
|
||||
e.forEach(function(o, i) {
|
||||
R(o) && (n[t] += o * ('-' === e[i - 1] ? -1 : 1))
|
||||
})
|
||||
}), n
|
||||
}
|
||||
for (var z = Math.min, V = Math.floor, _ = Math.max, X = ['native code', '[object MutationObserverConstructor]'], Q = function(e) {
|
||||
return X.some(function(t) {
|
||||
return -1 < (e || '').toString().indexOf(t)
|
||||
})
|
||||
}, J = 'undefined' != typeof window, Z = ['Edge', 'Trident', 'Firefox'], $ = 0, ee = 0; ee < Z.length; ee += 1)
|
||||
if (J && 0 <= navigator.userAgent.indexOf(Z[ee])) {
|
||||
$ = 1;
|
||||
break
|
||||
}
|
||||
var i, te = J && Q(window.MutationObserver),
|
||||
oe = te ? function(e) {
|
||||
var t = !1,
|
||||
o = 0,
|
||||
i = document.createElement('span'),
|
||||
n = new MutationObserver(function() {
|
||||
e(), t = !1
|
||||
});
|
||||
return n.observe(i, {
|
||||
attributes: !0
|
||||
}),
|
||||
function() {
|
||||
t || (t = !0, i.setAttribute('x-index', o), ++o)
|
||||
}
|
||||
} : function(e) {
|
||||
var t = !1;
|
||||
return function() {
|
||||
t || (t = !0, setTimeout(function() {
|
||||
t = !1, e()
|
||||
}, $))
|
||||
}
|
||||
},
|
||||
ie = function() {
|
||||
return void 0 == i && (i = -1 !== navigator.appVersion.indexOf('MSIE 10')), i
|
||||
},
|
||||
ne = function(e, t) {
|
||||
if (!(e instanceof t)) throw new TypeError('Cannot call a class as a function')
|
||||
},
|
||||
re = function() {
|
||||
function e(e, t) {
|
||||
for (var o, n = 0; n < t.length; n++) o = t[n], o.enumerable = o.enumerable || !1, o.configurable = !0, 'value' in o && (o.writable = !0), Object.defineProperty(e, o.key, o)
|
||||
}
|
||||
return function(t, o, i) {
|
||||
return o && e(t.prototype, o), i && e(t, i), t
|
||||
}
|
||||
}(),
|
||||
pe = function(e, t, o) {
|
||||
return t in e ? Object.defineProperty(e, t, {
|
||||
value: o,
|
||||
enumerable: !0,
|
||||
configurable: !0,
|
||||
writable: !0
|
||||
}) : e[t] = o, e
|
||||
},
|
||||
se = Object.assign || function(e) {
|
||||
for (var t, o = 1; o < arguments.length; o++)
|
||||
for (var i in t = arguments[o], t) Object.prototype.hasOwnProperty.call(t, i) && (e[i] = t[i]);
|
||||
return e
|
||||
},
|
||||
de = ['auto-start', 'auto', 'auto-end', 'top-start', 'top', 'top-end', 'right-start', 'right', 'right-end', 'bottom-end', 'bottom', 'bottom-start', 'left-end', 'left', 'left-start'],
|
||||
ae = de.slice(3),
|
||||
fe = {
|
||||
FLIP: 'flip',
|
||||
CLOCKWISE: 'clockwise',
|
||||
COUNTERCLOCKWISE: 'counterclockwise'
|
||||
},
|
||||
le = function() {
|
||||
function t(o, i) {
|
||||
var n = this,
|
||||
r = 2 < arguments.length && void 0 !== arguments[2] ? arguments[2] : {};
|
||||
ne(this, t), this.scheduleUpdate = function() {
|
||||
return requestAnimationFrame(n.update)
|
||||
}, this.update = oe(this.update.bind(this)), this.options = se({}, t.Defaults, r), this.state = {
|
||||
isDestroyed: !1,
|
||||
isCreated: !1,
|
||||
scrollParents: []
|
||||
}, this.reference = o.jquery ? o[0] : o, this.popper = i.jquery ? i[0] : i, this.options.modifiers = {}, Object.keys(se({}, t.Defaults.modifiers, r.modifiers)).forEach(function(e) {
|
||||
n.options.modifiers[e] = se({}, t.Defaults.modifiers[e] || {}, r.modifiers ? r.modifiers[e] : {})
|
||||
}), this.modifiers = Object.keys(this.options.modifiers).map(function(e) {
|
||||
return se({
|
||||
name: e
|
||||
}, n.options.modifiers[e])
|
||||
}).sort(function(e, t) {
|
||||
return e.order - t.order
|
||||
}), this.modifiers.forEach(function(t) {
|
||||
t.enabled && e(t.onLoad) && t.onLoad(n.reference, n.popper, n.options, t, n.state)
|
||||
}), this.update();
|
||||
var p = this.options.eventsEnabled;
|
||||
p && this.enableEventListeners(), this.state.eventsEnabled = p
|
||||
}
|
||||
return re(t, [{
|
||||
key: 'update',
|
||||
value: function() {
|
||||
return k.call(this)
|
||||
}
|
||||
}, {
|
||||
key: 'destroy',
|
||||
value: function() {
|
||||
return D.call(this)
|
||||
}
|
||||
}, {
|
||||
key: 'enableEventListeners',
|
||||
value: function() {
|
||||
return A.call(this)
|
||||
}
|
||||
}, {
|
||||
key: 'disableEventListeners',
|
||||
value: function() {
|
||||
return I.call(this)
|
||||
}
|
||||
}]), t
|
||||
}();
|
||||
return le.Utils = ('undefined' == typeof window ? global : window).PopperUtils, le.placements = de, le.Defaults = {
|
||||
placement: 'bottom',
|
||||
eventsEnabled: !0,
|
||||
removeOnDestroy: !1,
|
||||
onCreate: function() {},
|
||||
onUpdate: function() {},
|
||||
modifiers: {
|
||||
shift: {
|
||||
order: 100,
|
||||
enabled: !0,
|
||||
fn: function(e) {
|
||||
var t = e.placement,
|
||||
o = t.split('-')[0],
|
||||
i = t.split('-')[1];
|
||||
if (i) {
|
||||
var n = e.offsets,
|
||||
r = n.reference,
|
||||
p = n.popper,
|
||||
s = -1 !== ['bottom', 'top'].indexOf(o),
|
||||
d = s ? 'left' : 'top',
|
||||
a = s ? 'width' : 'height',
|
||||
f = {
|
||||
start: pe({}, d, r[d]),
|
||||
end: pe({}, d, r[d] + r[a] - p[a])
|
||||
};
|
||||
e.offsets.popper = se({}, p, f[i])
|
||||
}
|
||||
return e
|
||||
}
|
||||
},
|
||||
offset: {
|
||||
order: 200,
|
||||
enabled: !0,
|
||||
fn: function(e, t) {
|
||||
var o, i = t.offset,
|
||||
n = e.placement,
|
||||
r = e.offsets,
|
||||
p = r.popper,
|
||||
s = r.reference,
|
||||
d = n.split('-')[0];
|
||||
return o = R(+i) ? [+i, 0] : G(i, p, s, d), 'left' === d ? (p.top += o[0], p.left -= o[1]) : 'right' === d ? (p.top += o[0], p.left += o[1]) : 'top' === d ? (p.left += o[0], p.top -= o[1]) : 'bottom' === d && (p.left += o[0], p.top += o[1]), e.popper = p, e
|
||||
},
|
||||
offset: 0
|
||||
},
|
||||
preventOverflow: {
|
||||
order: 300,
|
||||
enabled: !0,
|
||||
fn: function(e, t) {
|
||||
var o = t.boundariesElement || r(e.instance.popper);
|
||||
e.instance.reference === o && (o = r(o));
|
||||
var i = w(e.instance.popper, e.instance.reference, t.padding, o);
|
||||
t.boundaries = i;
|
||||
var n = t.priority,
|
||||
p = e.offsets.popper,
|
||||
s = {
|
||||
primary: function(e) {
|
||||
var o = p[e];
|
||||
return p[e] < i[e] && !t.escapeWithReference && (o = _(p[e], i[e])), pe({}, e, o)
|
||||
},
|
||||
secondary: function(e) {
|
||||
var o = 'right' === e ? 'left' : 'top',
|
||||
n = p[o];
|
||||
return p[e] > i[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[d]) && (e.offsets.popper[d] = r(i[d]) - o[a]), o[d] > 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] - m < r[a] && (e.offsets.popper[a] -= r[a] - (p[l] - m)), p[a] + m > r[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.right) || 'top' === i && l(a.bottom) > l(f.top) || 'bottom' === i && l(a.top) < l(f.bottom),
|
||||
h = l(a.left) < l(o.left),
|
||||
c = l(a.right) > l(o.right),
|
||||
g = l(a.top) < l(o.top),
|
||||
u = l(a.bottom) > 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.bottom < o.top || t.left > o.right || t.top > o.bottom || t.right < o.left) {
|
||||
if (!0 === e.hide) return e;
|
||||
e.hide = !0, e.attributes['x-out-of-boundaries'] = ''
|
||||
} else {
|
||||
if (!1 === e.hide) return e;
|
||||
e.hide = !1, e.attributes['x-out-of-boundaries'] = !1
|
||||
}
|
||||
return e
|
||||
}
|
||||
},
|
||||
computeStyle: {
|
||||
order: 850,
|
||||
enabled: !0,
|
||||
fn: function(e, t) {
|
||||
var o = t.x,
|
||||
i = t.y,
|
||||
n = e.offsets.popper,
|
||||
p = T(e.instance.modifiers, function(e) {
|
||||
return 'applyStyle' === e.name
|
||||
}).gpuAcceleration;
|
||||
void 0 !== p && console.warn('WARNING: `gpuAcceleration` option moved to `computeStyle` modifier and will not be supported in future versions of Popper.js!');
|
||||
var s, d, a = void 0 === p ? t.gpuAcceleration : p,
|
||||
f = r(e.instance.popper),
|
||||
l = g(f),
|
||||
m = {
|
||||
position: n.position
|
||||
},
|
||||
h = {
|
||||
left: V(n.left),
|
||||
top: V(n.top),
|
||||
bottom: V(n.bottom),
|
||||
right: V(n.right)
|
||||
},
|
||||
c = 'bottom' === o ? 'top' : 'bottom',
|
||||
u = 'right' === i ? 'left' : 'right',
|
||||
b = B('transform');
|
||||
if (d = 'bottom' == c ? -l.height + h.bottom : h.top, s = 'right' == u ? -l.width + h.right : h.left, a && b) m[b] = 'translate3d(' + s + 'px, ' + d + 'px, 0)', m[c] = 0, m[u] = 0, m.willChange = 'transform';
|
||||
else {
|
||||
var y = 'bottom' == c ? -1 : 1,
|
||||
w = 'right' == u ? -1 : 1;
|
||||
m[c] = d * y, m[u] = s * w, m.willChange = c + ', ' + u
|
||||
}
|
||||
var v = {
|
||||
"x-placement": e.placement
|
||||
};
|
||||
return e.attributes = se({}, v, e.attributes), e.styles = se({}, m, e.styles), e
|
||||
},
|
||||
gpuAcceleration: !0,
|
||||
x: 'bottom',
|
||||
y: 'right'
|
||||
},
|
||||
applyStyle: {
|
||||
order: 900,
|
||||
enabled: !0,
|
||||
fn: function(e) {
|
||||
return U(e.instance.popper, e.styles), Y(e.instance.popper, e.attributes), e.offsets.arrow && U(e.arrowElement, e.offsets.arrow), e
|
||||
},
|
||||
onLoad: function(e, t, o, i, n) {
|
||||
var r = x(n, t, e),
|
||||
p = E(o.placement, r, t, e, o.modifiers.flip.boundariesElement, o.modifiers.flip.padding);
|
||||
return t.setAttribute('x-placement', p), U(t, {
|
||||
position: 'absolute'
|
||||
}), o
|
||||
},
|
||||
gpuAcceleration: void 0
|
||||
}
|
||||
}
|
||||
}, le
|
||||
});
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
/*!
|
||||
|
||||
=========================================================
|
||||
* Now-ui-kit - v1.1.0
|
||||
=========================================================
|
||||
|
||||
* Product Page: http://www.creative-tim.com/product/now-ui-kit
|
||||
* Copyright 2017 Creative Tim (http://www.creative-tim.com)
|
||||
* Licensed under MIT (https://github.com/creativetimofficial/now-ui-kit/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.
|
||||
|
||||
*/
|
||||
|
||||
@import 'now-ui-kit/variables';
|
||||
@import 'now-ui-kit/mixins';
|
||||
|
||||
// Plugins CSS
|
||||
@import "now-ui-kit/plugins/plugin-bootstrap-switch";
|
||||
@import "now-ui-kit/plugins/plugin-nouislider";
|
||||
@import "now-ui-kit/plugins/plugin-datepicker";
|
||||
|
||||
// Core CSS
|
||||
@import "now-ui-kit/buttons";
|
||||
@import "now-ui-kit/inputs";
|
||||
@import "now-ui-kit/checkboxes-radio";
|
||||
@import "now-ui-kit/progress";
|
||||
@import "now-ui-kit/badges";
|
||||
@import "now-ui-kit/pagination";
|
||||
@import "now-ui-kit/typography";
|
||||
@import "now-ui-kit/misc";
|
||||
@import "now-ui-kit/pills";
|
||||
|
||||
// components
|
||||
@import "now-ui-kit/social-buttons";
|
||||
@import "now-ui-kit/tabs";
|
||||
@import "now-ui-kit/navbar";
|
||||
@import "now-ui-kit/dropdown";
|
||||
@import "now-ui-kit/alerts";
|
||||
@import "now-ui-kit/images";
|
||||
@import "now-ui-kit/popups";
|
||||
@import "now-ui-kit/nucleo-outline";
|
||||
@import "now-ui-kit/modals";
|
||||
@import "now-ui-kit/carousel";
|
||||
@import "now-ui-kit/cards";
|
||||
@import "now-ui-kit/footers";
|
||||
|
||||
// example pages and sections
|
||||
@import "now-ui-kit/example-pages";
|
||||
@import "now-ui-kit/sections";
|
||||
|
||||
|
||||
@import "now-ui-kit/responsive";
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
// This file has been autogenerated by grunt task lessToSass. Any changes will be overwritten.
|
||||
.alert{
|
||||
border: 0;
|
||||
border-radius: 0;
|
||||
color: $white-color;
|
||||
padding-top: .9rem;
|
||||
padding-bottom: .9rem;
|
||||
position: relative;
|
||||
|
||||
&.alert-success{
|
||||
background-color: $success-color-alert;
|
||||
}
|
||||
|
||||
&.alert-danger{
|
||||
background-color: $danger-color-alert;
|
||||
}
|
||||
|
||||
&.alert-warning{
|
||||
background-color: $warning-color-alert;
|
||||
}
|
||||
|
||||
&.alert-info{
|
||||
background-color: $info-color-alert;
|
||||
}
|
||||
|
||||
&.alert-primary{
|
||||
background-color: $primary-color-alert;
|
||||
}
|
||||
|
||||
.alert-icon{
|
||||
display: block;
|
||||
float: left;
|
||||
margin-right: 15px;
|
||||
margin-top: -1px;
|
||||
}
|
||||
|
||||
strong{
|
||||
text-transform: uppercase;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
i.fa,
|
||||
i.now-ui-icons{
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.close{
|
||||
color: $white-color;
|
||||
opacity: .9;
|
||||
text-shadow: none;
|
||||
line-height: 0;
|
||||
outline: 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
/* badges */
|
||||
.badge{
|
||||
border-radius: 8px;
|
||||
padding: 4px 8px;
|
||||
text-transform: uppercase;
|
||||
font-size: $font-size-mini;
|
||||
line-height: 12px;
|
||||
background-color: $transparent-bg;
|
||||
border: $border;
|
||||
margin-bottom: 5px;
|
||||
border-radius: $border-radius-extreme;
|
||||
}
|
||||
.badge-icon{
|
||||
padding: 0.4em 0.55em;
|
||||
i{
|
||||
font-size: 0.8em;
|
||||
}
|
||||
}
|
||||
.badge-default{
|
||||
@include badge-color($default-color);
|
||||
}
|
||||
.badge-primary{
|
||||
@include badge-color($primary-color);
|
||||
}
|
||||
.badge-info{
|
||||
@include badge-color($info-color);
|
||||
}
|
||||
.badge-success{
|
||||
@include badge-color($success-color);
|
||||
}
|
||||
.badge-warning{
|
||||
@include badge-color($warning-color);
|
||||
}
|
||||
.badge-danger{
|
||||
@include badge-color($danger-color);
|
||||
}
|
||||
.badge-neutral{
|
||||
@include badge-color($white-color);
|
||||
}
|
||||
|
|
@ -0,0 +1,158 @@
|
|||
.btn,
|
||||
.navbar .navbar-nav > a.btn{
|
||||
border-width: $border-thick;
|
||||
font-weight: $font-weight-normal;
|
||||
font-size: $font-size-small;
|
||||
line-height: $line-height;
|
||||
margin: 5px 1px;
|
||||
border: none;
|
||||
border-radius: $border-radius-small;
|
||||
padding: $padding-btn-vertical $padding-btn-horizontal;
|
||||
cursor: pointer;
|
||||
|
||||
@include btn-styles($default-color, $default-states-color);
|
||||
|
||||
&:hover,
|
||||
&:focus{
|
||||
@include opacity(1);
|
||||
outline: 0 !important;
|
||||
}
|
||||
&:active,
|
||||
&.active,
|
||||
.open > &.dropdown-toggle {
|
||||
@include box-shadow(none);
|
||||
outline: 0 !important;
|
||||
}
|
||||
|
||||
&.btn-icon {
|
||||
// see above for color variations
|
||||
height: $btn-icon-size-regular;
|
||||
min-width: $btn-icon-size-regular;
|
||||
width: $btn-icon-size-regular;
|
||||
padding: 0;
|
||||
font-size: $btn-icon-font-size-regular;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
line-height: normal;
|
||||
|
||||
&.btn-simple{
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
&.btn-sm{
|
||||
height: $btn-icon-size-small;
|
||||
min-width: $btn-icon-size-small;
|
||||
width: $btn-icon-size-small;
|
||||
|
||||
i.fa,
|
||||
i.now-ui-icons{
|
||||
font-size: $btn-icon-font-size-small;
|
||||
}
|
||||
}
|
||||
|
||||
&.btn-lg{
|
||||
height: $btn-icon-size-lg;
|
||||
min-width: $btn-icon-size-lg;
|
||||
width: $btn-icon-size-lg;
|
||||
|
||||
i.now-ui-icons,
|
||||
i.fa{
|
||||
font-size: $btn-icon-font-size-lg;
|
||||
}
|
||||
}
|
||||
|
||||
&:not(.btn-footer) i.now-ui-icons,
|
||||
&:not(.btn-footer) i.fa{
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-12px, -12px);
|
||||
line-height: 1.5626rem;
|
||||
width: 25px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
&:not(.btn-icon) .now-ui-icons{
|
||||
position: relative;
|
||||
top: 1px;
|
||||
}
|
||||
}
|
||||
|
||||
// Apply the mixin to the buttons
|
||||
// .btn-default { @include btn-styles($default-color, $default-states-color); }
|
||||
.btn-primary { @include btn-styles($primary-color, $primary-states-color); }
|
||||
.btn-success { @include btn-styles($success-color, $success-states-color); }
|
||||
.btn-info { @include btn-styles($info-color, $info-states-color); }
|
||||
.btn-warning { @include btn-styles($warning-color, $warning-states-color); }
|
||||
.btn-danger { @include btn-styles($danger-color, $danger-states-color); }
|
||||
.btn-neutral { @include btn-styles($white-color, $white-color); }
|
||||
|
||||
.btn{
|
||||
&:disabled,
|
||||
&[disabled],
|
||||
&.disabled{
|
||||
@include opacity(.5);
|
||||
}
|
||||
}
|
||||
.btn-round{
|
||||
border-width: $border-thin;
|
||||
border-radius: $btn-round-radius !important;
|
||||
padding: $padding-btn-vertical $padding-round-horizontal;
|
||||
|
||||
&.btn-simple{
|
||||
padding: $padding-btn-vertical - 1 $padding-round-horizontal - 1;
|
||||
}
|
||||
}
|
||||
.btn-simple{
|
||||
border: $border;
|
||||
border-color: $default-color;
|
||||
padding: $padding-btn-vertical - 1 $padding-round-horizontal - 1;
|
||||
background-color: $transparent-bg;
|
||||
}
|
||||
|
||||
.btn-simple,
|
||||
.btn-link{
|
||||
&.disabled,
|
||||
&:disabled,
|
||||
&[disabled],
|
||||
fieldset[disabled] & {
|
||||
&,
|
||||
&:hover,
|
||||
&:focus,
|
||||
&.focus,
|
||||
&:active,
|
||||
&.active {
|
||||
background-color: $transparent-bg;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.btn-lg{
|
||||
@include btn-size($padding-large-vertical, $padding-large-horizontal, $font-size-large, $border-radius-large);
|
||||
}
|
||||
.btn-sm{
|
||||
@include btn-size($padding-small-vertical, $padding-small-horizontal, $font-size-base, $border-radius-small);
|
||||
}
|
||||
|
||||
.btn-link{
|
||||
border: $none;
|
||||
padding: $padding-base-vertical $padding-base-horizontal;
|
||||
background-color: $transparent-bg;
|
||||
}
|
||||
|
||||
.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;
|
||||
}
|
||||
|
|
@ -0,0 +1,98 @@
|
|||
.card{
|
||||
border: 0;
|
||||
border-radius: $border-radius-small;
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
margin-bottom: 20px;
|
||||
box-shadow: 0px 5px 25px 0px rgba(0, 0, 0, 0.2);
|
||||
|
||||
.card-body{
|
||||
min-height: 190px;
|
||||
}
|
||||
|
||||
&[data-background-color="orange"]{
|
||||
background-color: $primary-color;
|
||||
}
|
||||
|
||||
&[data-background-color="red"]{
|
||||
background-color: $danger-color;
|
||||
}
|
||||
|
||||
&[data-background-color="yellow"]{
|
||||
background-color: $warning-color;
|
||||
}
|
||||
|
||||
&[data-background-color="blue"]{
|
||||
background-color: $info-color;
|
||||
}
|
||||
|
||||
&[data-background-color="green"]{
|
||||
background-color: $success-color;
|
||||
}
|
||||
}
|
||||
|
||||
.card-signup{
|
||||
max-width: 350px;
|
||||
margin: 0 auto;
|
||||
|
||||
.header{
|
||||
margin-left: 20px;
|
||||
margin-right: 20px;
|
||||
padding: 30px 0;
|
||||
}
|
||||
.text-divider{
|
||||
margin-top: 30px;
|
||||
margin-bottom: 0px;
|
||||
text-align: center;
|
||||
}
|
||||
.card-body{
|
||||
padding-top: 0px;
|
||||
padding-bottom: 0px;
|
||||
min-height: auto;
|
||||
}
|
||||
|
||||
.checkbox{
|
||||
margin-top: 20px;
|
||||
|
||||
label{
|
||||
margin-left: 17px;
|
||||
}
|
||||
.checkbox-material{
|
||||
padding-right: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
.social-line{
|
||||
margin-top: 20px;
|
||||
text-align: center;
|
||||
|
||||
.btn.btn-icon ,
|
||||
.btn.btn-icon .btn-icon -mini{
|
||||
margin-left: 5px;
|
||||
margin-right: 5px;
|
||||
box-shadow: 0px 5px 50px 0px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
}
|
||||
|
||||
.footer{
|
||||
margin-bottom: 10px;
|
||||
margin-top: 24px;
|
||||
}
|
||||
}
|
||||
|
||||
.card-plain{
|
||||
background: transparent;
|
||||
box-shadow: none;
|
||||
|
||||
.header{
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.content{
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
// display flex was causing errors
|
||||
.carousel-item-next,
|
||||
.carousel-item-prev,
|
||||
.carousel-item.active{
|
||||
display: block;
|
||||
}
|
||||
|
||||
.carousel{
|
||||
.carousel-inner{
|
||||
box-shadow: $box-shadow-raised;
|
||||
}
|
||||
.now-ui-icons{
|
||||
font-size: 2em;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,178 @@
|
|||
.checkbox,
|
||||
.radio {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.checkbox label,
|
||||
.radio label {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
padding-left: 35px;
|
||||
line-height: 26px;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.radio label{
|
||||
padding-left: 28px;
|
||||
}
|
||||
|
||||
.checkbox label::before,
|
||||
.checkbox label::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 $light-gray;
|
||||
-webkit-transition: opacity 0.3s linear;
|
||||
-moz-transition: opacity 0.3s linear;
|
||||
-o-transition: opacity 0.3s linear;
|
||||
-ms-transition: opacity 0.3s linear;
|
||||
transition: opacity 0.3s linear;
|
||||
}
|
||||
|
||||
.checkbox label::after{
|
||||
font-family: 'Nucleo Outline';
|
||||
content: "\ea22";
|
||||
top: 0px;
|
||||
text-align: center;
|
||||
font-size: 14px;
|
||||
opacity: 0;
|
||||
color: $dark-background;
|
||||
border: 0;
|
||||
background-color: inherit;
|
||||
}
|
||||
|
||||
.checkbox input[type="checkbox"],
|
||||
.radio input[type="radio"]{
|
||||
opacity: 0;
|
||||
position: absolute;
|
||||
visibility: hidden;
|
||||
}
|
||||
.checkbox input[type="checkbox"]:checked + label::after{
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.checkbox input[type="checkbox"]:disabled + label,
|
||||
.radio input[type="radio"]:disabled + label {
|
||||
color: $dark-gray;
|
||||
opacity: .5;
|
||||
}
|
||||
|
||||
.checkbox input[type="checkbox"]:disabled + label::before,
|
||||
.checkbox input[type="checkbox"]:disabled + label::after{
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.checkbox input[type="checkbox"]:disabled + label,
|
||||
.radio input[type="radio"]:disabled + label{
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.checkbox.checkbox-circle label::before {
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.checkbox.checkbox-inline {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.checkbox-primary input[type="checkbox"]:checked + label::before {
|
||||
background-color: #428bca;
|
||||
border-color: #428bca;
|
||||
}
|
||||
|
||||
.checkbox-primary input[type="checkbox"]:checked + label::after {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.checkbox-danger input[type="checkbox"]:checked + label::before {
|
||||
background-color: #d9534f;
|
||||
border-color: #d9534f;
|
||||
}
|
||||
|
||||
.checkbox-danger input[type="checkbox"]:checked + label::after {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.checkbox-info input[type="checkbox"]:checked + label::before {
|
||||
background-color: #5bc0de;
|
||||
border-color: #5bc0de;
|
||||
}
|
||||
|
||||
.checkbox-info input[type="checkbox"]:checked + label::after {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.checkbox-warning input[type="checkbox"]:checked + label::before {
|
||||
background-color: #f0ad4e;
|
||||
border-color: #f0ad4e;
|
||||
}
|
||||
|
||||
.checkbox-warning input[type="checkbox"]:checked + label::after {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.checkbox-success input[type="checkbox"]:checked + label::before {
|
||||
background-color: #5cb85c;
|
||||
border-color: #5cb85c;
|
||||
}
|
||||
|
||||
.checkbox-success input[type="checkbox"]:checked + label::after {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.radio label::before,
|
||||
.radio label::after{
|
||||
content: " ";
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border-radius: 50%;
|
||||
border: 1px solid $light-gray;
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
left: 3px;
|
||||
top: 3px;
|
||||
padding: 1px;
|
||||
-webkit-transition: opacity 0.3s linear;
|
||||
-moz-transition: opacity 0.3s linear;
|
||||
-o-transition: opacity 0.3s linear;
|
||||
-ms-transition: opacity 0.3s linear;
|
||||
transition: opacity 0.3s linear;
|
||||
}
|
||||
|
||||
.radio input[type="radio"] + label:after,
|
||||
.radio input[type="radio"] {
|
||||
opacity: 0;
|
||||
}
|
||||
.radio input[type="radio"]:checked + label::after {
|
||||
width: 4px;
|
||||
height: 4px;
|
||||
background-color: $dark-background;
|
||||
border-color: $dark-background;
|
||||
top: 11px;
|
||||
left: 11px;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.radio input[type="radio"]:checked + label::after{
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.radio input[type="radio"]:disabled + label {
|
||||
color: $dark-gray;
|
||||
}
|
||||
|
||||
.radio input[type="radio"]:disabled + label::before,
|
||||
.radio input[type="radio"]:disabled + label::after {
|
||||
color: $dark-gray;
|
||||
}
|
||||
|
||||
.radio.radio-inline {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,106 @@
|
|||
.dropdown-menu{
|
||||
border: 0;
|
||||
box-shadow: 0px 10px 50px 0px rgba(0, 0, 0, 0.2);
|
||||
border-radius: $border-radius-extra-small;
|
||||
@include transition($fast-transition-time, $transition-linear);
|
||||
font-size: $font-size-base;
|
||||
|
||||
&.dropdown-menu-right{
|
||||
&:before{
|
||||
left:auto;
|
||||
right: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
&:before{
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
width: 0;
|
||||
height: 0;
|
||||
vertical-align: middle;
|
||||
content: "";
|
||||
top: -5px;
|
||||
left: 10px;
|
||||
right: auto;
|
||||
color: $white-color;
|
||||
border-bottom: .4em solid;
|
||||
border-right: .4em solid transparent;
|
||||
border-left: .4em solid transparent;
|
||||
}
|
||||
|
||||
.dropdown-item{
|
||||
font-size: $font-size-small;
|
||||
padding-top: $padding-base-vertical;
|
||||
padding-bottom: $padding-base-vertical;
|
||||
@include transition($fast-transition-time, $transition-linear);
|
||||
|
||||
&:hover,
|
||||
&:focus{
|
||||
background-color: $opacity-gray-3;
|
||||
}
|
||||
}
|
||||
|
||||
.dropdown-divider{
|
||||
background-color: $opacity-gray-5;
|
||||
}
|
||||
|
||||
.dropdown-header:not([href]):not([tabindex]){
|
||||
color: $default-color-opacity;
|
||||
font-size: $font-size-mini;
|
||||
text-transform: uppercase;
|
||||
font-weight: $font-weight-bold;
|
||||
}
|
||||
|
||||
&.dropdown-primary{
|
||||
@include dropdown-colors(darken($primary-color, 3%),$opacity-8,$white-color, $opacity-2);
|
||||
}
|
||||
|
||||
&.dropdown-info{
|
||||
@include dropdown-colors(darken($info-color, 3%),$opacity-8,$white-color, $opacity-2);
|
||||
}
|
||||
|
||||
&.dropdown-danger{
|
||||
@include dropdown-colors(darken($danger-color, 3%),$opacity-8,$white-color, $opacity-2);
|
||||
}
|
||||
|
||||
&.dropdown-success{
|
||||
@include dropdown-colors(darken($success-color, 3%),$opacity-8,$white-color, $opacity-2);
|
||||
}
|
||||
|
||||
&.dropdown-warning{
|
||||
@include dropdown-colors(darken($warning-color, 3%),$opacity-8,$white-color, $opacity-2);
|
||||
}
|
||||
|
||||
.dropdown &{
|
||||
@include transform-translate-y(-25px);
|
||||
visibility: hidden;
|
||||
display: block;
|
||||
@include opacity(0);
|
||||
}
|
||||
|
||||
.dropdown.show &,
|
||||
&.open{
|
||||
@include opacity(1);
|
||||
visibility: visible;
|
||||
@include transform-translate-y(0px);
|
||||
}
|
||||
|
||||
.navbar .dropdown.show &{
|
||||
@include transform-translate-y(7px);
|
||||
}
|
||||
}
|
||||
|
||||
.button-dropdown{
|
||||
padding-right: $padding-base-horizontal;
|
||||
cursor: pointer;
|
||||
|
||||
& .dropdown-toggle{
|
||||
padding-top: $padding-base-vertical;
|
||||
padding-bottom: $padding-base-vertical;
|
||||
display: block;
|
||||
|
||||
&:after{
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,256 @@
|
|||
// style for the landing page
|
||||
.index-page{
|
||||
.page-header{
|
||||
height: 125vh;
|
||||
|
||||
.container{
|
||||
> .content-center{
|
||||
top: 37%;
|
||||
}
|
||||
}
|
||||
|
||||
.category-absolute{
|
||||
position: absolute;
|
||||
top: 100vh;
|
||||
margin-top: -60px;
|
||||
padding: 0 15px;
|
||||
width: 100%;
|
||||
color: rgba(255,255,255,.5);
|
||||
}
|
||||
}
|
||||
}
|
||||
.landing-page{
|
||||
|
||||
.header{
|
||||
height: 100vh;
|
||||
position: relative;
|
||||
|
||||
.container{
|
||||
padding-top: 26vh;
|
||||
color: #FFFFFF;
|
||||
z-index: 2;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.share{
|
||||
margin-top: 150px;
|
||||
}
|
||||
h1{
|
||||
font-weight: 600;
|
||||
}
|
||||
.title{
|
||||
color: $white-color;
|
||||
}
|
||||
}
|
||||
|
||||
.section-team{
|
||||
.team .team-player img{
|
||||
max-width: 100px;
|
||||
}
|
||||
|
||||
.team-player{
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
.section-contact-us{
|
||||
.title{
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.description{
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.input-group,
|
||||
.send-button,
|
||||
.textarea-container{
|
||||
padding: 0 40px;
|
||||
}
|
||||
|
||||
.textarea-container{
|
||||
margin: 40px 0;
|
||||
}
|
||||
|
||||
a.btn{
|
||||
margin-top: 35px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// style for the profile page
|
||||
.profile-page{
|
||||
|
||||
.page-header{
|
||||
min-height: 550px;
|
||||
}
|
||||
|
||||
.profile-container{
|
||||
color: #FFFFFF;
|
||||
}
|
||||
.photo-container{
|
||||
width: 123px;
|
||||
height: 123px;
|
||||
border-radius: 50%;
|
||||
overflow: hidden;
|
||||
margin: 0 auto;
|
||||
box-shadow: 0px 10px 25px 0px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.title{
|
||||
text-align: center;
|
||||
margin-top: 30px;
|
||||
}
|
||||
|
||||
.description,
|
||||
.category{
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
h5.description{
|
||||
max-width: 700px;
|
||||
margin: 20px auto 75px;
|
||||
}
|
||||
|
||||
.nav-align-center{
|
||||
margin-top: 30px;
|
||||
}
|
||||
|
||||
.content{
|
||||
max-width: 450px;
|
||||
margin: 0 auto;
|
||||
|
||||
.social-description{
|
||||
display: inline-block;
|
||||
max-width: 150px;
|
||||
width: 145px;
|
||||
text-align: center;
|
||||
margin: 15px 0 0px;
|
||||
|
||||
h2{
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.button-container{
|
||||
text-align: center;
|
||||
margin-top: -106px;
|
||||
}
|
||||
|
||||
.collections{
|
||||
img{
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
}
|
||||
|
||||
.gallery{
|
||||
margin-top: 45px;
|
||||
padding-bottom: 50px;
|
||||
}
|
||||
}
|
||||
|
||||
.section-full-page{
|
||||
|
||||
&:after,
|
||||
&:before{
|
||||
display: block;
|
||||
content: "";
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
&:before{
|
||||
background-color: rgba(0,0,0,.5);
|
||||
}
|
||||
|
||||
&[filter-color="purple"],
|
||||
&[filter-color="primary"]{
|
||||
&:after{
|
||||
@include linear-gradient(rgba($light-gray,.26), rgba($primary-color,.95));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
&[data-image]:after{
|
||||
opacity: .5;
|
||||
}
|
||||
|
||||
> .content,
|
||||
> .footer{
|
||||
position: relative;
|
||||
z-index: 4;
|
||||
}
|
||||
|
||||
> .content{
|
||||
min-height: calc(100vh - 80px);
|
||||
}
|
||||
|
||||
.full-page-background{
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
display: block;
|
||||
top: 0;
|
||||
left: 0;
|
||||
background-size: cover;
|
||||
background-position: center center;
|
||||
|
||||
}
|
||||
|
||||
.footer nav > ul a:not(.btn),
|
||||
.footer,
|
||||
.footer .copyright a{
|
||||
color: $white-color;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.login-page{
|
||||
|
||||
.card-login{
|
||||
border-radius: $border-radius-large;
|
||||
padding-bottom: $padding-base-horizontal;
|
||||
max-width: 320px;
|
||||
|
||||
.btn-wd{
|
||||
min-width: 180px;
|
||||
}
|
||||
|
||||
.logo-container{
|
||||
width: 65px;
|
||||
margin: 0 auto;
|
||||
margin-bottom: 55px;
|
||||
|
||||
img{
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.input-group:last-child{
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
|
||||
&.card-plain{
|
||||
@include input-coloured-bg($opacity-5, $white-color, $white-color, $transparent-bg, $opacity-1, $opacity-2);
|
||||
|
||||
.input-group-addon,
|
||||
.form-group.form-group-no-border .input-group-addon,
|
||||
.input-group.form-group-no-border .input-group-addon{
|
||||
color: $opacity-8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.link{
|
||||
font-size: 10px;
|
||||
color: $white-color;
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
.footer{
|
||||
padding: 24px 0;
|
||||
|
||||
&.footer-default{
|
||||
background-color: #f2f2f2;
|
||||
}
|
||||
|
||||
nav{
|
||||
display: inline-block;
|
||||
float: left;
|
||||
}
|
||||
|
||||
ul{
|
||||
margin-bottom: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
|
||||
li{
|
||||
display: inline-block;
|
||||
|
||||
a{
|
||||
color: inherit;
|
||||
padding: $padding-base-vertical;
|
||||
font-size: $font-size-small;
|
||||
text-transform: uppercase;
|
||||
text-decoration: none;
|
||||
|
||||
&:hover{
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.copyright{
|
||||
font-size: $font-size-small;
|
||||
}
|
||||
|
||||
&:after{
|
||||
display: table;
|
||||
clear: both;
|
||||
content: " ";
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
img{
|
||||
max-width: 100%;
|
||||
border-radius: 1px;
|
||||
}
|
||||
.img-raised{
|
||||
box-shadow: $box-shadow-raised;
|
||||
}
|
||||
|
|
@ -0,0 +1,264 @@
|
|||
@include form-control-placeholder($medium-gray, 1);
|
||||
|
||||
.form-control {
|
||||
background-color: $transparent-bg;
|
||||
border: 1px solid $light-gray;
|
||||
border-radius: $btn-round-radius;
|
||||
color: $black-color;
|
||||
line-height: normal;
|
||||
font-size: $font-size-small;
|
||||
@include transition-input-focus-color();
|
||||
@include box-shadow(none);
|
||||
|
||||
.has-success &{
|
||||
border-color: $light-gray;
|
||||
}
|
||||
|
||||
&:focus{
|
||||
border: 1px solid $primary-color;
|
||||
@include box-shadow(none);
|
||||
outline: 0 !important;
|
||||
color: $black-color;
|
||||
|
||||
& + .input-group-addon,
|
||||
& ~ .input-group-addon{
|
||||
border: 1px solid $primary-color;
|
||||
border-left: none;
|
||||
background-color: $transparent-bg;
|
||||
}
|
||||
}
|
||||
|
||||
.has-success &,
|
||||
.has-error &,
|
||||
.has-success &:focus,
|
||||
.has-error &:focus{
|
||||
@include box-shadow(none);
|
||||
}
|
||||
|
||||
.has-success &:focus{
|
||||
border-color: lighten($success-color, 5%);
|
||||
}
|
||||
|
||||
|
||||
.has-danger &,
|
||||
.has-success &{
|
||||
&.form-control-success,
|
||||
&.form-control-danger{
|
||||
background-image: none;
|
||||
}
|
||||
}
|
||||
|
||||
.has-danger &{
|
||||
border-color: lighten($danger-color, 30%);
|
||||
color: $danger-color;
|
||||
background-color: rgba(222,222,222, .1);
|
||||
|
||||
&:focus{
|
||||
background-color: $white-color;
|
||||
}
|
||||
}
|
||||
|
||||
& + .form-control-feedback{
|
||||
border-radius: $border-radius-large;
|
||||
font-size: $font-size-base;
|
||||
margin-top: 0;
|
||||
position: absolute;
|
||||
left: 18px;
|
||||
bottom: -20px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.open &{
|
||||
border-radius: $border-radius-large $border-radius-large 0 0;
|
||||
border-bottom-color: transparent;
|
||||
}
|
||||
|
||||
& + .input-group-addon{
|
||||
background-color: $white-bg;
|
||||
}
|
||||
}
|
||||
|
||||
.has-success,
|
||||
.has-danger{
|
||||
&:after{
|
||||
font-family: 'Nucleo Outline';
|
||||
content: "\ea22";
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
right: 15px;
|
||||
bottom: 10px;
|
||||
color: $success-color;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
&.input-lg{
|
||||
&:after{
|
||||
font-size: 13px;
|
||||
top: 13px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.has-danger{
|
||||
&:after{
|
||||
content: "\ea53";
|
||||
color: $danger-color;
|
||||
}
|
||||
}
|
||||
|
||||
@include input-lg-padding($padding-large-vertical, $padding-input-horizontal);
|
||||
@include input-base-padding($padding-input-vertical, $padding-input-horizontal);
|
||||
|
||||
.form-group.form-group-no-border,
|
||||
.input-group.form-group-no-border{
|
||||
.form-control,
|
||||
.form-control + .input-group-addon{
|
||||
background-color: $opacity-gray-3;
|
||||
border: medium none;
|
||||
&:focus,
|
||||
&:active,
|
||||
&:active{
|
||||
border: medium none;
|
||||
background-color: $opacity-gray-5;
|
||||
}
|
||||
}
|
||||
|
||||
.form-control{
|
||||
&:focus{
|
||||
& + .input-group-addon{
|
||||
background-color: $opacity-gray-5;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.input-group-addon{
|
||||
background-color: $opacity-gray-3;
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
|
||||
.has-error{
|
||||
.form-control-feedback, .control-label{
|
||||
color: $danger-color;
|
||||
}
|
||||
}
|
||||
.has-success{
|
||||
.form-control-feedback, .control-label{
|
||||
color: $success-color;
|
||||
}
|
||||
}
|
||||
|
||||
.input-group-addon {
|
||||
background-color: $white-bg;
|
||||
border: 1px solid $light-gray;
|
||||
border-radius: $btn-round-radius;
|
||||
color: $dark-background;
|
||||
padding: $padding-base-vertical - 1 0 $padding-base-vertical - 1 $padding-base-horizontal - 1;
|
||||
|
||||
@include transition-input-focus-color();
|
||||
|
||||
.has-success &,
|
||||
.has-danger &{
|
||||
background-color: $white-color;
|
||||
}
|
||||
.has-danger .form-control:focus + &{
|
||||
color: $danger-color;
|
||||
}
|
||||
.has-success .form-control:focus + &{
|
||||
color: $success-color;
|
||||
}
|
||||
|
||||
& + .form-control,
|
||||
& ~ .form-control{
|
||||
@include input-size($padding-base-vertical - 1, $padding-base-horizontal);
|
||||
padding-left: 18px;
|
||||
}
|
||||
|
||||
i{
|
||||
width: 17px;
|
||||
}
|
||||
}
|
||||
|
||||
.input-group-focus{
|
||||
.input-group-addon{
|
||||
background-color: $white-bg;
|
||||
border-color: $primary-color;
|
||||
}
|
||||
|
||||
&.form-group-no-border{
|
||||
.input-group-addon{
|
||||
background-color: $opacity-gray-5;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.input-group,
|
||||
.form-group{
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.input-group[disabled]{
|
||||
.input-group-addon{
|
||||
background-color: $light-gray;
|
||||
}
|
||||
}
|
||||
.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: $light-gray;
|
||||
color: $default-color;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.input-group-btn .btn{
|
||||
border-width: $border-thin;
|
||||
padding: $padding-btn-vertical $padding-base-horizontal;
|
||||
}
|
||||
.input-group-btn .btn-default:not(.btn-fill){
|
||||
border-color: $medium-gray;
|
||||
}
|
||||
|
||||
.input-group-btn:last-child > .btn{
|
||||
margin-left: 0;
|
||||
}
|
||||
textarea.form-control{
|
||||
max-width: 100%;
|
||||
padding: 10px 10px 0 0;
|
||||
resize: none;
|
||||
border: none;
|
||||
border-bottom: 1px solid $light-gray;
|
||||
border-radius: 0;
|
||||
line-height: 2;
|
||||
|
||||
&:focus,
|
||||
&:active{
|
||||
border-left: none;
|
||||
border-top: none;
|
||||
border-right: none;
|
||||
}
|
||||
}
|
||||
|
||||
.has-success,
|
||||
.has-danger{
|
||||
|
||||
&.form-group .form-control,
|
||||
&.form-group.form-group-no-border .form-control{
|
||||
padding-right: $padding-input-horizontal + 21;
|
||||
}
|
||||
}
|
||||
|
||||
.form-group{
|
||||
position:relative;
|
||||
}
|
||||
.form-group.has-error, .form-group.has-danger{
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
body{
|
||||
color: $black-color;
|
||||
font-size: $font-size-base;
|
||||
font-family: $sans-serif-family;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
|
||||
.main{
|
||||
position: relative;
|
||||
background: $white-color;
|
||||
}
|
||||
/* Animations */
|
||||
.nav-pills .nav-link,
|
||||
.nav-item .nav-link,
|
||||
.navbar,
|
||||
.nav-tabs .nav-link{
|
||||
@include transition($general-transition-time, $transition-ease);
|
||||
}
|
||||
|
||||
//transition for dropdown caret
|
||||
.dropdown-toggle:after,
|
||||
.bootstrap-switch-label:before{
|
||||
@include transition($fast-transition-time, $transition-ease);
|
||||
}
|
||||
|
||||
.dropdown-toggle[aria-expanded="true"]:after{
|
||||
@include rotate-180();
|
||||
}
|
||||
|
||||
.button-bar{
|
||||
display: block;
|
||||
position: relative;
|
||||
width: 22px;
|
||||
height: 1px;
|
||||
border-radius: 1px;
|
||||
background: $white-bg;
|
||||
|
||||
& + .button-bar{
|
||||
margin-top: 7px;
|
||||
}
|
||||
|
||||
&:nth-child(2){
|
||||
width: 17px;
|
||||
}
|
||||
}
|
||||
|
||||
.open{
|
||||
@include transform-translate-y(0);
|
||||
@include opacity(1);
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.separator{
|
||||
height: 2px;
|
||||
width: 44px;
|
||||
background-color: $default-color;
|
||||
margin: 20px auto;
|
||||
|
||||
&.separator-primary{
|
||||
background-color: $primary-color;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
//Utilities
|
||||
@import "mixins/transparency";
|
||||
|
||||
//Components
|
||||
@import "mixins/buttons";
|
||||
@import "mixins/vendor-prefixes";
|
||||
@import "mixins/inputs";
|
||||
@import "mixins/dropdown";
|
||||
@import "mixins/badges";
|
||||
@import "mixins/navbar";
|
||||
@import "mixins/popovers";
|
||||
@import "mixins/modals";
|
||||
@import "mixins/pages";
|
||||
@import "mixins/datepicker";
|
||||
|
|
@ -0,0 +1,173 @@
|
|||
//
|
||||
// Modals
|
||||
// Now Ui Kit Design element Dialogs
|
||||
// --------------------------------------------------
|
||||
.modal-content {
|
||||
|
||||
border-radius: $border-radius-small;
|
||||
border: none;
|
||||
box-shadow: 0px 10px 50px 0px rgba(0, 0, 0, 0.5);
|
||||
// Modal header
|
||||
// Top section of the modal w/ title and dismiss
|
||||
.modal-header {
|
||||
border-bottom: none;
|
||||
padding-top: 24px;
|
||||
padding-right: 24px;
|
||||
padding-bottom: 0;
|
||||
padding-left: 24px;
|
||||
|
||||
& button{
|
||||
position: absolute;
|
||||
right: 27px;
|
||||
top: 30px;
|
||||
outline: 0;
|
||||
}
|
||||
.title{
|
||||
margin-top: 5px;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
// Modal body
|
||||
// Where all modal content resides (sibling of .modal-header and .modal-footer)
|
||||
.modal-body {
|
||||
padding-top: 24px;
|
||||
padding-right: 24px;
|
||||
padding-bottom: 16px;
|
||||
padding-left: 24px;
|
||||
line-height: 1.9;
|
||||
}
|
||||
// Footer (for actions)
|
||||
.modal-footer {
|
||||
border-top: none;
|
||||
padding-right: 24px;
|
||||
padding-bottom: 16px;
|
||||
padding-left: 24px;
|
||||
-webkit-justify-content: space-between; /* Safari 6.1+ */
|
||||
justify-content: space-between;
|
||||
|
||||
button {
|
||||
margin: 0;
|
||||
padding-left: 16px;
|
||||
padding-right: 16px;
|
||||
width: auto;
|
||||
&.pull-left {
|
||||
padding-left: 5px;
|
||||
padding-right: 5px;
|
||||
position: relative;
|
||||
left: -5px;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
.modal-body + .modal-footer {
|
||||
padding-top: 0;
|
||||
}
|
||||
}
|
||||
.modal-backdrop {
|
||||
background: rgba(0,0,0,0.3);
|
||||
}
|
||||
|
||||
.modal{
|
||||
|
||||
&.modal-mini{
|
||||
p{
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.modal-dialog{
|
||||
max-width: 255px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.modal-profile{
|
||||
width: 70px;
|
||||
height: 70px;
|
||||
background-color: $white-color;
|
||||
border-radius: 50%;
|
||||
text-align: center;
|
||||
line-height: 5.9;
|
||||
box-shadow: 0px 5px 50px 0px rgba(0, 0, 0, 0.3);
|
||||
|
||||
i{
|
||||
color: $primary-color;
|
||||
font-size: 21px;
|
||||
}
|
||||
|
||||
&[class*="modal-profile-"]{
|
||||
i{
|
||||
color: $white-color;
|
||||
}
|
||||
}
|
||||
|
||||
&.modal-profile-primary{
|
||||
background-color: $primary-color;
|
||||
}
|
||||
|
||||
&.modal-profile-danger{
|
||||
background-color: $danger-color;
|
||||
}
|
||||
|
||||
&.modal-profile-warning{
|
||||
background-color: $warning-color;
|
||||
}
|
||||
|
||||
&.modal-profile-success{
|
||||
background-color: $success-color;
|
||||
}
|
||||
|
||||
&.modal-profile-info{
|
||||
background-color: $info-color;
|
||||
}
|
||||
}
|
||||
|
||||
.modal-footer{
|
||||
button{
|
||||
text-transform: uppercase;
|
||||
|
||||
&:first-child{
|
||||
opacity: .5;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.modal-default{
|
||||
@include modal-colors($white-color, $black-color);
|
||||
}
|
||||
|
||||
&.modal-primary{
|
||||
@include modal-colors($primary-color, $white-color);
|
||||
}
|
||||
|
||||
&.modal-danger{
|
||||
@include modal-colors($danger-color, $white-color);
|
||||
}
|
||||
|
||||
&.modal-warning{
|
||||
@include modal-colors($warning-color, $white-color);
|
||||
}
|
||||
|
||||
&.modal-success{
|
||||
@include modal-colors($success-color, $white-color);
|
||||
}
|
||||
|
||||
&.modal-info{
|
||||
@include modal-colors($info-color, $white-color);
|
||||
}
|
||||
|
||||
&.show.modal-mini .modal-dialog{
|
||||
-webkit-transform: translate(0,30%);
|
||||
-o-transform: translate(0,30%);
|
||||
transform: translate(0,30%);
|
||||
}
|
||||
|
||||
.modal-header .close{
|
||||
color: $danger-color;
|
||||
text-shadow: none;
|
||||
|
||||
&:hover,
|
||||
&:focus{
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,193 @@
|
|||
.navbar{
|
||||
padding-top: $navbar-padding-base;
|
||||
padding-bottom: $navbar-padding-base;
|
||||
min-height: 53px;
|
||||
margin-bottom: 20px;
|
||||
box-shadow: 0px 0px 20px 0px rgba(0, 0, 0, 0.15);
|
||||
|
||||
a{
|
||||
vertical-align: middle;
|
||||
|
||||
&:not(.btn):not(.dropdown-item){
|
||||
color: $white-color;
|
||||
}
|
||||
}
|
||||
|
||||
p{
|
||||
display: inline-block;
|
||||
margin: 0;
|
||||
line-height: 21px;
|
||||
}
|
||||
|
||||
.navbar-nav{
|
||||
&.navbar-logo{
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
margin: 0 auto;
|
||||
width: 49px;
|
||||
top: -4px;
|
||||
}
|
||||
|
||||
.nav-link.btn{
|
||||
padding: $padding-btn-vertical $padding-btn-horizontal;
|
||||
|
||||
&.btn-lg{
|
||||
padding: $padding-large-vertical $padding-large-horizontal;
|
||||
}
|
||||
|
||||
&.btn-sm{
|
||||
padding: $padding-small-vertical $padding-small-horizontal;
|
||||
}
|
||||
}
|
||||
|
||||
.nav-link:not(.btn){
|
||||
text-transform: uppercase;
|
||||
font-size: $font-size-mini;
|
||||
padding: $padding-base-vertical $padding-base-horizontal;
|
||||
line-height: $line-height-nav-link;
|
||||
|
||||
i.fa + p,
|
||||
i.now-ui-icons + p{
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
i.fa,
|
||||
i.now-ui-icons{
|
||||
font-size: 18px;
|
||||
position: relative;
|
||||
top: 2px;
|
||||
text-align: center;
|
||||
width: 21px;
|
||||
}
|
||||
|
||||
i.now-ui-icons{
|
||||
top: 4px;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
&.profile-photo{
|
||||
.profile-photo-small{
|
||||
width: 27px;
|
||||
height: 27px;
|
||||
}
|
||||
}
|
||||
|
||||
&.disabled{
|
||||
opacity: .5;
|
||||
color: $white-color;
|
||||
}
|
||||
}
|
||||
|
||||
.nav-item.active .nav-link:not(.btn),
|
||||
.nav-item .nav-link:not(.btn):focus,
|
||||
.nav-item .nav-link:not(.btn):hover,
|
||||
.nav-item .nav-link:not(.btn):active{
|
||||
background-color: $opacity-2;
|
||||
border-radius: $border-radius-small;
|
||||
}
|
||||
}
|
||||
|
||||
.logo-container{
|
||||
width: 27px;
|
||||
height: 27px;
|
||||
overflow: hidden;
|
||||
margin: 0 auto;
|
||||
border-radius: 50%;
|
||||
border: 1px solid transparent;
|
||||
}
|
||||
|
||||
.navbar-brand{
|
||||
text-transform: uppercase;
|
||||
font-size: $font-size-small;
|
||||
padding-top: $padding-base-vertical;
|
||||
padding-bottom: $padding-base-vertical;
|
||||
line-height: $line-height-nav-link;
|
||||
}
|
||||
|
||||
.navbar-toggler{
|
||||
width: 37px;
|
||||
height: 27px;
|
||||
outline: 0;
|
||||
cursor: pointer;
|
||||
|
||||
&.navbar-toggler-left{
|
||||
position: relative;
|
||||
left: 0;
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
&:hover{
|
||||
& .navbar-toggler-bar.bar2{
|
||||
width: 22px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.button-dropdown{
|
||||
.navbar-toggler-bar:nth-child(2){
|
||||
width: 17px;
|
||||
}
|
||||
}
|
||||
|
||||
&.navbar-transparent{
|
||||
background-color: $transparent-bg !important;
|
||||
box-shadow: none;
|
||||
color: $white-color;
|
||||
padding-top: 20px;
|
||||
}
|
||||
|
||||
&.bg-white:not(.navbar-transparent){
|
||||
a:not(.dropdown-item){
|
||||
color: $default-color;
|
||||
|
||||
&.disabled{
|
||||
opacity: .5;
|
||||
color: $default-color;
|
||||
}
|
||||
}
|
||||
|
||||
.button-bar{
|
||||
background: $default-color;
|
||||
}
|
||||
|
||||
.nav-item.active .nav-link:not(.btn),
|
||||
.nav-item .nav-link:not(.btn):focus,
|
||||
.nav-item .nav-link:not(.btn):hover,
|
||||
.nav-item .nav-link:not(.btn):active{
|
||||
background-color: $opacity-gray-3;
|
||||
}
|
||||
|
||||
.logo-container{
|
||||
border: 1px solid $default-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.bg-default{
|
||||
background-color: $default-color !important;
|
||||
}
|
||||
|
||||
.bg-primary{
|
||||
background-color: $primary-color !important;
|
||||
}
|
||||
|
||||
.bg-info{
|
||||
background-color: $info-color !important;
|
||||
}
|
||||
|
||||
.bg-success{
|
||||
background-color: $success-color !important;
|
||||
}
|
||||
|
||||
.bg-danger{
|
||||
background-color: $danger-color !important;
|
||||
}
|
||||
|
||||
.bg-warning{
|
||||
background-color: $warning-color !important;
|
||||
}
|
||||
|
||||
.bg-white{
|
||||
background-color: $white-color !important;
|
||||
}
|
||||
|
|
@ -0,0 +1,533 @@
|
|||
/* --------------------------------
|
||||
|
||||
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');
|
||||
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;
|
||||
-moz-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);
|
||||
}
|
||||
}
|
||||
|
||||
@-moz-keyframes nc-icon-spin {
|
||||
0% {
|
||||
-moz-transform: rotate(0deg);
|
||||
}
|
||||
|
||||
100% {
|
||||
-moz-transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes nc-icon-spin {
|
||||
0% {
|
||||
-webkit-transform: rotate(0deg);
|
||||
-moz-transform: rotate(0deg);
|
||||
-ms-transform: rotate(0deg);
|
||||
-o-transform: rotate(0deg);
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
100% {
|
||||
-webkit-transform: rotate(360deg);
|
||||
-moz-transform: rotate(360deg);
|
||||
-ms-transform: rotate(360deg);
|
||||
-o-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";
|
||||
}
|
||||
|
|
@ -0,0 +1,136 @@
|
|||
.pagination{
|
||||
.page-item .page-link{
|
||||
border: 0;
|
||||
border-radius: 30px !important;
|
||||
transition: all .3s;
|
||||
padding: 0px 11px;
|
||||
margin: 0 3px;
|
||||
min-width: 30px;
|
||||
text-align: center;
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
color: $black-color;
|
||||
cursor: pointer;
|
||||
font-size: $font-size-base;
|
||||
text-transform: uppercase;
|
||||
background: transparent;
|
||||
|
||||
&:hover,
|
||||
&:focus{
|
||||
color: $black-color;
|
||||
background-color: $opacity-gray-3;
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
|
||||
.arrow-margin-left,
|
||||
.arrow-margin-right{
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.arrow-margin-right{
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.arrow-margin-left{
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.page-item.active > .page-link{
|
||||
color: $light-gray;
|
||||
box-shadow: 0px 5px 25px 0px rgba(0, 0, 0, 0.2);
|
||||
|
||||
&,
|
||||
&:focus,
|
||||
&:hover{
|
||||
background-color: $default-color;
|
||||
border-color: $default-color;
|
||||
color: $white-color;
|
||||
}
|
||||
}
|
||||
|
||||
.page-item.disabled > .page-link{
|
||||
opacity: .5;
|
||||
background-color: rgba(255,255,255, .2);
|
||||
color: $white-color;
|
||||
}
|
||||
|
||||
// Colors
|
||||
&.pagination-info{
|
||||
.page-item.active > .page-link{
|
||||
&,
|
||||
&:focus,
|
||||
&:hover{
|
||||
background-color: $brand-info;
|
||||
border-color: $brand-info;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.pagination-success{
|
||||
.page-item.active > .page-link{
|
||||
&,
|
||||
&:focus,
|
||||
&:hover{
|
||||
background-color: $brand-success;
|
||||
border-color: $brand-success;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.pagination-primary{
|
||||
.page-item.active > .page-link{
|
||||
&,
|
||||
&:focus,
|
||||
&:hover{
|
||||
background-color: $brand-primary;
|
||||
border-color: $brand-primary;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.pagination-warning{
|
||||
.page-item.active > .page-link{
|
||||
&,
|
||||
&:focus,
|
||||
&:hover{
|
||||
background-color: $brand-warning;
|
||||
border-color: $brand-warning;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.pagination-danger{
|
||||
.page-item.active > .page-link{
|
||||
&,
|
||||
&:focus,
|
||||
&:hover{
|
||||
background-color: $brand-danger;
|
||||
border-color: $brand-danger;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.pagination-neutral{
|
||||
.page-item > .page-link{
|
||||
color: $white-color;
|
||||
|
||||
&:focus,
|
||||
&:hover{
|
||||
background-color: $opacity-2;
|
||||
color: $white-color;
|
||||
}
|
||||
}
|
||||
|
||||
.page-item.active > .page-link{
|
||||
&,
|
||||
&:focus,
|
||||
&:hover{
|
||||
background-color: $white-bg;
|
||||
border-color: $white-bg;
|
||||
color: $brand-primary;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,131 @@
|
|||
.nav-pills{
|
||||
|
||||
.nav-item {
|
||||
.nav-link{
|
||||
padding: 0 15.5px;
|
||||
text-align: center;
|
||||
height: 60px;
|
||||
width: 60px;
|
||||
font-weight: $font-weight-normal;
|
||||
color: $dark-gray;
|
||||
margin-right: 19px;
|
||||
background-color: $opacity-gray-3;
|
||||
border-radius: $btn-round-radius;
|
||||
|
||||
&:hover{
|
||||
background-color: $opacity-gray-3;
|
||||
}
|
||||
|
||||
&.active{
|
||||
&,
|
||||
&:focus,
|
||||
&:hover{
|
||||
background-color: $dark-gray;
|
||||
color: $white-color;
|
||||
box-shadow: 0px 5px 35px 0px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
}
|
||||
|
||||
&.disabled,
|
||||
&:disabled,
|
||||
&[disabled]{
|
||||
opacity: .5;
|
||||
}
|
||||
}
|
||||
|
||||
i{
|
||||
display: block;
|
||||
font-size: 20px;
|
||||
line-height: 60px;
|
||||
}
|
||||
}
|
||||
|
||||
&.nav-pills-neutral{
|
||||
.nav-item {
|
||||
.nav-link{
|
||||
background-color: $opacity-2;
|
||||
color: $white-color;
|
||||
|
||||
&.active{
|
||||
&,
|
||||
&:focus,
|
||||
&:hover{
|
||||
background-color: $white-color;
|
||||
color: $primary-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.nav-pills-primary{
|
||||
.nav-item {
|
||||
.nav-link.active{
|
||||
&,
|
||||
&:focus,
|
||||
&:hover{
|
||||
background-color: $brand-primary;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.nav-pills-info{
|
||||
.nav-item {
|
||||
.nav-link.active{
|
||||
&,
|
||||
&:focus,
|
||||
&:hover{
|
||||
background-color: $brand-info;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.nav-pills-success{
|
||||
.nav-item {
|
||||
.nav-link.active{
|
||||
&,
|
||||
&:focus,
|
||||
&:hover{
|
||||
background-color: $brand-success;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.nav-pills-warning{
|
||||
.nav-item {
|
||||
.nav-link.active{
|
||||
&,
|
||||
&:focus,
|
||||
&:hover{
|
||||
background-color: $brand-warning;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.nav-pills-danger{
|
||||
.nav-item {
|
||||
.nav-link.active{
|
||||
&,
|
||||
&:focus,
|
||||
&:hover{
|
||||
background-color: $brand-danger;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.tab-space{
|
||||
padding: 20px 0 50px 0px;
|
||||
}
|
||||
|
||||
.nav-align-center{
|
||||
text-align: center;
|
||||
|
||||
.nav-pills{
|
||||
display: inline-flex;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
.popover{
|
||||
font-size: $font-size-base;
|
||||
box-shadow: 0px 10px 50px 0px rgba(0, 0, 0, 0.2);
|
||||
border: none;
|
||||
line-height: 1.7;
|
||||
max-width: 240px;
|
||||
|
||||
&.bs-popover-top .arrow:before,
|
||||
&.bs-popover-left .arrow:before,
|
||||
&.bs-popover-right .arrow:before,
|
||||
&.bs-popover-bottom .arrow:before,{
|
||||
border-top-color: transparent;
|
||||
border-left-color: transparent;
|
||||
border-right-color: transparent;
|
||||
border-bottom-color: transparent;
|
||||
}
|
||||
|
||||
.popover-header{
|
||||
color: $default-color-opacity;
|
||||
font-size: $font-size-base;
|
||||
text-transform: capitalize;
|
||||
font-weight: $font-weight-semi;
|
||||
margin: 0;
|
||||
margin-top: 5px;
|
||||
border: none;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
&:before{
|
||||
display: none;
|
||||
}
|
||||
|
||||
&.bs-tether-element-attached-top:after{
|
||||
border-bottom-color:$white-color;
|
||||
top: -9px;
|
||||
}
|
||||
|
||||
&.popover-primary{
|
||||
@include popover-color($primary-color, $white-color);
|
||||
}
|
||||
|
||||
&.popover-info{
|
||||
@include popover-color($info-color, $white-color);
|
||||
}
|
||||
|
||||
&.popover-warning{
|
||||
@include popover-color($warning-color, $white-color);
|
||||
}
|
||||
|
||||
&.popover-danger{
|
||||
@include popover-color($danger-color, $white-color);
|
||||
}
|
||||
|
||||
&.popover-success{
|
||||
@include popover-color($success-color, $white-color);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.tooltip{
|
||||
&.bs-tooltip-right .arrow:before{
|
||||
border-right-color:$white-color;
|
||||
}
|
||||
|
||||
&.bs-tooltip-top .arrow:before{
|
||||
border-top-color:$white-color;
|
||||
}
|
||||
|
||||
&.bs-tooltip-bottom .arrow:before{
|
||||
border-bottom-color:$white-color;
|
||||
}
|
||||
|
||||
&.bs-tooltip-left .arrow:before{
|
||||
border-left-color:$white-color;
|
||||
}
|
||||
}
|
||||
|
||||
.tooltip-inner{
|
||||
padding: $padding-base-vertical $padding-base-horizontal;
|
||||
min-width: 130px;
|
||||
background-color: $white-color;
|
||||
font-size: $font-size-base;
|
||||
color: inherit;
|
||||
box-shadow: 0px 5px 25px 0px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
|
@ -0,0 +1,126 @@
|
|||
// This file has been autogenerated by grunt task lessToSass. Any changes will be overwritten.
|
||||
.progress-container{
|
||||
position: relative;
|
||||
|
||||
& + .progress-container,
|
||||
& ~ .progress-container{
|
||||
margin-top: $margin-base-vertical;
|
||||
}
|
||||
.progress-badge{
|
||||
color: $default-color;
|
||||
font-size: $font-size-small;
|
||||
text-transform: uppercase;
|
||||
|
||||
}
|
||||
|
||||
.progress {
|
||||
height: 1px;
|
||||
border-radius: 0;
|
||||
box-shadow: none;
|
||||
background: $opacity-gray-8;
|
||||
margin-top: 14px;
|
||||
|
||||
.progress-bar {
|
||||
box-shadow: none;
|
||||
background-color: $default-color;
|
||||
}
|
||||
|
||||
.progress-value{
|
||||
position: absolute;
|
||||
top: 2px;
|
||||
right: 0;
|
||||
color: $default-color;
|
||||
font-size: $font-size-small;
|
||||
}
|
||||
}
|
||||
|
||||
&.progress-neutral{
|
||||
.progress{
|
||||
background: rgba(255, 255, 255, .3);
|
||||
}
|
||||
|
||||
.progress-bar{
|
||||
background: $white-bg;
|
||||
}
|
||||
|
||||
.progress-value,
|
||||
.progress-badge{
|
||||
color: $white-color;
|
||||
}
|
||||
}
|
||||
|
||||
&.progress-primary{
|
||||
.progress{
|
||||
background: $primary-color-opacity;
|
||||
}
|
||||
|
||||
.progress-bar{
|
||||
background: $brand-primary;
|
||||
}
|
||||
|
||||
.progress-value,
|
||||
.progress-badge{
|
||||
color: $brand-primary;
|
||||
}
|
||||
}
|
||||
|
||||
&.progress-info{
|
||||
.progress{
|
||||
background: $info-color-opacity;
|
||||
}
|
||||
|
||||
.progress-bar{
|
||||
background: $brand-info;
|
||||
}
|
||||
|
||||
.progress-value,
|
||||
.progress-badge{
|
||||
color: $brand-info;
|
||||
}
|
||||
}
|
||||
|
||||
&.progress-success{
|
||||
.progress{
|
||||
background: $success-color-opacity;
|
||||
}
|
||||
|
||||
.progress-bar{
|
||||
background: $brand-success;
|
||||
}
|
||||
|
||||
.progress-value,
|
||||
.progress-badge{
|
||||
color: $brand-success;
|
||||
}
|
||||
}
|
||||
|
||||
&.progress-warning{
|
||||
.progress{
|
||||
background: $warning-color-opacity;
|
||||
}
|
||||
|
||||
.progress-bar{
|
||||
background: $brand-warning;
|
||||
}
|
||||
|
||||
.progress-value,
|
||||
.progress-badge{
|
||||
color: $brand-warning;
|
||||
}
|
||||
}
|
||||
|
||||
&.progress-danger{
|
||||
.progress{
|
||||
background: $danger-color-opacity;
|
||||
}
|
||||
|
||||
.progress-bar{
|
||||
background: $brand-danger;
|
||||
}
|
||||
|
||||
.progress-value,
|
||||
.progress-badge{
|
||||
color: $brand-danger;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,392 @@
|
|||
@media screen and (max-width: 991px){
|
||||
.sidebar-collapse{
|
||||
@include navbar-collapse();
|
||||
|
||||
&.menu-on-left{
|
||||
.navbar-collapse{
|
||||
right: auto;
|
||||
left: 0;
|
||||
@include transform-translate-x(-300px);
|
||||
}
|
||||
}
|
||||
|
||||
.nav-open &{
|
||||
.navbar-collapse{
|
||||
@include transform-translate-x(0px);
|
||||
}
|
||||
|
||||
.wrapper{
|
||||
@include transform-translate-x(-150px);
|
||||
}
|
||||
|
||||
.navbar-translate{
|
||||
@include transform-translate-x(-300px);
|
||||
}
|
||||
|
||||
&.menu-on-left{
|
||||
.navbar-collapse{
|
||||
@include transform-translate-x(0px);
|
||||
}
|
||||
|
||||
.navbar-translate{
|
||||
@include transform-translate-x(300px);
|
||||
}
|
||||
|
||||
.wrapper{
|
||||
@include transform-translate-x(150px);
|
||||
}
|
||||
|
||||
#bodyClick{
|
||||
right: auto;
|
||||
left: 300px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.bootstrap-collapse{
|
||||
.navbar .navbar-collapse{
|
||||
background: none !important;
|
||||
}
|
||||
@include navbar-responsive();
|
||||
}
|
||||
|
||||
.profile-photo .profile-photo-small{
|
||||
margin-left: -2px;
|
||||
}
|
||||
|
||||
.button-dropdown{
|
||||
display: none;
|
||||
}
|
||||
|
||||
.section-nucleo-icons .container .row > [class*="col-"]:first-child{
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.footer{
|
||||
.copyright{
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
|
||||
.section-nucleo-icons .icons-container{
|
||||
margin-top: 65px;
|
||||
}
|
||||
|
||||
.navbar-nav{
|
||||
.nav-link{
|
||||
i.fa,
|
||||
i.now-ui-icons{
|
||||
opacity: .5;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.section-images{
|
||||
height: 500px;
|
||||
max-height: 500px;
|
||||
|
||||
.hero-images-container{
|
||||
max-width: 500px;
|
||||
}
|
||||
|
||||
.hero-images-container-1{
|
||||
right: 10%;
|
||||
top: 68%;
|
||||
max-width: 269px;
|
||||
}
|
||||
|
||||
.hero-images-container-2{
|
||||
right: 5%;
|
||||
max-width: 135px;
|
||||
top: 93%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (min-width: 992px){
|
||||
.burger-menu{
|
||||
@include navbar-collapse();
|
||||
|
||||
.nav-open & .navbar-collapse{
|
||||
@include transform-translate-x(0px);
|
||||
}
|
||||
|
||||
.navbar-collapse {
|
||||
display: block !important;
|
||||
|
||||
.navbar-nav {
|
||||
margin-top: 53px;
|
||||
height: 100%;
|
||||
z-index: 2;
|
||||
position: relative;
|
||||
display: -webkit-box;
|
||||
display: -webkit-flex;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-box-direction: normal;
|
||||
-webkit-flex-direction: column;
|
||||
-ms-flex-direction: column;
|
||||
flex-direction: column;
|
||||
|
||||
.nav-item{
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.menu-on-left .navbar-collapse{
|
||||
right: auto;
|
||||
left: 0;
|
||||
@include transform-translate-x(-300px);
|
||||
}
|
||||
|
||||
[class*="navbar-expand-"]{
|
||||
.navbar-nav .dropdown-menu{
|
||||
position: static;
|
||||
float: none;
|
||||
}
|
||||
|
||||
.navbar-toggler{
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
|
||||
.section-navbars .navbar-collapse{
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.nav-open &{
|
||||
&.menu-on-left .navbar .navbar-translate{
|
||||
@include transform-translate-x(300px);
|
||||
}
|
||||
|
||||
.navbar .navbar-translate{
|
||||
@include transform-translate-x(-300px);
|
||||
}
|
||||
|
||||
&.menu-on-left .navbar-collapse{
|
||||
@include transform-translate-x(0px);
|
||||
}
|
||||
|
||||
&.menu-on-left #bodyClick{
|
||||
right: auto;
|
||||
left: 300px;
|
||||
}
|
||||
}
|
||||
|
||||
&.menu-on-left .navbar-brand{
|
||||
float: right;
|
||||
margin-right: 0;
|
||||
margin-left: 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
.navbar-nav{
|
||||
.nav-link{
|
||||
&.profile-photo{
|
||||
padding: 0;
|
||||
margin: 7px $padding-base-horizontal;
|
||||
}
|
||||
|
||||
&.btn:not(.btn-sm){
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.nav-item:not(:last-child){
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.section-nucleo-icons .icons-container{
|
||||
margin: 0 0 0 auto;
|
||||
}
|
||||
|
||||
.dropdown-menu .dropdown-item{
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.footer{
|
||||
.copyright{
|
||||
float: right;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (min-width: 768px){
|
||||
.image-container{
|
||||
&.image-right{
|
||||
top: 80px;
|
||||
margin-left: - 100px;
|
||||
margin-bottom: 130px;
|
||||
}
|
||||
|
||||
&.image-left{
|
||||
margin-right: -100px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 768px){
|
||||
.image-container{
|
||||
&.image-left{
|
||||
margin-bottom: 220px;
|
||||
|
||||
p.blockquote{
|
||||
margin: 0 auto;
|
||||
position: relative;
|
||||
right: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.nav-tabs{
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
padding-left: 100px;
|
||||
padding-right: 100px;
|
||||
text-align: center;
|
||||
|
||||
.nav-item > .nav-link{
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.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-expand-'] .container{
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.footer{
|
||||
.copyright{
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
.section-nucleo-icons{
|
||||
.icons-container{
|
||||
i{
|
||||
font-size: 30px;
|
||||
|
||||
&:nth-child(6){
|
||||
font-size: 48px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.page-header{
|
||||
.container h6.category-absolute{
|
||||
width: 90%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (min-width: 991px) and (max-width: 1200px){
|
||||
.section-images{
|
||||
.hero-images-container-1{
|
||||
right: 9%;
|
||||
max-width: 370px;
|
||||
}
|
||||
|
||||
.hero-images-container-2{
|
||||
right: 2%;
|
||||
max-width: 216px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 768px){
|
||||
.section-images{
|
||||
height: 300px;
|
||||
max-height: 300px;
|
||||
|
||||
.hero-images-container{
|
||||
max-width: 380px;
|
||||
}
|
||||
|
||||
.hero-images-container-1{
|
||||
right: 7%;
|
||||
top: 87%;
|
||||
max-width: 210px;
|
||||
}
|
||||
|
||||
.hero-images-container-2{
|
||||
right: 1%;
|
||||
max-width: 133px;
|
||||
top: 99%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 517px) {
|
||||
.alert .alert-icon{
|
||||
margin-top: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (min-width: 1200px) {
|
||||
.section-images{
|
||||
.hero-images-container-1{
|
||||
top: 51%;
|
||||
right: 21%;
|
||||
}
|
||||
|
||||
.hero-images-container-2{
|
||||
top: 66%;
|
||||
right: 14%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Ipad responsive portrait mode
|
||||
@media only screen
|
||||
and (min-device-width : 768px)
|
||||
and (max-device-width : 1024px)
|
||||
and ( orientation : portrait){
|
||||
.section-images .hero-images-container,
|
||||
.section-images .hero-images-container-1,
|
||||
.section-images .hero-images-container-2{
|
||||
margin-top: -15vh;
|
||||
margin-left: 80px;
|
||||
}
|
||||
|
||||
.section-images .hero-images-container{
|
||||
max-width: 300px;
|
||||
}
|
||||
|
||||
.section-images .hero-images-container-1{
|
||||
right: 28%;
|
||||
top: 40%;
|
||||
}
|
||||
|
||||
.section-images .hero-images-container-2{
|
||||
right: 21%;
|
||||
top: 55%;
|
||||
}
|
||||
|
||||
.index-page .category-absolute{
|
||||
top: 90vh;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 580px) {
|
||||
.alert{
|
||||
button.close{
|
||||
position: absolute;
|
||||
right: 11px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,396 @@
|
|||
.section{
|
||||
padding: 70px 0;
|
||||
position: relative;
|
||||
background: $white-color;
|
||||
|
||||
.row + .category{
|
||||
margin-top: $margin-base-vertical;
|
||||
}
|
||||
}
|
||||
.section-navbars{
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
.section-full-screen{
|
||||
height: 100vh;
|
||||
}
|
||||
.section-signup{
|
||||
padding-top: 20vh;
|
||||
}
|
||||
|
||||
.page-header{
|
||||
height: 100vh;
|
||||
max-height: 1050px;
|
||||
padding: 0;
|
||||
color: $white-color;
|
||||
position: relative;
|
||||
|
||||
background-position: center center;
|
||||
background-size: cover;
|
||||
|
||||
.page-header-image{
|
||||
position: absolute;
|
||||
background-size: cover;
|
||||
background-position: center center;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
footer{
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
}
|
||||
.container{
|
||||
height: 100%;
|
||||
z-index: 1;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
|
||||
> .content-center{
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
|
||||
-ms-transform: translate(-50%,-50%);
|
||||
-webkit-transform: translate(-50%,-50%);
|
||||
transform: translate(-50%,-50%);
|
||||
|
||||
text-align: center;
|
||||
padding: 0 15px;
|
||||
color: #FFFFFF;
|
||||
width: 100%;
|
||||
max-width: 880px;
|
||||
}
|
||||
}
|
||||
.category,
|
||||
.description{
|
||||
color: $opacity-5;
|
||||
}
|
||||
|
||||
&.page-header-small{
|
||||
height: 60vh;
|
||||
max-height: 440px;
|
||||
}
|
||||
|
||||
&:after,
|
||||
&:before{
|
||||
position: absolute;
|
||||
z-index: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: block;
|
||||
left: 0;
|
||||
top: 0;
|
||||
content: "";
|
||||
}
|
||||
|
||||
&:before{
|
||||
background-color: rgba(0,0,0,.5);
|
||||
}
|
||||
|
||||
&[filter-color="orange"]{
|
||||
@include linear-gradient(rgba($black-color,.20), rgba(224, 23, 3, 0.6));
|
||||
}
|
||||
|
||||
.container{
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.clear-filter{
|
||||
&:after,
|
||||
&:before{
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.section-story-overview{
|
||||
padding: 50px 0;
|
||||
|
||||
.image-container{
|
||||
height: 335px;
|
||||
position: relative;
|
||||
background-position: center center;
|
||||
background-size: cover;
|
||||
box-shadow: $box-shadow-raised;
|
||||
border-radius: .25rem;
|
||||
|
||||
& + .category{
|
||||
padding-top: 15px;
|
||||
}
|
||||
|
||||
&.image-right{
|
||||
z-index: 2;
|
||||
|
||||
+ h3.title{
|
||||
margin-top: 120px;
|
||||
}
|
||||
}
|
||||
|
||||
&.image-left{
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
&:nth-child(2){
|
||||
margin-top: 420px;
|
||||
margin-left: -105px;
|
||||
}
|
||||
}
|
||||
|
||||
p.blockquote{
|
||||
width: 220px;
|
||||
min-height: 180px;
|
||||
text-align: left;
|
||||
position: absolute;
|
||||
top: 376px;
|
||||
right: 155px;
|
||||
z-index: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.section-nucleo-icons{
|
||||
.nucleo-container img{
|
||||
width: auto;
|
||||
left: 0;
|
||||
top: 0;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.nucleo-container{
|
||||
height: 335px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
h5{
|
||||
margin-bottom: 35px;
|
||||
}
|
||||
|
||||
.icons-container{
|
||||
position: relative;
|
||||
max-width: 450px;
|
||||
height: 300px;
|
||||
max-height: 300px;
|
||||
margin: 0 auto;
|
||||
|
||||
}
|
||||
.icons-container i{
|
||||
font-size: 34px;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.icons-container i:nth-child(1){
|
||||
top: 5%;
|
||||
left: 7%;
|
||||
}
|
||||
|
||||
.icons-container i:nth-child(2){
|
||||
top: 28%;
|
||||
left: 24%;
|
||||
}
|
||||
|
||||
.icons-container i:nth-child(3){
|
||||
top: 40%;
|
||||
}
|
||||
|
||||
.icons-container i:nth-child(4){
|
||||
top: 18%;
|
||||
left: 62%;
|
||||
}
|
||||
|
||||
.icons-container i:nth-child(5){
|
||||
top: 74%;
|
||||
left: 3%;
|
||||
}
|
||||
|
||||
.icons-container i:nth-child(6){
|
||||
top: 36%;
|
||||
left: 44%;
|
||||
font-size: 65px;
|
||||
color: #f96332;
|
||||
padding: 1px;
|
||||
}
|
||||
|
||||
.icons-container i:nth-child(7){
|
||||
top: 59%;
|
||||
left: 26%;
|
||||
}
|
||||
|
||||
.icons-container i:nth-child(8){
|
||||
top: 60%;
|
||||
left: 69%;
|
||||
}
|
||||
|
||||
.icons-container i:nth-child(9){
|
||||
top: 72%;
|
||||
left: 47%;
|
||||
}
|
||||
|
||||
.icons-container i:nth-child(10){
|
||||
top: 88%;
|
||||
left: 27%;
|
||||
}
|
||||
|
||||
.icons-container i:nth-child(11){
|
||||
top: 31%;
|
||||
left: 80%;
|
||||
}
|
||||
|
||||
.icons-container i:nth-child(12){
|
||||
top: 88%;
|
||||
left: 68%;
|
||||
}
|
||||
|
||||
.icons-container i:nth-child(13){
|
||||
top: 5%;
|
||||
left: 81%;
|
||||
}
|
||||
|
||||
.icons-container i:nth-child(14){
|
||||
top: 58%;
|
||||
left: 90%;
|
||||
}
|
||||
|
||||
.icons-container i:nth-child(15){
|
||||
top: 6%;
|
||||
left: 40%;
|
||||
}
|
||||
}
|
||||
|
||||
.section-images{
|
||||
max-height: 670px;
|
||||
height: 670px;
|
||||
|
||||
.hero-images-container,
|
||||
.hero-images-container-1,
|
||||
.hero-images-container-2{
|
||||
margin-top: -38vh;
|
||||
}
|
||||
|
||||
.hero-images-container{
|
||||
max-width: 670px;
|
||||
}
|
||||
|
||||
.hero-images-container-1{
|
||||
max-width: 390px;
|
||||
position: absolute;
|
||||
top: 55%;
|
||||
right: 18%;
|
||||
|
||||
}
|
||||
|
||||
.hero-images-container-2{
|
||||
max-width: 225px;
|
||||
position: absolute;
|
||||
top: 68%;
|
||||
right: 12%;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[data-background-color="orange"]{
|
||||
background-color: $orange-bg;
|
||||
}
|
||||
[data-background-color="black"]{
|
||||
background-color: $black-color;
|
||||
}
|
||||
|
||||
[data-background-color]{
|
||||
color: $white-color;
|
||||
|
||||
.title,
|
||||
.social-description h2,
|
||||
p,
|
||||
p.blockquote,
|
||||
p.blockquote small,
|
||||
h1,h2,h3,h4,h5,h6,a:not(.btn):not(.dropdown-item),
|
||||
.icons-container i{
|
||||
color: $white-color;
|
||||
}
|
||||
|
||||
.separator{
|
||||
background-color: $white-color;
|
||||
}
|
||||
|
||||
.navbar.bg-white p{
|
||||
color: $default-color;
|
||||
}
|
||||
|
||||
.description,
|
||||
.social-description p{
|
||||
color: $opacity-8;
|
||||
}
|
||||
|
||||
p.blockquote{
|
||||
border-color: $opacity-2;
|
||||
}
|
||||
|
||||
//radio and checkboxes
|
||||
.checkbox label::before,
|
||||
.checkbox label::after,
|
||||
.radio label::before,
|
||||
.radio label::after{
|
||||
border-color: $opacity-2;
|
||||
}
|
||||
|
||||
.checkbox label::after,
|
||||
.checkbox label,
|
||||
.radio label{
|
||||
color: $white-color;
|
||||
}
|
||||
|
||||
.checkbox input[type="checkbox"]:disabled + label,
|
||||
.radio input[type="radio"]:disabled + label {
|
||||
color: $white-color;
|
||||
}
|
||||
|
||||
.radio input[type="radio"]:not(:disabled):hover + label::after,
|
||||
.radio input[type="radio"]:checked + label::after {
|
||||
background-color: $white-color;
|
||||
border-color: $white-color;
|
||||
}
|
||||
|
||||
//inputs
|
||||
@include input-coloured-bg($opacity-5, $white-color, $white-color, $transparent-bg, $opacity-1, $opacity-2);
|
||||
|
||||
.input-group-addon,
|
||||
.form-group.form-group-no-border .input-group-addon,
|
||||
.input-group.form-group-no-border .input-group-addon{
|
||||
color: $opacity-8;
|
||||
}
|
||||
|
||||
//buttons
|
||||
.btn.btn-simple{
|
||||
background-color: $transparent-bg;
|
||||
border-color: $opacity-5;
|
||||
color: $white-color;
|
||||
|
||||
&:hover,
|
||||
&:hover,
|
||||
&:focus,
|
||||
&:active{
|
||||
background-color: $transparent-bg;
|
||||
border-color: $white-color;
|
||||
}
|
||||
}
|
||||
|
||||
//tabs
|
||||
.nav-tabs{
|
||||
> .nav-item{
|
||||
>.nav-link{
|
||||
i.now-ui-icons{
|
||||
color: $white-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.section-nucleo-icons .icons-container i:nth-child(6){
|
||||
color: $white-color;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
.btn-twitter{
|
||||
color: $social-twitter;
|
||||
|
||||
&:hover,
|
||||
&:focus,
|
||||
&:active{
|
||||
color: $social-twitter-state-color;
|
||||
}
|
||||
}
|
||||
|
||||
.btn-facebook{
|
||||
color: $social-facebook;
|
||||
|
||||
&:hover,
|
||||
&:focus,
|
||||
&:active{
|
||||
color: $social-facebook-state-color;
|
||||
}
|
||||
}
|
||||
|
||||
.btn-google{
|
||||
color: $social-google;
|
||||
|
||||
&:hover,
|
||||
&:focus,
|
||||
&:active{
|
||||
color: $social-google-state-color;
|
||||
}
|
||||
}
|
||||
|
||||
.btn-linkedin{
|
||||
color: $social-linkedin;
|
||||
|
||||
&:hover,
|
||||
&:focus,
|
||||
&:active{
|
||||
color: $social-linkedin-state-color;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,110 @@
|
|||
// This file has been autogenerated by grunt task lessToSass. Any changes will be overwritten.
|
||||
|
||||
.nav-tabs {
|
||||
border: 0;
|
||||
padding: $padding-large-vertical $padding-base-horizontal;
|
||||
|
||||
> .nav-item{
|
||||
> .nav-link{
|
||||
color: $default-color;
|
||||
margin: 0;
|
||||
margin-right: 5px;
|
||||
background-color: $transparent-bg;
|
||||
border: 1px solid $transparent-bg;
|
||||
border-radius: 30px;
|
||||
font-size: $font-size-base;
|
||||
padding: $padding-btn-vertical $padding-round-horizontal;
|
||||
line-height: $line-height-general;
|
||||
|
||||
&:hover {
|
||||
background-color: $transparent-bg;
|
||||
}
|
||||
|
||||
&.active{
|
||||
border: 1px solid $default-color;
|
||||
border-radius: 30px;
|
||||
}
|
||||
|
||||
i.now-ui-icons{
|
||||
font-size: 14px;
|
||||
position: relative;
|
||||
top: 1px;
|
||||
margin-right: 3px;
|
||||
}
|
||||
}
|
||||
|
||||
&.disabled > .nav-link,
|
||||
&.disabled > .nav-link:hover {
|
||||
color: rgba(255,255,255,0.5);
|
||||
}
|
||||
}
|
||||
|
||||
&.nav-tabs-neutral{
|
||||
> .nav-item{
|
||||
> .nav-link{
|
||||
color: $white-color;
|
||||
|
||||
&.active{
|
||||
border-color: $opacity-5;
|
||||
color: $white-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.nav-tabs-primary{
|
||||
> .nav-item{
|
||||
> .nav-link{
|
||||
&.active{
|
||||
border-color: $primary-color;
|
||||
color: $primary-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.nav-tabs-info{
|
||||
> .nav-item{
|
||||
> .nav-link{
|
||||
&.active{
|
||||
border-color: $info-color;
|
||||
color: $info-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.nav-tabs-danger{
|
||||
> .nav-item{
|
||||
> .nav-link{
|
||||
&.active{
|
||||
border-color: $danger-color;
|
||||
color: $danger-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.nav-tabs-warning{
|
||||
> .nav-item{
|
||||
> .nav-link{
|
||||
&.active{
|
||||
border-color: $warning-color;
|
||||
color: $warning-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.nav-tabs-success{
|
||||
> .nav-item{
|
||||
> .nav-link{
|
||||
&.active{
|
||||
border-color: $success-color;
|
||||
color: $success-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,158 @@
|
|||
button,
|
||||
input,
|
||||
optgroup,
|
||||
select,
|
||||
textarea{
|
||||
font-family: $sans-serif-family;
|
||||
}
|
||||
h1,h2,h3,h4,h5,h6{
|
||||
font-weight: $font-weight-normal;
|
||||
}
|
||||
|
||||
small{
|
||||
font-size: 60%;
|
||||
}
|
||||
|
||||
a{
|
||||
color: $primary-color;
|
||||
&:hover,
|
||||
&:focus{
|
||||
color: $primary-color;
|
||||
}
|
||||
}
|
||||
h1, .h1 {
|
||||
font-size: $font-size-h1;
|
||||
line-height: 1.15;
|
||||
margin-bottom: $margin-base-vertical * 2;
|
||||
|
||||
small{
|
||||
font-weight: $font-weight-bold;
|
||||
text-transform: uppercase;
|
||||
opacity: .8;
|
||||
}
|
||||
}
|
||||
h2, .h2{
|
||||
font-size: $font-size-h2;
|
||||
margin-bottom: $margin-base-vertical * 2;
|
||||
}
|
||||
h3, .h3{
|
||||
font-size: $font-size-h3;
|
||||
margin-bottom: $margin-base-vertical * 2;
|
||||
line-height: 1.4em;
|
||||
}
|
||||
h4, .h4{
|
||||
font-size: $font-size-h4;
|
||||
line-height: 1.45em;
|
||||
margin-top: $margin-base-vertical * 2;
|
||||
margin-bottom: $margin-base-vertical;
|
||||
|
||||
& + .category,
|
||||
&.title + .category{
|
||||
margin-top: -10px;
|
||||
}
|
||||
}
|
||||
h5, .h5 {
|
||||
font-size: $font-size-h5;
|
||||
line-height: 1.4em;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
h6, .h6{
|
||||
font-size: $font-size-h6;
|
||||
font-weight: $font-weight-bold;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
p{
|
||||
line-height: 1.61em;
|
||||
|
||||
.description &,
|
||||
&.description{
|
||||
font-size: 1.14em;
|
||||
}
|
||||
}
|
||||
|
||||
.title{
|
||||
font-weight: $font-weight-bold;
|
||||
|
||||
&.title-up{
|
||||
text-transform: uppercase;
|
||||
|
||||
a{
|
||||
color: $black-color;
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
& + .category{
|
||||
margin-top: -25px;
|
||||
}
|
||||
}
|
||||
|
||||
.description,
|
||||
.card-description,
|
||||
.footer-big p{
|
||||
color: $dark-gray;
|
||||
font-weight: $font-weight-light;
|
||||
}
|
||||
.category{
|
||||
text-transform: uppercase;
|
||||
font-weight: $font-weight-bold;
|
||||
color: $dark-gray;
|
||||
}
|
||||
.text-primary {
|
||||
color: $brand-primary !important;
|
||||
}
|
||||
.text-info {
|
||||
color: $brand-info !important;
|
||||
}
|
||||
.text-success {
|
||||
color: $brand-success !important;
|
||||
}
|
||||
.text-warning {
|
||||
color: $brand-warning !important;
|
||||
}
|
||||
.text-danger {
|
||||
color: $brand-danger !important;
|
||||
}
|
||||
.text-black{
|
||||
color: $light-black;
|
||||
}
|
||||
|
||||
.blockquote{
|
||||
border-left: none;
|
||||
border: 1px solid $default-color;
|
||||
padding: 20px;
|
||||
font-size: $font-size-blockquote;
|
||||
line-height: 1.8;
|
||||
|
||||
small{
|
||||
color: $default-color;
|
||||
font-size: $font-size-small;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
&.blockquote-primary{
|
||||
border-color: $primary-color;
|
||||
color: $primary-color;
|
||||
|
||||
small{
|
||||
color: $primary-color;
|
||||
}
|
||||
}
|
||||
|
||||
&.blockquote-danger{
|
||||
border-color: $danger-color;
|
||||
color: $danger-color;
|
||||
|
||||
small{
|
||||
color: $danger-color;
|
||||
}
|
||||
}
|
||||
|
||||
&.blockquote-white{
|
||||
border-color: $opacity-8;
|
||||
color: $white-color;
|
||||
|
||||
small{
|
||||
color: $opacity-8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,254 @@
|
|||
//== Buttons
|
||||
//
|
||||
//## For each of Bootstrap's buttons, define text, background and border color.
|
||||
|
||||
$sans-serif-family: 'Montserrat', 'Helvetica Neue', Arial, sans-serif;
|
||||
|
||||
$none: 0 !default;
|
||||
$border-thin: 1px !default;
|
||||
$border-thick: 2px !default;
|
||||
|
||||
$white-color: #FFFFFF !default;
|
||||
$white-bg: #FFFFFF !default;
|
||||
$orange-bg: #e95e38 !default;
|
||||
|
||||
$smoke-bg: #F5F5F5 !default;
|
||||
$light-black: #444 !default;
|
||||
|
||||
$black-bg: rgba(30,30,30,.97) !default;
|
||||
|
||||
$black-color: #2c2c2c !default;
|
||||
$black-hr: #444444 !default;
|
||||
|
||||
$light-gray: #E3E3E3 !default;
|
||||
$medium-gray: #DDDDDD !default;
|
||||
$dark-gray: #9A9A9A !default;
|
||||
|
||||
$opacity-gray-3: rgba(222,222,222, .3) !default;
|
||||
$opacity-gray-5: rgba(222,222,222, .5) !default;
|
||||
$opacity-gray-8: rgba(222,222,222, .8) !default;
|
||||
|
||||
|
||||
$opacity-5: rgba(255,255,255, .5) !default;
|
||||
$opacity-8: rgba(255,255,255, .8) !default;
|
||||
|
||||
$datepicker-color-days: rgba(255,255,255, .8) !default;
|
||||
$datepicker-color-old-new-days: rgba(255,255,255, .4) !default;
|
||||
|
||||
|
||||
$opacity-1: rgba(255,255,255, .1) !default;
|
||||
$opacity-2: rgba(255,255,255, .2) !default;
|
||||
|
||||
$transparent-bg: transparent !default;
|
||||
$dark-background: #555555 !default;
|
||||
|
||||
$default-color: #888 !default;
|
||||
$default-states-color: lighten($default-color, 6%) !default;
|
||||
$default-color-opacity: rgba(182, 182, 182, .6) !default;
|
||||
|
||||
$primary-color: #f96332 !default;
|
||||
$primary-states-color: lighten($primary-color, 6%) !default;
|
||||
$primary-color-opacity: rgba(249, 99, 50, .3) !default;
|
||||
$primary-color-alert: rgba(249, 99, 50, .8) !default;
|
||||
|
||||
$success-color: #18ce0f !default;
|
||||
$success-states-color: lighten($success-color, 6%) !default;
|
||||
$success-color-opacity: rgba(24, 206, 15, .3) !default;
|
||||
$success-color-alert: rgba(24, 206, 15, .8) !default;
|
||||
|
||||
$info-color: #2CA8FF !default;
|
||||
$info-states-color: lighten($info-color, 6%) !default;
|
||||
$info-color-opacity: rgba(44, 168, 255, .3) !default;
|
||||
$info-color-alert: rgba(44, 168, 255, .8) !default;
|
||||
|
||||
$warning-color: #FFB236 !default;
|
||||
$warning-states-color: lighten($warning-color, 6%) !default;
|
||||
$warning-color-opacity: rgba(255, 178, 54, .3) !default;
|
||||
$warning-color-alert: rgba(255, 178, 54, .8) !default;
|
||||
|
||||
$danger-color: #FF3636 !default;
|
||||
$danger-states-color: lighten($danger-color, 6%) !default;
|
||||
$danger-color-opacity: rgba(255, 54, 54, .3) !default;
|
||||
$danger-color-alert: rgba(255, 54, 54, .8) !default;
|
||||
|
||||
/* brand Colors */
|
||||
$brand-primary: $primary-color !default;
|
||||
$brand-info: $info-color !default;
|
||||
$brand-success: $success-color !default;
|
||||
$brand-warning: $warning-color !default;
|
||||
$brand-danger: $danger-color !default;
|
||||
$brand-inverse: $black-color !default;
|
||||
|
||||
$link-disabled-color: #666666 !default;
|
||||
|
||||
/* light colors */
|
||||
$light-blue: rgba($primary-color, .2);
|
||||
$light-azure: rgba($info-color, .2);
|
||||
$light-green: rgba($success-color, .2);
|
||||
$light-orange: rgba($warning-color, .2);
|
||||
$light-red: rgba($danger-color, .2);
|
||||
|
||||
//== Components
|
||||
//
|
||||
|
||||
$padding-input-vertical: 11px !default;
|
||||
$padding-input-horizontal: 19px !default;
|
||||
|
||||
$padding-btn-vertical: 11px !default;
|
||||
$padding-btn-horizontal: 22px !default;
|
||||
|
||||
$padding-base-vertical: .5rem !default;
|
||||
$padding-base-horizontal: .7rem !default;
|
||||
|
||||
$padding-round-horizontal: 23px !default;
|
||||
|
||||
$padding-simple-vertical: 10px !default;
|
||||
$padding-simple-horizontal: 17px !default;
|
||||
|
||||
$padding-large-vertical: 15px !default;
|
||||
$padding-large-horizontal: 48px !default;
|
||||
|
||||
$padding-small-vertical: 5px !default;
|
||||
$padding-small-horizontal: 15px !default;
|
||||
|
||||
// $padding-xs-vertical: 1px !default;
|
||||
// $padding-xs-horizontal: 5px !default;
|
||||
|
||||
$padding-label-vertical: 2px !default;
|
||||
$padding-label-horizontal: 12px !default;
|
||||
|
||||
$margin-large-vertical: 30px !default;
|
||||
$margin-base-vertical: 15px !default;
|
||||
|
||||
$margin-base-horizontal: 15px !default;
|
||||
|
||||
$margin-bottom: 10px !default;
|
||||
$border: 1px solid !default;
|
||||
$border-radius-extra-small: 0.125rem !default;
|
||||
$border-radius-small: 0.1875rem !default;
|
||||
$border-radius-large: 0.25rem !default;
|
||||
$border-radius-extreme: 0.875rem !default;
|
||||
|
||||
$border-radius-large-top: $border-radius-large $border-radius-large 0 0 !default;
|
||||
$border-radius-large-bottom: 0 0 $border-radius-large $border-radius-large !default;
|
||||
|
||||
$btn-round-radius: 30px !default;
|
||||
|
||||
$height-base: 55px !default;
|
||||
|
||||
$btn-icon-size: 3.5rem !default;
|
||||
$btn-icon-size-regular: 2.375rem !default;
|
||||
$btn-icon-font-size-regular: 0.9375rem !default;
|
||||
$btn-icon-font-size-small: 0.6875rem !default;
|
||||
$btn-icon-size-small: 1.875rem !default;
|
||||
$btn-icon-font-size-lg: 1.325rem !default;
|
||||
$btn-icon-size-lg: 3.6rem !default;
|
||||
|
||||
$font-size-h1: 3.5em !default; // ~ 49px
|
||||
$font-size-h2: 2.5em !default; // ~ 35px
|
||||
$font-size-h3: 2em !default; // ~ 28px
|
||||
$font-size-h4: 1.714em !default; // ~ 24px
|
||||
$font-size-h5: 1.57em !default; // ~ 22px
|
||||
$font-size-h6: 1em !default; // ~ 14px
|
||||
|
||||
$font-paragraph: 1em !default;
|
||||
$font-size-navbar: 1em !default;
|
||||
$font-size-mini: 0.7142em !default;
|
||||
$font-size-small: 0.8571em !default;
|
||||
$font-size-base: 14px !default;
|
||||
$font-size-large: 1em !default;
|
||||
$font-size-large-navbar: 20px !default;
|
||||
$font-size-blockquote: 1.1em !default; // ~ 15px
|
||||
|
||||
$font-weight-light: 300 !default;
|
||||
$font-weight-normal: 400 !default;
|
||||
$font-weight-semi: 600 !default;
|
||||
$font-weight-bold: 700 !default;
|
||||
|
||||
$line-height-general: 1.5 !default;
|
||||
$line-height-nav-link: 1.625rem !default;
|
||||
$btn-icon-line-height: 2.4em !default;
|
||||
$line-height: 1.35em !default;
|
||||
$line-height-lg: 54px !default;
|
||||
|
||||
|
||||
$border-radius-top: 10px 10px 0 0 !default;
|
||||
$border-radius-bottom: 0 0 10px 10px !default;
|
||||
|
||||
$dropdown-shadow: 1px 2px 3px rgba(0, 0, 0, 0.125);
|
||||
$box-shadow-raised: 0px 10px 25px 0px rgba(0, 0, 0, 0.3);
|
||||
|
||||
$general-transition-time: 300ms !default;
|
||||
|
||||
$slow-transition-time: 370ms !default;
|
||||
$dropdown-coordinates: 29px -50px !default;
|
||||
|
||||
$fast-transition-time: 150ms !default;
|
||||
$select-coordinates: 50% -40px !default;
|
||||
|
||||
$transition-linear: linear !default;
|
||||
$transition-bezier: cubic-bezier(0.34, 1.61, 0.7, 1) !default;
|
||||
$transition-ease: ease 0s;
|
||||
|
||||
|
||||
//$navbar-padding-a: 9px 13px;
|
||||
$navbar-margin-a: 15px 0px;
|
||||
|
||||
$padding-social-a: 10px 5px;
|
||||
|
||||
$navbar-margin-a-btn: 15px 0px;
|
||||
$navbar-margin-a-btn-round: 16px 0px;
|
||||
|
||||
$navbar-padding-a-icons: 6px 15px;
|
||||
$navbar-margin-a-icons: 6px 3px;
|
||||
|
||||
$navbar-padding-base: 0.625rem;
|
||||
//$navbar-margin-brand: 5px 0px;
|
||||
|
||||
$navbar-margin-brand-icons: 12px auto;
|
||||
$navbar-margin-btn: 15px 3px;
|
||||
|
||||
$height-icon-sm: 32px;
|
||||
$width-icon-sm: 32px;
|
||||
$padding-icon-sm: 4px;
|
||||
$border-radius-icon-sm: 7px;
|
||||
|
||||
$height-icon-message: 40px;
|
||||
$width-icon-message: 40px;
|
||||
|
||||
$height-icon-message-sm: 20px;
|
||||
$width-icon-message-sm: 20px;
|
||||
|
||||
$white-navbar: rgba(#FFFFFF, .96);
|
||||
$primary-navbar: rgba(#34ACDC, .98);
|
||||
$info-navbar: rgba(#5BCAFF, .98);
|
||||
$success-navbar: rgba(#4CD964, .98);
|
||||
$warning-navbar: rgba(#FF9500, .98);
|
||||
$danger-navbar: rgba(#FF4C40, .98);
|
||||
|
||||
$topbar-x: topbar-x !default;
|
||||
$topbar-back: topbar-back !default;
|
||||
$bottombar-x: bottombar-x !default;
|
||||
$bottombar-back: bottombar-back !default;
|
||||
|
||||
//Nucleo Icons
|
||||
|
||||
$nc-font-path: '../fonts' !default;
|
||||
$nc-font-size-base: 14px !default;
|
||||
$nc-css-prefix: now-ui !default;
|
||||
$nc-background-color: #eee !default;
|
||||
$nc-li-width: (30em / 14) !default;
|
||||
$nc-padding-width: (1em/3) !default;
|
||||
|
||||
// Social icons color
|
||||
$social-twitter: #55acee !default;
|
||||
$social-twitter-state-color: darken(#55acee, 5%) !default;
|
||||
|
||||
$social-facebook: #3b5998 !default;
|
||||
$social-facebook-state-color: darken(#3b5998, 5%) !default;
|
||||
|
||||
$social-google: #dd4b39 !default;
|
||||
$social-google-state-color: darken(#dd4b39, 5%) !default;
|
||||
|
||||
$social-linkedin: #0077B5 !default;
|
||||
$social-linkedin-state-color: darken(#0077B5, 5%) !default;
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
@mixin badge-color($color) {
|
||||
border-color: $color;
|
||||
color: $color;
|
||||
}
|
||||
|
|
@ -0,0 +1,160 @@
|
|||
// Mixin for generating new styles
|
||||
@mixin btn-styles($btn-color, $btn-states-color) {
|
||||
background-color: $btn-color;
|
||||
|
||||
&:hover,
|
||||
&:focus,
|
||||
&:active,
|
||||
&.active,
|
||||
&:active:focus,
|
||||
&:active:hover,
|
||||
&.active:focus,
|
||||
&.active:hover,
|
||||
.show > &.dropdown-toggle,
|
||||
.show > &.dropdown-toggle:focus,
|
||||
.show > &.dropdown-toggle:hover {
|
||||
background-color: $btn-states-color;
|
||||
color: $white-color;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
&:hover{
|
||||
box-shadow: 0 3px 8px 0 rgba(0,0,0, 0.17);
|
||||
}
|
||||
|
||||
&.disabled,
|
||||
&:disabled,
|
||||
&[disabled],
|
||||
fieldset[disabled] & {
|
||||
&,
|
||||
&:hover,
|
||||
&:focus,
|
||||
&.focus,
|
||||
&:active,
|
||||
&.active {
|
||||
background-color: $btn-color;
|
||||
border-color: $btn-color;
|
||||
}
|
||||
}
|
||||
|
||||
// btn-neutral style
|
||||
@if $btn-color == $white-color{
|
||||
color: $primary-color;
|
||||
|
||||
&.btn-danger{
|
||||
color: $danger-color;
|
||||
|
||||
&:hover,
|
||||
&:focus,
|
||||
&:active{
|
||||
color: $danger-states-color;
|
||||
}
|
||||
}
|
||||
|
||||
&.btn-info{
|
||||
color: $info-color;
|
||||
|
||||
&:hover,
|
||||
&:focus,
|
||||
&:active{
|
||||
color: $info-states-color;
|
||||
}
|
||||
}
|
||||
|
||||
&.btn-warning{
|
||||
color: $warning-color;
|
||||
|
||||
&:hover,
|
||||
&:focus,
|
||||
&:active{
|
||||
color: $warning-states-color;
|
||||
}
|
||||
}
|
||||
|
||||
&.btn-success{
|
||||
color: $success-color;
|
||||
|
||||
&:hover,
|
||||
&:focus,
|
||||
&:active{
|
||||
color: $success-states-color;
|
||||
}
|
||||
}
|
||||
|
||||
&.btn-default{
|
||||
color: $default-color;
|
||||
|
||||
&:hover,
|
||||
&:focus,
|
||||
&:active{
|
||||
color: $default-states-color;
|
||||
}
|
||||
}
|
||||
|
||||
&.active,
|
||||
&:active,
|
||||
&:active:focus,
|
||||
&:active:hover,
|
||||
&.active:focus,
|
||||
&.active:hover,
|
||||
.show > &.dropdown-toggle,
|
||||
.show > &.dropdown-toggle:focus,
|
||||
.show > &.dropdown-toggle:hover {
|
||||
background-color: $white-color;
|
||||
color: $primary-states-color;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
&:hover,
|
||||
&:focus{
|
||||
color: $primary-states-color;
|
||||
|
||||
&:not(.nav-link){
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} @else {
|
||||
color: $white-color;
|
||||
}
|
||||
|
||||
&.btn-simple{
|
||||
color: $btn-color;
|
||||
border-color: $btn-color;
|
||||
|
||||
&:hover,
|
||||
&:focus,
|
||||
&:active{
|
||||
background-color: $transparent-bg;
|
||||
color: $btn-states-color;
|
||||
border-color: $btn-states-color;
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
|
||||
&.btn-link{
|
||||
color: $btn-color;
|
||||
|
||||
&:hover,
|
||||
&:focus,
|
||||
&:active{
|
||||
background-color: $transparent-bg;
|
||||
color: $btn-states-color;
|
||||
text-decoration: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@mixin btn-size($padding-vertical, $padding-horizontal, $font-size, $border){
|
||||
font-size: $font-size;
|
||||
border-radius: $border;
|
||||
padding: $padding-vertical $padding-horizontal;
|
||||
|
||||
&.btn-simple{
|
||||
padding: $padding-vertical - 1 $padding-horizontal - 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,121 @@
|
|||
@mixin datepicker-colors($color) {
|
||||
background-color: $color;
|
||||
|
||||
th,
|
||||
.day div,
|
||||
table tr td span{
|
||||
color: $white-color;
|
||||
}
|
||||
|
||||
&:after{
|
||||
border-bottom-color: $color;
|
||||
}
|
||||
|
||||
&.datepicker-orient-top:after{
|
||||
border-top-color: $color;
|
||||
}
|
||||
|
||||
.dow{
|
||||
color: $datepicker-color-days;
|
||||
}
|
||||
|
||||
table tr td.old div,
|
||||
table tr td.new div,
|
||||
table tr td span.old,
|
||||
table tr td span.new{
|
||||
color: $datepicker-color-old-new-days;
|
||||
}
|
||||
|
||||
table tr td span:hover,
|
||||
table tr td span.focused{
|
||||
background:$opacity-1;
|
||||
}
|
||||
|
||||
.datepicker-switch:hover,
|
||||
.prev:hover,
|
||||
.next:hover,
|
||||
tfoot tr th:hover {
|
||||
background: $opacity-2;
|
||||
}
|
||||
|
||||
table tr td.active div,
|
||||
table tr td.active:hover div,
|
||||
table tr td.active.disabled div,
|
||||
table tr td.active.disabled:hover div {
|
||||
|
||||
background-color: $white-color;
|
||||
color: $color;
|
||||
}
|
||||
|
||||
table tr td.day:hover div,
|
||||
table tr td.day.focused div {
|
||||
background: $opacity-2;
|
||||
}
|
||||
|
||||
table tr td.active:hover div,
|
||||
table tr td.active:hover:hover div,
|
||||
table tr td.active.disabled:hover div,
|
||||
table tr td.active.disabled:hover:hover div,
|
||||
table tr td.active:active div,
|
||||
table tr td.active:hover:active div,
|
||||
table tr td.active.disabled:active div,
|
||||
table tr td.active.disabled:hover:active div,
|
||||
table tr td.active.active div,
|
||||
table tr td.active:hover.active div,
|
||||
table tr td.active.disabled.active div,
|
||||
table tr td.active.disabled:hover.active div,
|
||||
table tr td.active.disabled div,
|
||||
table tr td.active:hover.disabled div,
|
||||
table tr td.active.disabled.disabled div,
|
||||
table tr td.active.disabled:hover.disabled div,
|
||||
table tr td.active[disabled] div,
|
||||
table tr td.active:hover[disabled] div,
|
||||
table tr td.active.disabled[disabled] div,
|
||||
table tr td.active.disabled:hover[disabled] div,
|
||||
table tr td span.active:hover,
|
||||
table tr td span.active:hover:hover,
|
||||
table tr td span.active.disabled:hover,
|
||||
table tr td span.active.disabled:hover:hover,
|
||||
table tr td span.active:active,
|
||||
table tr td span.active:hover:active,
|
||||
table tr td span.active.disabled:active,
|
||||
table tr td span.active.disabled:hover:active,
|
||||
table tr td span.active.active,
|
||||
table tr td span.active:hover.active,
|
||||
table tr td span.active.disabled.active,
|
||||
table tr td span.active.disabled:hover.active,
|
||||
table tr td span.active.disabled,
|
||||
table tr td span.active:hover.disabled,
|
||||
table tr td span.active.disabled.disabled,
|
||||
table tr td span.active.disabled:hover.disabled,
|
||||
table tr td span.active[disabled],
|
||||
table tr td span.active:hover[disabled],
|
||||
table tr td span.active.disabled[disabled],
|
||||
table tr td span.active.disabled:hover[disabled]{
|
||||
background-color: $white-color;
|
||||
}
|
||||
|
||||
table tr td span.active:hover,
|
||||
table tr td span.active:hover:hover,
|
||||
table tr td span.active.disabled:hover,
|
||||
table tr td span.active.disabled:hover:hover,
|
||||
table tr td span.active:active,
|
||||
table tr td span.active:hover:active,
|
||||
table tr td span.active.disabled:active,
|
||||
table tr td span.active.disabled:hover:active,
|
||||
table tr td span.active.active,
|
||||
table tr td span.active:hover.active,
|
||||
table tr td span.active.disabled.active,
|
||||
table tr td span.active.disabled:hover.active,
|
||||
table tr td span.active.disabled,
|
||||
table tr td span.active:hover.disabled,
|
||||
table tr td span.active.disabled.disabled,
|
||||
table tr td span.active.disabled:hover.disabled,
|
||||
table tr td span.active[disabled],
|
||||
table tr td span.active:hover[disabled],
|
||||
table tr td span.active.disabled[disabled],
|
||||
table tr td span.active.disabled:hover[disabled]{
|
||||
color: $color;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
@mixin dropdown-colors($brand-color, $dropdown-header-color, $dropdown-color, $background-color ) {
|
||||
background-color: $brand-color;
|
||||
|
||||
&:before{
|
||||
color: $brand-color;
|
||||
}
|
||||
|
||||
.dropdown-header:not([href]):not([tabindex]){
|
||||
color: $dropdown-header-color;
|
||||
}
|
||||
|
||||
.dropdown-item{
|
||||
color: $dropdown-color;
|
||||
|
||||
&:hover,
|
||||
&:focus{
|
||||
background-color: $background-color;
|
||||
}
|
||||
}
|
||||
|
||||
.dropdown-divider{
|
||||
background-color: $background-color;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,205 @@
|
|||
@mixin input-size($padding-vertical, $padding-horizontal){
|
||||
padding: $padding-vertical $padding-horizontal;
|
||||
}
|
||||
|
||||
@mixin form-control-placeholder($color, $opacity){
|
||||
.form-control::-moz-placeholder{
|
||||
color: $color;
|
||||
@include opacity(1);
|
||||
}
|
||||
.form-control:-moz-placeholder{
|
||||
color: $color;
|
||||
@include opacity(1);
|
||||
}
|
||||
.form-control::-webkit-input-placeholder{
|
||||
color: $color;
|
||||
@include opacity(1);
|
||||
}
|
||||
.form-control:-ms-input-placeholder{
|
||||
color: $color;
|
||||
@include opacity(1);
|
||||
}
|
||||
}
|
||||
|
||||
@mixin light-form(){
|
||||
border-radius: 0;
|
||||
border:0;
|
||||
padding: 0;
|
||||
background-color: transparent;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@mixin input-lg-padding($padding-vertical, $padding-horizontal) {
|
||||
.form-group.form-group-no-border.input-lg,
|
||||
.input-group.form-group-no-border.input-lg{
|
||||
.input-group-addon{
|
||||
padding: $padding-vertical 0 $padding-vertical $padding-horizontal;
|
||||
}
|
||||
|
||||
.form-control{
|
||||
padding: $padding-vertical $padding-horizontal;
|
||||
|
||||
& + .input-group-addon{
|
||||
padding: $padding-vertical $padding-horizontal $padding-vertical 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.form-group.input-lg,
|
||||
.input-group.input-lg{
|
||||
.form-control{
|
||||
padding: $padding-vertical - 1 $padding-horizontal - 1;
|
||||
|
||||
& + .input-group-addon{
|
||||
padding: $padding-vertical - 1 $padding-horizontal - 1 $padding-vertical - 1 0;
|
||||
}
|
||||
}
|
||||
|
||||
.input-group-addon{
|
||||
padding: $padding-vertical - 1 0 $padding-vertical $padding-horizontal - 1;
|
||||
|
||||
& + .form-control{
|
||||
padding: $padding-vertical $padding-horizontal - 1 $padding-vertical $padding-horizontal - 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@mixin input-base-padding($padding-vertical, $padding-horizontal) {
|
||||
.form-group.form-group-no-border,
|
||||
.input-group.form-group-no-border{
|
||||
.form-control{
|
||||
padding: $padding-vertical $padding-horizontal;
|
||||
|
||||
& + .input-group-addon{
|
||||
padding: $padding-vertical $padding-horizontal $padding-vertical 0;
|
||||
}
|
||||
}
|
||||
|
||||
.input-group-addon{
|
||||
padding: $padding-vertical 0 $padding-vertical $padding-horizontal;
|
||||
}
|
||||
}
|
||||
|
||||
.form-group,
|
||||
.input-group{
|
||||
.form-control{
|
||||
padding: $padding-vertical - 1 $padding-horizontal - 1 $padding-vertical - 1 $padding-horizontal - 1;
|
||||
|
||||
& + .input-group-addon{
|
||||
padding: $padding-vertical - 1 $padding-horizontal - 1 $padding-vertical - 1 0;
|
||||
}
|
||||
}
|
||||
|
||||
.input-group-addon{
|
||||
padding: $padding-vertical - 1 0 $padding-vertical - 1 $padding-horizontal - 1;
|
||||
|
||||
& + .form-control,
|
||||
& ~ .form-control{
|
||||
padding:$padding-vertical - 1 $padding-horizontal $padding-vertical $padding-horizontal - 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//color1 = $opacity-5
|
||||
//color2 = $opacity-8
|
||||
//color3 = $white-color
|
||||
//color4 = $transparent-bg
|
||||
//color5 = $opacity-1
|
||||
//color6 = $opacity-2
|
||||
|
||||
|
||||
@mixin input-coloured-bg($color1, $color2, $color3, $color4, $color5, $color6) {
|
||||
@include form-control-placeholder(darken($color2, 8%), 1);
|
||||
|
||||
.form-control{
|
||||
border-color: $color1;
|
||||
color: $color2;
|
||||
|
||||
&:focus{
|
||||
border-color: $color3;
|
||||
background-color: $color4;
|
||||
color: $color3;
|
||||
}
|
||||
}
|
||||
|
||||
.has-success,
|
||||
.has-danger{
|
||||
&:after{
|
||||
color: $color3;
|
||||
}
|
||||
}
|
||||
|
||||
.has-danger{
|
||||
.form-control{
|
||||
background-color: $color4;
|
||||
}
|
||||
}
|
||||
|
||||
.input-group-addon{
|
||||
background-color: $color4;
|
||||
border-color: $color1;
|
||||
color: $color2;
|
||||
}
|
||||
|
||||
.input-group-focus{
|
||||
.input-group-addon{
|
||||
background-color: $color4;
|
||||
border-color: $color3;
|
||||
color: $color3;
|
||||
}
|
||||
}
|
||||
|
||||
.form-group.form-group-no-border,
|
||||
.input-group.form-group-no-border{
|
||||
.form-control{
|
||||
background-color: $color5;
|
||||
color: $color2;
|
||||
|
||||
&:focus,
|
||||
&:active,
|
||||
&:active{
|
||||
background-color: $color6;
|
||||
color: $color3;
|
||||
}
|
||||
}
|
||||
|
||||
.form-control + .input-group-addon{
|
||||
background-color: $color5;
|
||||
|
||||
&:focus,
|
||||
&:active,
|
||||
&:active{
|
||||
background-color: $color6;
|
||||
color: $color3;
|
||||
}
|
||||
}
|
||||
|
||||
.form-control{
|
||||
&:focus{
|
||||
& + .input-group-addon{
|
||||
background-color: $color6;
|
||||
color: $color3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.input-group-addon{
|
||||
background-color: $color5;
|
||||
border: none;
|
||||
color: $color2;
|
||||
}
|
||||
|
||||
&.input-group-focus{
|
||||
.input-group-addon{
|
||||
background-color: $color6;
|
||||
color: $color3;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
@mixin modal-colors($bg-color, $color) {
|
||||
.modal-content{
|
||||
background-color: $bg-color;
|
||||
color: $color;
|
||||
}
|
||||
|
||||
.modal-header .close{
|
||||
color: $color;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,226 @@
|
|||
@mixin navbar-responsive() {
|
||||
.navbar{
|
||||
.navbar-nav{
|
||||
margin-top: 53px;
|
||||
|
||||
.nav-link{
|
||||
padding-top: 0.75rem;
|
||||
padding-bottom: .75rem;
|
||||
}
|
||||
|
||||
&.navbar-logo{
|
||||
top: 0;
|
||||
height: 53px;
|
||||
}
|
||||
}
|
||||
|
||||
.dropdown.show .dropdown-menu,
|
||||
.dropdown .dropdown-menu{
|
||||
background-color: transparent;
|
||||
border: 0;
|
||||
transition: none;
|
||||
-webkit-box-shadow: none;
|
||||
box-shadow: none;
|
||||
width: auto;
|
||||
margin: 0 1rem;
|
||||
margin-bottom: 15px;
|
||||
padding-top: 0;
|
||||
height: 150px;
|
||||
overflow-y: scroll;
|
||||
|
||||
&:before{
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.dropdown{
|
||||
.dropdown-item{
|
||||
padding-left: 2.5rem;
|
||||
}
|
||||
|
||||
.dropdown-menu{
|
||||
display: none;
|
||||
}
|
||||
|
||||
&.show .dropdown-menu{
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.dropdown-menu .dropdown-item:focus,
|
||||
.dropdown-menu .dropdown-item:hover{
|
||||
color: $white-color;
|
||||
}
|
||||
|
||||
.navbar-translate{
|
||||
width: 100%;
|
||||
position: relative;
|
||||
display: flex;
|
||||
-ms-flex-pack: justify!important;
|
||||
justify-content: space-between!important;
|
||||
-ms-flex-align: center;
|
||||
align-items: center;
|
||||
@include transform-translate-x(0px);
|
||||
@include transition (0.50s, cubic-bezier(0.685, 0.0473, 0.346, 1));
|
||||
}
|
||||
|
||||
.navbar-toggler-bar{
|
||||
display: block;
|
||||
position: relative;
|
||||
width: 22px;
|
||||
height: 1px;
|
||||
border-radius: 1px;
|
||||
background: $white-bg;
|
||||
|
||||
& + .navbar-toggler-bar{
|
||||
margin-top: 7px;
|
||||
}
|
||||
|
||||
&.bar2{
|
||||
width: 17px;
|
||||
transition: width .2s linear;
|
||||
}
|
||||
}
|
||||
|
||||
&.bg-white:not(.navbar-transparent) .navbar-toggler-bar{
|
||||
background: $default-color;
|
||||
}
|
||||
|
||||
& .toggled .navbar-toggler-bar{
|
||||
width: 24px;
|
||||
|
||||
& + .navbar-toggler-bar{
|
||||
margin-top: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.bar1,
|
||||
.bar2,
|
||||
.bar3 {
|
||||
outline: 1px solid transparent;
|
||||
}
|
||||
.bar1 {
|
||||
top: 0px;
|
||||
@include bar-animation($topbar-back);
|
||||
}
|
||||
.bar2 {
|
||||
opacity: 1;
|
||||
}
|
||||
.bar3 {
|
||||
bottom: 0px;
|
||||
@include bar-animation($bottombar-back);
|
||||
}
|
||||
.toggled .bar1 {
|
||||
top: 6px;
|
||||
@include bar-animation($topbar-x);
|
||||
}
|
||||
.toggled .bar2 {
|
||||
opacity: 0;
|
||||
}
|
||||
.toggled .bar3 {
|
||||
bottom: 6px;
|
||||
@include bar-animation($bottombar-x);
|
||||
}
|
||||
|
||||
@include topbar-x-rotation();
|
||||
@include topbar-back-rotation();
|
||||
@include bottombar-x-rotation();
|
||||
@include bottombar-back-rotation();
|
||||
|
||||
@-webkit-keyframes fadeIn {
|
||||
0% {opacity: 0;}
|
||||
100% {opacity: 1;}
|
||||
}
|
||||
@-moz-keyframes fadeIn {
|
||||
0% {opacity: 0;}
|
||||
100% {opacity: 1;}
|
||||
}
|
||||
@keyframes fadeIn {
|
||||
0% {opacity: 0;}
|
||||
100% {opacity: 1;}
|
||||
}
|
||||
}
|
||||
|
||||
@mixin navbar-collapse() {
|
||||
.navbar-collapse{
|
||||
position: fixed;
|
||||
display: block;
|
||||
top: 0;
|
||||
height: 100% !important;
|
||||
width: 300px;
|
||||
right: 0;
|
||||
z-index: 1032;
|
||||
visibility: visible;
|
||||
background-color: #999;
|
||||
overflow-y: visible;
|
||||
border-top: none;
|
||||
text-align: left;
|
||||
|
||||
max-height: none !important;
|
||||
|
||||
@include transform-translate-x(300px);
|
||||
@include transition (0.50s, cubic-bezier(0.685, 0.0473, 0.346, 1));
|
||||
|
||||
&:before{
|
||||
background: $brand-primary; /* For browsers that do not support gradients */
|
||||
background: -webkit-linear-gradient($brand-primary 0%, #000 80%); /* For Safari 5.1 to 6.0 */
|
||||
background: -o-linear-gradient($brand-primary 0%, #000 80%); /* For Opera 11.1 to 12.0 */
|
||||
background: -moz-linear-gradient($brand-primary 0%, #000 80%); /* For Firefox 3.6 to 15 */
|
||||
background: linear-gradient($brand-primary 0%, #000 80%); /* Standard syntax (must be last) */
|
||||
@include opacity(.76);
|
||||
|
||||
display: block;
|
||||
content: "";
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
.navbar-nav:not(.navbar-logo){
|
||||
.nav-link {
|
||||
margin: 0 1rem;
|
||||
margin-top: 0.3125rem;
|
||||
|
||||
&:not(.btn){
|
||||
color: $white-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.dropdown-menu .dropdown-item{
|
||||
color: $white-color;
|
||||
}
|
||||
}
|
||||
|
||||
@include navbar-responsive();
|
||||
|
||||
|
||||
[class*="navbar-expand-"] .navbar-collapse{
|
||||
width: 300px;
|
||||
}
|
||||
|
||||
.wrapper{
|
||||
@include transition (0.50s, cubic-bezier(0.685, 0.0473, 0.346, 1));
|
||||
}
|
||||
|
||||
#bodyClick{
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
position: fixed;
|
||||
opacity: 1;
|
||||
top: 0;
|
||||
left: auto;
|
||||
right: 300px;
|
||||
content: "";
|
||||
z-index: 9999;
|
||||
overflow-x: hidden;
|
||||
background-color: transparent;
|
||||
@include transition (0.50s, cubic-bezier(0.685, 0.0473, 0.346, 1));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
@mixin linear-gradient($color1, $color2){
|
||||
background: $color1; /* For browsers that do not support gradients */
|
||||
background: -webkit-linear-gradient(90deg, $color1 , $color2); /* For Safari 5.1 to 6.0 */
|
||||
background: -o-linear-gradient(90deg, $color1, $color2); /* For Opera 11.1 to 12.0 */
|
||||
background: -moz-linear-gradient(90deg, $color1, $color2); /* For Firefox 3.6 to 15 */
|
||||
background: linear-gradient(0deg, $color1 , $color2); /* Standard syntax */
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
@mixin popover-color($color, $text-color) {
|
||||
background-color: $color;
|
||||
|
||||
.popover-body{
|
||||
color: $text-color;
|
||||
}
|
||||
|
||||
|
||||
&.bs-popover-right .arrow:after{
|
||||
border-right-color:$color;
|
||||
}
|
||||
|
||||
&.bs-popover-top .arrow:after{
|
||||
border-top-color:$color;
|
||||
}
|
||||
|
||||
&.bs-popover-bottom .arrow:after{
|
||||
border-bottom-color:$color;
|
||||
}
|
||||
|
||||
&.bs-popover-left .arrow:after{
|
||||
border-left-color:$color;
|
||||
}
|
||||
|
||||
.popover-header{
|
||||
color: $text-color;
|
||||
opacity: .6;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
// Opacity
|
||||
|
||||
@mixin opacity($opacity) {
|
||||
opacity: $opacity;
|
||||
// IE8 filter
|
||||
$opacity-ie: ($opacity * 100);
|
||||
filter: #{alpha(opacity=$opacity-ie)};
|
||||
}
|
||||
|
|
@ -0,0 +1,160 @@
|
|||
@mixin box-shadow($shadow...) {
|
||||
-webkit-box-shadow: $shadow; // iOS <4.3 & Android <4.1
|
||||
box-shadow: $shadow;
|
||||
}
|
||||
|
||||
@mixin transition-input-focus-color() {
|
||||
-webkit-transition: color 0.3s ease-in-out, border-color 0.3s ease-in-out, background-color 0.3s ease-in-out;
|
||||
-moz-transition: color 0.3s ease-in-out, border-color 0.3s ease-in-out, background-color 0.3s ease-in-out;
|
||||
-o-transition: color 0.3s ease-in-out, border-color 0.3s ease-in-out, background-color 0.3s ease-in-out;
|
||||
-ms-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;
|
||||
}
|
||||
|
||||
|
||||
@mixin transition($time, $type){
|
||||
-webkit-transition: all $time $type;
|
||||
-moz-transition: all $time $type;
|
||||
-o-transition: all $time $type;
|
||||
-ms-transition: all $time $type;
|
||||
transition: all $time $type;
|
||||
}
|
||||
|
||||
@mixin rotate-180(){
|
||||
filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=2);
|
||||
-webkit-transform: rotate(180deg);
|
||||
-ms-transform: rotate(180deg);
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
|
||||
@mixin transform-translate-x($value){
|
||||
-webkit-transform: translate3d($value, 0, 0);
|
||||
-moz-transform: translate3d($value, 0, 0);
|
||||
-o-transform: translate3d($value, 0, 0);
|
||||
-ms-transform: translate3d($value, 0, 0);
|
||||
transform: translate3d($value, 0, 0);
|
||||
}
|
||||
|
||||
@mixin transform-translate-y($value){
|
||||
-webkit-transform: translate3d(0,$value,0);
|
||||
-moz-transform: translate3d(0,$value,0);
|
||||
-o-transform: translate3d(0,$value,0);
|
||||
-ms-transform: translate3d(0,$value,0);
|
||||
transform: translate3d(0,$value,0);
|
||||
}
|
||||
|
||||
@mixin bar-animation($type){
|
||||
-webkit-animation: $type 500ms linear 0s;
|
||||
-moz-animation: $type 500ms linear 0s;
|
||||
animation: $type 500ms 0s;
|
||||
-webkit-animation-fill-mode: forwards;
|
||||
-moz-animation-fill-mode: forwards;
|
||||
animation-fill-mode: forwards;
|
||||
}
|
||||
|
||||
@mixin topbar-x-rotation(){
|
||||
@keyframes topbar-x {
|
||||
0% {top: 0px; transform: rotate(0deg); }
|
||||
45% {top: 6px; transform: rotate(145deg); }
|
||||
75% {transform: rotate(130deg); }
|
||||
100% {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); }
|
||||
}
|
||||
@-moz-keyframes topbar-x {
|
||||
0% {top: 0px; -moz-transform: rotate(0deg); }
|
||||
45% {top: 6px; -moz-transform: rotate(145deg); }
|
||||
75% {-moz-transform: rotate(130deg); }
|
||||
100% { -moz-transform: rotate(135deg); }
|
||||
}
|
||||
}
|
||||
|
||||
@mixin topbar-back-rotation(){
|
||||
@keyframes topbar-back {
|
||||
0% { top: 6px; transform: rotate(135deg); }
|
||||
45% { transform: rotate(-10deg); }
|
||||
75% { transform: rotate(5deg); }
|
||||
100% { top: 0px; 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); }
|
||||
}
|
||||
|
||||
@-moz-keyframes topbar-back {
|
||||
0% { top: 6px; -moz-transform: rotate(135deg); }
|
||||
45% { -moz-transform: rotate(-10deg); }
|
||||
75% { -moz-transform: rotate(5deg); }
|
||||
100% { top: 0px; -moz-transform: rotate(0); }
|
||||
}
|
||||
}
|
||||
|
||||
@mixin bottombar-x-rotation(){
|
||||
@keyframes bottombar-x {
|
||||
0% {bottom: 0px; transform: rotate(0deg);}
|
||||
45% {bottom: 6px; transform: rotate(-145deg);}
|
||||
75% {transform: rotate(-130deg);}
|
||||
100% {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);}
|
||||
}
|
||||
@-moz-keyframes bottombar-x {
|
||||
0% {bottom: 0px; -moz-transform: rotate(0deg);}
|
||||
45% {bottom: 6px; -moz-transform: rotate(-145deg);}
|
||||
75% {-moz-transform: rotate(-130deg);}
|
||||
100% {-moz-transform: rotate(-135deg);}
|
||||
}
|
||||
}
|
||||
|
||||
@mixin bottombar-back-rotation{
|
||||
@keyframes bottombar-back {
|
||||
0% { bottom: 6px;transform: rotate(-135deg);}
|
||||
45% { transform: rotate(10deg);}
|
||||
75% { transform: rotate(-5deg);}
|
||||
100% { bottom: 0px;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);}
|
||||
}
|
||||
@-moz-keyframes bottombar-back {
|
||||
0% {bottom: 6px;-moz-transform: rotate(-135deg);}
|
||||
45% {-moz-transform: rotate(10deg);}
|
||||
75% {-moz-transform: rotate(-5deg);}
|
||||
100% {bottom: 0px;-moz-transform: rotate(0);}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@mixin nc-rotate($degrees, $rotation) {
|
||||
filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=#{$rotation});
|
||||
-webkit-transform: rotate($degrees);
|
||||
-moz-transform: rotate($degrees);
|
||||
-ms-transform: rotate($degrees);
|
||||
-o-transform: rotate($degrees);
|
||||
transform: rotate($degrees);
|
||||
}
|
||||
|
||||
@mixin nc-flip($horiz, $vert, $rotation) {
|
||||
filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=#{$rotation});
|
||||
-webkit-transform: scale($horiz, $vert);
|
||||
-moz-transform: scale($horiz, $vert);
|
||||
-ms-transform: scale($horiz, $vert);
|
||||
-o-transform: scale($horiz, $vert);
|
||||
transform: scale($horiz, $vert);
|
||||
}
|
||||
|
|
@ -0,0 +1,304 @@
|
|||
/* ========================================================================
|
||||
* bootstrap-switch - v3.3.2
|
||||
* http://www.bootstrap-switch.org
|
||||
* ========================================================================
|
||||
* Copyright 2012-2013 Mattia Larentis
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//* IMPORTANT! Creative Tim Notice: this file has major changes to fit the NOW UI Kit's design. If you want to use the plugin as it was before our changes, please get the old files from http://www.bootstrap-switch.org
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
.bootstrap-switch {
|
||||
display: inline-block;
|
||||
direction: ltr;
|
||||
cursor: pointer;
|
||||
border-radius: 30px;
|
||||
border: 0;
|
||||
position: relative;
|
||||
text-align: left;
|
||||
margin-bottom: 10px;
|
||||
line-height: 8px;
|
||||
width: 59px !important;
|
||||
height: 22px;
|
||||
outline: none;
|
||||
z-index: 0;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
vertical-align: middle;
|
||||
-webkit-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
|
||||
transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
|
||||
margin-right: 20px;
|
||||
background: rgba($black-color, .2);
|
||||
}
|
||||
|
||||
.bootstrap-switch .bootstrap-switch-container {
|
||||
display: inline-flex;
|
||||
top: 0;
|
||||
height: 22px;
|
||||
border-radius: 4px;
|
||||
-webkit-transform: translate3d(0, 0, 0);
|
||||
transform: translate3d(0, 0, 0);
|
||||
width: 100px !important;
|
||||
}
|
||||
.bootstrap-switch .bootstrap-switch-handle-on,
|
||||
.bootstrap-switch .bootstrap-switch-handle-off,
|
||||
.bootstrap-switch .bootstrap-switch-label {
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
cursor: pointer;
|
||||
display: inline-block !important;
|
||||
height: 100%;
|
||||
color: #fff;
|
||||
padding: 6px 12px;
|
||||
font-size: 11px;
|
||||
text-indent: -5px;
|
||||
line-height: 15px;
|
||||
-webkit-transition: 0.25s ease-out;
|
||||
transition: 0.25s ease-out;
|
||||
|
||||
}
|
||||
.bootstrap-switch .bootstrap-switch-handle-on,
|
||||
.bootstrap-switch .bootstrap-switch-handle-off {
|
||||
text-align: center;
|
||||
z-index: 1;
|
||||
float: left;
|
||||
line-height: 11px;
|
||||
width: 50% !important;
|
||||
}
|
||||
.bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-brown,
|
||||
.bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-brown {
|
||||
color: #fff;
|
||||
background: $brand-primary;
|
||||
}
|
||||
.bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-blue,
|
||||
.bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-blue {
|
||||
color: #fff;
|
||||
background: $brand-info;
|
||||
}
|
||||
.bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-green,
|
||||
.bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-green {
|
||||
color: #fff;
|
||||
background: $brand-success;
|
||||
}
|
||||
.bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-orange,
|
||||
.bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-orange {
|
||||
background: $brand-warning;
|
||||
color: #fff;
|
||||
}
|
||||
.bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-red,
|
||||
.bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-red {
|
||||
color: #fff;
|
||||
background: $brand-danger;
|
||||
}
|
||||
.bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-default,
|
||||
.bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-default {
|
||||
color: #fff;
|
||||
}
|
||||
.bootstrap-switch .bootstrap-switch-label {
|
||||
text-align: center;
|
||||
z-index: 100;
|
||||
color: #333333;
|
||||
background: #ffffff;
|
||||
width: 22px !important;
|
||||
height: 22px !important;
|
||||
margin: 0px -11px;
|
||||
border-radius: 20px;
|
||||
position: absolute;
|
||||
float: left;
|
||||
top: 0;
|
||||
left: 50%;
|
||||
padding: 0;
|
||||
box-shadow: 0 1px 11px rgba(0, 0, 0, 0.25);
|
||||
}
|
||||
|
||||
.bootstrap-switch.bootstrap-switch-off .bootstrap-switch-label{
|
||||
background-color: rgba(23, 23, 23, .4);
|
||||
}
|
||||
.bootstrap-switch.bootstrap-switch-on:hover .bootstrap-switch-label{
|
||||
width: 27px !important;
|
||||
margin-left: -16px;
|
||||
}
|
||||
.bootstrap-switch.bootstrap-switch-off:hover .bootstrap-switch-label{
|
||||
width: 27px !important;
|
||||
margin-left: -11px;
|
||||
}
|
||||
.bootstrap-switch .bootstrap-switch-handle-on {
|
||||
border-bottom-left-radius: 3px;
|
||||
border-top-left-radius: 3px;
|
||||
}
|
||||
.bootstrap-switch .bootstrap-switch-handle-off {
|
||||
text-indent: 6px;
|
||||
}
|
||||
.bootstrap-switch input[type='radio'],
|
||||
.bootstrap-switch input[type='checkbox'] {
|
||||
position: absolute !important;
|
||||
top: 0;
|
||||
left: 0;
|
||||
opacity: 0;
|
||||
filter: alpha(opacity=0);
|
||||
z-index: -1;
|
||||
}
|
||||
.bootstrap-switch input[type='radio'].form-control,
|
||||
.bootstrap-switch input[type='checkbox'].form-control {
|
||||
height: auto;
|
||||
}
|
||||
.bootstrap-switch.bootstrap-switch-mini .bootstrap-switch-handle-on,
|
||||
.bootstrap-switch.bootstrap-switch-mini .bootstrap-switch-handle-off,
|
||||
.bootstrap-switch.bootstrap-switch-mini .bootstrap-switch-label {
|
||||
padding: 1px 5px;
|
||||
font-size: 12px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
.bootstrap-switch.bootstrap-switch-small .bootstrap-switch-handle-on,
|
||||
.bootstrap-switch.bootstrap-switch-small .bootstrap-switch-handle-off,
|
||||
.bootstrap-switch.bootstrap-switch-small .bootstrap-switch-label {
|
||||
padding: 5px 10px;
|
||||
font-size: 12px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
.bootstrap-switch.bootstrap-switch-large .bootstrap-switch-handle-on,
|
||||
.bootstrap-switch.bootstrap-switch-large .bootstrap-switch-handle-off,
|
||||
.bootstrap-switch.bootstrap-switch-large .bootstrap-switch-label {
|
||||
padding: 6px 16px;
|
||||
font-size: 18px;
|
||||
line-height: 1.33;
|
||||
}
|
||||
.bootstrap-switch.bootstrap-switch-disabled,
|
||||
.bootstrap-switch.bootstrap-switch-readonly,
|
||||
.bootstrap-switch.bootstrap-switch-indeterminate {
|
||||
cursor: default !important;
|
||||
}
|
||||
.bootstrap-switch.bootstrap-switch-disabled .bootstrap-switch-handle-on,
|
||||
.bootstrap-switch.bootstrap-switch-readonly .bootstrap-switch-handle-on,
|
||||
.bootstrap-switch.bootstrap-switch-indeterminate .bootstrap-switch-handle-on,
|
||||
.bootstrap-switch.bootstrap-switch-disabled .bootstrap-switch-handle-off,
|
||||
.bootstrap-switch.bootstrap-switch-readonly .bootstrap-switch-handle-off,
|
||||
.bootstrap-switch.bootstrap-switch-indeterminate .bootstrap-switch-handle-off,
|
||||
.bootstrap-switch.bootstrap-switch-disabled .bootstrap-switch-label,
|
||||
.bootstrap-switch.bootstrap-switch-readonly .bootstrap-switch-label,
|
||||
.bootstrap-switch.bootstrap-switch-indeterminate .bootstrap-switch-label {
|
||||
opacity: 0.5;
|
||||
filter: alpha(opacity=50);
|
||||
cursor: default !important;
|
||||
}
|
||||
.bootstrap-switch.bootstrap-switch-animate .bootstrap-switch-container {
|
||||
-webkit-transition: margin-left 0.5s;
|
||||
transition: margin-left 0.5s;
|
||||
}
|
||||
.bootstrap-switch.bootstrap-switch-inverse .bootstrap-switch-handle-on {
|
||||
border-bottom-left-radius: 0;
|
||||
border-top-left-radius: 0;
|
||||
border-bottom-right-radius: 3px;
|
||||
border-top-right-radius: 3px;
|
||||
}
|
||||
.bootstrap-switch.bootstrap-switch-inverse .bootstrap-switch-handle-off {
|
||||
border-bottom-right-radius: 0;
|
||||
border-top-right-radius: 0;
|
||||
border-bottom-left-radius: 3px;
|
||||
border-top-left-radius: 3px;
|
||||
}
|
||||
.bootstrap-switch.bootstrap-switch-focused {
|
||||
// border-color: #66afe9;
|
||||
// outline: 0;
|
||||
// -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);
|
||||
// box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);
|
||||
}
|
||||
// .bootstrap-switch.bootstrap-switch-on .bootstrap-switch-label,
|
||||
// .bootstrap-switch.bootstrap-switch-inverse.bootstrap-switch-off .bootstrap-switch-label {
|
||||
// border-bottom-right-radius: 3px;
|
||||
// border-top-right-radius: 3px;
|
||||
// }
|
||||
// .bootstrap-switch.bootstrap-switch-off .bootstrap-switch-label,
|
||||
// .bootstrap-switch.bootstrap-switch-inverse.bootstrap-switch-on .bootstrap-switch-label {
|
||||
// border-bottom-left-radius: 3px;
|
||||
// border-top-left-radius: 3px;
|
||||
// }
|
||||
|
||||
.bootstrap-switch.bootstrap-switch-on .bootstrap-switch-container{
|
||||
margin-left: -2px !important;
|
||||
}
|
||||
|
||||
.bootstrap-switch.bootstrap-switch-off .bootstrap-switch-container{
|
||||
margin-left: -39px !important;
|
||||
}
|
||||
|
||||
.bootstrap-switch.bootstrap-switch-on .bootstrap-switch-label{
|
||||
&:before{
|
||||
background-color: #FFFFFF;
|
||||
}
|
||||
}
|
||||
|
||||
.bootstrap-switch.bootstrap-switch-on .bootstrap-switch-red ~ .bootstrap-switch-default{
|
||||
background-color: $brand-danger;
|
||||
}
|
||||
|
||||
.bootstrap-switch.bootstrap-switch-on .bootstrap-switch-orange ~ .bootstrap-switch-default{
|
||||
background-color: $brand-warning;
|
||||
}
|
||||
|
||||
.bootstrap-switch.bootstrap-switch-on .bootstrap-switch-green ~ .bootstrap-switch-default{
|
||||
background-color: $brand-success;
|
||||
}
|
||||
|
||||
.bootstrap-switch.bootstrap-switch-on .bootstrap-switch-brown ~ .bootstrap-switch-default{
|
||||
background-color: $brand-primary;
|
||||
}
|
||||
|
||||
.bootstrap-switch.bootstrap-switch-on .bootstrap-switch-blue ~ .bootstrap-switch-default{
|
||||
background-color: $brand-info;
|
||||
}
|
||||
|
||||
.bootstrap-switch.bootstrap-switch-off .bootstrap-switch-red,
|
||||
.bootstrap-switch.bootstrap-switch-off .bootstrap-switch-brown,
|
||||
.bootstrap-switch.bootstrap-switch-off .bootstrap-switch-blue,
|
||||
.bootstrap-switch.bootstrap-switch-off .bootstrap-switch-orange,
|
||||
.bootstrap-switch.bootstrap-switch-off .bootstrap-switch-green{
|
||||
background-color: $light-gray;
|
||||
}
|
||||
|
||||
.bootstrap-switch-off .bootstrap-switch-handle-on{
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.bootstrap-switch-on .bootstrap-switch-handle-off{
|
||||
opacity: 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,520 @@
|
|||
/*!
|
||||
* Datepicker for Bootstrap v1.7.0-dev (https://github.com/uxsolutions/bootstrap-datepicker)
|
||||
*
|
||||
* Licensed under the Apache License v2.0 (http://www.apache.org/licenses/LICENSE-2.0)
|
||||
*/
|
||||
|
||||
.datepicker {
|
||||
padding: 8px 6px;
|
||||
-webkit-border-radius: 4px;
|
||||
-moz-border-radius: 4px;
|
||||
border-radius: 4px;
|
||||
direction: ltr;
|
||||
@include transform-translate-y(-40px);
|
||||
transition: all 0.3s cubic-bezier(0.215, 0.61, 0.355, 1) 0s, opacity 0.3s ease 0s, height 0s linear 0.35s;
|
||||
|
||||
@include opacity(0);
|
||||
visibility: hidden;
|
||||
display: block;
|
||||
width: 254px;
|
||||
max-width: 254px;
|
||||
|
||||
&.dropdown-menu:before{
|
||||
display: none;
|
||||
}
|
||||
|
||||
&.datepicker-primary{
|
||||
@include datepicker-colors($primary-color);
|
||||
}
|
||||
}
|
||||
.datepicker-inline {
|
||||
width: 220px;
|
||||
}
|
||||
.datepicker.datepicker-rtl {
|
||||
direction: rtl;
|
||||
}
|
||||
.datepicker.datepicker-rtl.dropdown-menu {
|
||||
left: auto;
|
||||
}
|
||||
.datepicker.datepicker-rtl table tr td span {
|
||||
float: right;
|
||||
}
|
||||
.datepicker-dropdown {
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
.datepicker-dropdown:before {
|
||||
content: '';
|
||||
display: inline-block;
|
||||
border-left: 7px solid transparent;
|
||||
border-right: 7px solid transparent;
|
||||
border-bottom: 7px solid transparent;
|
||||
border-top: 0;
|
||||
border-bottom-color: rgba(0, 0, 0, 0.2);
|
||||
position: absolute;
|
||||
}
|
||||
.datepicker-dropdown:after {
|
||||
content: '';
|
||||
display: inline-block;
|
||||
border-left: 6px solid transparent;
|
||||
border-right: 6px solid transparent;
|
||||
border-bottom: 6px solid #fff;
|
||||
border-top: 0;
|
||||
position: absolute;
|
||||
}
|
||||
.datepicker-dropdown.datepicker-orient-left:before {
|
||||
left: 6px;
|
||||
}
|
||||
.datepicker-dropdown.datepicker-orient-left:after {
|
||||
left: 7px;
|
||||
}
|
||||
.datepicker-dropdown.datepicker-orient-right:before {
|
||||
right: 6px;
|
||||
}
|
||||
.datepicker-dropdown.datepicker-orient-right:after {
|
||||
right: 7px;
|
||||
}
|
||||
.datepicker-dropdown.datepicker-orient-bottom:before {
|
||||
top: -7px;
|
||||
}
|
||||
.datepicker-dropdown.datepicker-orient-bottom:after {
|
||||
top: -6px;
|
||||
}
|
||||
.datepicker-dropdown.datepicker-orient-top:before {
|
||||
bottom: -7px;
|
||||
border-bottom: 0;
|
||||
border-top: 7px solid transparent;
|
||||
}
|
||||
.datepicker-dropdown.datepicker-orient-top:after {
|
||||
bottom: -6px;
|
||||
border-bottom: 0;
|
||||
border-top: 6px solid #fff;
|
||||
}
|
||||
.datepicker table {
|
||||
margin: 0;
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-user-select: none;
|
||||
-khtml-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
width: 241px;
|
||||
max-width: 241px;
|
||||
}
|
||||
.datepicker .day div,
|
||||
.datepicker th {
|
||||
@include transition($general-transition-time, $transition-ease);
|
||||
text-align: center;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
line-height: 2.2;
|
||||
-webkit-border-radius: 4px;
|
||||
-moz-border-radius: 4px;
|
||||
border-radius: 50%;
|
||||
font-weight: $font-weight-light;
|
||||
font-size: $font-size-base;
|
||||
border: none;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.datepicker th{
|
||||
color: $primary-color;
|
||||
}
|
||||
|
||||
.table-condensed > tbody > tr > td,
|
||||
.table-condensed > tbody > tr > th,
|
||||
.table-condensed > tfoot > tr > td,
|
||||
.table-condensed > tfoot > tr > th,
|
||||
.table-condensed > thead > tr > td,
|
||||
.table-condensed > thead > tr > th{
|
||||
padding: 2px;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.table-striped .datepicker table tr td,
|
||||
.table-striped .datepicker table tr th {
|
||||
background-color: transparent;
|
||||
}
|
||||
.datepicker table tr td.day:hover div,
|
||||
.datepicker table tr td.day.focused div {
|
||||
background: #eee;
|
||||
cursor: pointer;
|
||||
}
|
||||
.datepicker table tr td.old,
|
||||
.datepicker table tr td.new {
|
||||
color: $default-color;
|
||||
}
|
||||
.datepicker table tr td.disabled,
|
||||
.datepicker table tr td.disabled:hover {
|
||||
background: none;
|
||||
color: $default-color ;
|
||||
cursor: default;
|
||||
}
|
||||
.datepicker table tr td.highlighted {
|
||||
background: #d9edf7;
|
||||
border-radius: 0;
|
||||
}
|
||||
.datepicker table tr td.today,
|
||||
.datepicker table tr td.today:hover,
|
||||
.datepicker table tr td.today.disabled,
|
||||
.datepicker table tr td.today.disabled:hover {
|
||||
background-color: #fde19a;
|
||||
background-image: -moz-linear-gradient(to bottom, #fdd49a, #fdf59a);
|
||||
background-image: -ms-linear-gradient(to bottom, #fdd49a, #fdf59a);
|
||||
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fdd49a), to(#fdf59a));
|
||||
background-image: -webkit-linear-gradient(to bottom, #fdd49a, #fdf59a);
|
||||
background-image: -o-linear-gradient(to bottom, #fdd49a, #fdf59a);
|
||||
background-image: linear-gradient(to bottom, #fdd49a, #fdf59a);
|
||||
background-repeat: repeat-x;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fdd49a', endColorstr='#fdf59a', GradientType=0);
|
||||
border-color: #fdf59a #fdf59a #fbed50;
|
||||
border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
|
||||
color: #000;
|
||||
}
|
||||
.datepicker table tr td.today:hover,
|
||||
.datepicker table tr td.today:hover:hover,
|
||||
.datepicker table tr td.today.disabled:hover,
|
||||
.datepicker table tr td.today.disabled:hover:hover,
|
||||
.datepicker table tr td.today:active,
|
||||
.datepicker table tr td.today:hover:active,
|
||||
.datepicker table tr td.today.disabled:active,
|
||||
.datepicker table tr td.today.disabled:hover:active,
|
||||
.datepicker table tr td.today.active,
|
||||
.datepicker table tr td.today:hover.active,
|
||||
.datepicker table tr td.today.disabled.active,
|
||||
.datepicker table tr td.today.disabled:hover.active,
|
||||
.datepicker table tr td.today.disabled,
|
||||
.datepicker table tr td.today:hover.disabled,
|
||||
.datepicker table tr td.today.disabled.disabled,
|
||||
.datepicker table tr td.today.disabled:hover.disabled,
|
||||
.datepicker table tr td.today[disabled],
|
||||
.datepicker table tr td.today:hover[disabled],
|
||||
.datepicker table tr td.today.disabled[disabled],
|
||||
.datepicker table tr td.today.disabled:hover[disabled] {
|
||||
background-color: #fdf59a;
|
||||
}
|
||||
.datepicker table tr td.today:active,
|
||||
.datepicker table tr td.today:hover:active,
|
||||
.datepicker table tr td.today.disabled:active,
|
||||
.datepicker table tr td.today.disabled:hover:active,
|
||||
.datepicker table tr td.today.active,
|
||||
.datepicker table tr td.today:hover.active,
|
||||
.datepicker table tr td.today.disabled.active,
|
||||
.datepicker table tr td.today.disabled:hover.active {
|
||||
background-color: #fbf069 \9;
|
||||
}
|
||||
.datepicker table tr td.today:hover:hover {
|
||||
color: #000;
|
||||
}
|
||||
.datepicker table tr td.today.active:hover {
|
||||
color: #fff;
|
||||
}
|
||||
.datepicker table tr td.range,
|
||||
.datepicker table tr td.range:hover,
|
||||
.datepicker table tr td.range.disabled,
|
||||
.datepicker table tr td.range.disabled:hover {
|
||||
background: #eee;
|
||||
-webkit-border-radius: 0;
|
||||
-moz-border-radius: 0;
|
||||
border-radius: 0;
|
||||
}
|
||||
.datepicker table tr td.range.today,
|
||||
.datepicker table tr td.range.today:hover,
|
||||
.datepicker table tr td.range.today.disabled,
|
||||
.datepicker table tr td.range.today.disabled:hover {
|
||||
background-color: #f3d17a;
|
||||
background-image: -moz-linear-gradient(to bottom, #f3c17a, #f3e97a);
|
||||
background-image: -ms-linear-gradient(to bottom, #f3c17a, #f3e97a);
|
||||
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f3c17a), to(#f3e97a));
|
||||
background-image: -webkit-linear-gradient(to bottom, #f3c17a, #f3e97a);
|
||||
background-image: -o-linear-gradient(to bottom, #f3c17a, #f3e97a);
|
||||
background-image: linear-gradient(to bottom, #f3c17a, #f3e97a);
|
||||
background-repeat: repeat-x;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f3c17a', endColorstr='#f3e97a', GradientType=0);
|
||||
border-color: #f3e97a #f3e97a #edde34;
|
||||
border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
|
||||
-webkit-border-radius: 0;
|
||||
-moz-border-radius: 0;
|
||||
border-radius: 0;
|
||||
}
|
||||
.datepicker table tr td.range.today:hover,
|
||||
.datepicker table tr td.range.today:hover:hover,
|
||||
.datepicker table tr td.range.today.disabled:hover,
|
||||
.datepicker table tr td.range.today.disabled:hover:hover,
|
||||
.datepicker table tr td.range.today:active,
|
||||
.datepicker table tr td.range.today:hover:active,
|
||||
.datepicker table tr td.range.today.disabled:active,
|
||||
.datepicker table tr td.range.today.disabled:hover:active,
|
||||
.datepicker table tr td.range.today.active,
|
||||
.datepicker table tr td.range.today:hover.active,
|
||||
.datepicker table tr td.range.today.disabled.active,
|
||||
.datepicker table tr td.range.today.disabled:hover.active,
|
||||
.datepicker table tr td.range.today.disabled,
|
||||
.datepicker table tr td.range.today:hover.disabled,
|
||||
.datepicker table tr td.range.today.disabled.disabled,
|
||||
.datepicker table tr td.range.today.disabled:hover.disabled,
|
||||
.datepicker table tr td.range.today[disabled],
|
||||
.datepicker table tr td.range.today:hover[disabled],
|
||||
.datepicker table tr td.range.today.disabled[disabled],
|
||||
.datepicker table tr td.range.today.disabled:hover[disabled] {
|
||||
background-color: #f3e97a;
|
||||
}
|
||||
.datepicker table tr td.range.today:active,
|
||||
.datepicker table tr td.range.today:hover:active,
|
||||
.datepicker table tr td.range.today.disabled:active,
|
||||
.datepicker table tr td.range.today.disabled:hover:active,
|
||||
.datepicker table tr td.range.today.active,
|
||||
.datepicker table tr td.range.today:hover.active,
|
||||
.datepicker table tr td.range.today.disabled.active,
|
||||
.datepicker table tr td.range.today.disabled:hover.active {
|
||||
background-color: #efe24b \9;
|
||||
}
|
||||
.datepicker table tr td.selected,
|
||||
.datepicker table tr td.selected:hover,
|
||||
.datepicker table tr td.selected.disabled,
|
||||
.datepicker table tr td.selected.disabled:hover {
|
||||
background-color: #9e9e9e;
|
||||
background-image: -moz-linear-gradient(to bottom, #b3b3b3, #808080);
|
||||
background-image: -ms-linear-gradient(to bottom, #b3b3b3, #808080);
|
||||
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#b3b3b3), to(#808080));
|
||||
background-image: -webkit-linear-gradient(to bottom, #b3b3b3, #808080);
|
||||
background-image: -o-linear-gradient(to bottom, #b3b3b3, #808080);
|
||||
background-image: linear-gradient(to bottom, #b3b3b3, #808080);
|
||||
background-repeat: repeat-x;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#b3b3b3', endColorstr='#808080', GradientType=0);
|
||||
border-color: #808080 #808080 #595959;
|
||||
border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
|
||||
color: #fff;
|
||||
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
|
||||
}
|
||||
.datepicker table tr td.selected:hover,
|
||||
.datepicker table tr td.selected:hover:hover,
|
||||
.datepicker table tr td.selected.disabled:hover,
|
||||
.datepicker table tr td.selected.disabled:hover:hover,
|
||||
.datepicker table tr td.selected:active,
|
||||
.datepicker table tr td.selected:hover:active,
|
||||
.datepicker table tr td.selected.disabled:active,
|
||||
.datepicker table tr td.selected.disabled:hover:active,
|
||||
.datepicker table tr td.selected.active,
|
||||
.datepicker table tr td.selected:hover.active,
|
||||
.datepicker table tr td.selected.disabled.active,
|
||||
.datepicker table tr td.selected.disabled:hover.active,
|
||||
.datepicker table tr td.selected.disabled,
|
||||
.datepicker table tr td.selected:hover.disabled,
|
||||
.datepicker table tr td.selected.disabled.disabled,
|
||||
.datepicker table tr td.selected.disabled:hover.disabled,
|
||||
.datepicker table tr td.selected[disabled],
|
||||
.datepicker table tr td.selected:hover[disabled],
|
||||
.datepicker table tr td.selected.disabled[disabled],
|
||||
.datepicker table tr td.selected.disabled:hover[disabled] {
|
||||
background-color: #808080;
|
||||
}
|
||||
.datepicker table tr td.selected:active,
|
||||
.datepicker table tr td.selected:hover:active,
|
||||
.datepicker table tr td.selected.disabled:active,
|
||||
.datepicker table tr td.selected.disabled:hover:active,
|
||||
.datepicker table tr td.selected.active,
|
||||
.datepicker table tr td.selected:hover.active,
|
||||
.datepicker table tr td.selected.disabled.active,
|
||||
.datepicker table tr td.selected.disabled:hover.active {
|
||||
background-color: #666666 \9;
|
||||
}
|
||||
.datepicker table tr td.active div,
|
||||
.datepicker table tr td.active:hover div,
|
||||
.datepicker table tr td.active.disabled div,
|
||||
.datepicker table tr td.active.disabled:hover div {
|
||||
|
||||
background-color: $primary-color;
|
||||
color: $white-color;
|
||||
box-shadow: 0px 1px 10px 0px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
.datepicker table tr td.active:hover div,
|
||||
.datepicker table tr td.active:hover:hover div,
|
||||
.datepicker table tr td.active.disabled:hover div,
|
||||
.datepicker table tr td.active.disabled:hover:hover div,
|
||||
.datepicker table tr td.active:active div,
|
||||
.datepicker table tr td.active:hover:active div,
|
||||
.datepicker table tr td.active.disabled:active div,
|
||||
.datepicker table tr td.active.disabled:hover:active div,
|
||||
.datepicker table tr td.active.active div,
|
||||
.datepicker table tr td.active:hover.active div,
|
||||
.datepicker table tr td.active.disabled.active div,
|
||||
.datepicker table tr td.active.disabled:hover.active div,
|
||||
.datepicker table tr td.active.disabled div,
|
||||
.datepicker table tr td.active:hover.disabled div,
|
||||
.datepicker table tr td.active.disabled.disabled div,
|
||||
.datepicker table tr td.active.disabled:hover.disabled div,
|
||||
.datepicker table tr td.active[disabled] div,
|
||||
.datepicker table tr td.active:hover[disabled] div,
|
||||
.datepicker table tr td.active.disabled[disabled] div,
|
||||
.datepicker table tr td.active.disabled:hover[disabled] div{
|
||||
background-color: $primary-color;
|
||||
}
|
||||
.datepicker table tr td.active:active,
|
||||
.datepicker table tr td.active:hover:active,
|
||||
.datepicker table tr td.active.disabled:active,
|
||||
.datepicker table tr td.active.disabled:hover:active,
|
||||
.datepicker table tr td.active.active,
|
||||
.datepicker table tr td.active:hover.active,
|
||||
.datepicker table tr td.active.disabled.active,
|
||||
.datepicker table tr td.active.disabled:hover.active {
|
||||
background-color: #003399 \9;
|
||||
}
|
||||
.datepicker table tr td span {
|
||||
display: block;
|
||||
width: 41px;
|
||||
height: 41px;
|
||||
line-height: 41px;
|
||||
float: left;
|
||||
margin: 1%;
|
||||
font-size: $font-size-base;
|
||||
cursor: pointer;
|
||||
-webkit-border-radius: 50%;
|
||||
-moz-border-radius: 50%;
|
||||
border-radius: 50%;
|
||||
|
||||
}
|
||||
.datepicker table tr td span:hover,
|
||||
.datepicker table tr td span.focused {
|
||||
background: #eee;
|
||||
}
|
||||
.datepicker table tr td span.disabled,
|
||||
.datepicker table tr td span.disabled:hover {
|
||||
background: none;
|
||||
color: $default-color;
|
||||
cursor: default;
|
||||
}
|
||||
.datepicker table tr td span.active,
|
||||
.datepicker table tr td span.active:hover,
|
||||
.datepicker table tr td span.active.disabled,
|
||||
.datepicker table tr td span.active.disabled:hover {
|
||||
color: #fff;
|
||||
background-color: $primary-color;
|
||||
}
|
||||
.datepicker table tr td span.active:hover,
|
||||
.datepicker table tr td span.active:hover:hover,
|
||||
.datepicker table tr td span.active.disabled:hover,
|
||||
.datepicker table tr td span.active.disabled:hover:hover,
|
||||
.datepicker table tr td span.active:active,
|
||||
.datepicker table tr td span.active:hover:active,
|
||||
.datepicker table tr td span.active.disabled:active,
|
||||
.datepicker table tr td span.active.disabled:hover:active,
|
||||
.datepicker table tr td span.active.active,
|
||||
.datepicker table tr td span.active:hover.active,
|
||||
.datepicker table tr td span.active.disabled.active,
|
||||
.datepicker table tr td span.active.disabled:hover.active,
|
||||
.datepicker table tr td span.active.disabled,
|
||||
.datepicker table tr td span.active:hover.disabled,
|
||||
.datepicker table tr td span.active.disabled.disabled,
|
||||
.datepicker table tr td span.active.disabled:hover.disabled,
|
||||
.datepicker table tr td span.active[disabled],
|
||||
.datepicker table tr td span.active:hover[disabled],
|
||||
.datepicker table tr td span.active.disabled[disabled],
|
||||
.datepicker table tr td span.active.disabled:hover[disabled] {
|
||||
background-color: $primary-color;
|
||||
box-shadow: 0px 1px 10px 0px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
.datepicker table tr td span.active:active,
|
||||
.datepicker table tr td span.active:hover:active,
|
||||
.datepicker table tr td span.active.disabled:active,
|
||||
.datepicker table tr td span.active.disabled:hover:active,
|
||||
.datepicker table tr td span.active.active,
|
||||
.datepicker table tr td span.active:hover.active,
|
||||
.datepicker table tr td span.active.disabled.active,
|
||||
.datepicker table tr td span.active.disabled:hover.active {
|
||||
background-color: #003399 \9;
|
||||
}
|
||||
.datepicker table tr td span.old,
|
||||
.datepicker table tr td span.new {
|
||||
color: $default-color;
|
||||
}
|
||||
.datepicker .datepicker-switch {
|
||||
width: auto;
|
||||
border-radius: $border-radius-small;
|
||||
}
|
||||
.datepicker .datepicker-switch,
|
||||
.datepicker .prev,
|
||||
.datepicker .next,
|
||||
.datepicker tfoot tr th {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.datepicker{
|
||||
.prev,
|
||||
.next{
|
||||
width: 35px;
|
||||
height: 35px;
|
||||
}
|
||||
|
||||
i{
|
||||
position: relative;
|
||||
top: 2px;
|
||||
}
|
||||
|
||||
.prev i{
|
||||
left: -1px;
|
||||
}
|
||||
|
||||
.next i{
|
||||
right: -1px;
|
||||
}
|
||||
}
|
||||
|
||||
.datepicker .datepicker-switch:hover,
|
||||
.datepicker .prev:hover,
|
||||
.datepicker .next:hover,
|
||||
.datepicker tfoot tr th:hover {
|
||||
background: #eee;
|
||||
}
|
||||
.datepicker .prev.disabled,
|
||||
.datepicker .next.disabled {
|
||||
visibility: hidden;
|
||||
}
|
||||
.datepicker .cw {
|
||||
font-size: 10px;
|
||||
width: 12px;
|
||||
padding: 0 2px 0 5px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.input-append.date .add-on,
|
||||
.input-prepend.date .add-on {
|
||||
cursor: pointer;
|
||||
}
|
||||
.input-append.date .add-on i,
|
||||
.input-prepend.date .add-on i {
|
||||
margin-top: 3px;
|
||||
}
|
||||
.input-daterange input {
|
||||
text-align: center;
|
||||
}
|
||||
.input-daterange input:first-child {
|
||||
-webkit-border-radius: 3px 0 0 3px;
|
||||
-moz-border-radius: 3px 0 0 3px;
|
||||
border-radius: 3px 0 0 3px;
|
||||
}
|
||||
.input-daterange input:last-child {
|
||||
-webkit-border-radius: 0 3px 3px 0;
|
||||
-moz-border-radius: 0 3px 3px 0;
|
||||
border-radius: 0 3px 3px 0;
|
||||
}
|
||||
.input-daterange .add-on {
|
||||
display: inline-block;
|
||||
width: auto;
|
||||
min-width: 16px;
|
||||
height: 18px;
|
||||
padding: 4px 5px;
|
||||
font-weight: normal;
|
||||
line-height: 18px;
|
||||
text-align: center;
|
||||
text-shadow: 0 1px 0 #fff;
|
||||
vertical-align: middle;
|
||||
background-color: #eee;
|
||||
border: 1px solid #ccc;
|
||||
margin-left: -5px;
|
||||
margin-right: -5px;
|
||||
}
|
||||
|
|
@ -0,0 +1,351 @@
|
|||
/*! nouislider - 9.1.0 - 2016-12-10 16:00:32 */
|
||||
|
||||
|
||||
/* Functional styling;
|
||||
* These styles are required for noUiSlider to function.
|
||||
* You don't need to change these rules to apply your design.
|
||||
*/
|
||||
.noUi-target,
|
||||
.noUi-target * {
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-tap-highlight-color: rgba(0,0,0,0);
|
||||
-webkit-user-select: none;
|
||||
-ms-touch-action: none;
|
||||
touch-action: none;
|
||||
-ms-user-select: none;
|
||||
-moz-user-select: none;
|
||||
user-select: none;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.noUi-target {
|
||||
position: relative;
|
||||
direction: ltr;
|
||||
}
|
||||
.noUi-base {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
z-index: 1; /* Fix 401 */
|
||||
}
|
||||
.noUi-connect {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
.noUi-origin {
|
||||
position: absolute;
|
||||
height: 0;
|
||||
width: 0;
|
||||
}
|
||||
.noUi-handle {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
.noUi-state-tap .noUi-connect,
|
||||
.noUi-state-tap .noUi-origin {
|
||||
-webkit-transition: top 0.3s, right 0.3s, bottom 0.3s, left 0.3s;
|
||||
transition: top 0.3s, right 0.3s, bottom 0.3s, left 0.3s;
|
||||
}
|
||||
.noUi-state-drag * {
|
||||
cursor: inherit !important;
|
||||
}
|
||||
|
||||
/* Painting and performance;
|
||||
* Browsers can paint handles in their own layer.
|
||||
*/
|
||||
.noUi-base,
|
||||
.noUi-handle {
|
||||
-webkit-transform: translate3d(0,0,0);
|
||||
transform: translate3d(0,0,0);
|
||||
}
|
||||
|
||||
/* Slider size and handle placement;
|
||||
*/
|
||||
.noUi-horizontal {
|
||||
height: 1px;
|
||||
}
|
||||
.noUi-horizontal .noUi-handle {
|
||||
border-radius: 50%;
|
||||
background-color: $white-color;
|
||||
box-shadow: 0 1px 13px 0 rgba(0, 0, 0, 0.2);
|
||||
height:15px;
|
||||
width:15px;
|
||||
cursor:pointer;
|
||||
margin-left: -10px;
|
||||
margin-top: -7px;
|
||||
}
|
||||
.noUi-vertical {
|
||||
width: 18px;
|
||||
}
|
||||
.noUi-vertical .noUi-handle {
|
||||
width: 28px;
|
||||
height: 34px;
|
||||
left: -6px;
|
||||
top: -17px;
|
||||
}
|
||||
|
||||
/* Styling;
|
||||
*/
|
||||
.noUi-target {
|
||||
background-color: rgba(182, 182, 182, .3);
|
||||
border-radius: 3px;
|
||||
}
|
||||
.noUi-connect {
|
||||
background: $default-color;
|
||||
border-radius: 3px;
|
||||
-webkit-transition: background 450ms;
|
||||
transition: background 450ms;
|
||||
}
|
||||
|
||||
/* Handles and cursors;
|
||||
*/
|
||||
.noUi-draggable {
|
||||
cursor: ew-resize;
|
||||
}
|
||||
.noUi-vertical .noUi-draggable {
|
||||
cursor: ns-resize;
|
||||
}
|
||||
.noUi-handle {
|
||||
// border: 1px solid #D9D9D9;
|
||||
border-radius: 3px;
|
||||
background: #FFF;
|
||||
cursor: default;
|
||||
box-shadow: inset 0 0 1px #FFF,
|
||||
inset 0 1px 7px #EBEBEB,
|
||||
0 3px 6px -3px #BBB;
|
||||
-webkit-transition: $general-transition-time $transition-ease;
|
||||
-moz-transition: $general-transition-time $transition-ease;
|
||||
-ms-transition: $general-transition-time $transition-ease;
|
||||
-o-transform: $general-transition-time $transition-ease;
|
||||
transition: $general-transition-time $transition-ease;
|
||||
}
|
||||
.noUi-active {
|
||||
-webkit-transform: scale3d(1.5,1.5,1);
|
||||
-moz-transform: scale3d(1.5,1.5,1);
|
||||
-ms-transform: scale3d(1.5,1.5,1);
|
||||
-o-transform: scale3d(1.5,1.5,1);
|
||||
transform: scale3d(1.5,1.5,1);
|
||||
}
|
||||
|
||||
/* Disabled state;
|
||||
*/
|
||||
|
||||
[disabled] .noUi-connect {
|
||||
background: #B8B8B8;
|
||||
}
|
||||
[disabled].noUi-target,
|
||||
[disabled].noUi-handle,
|
||||
[disabled] .noUi-handle {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
/* Base;
|
||||
*
|
||||
*/
|
||||
.noUi-pips,
|
||||
.noUi-pips * {
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.noUi-pips {
|
||||
position: absolute;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
/* Values;
|
||||
*
|
||||
*/
|
||||
.noUi-value {
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
}
|
||||
.noUi-value-sub {
|
||||
color: #ccc;
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
/* Markings;
|
||||
*
|
||||
*/
|
||||
.noUi-marker {
|
||||
position: absolute;
|
||||
background: #CCC;
|
||||
}
|
||||
.noUi-marker-sub {
|
||||
background: #AAA;
|
||||
}
|
||||
.noUi-marker-large {
|
||||
background: #AAA;
|
||||
}
|
||||
|
||||
/* Horizontal layout;
|
||||
*
|
||||
*/
|
||||
.noUi-pips-horizontal {
|
||||
padding: 10px 0;
|
||||
height: 80px;
|
||||
top: 100%;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
}
|
||||
.noUi-value-horizontal {
|
||||
-webkit-transform: translate3d(-50%,50%,0);
|
||||
transform: translate3d(-50%,50%,0);
|
||||
}
|
||||
|
||||
.noUi-marker-horizontal.noUi-marker {
|
||||
margin-left: -1px;
|
||||
width: 2px;
|
||||
height: 5px;
|
||||
}
|
||||
.noUi-marker-horizontal.noUi-marker-sub {
|
||||
height: 10px;
|
||||
}
|
||||
.noUi-marker-horizontal.noUi-marker-large {
|
||||
height: 15px;
|
||||
}
|
||||
|
||||
/* Vertical layout;
|
||||
*
|
||||
*/
|
||||
.noUi-pips-vertical {
|
||||
padding: 0 10px;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
left: 100%;
|
||||
}
|
||||
.noUi-value-vertical {
|
||||
-webkit-transform: translate3d(0,50%,0);
|
||||
transform: translate3d(0,50%,0);
|
||||
padding-left: 25px;
|
||||
}
|
||||
|
||||
.noUi-marker-vertical.noUi-marker {
|
||||
width: 5px;
|
||||
height: 2px;
|
||||
margin-top: -1px;
|
||||
}
|
||||
.noUi-marker-vertical.noUi-marker-sub {
|
||||
width: 10px;
|
||||
}
|
||||
.noUi-marker-vertical.noUi-marker-large {
|
||||
width: 15px;
|
||||
}
|
||||
|
||||
.noUi-tooltip {
|
||||
display: block;
|
||||
position: absolute;
|
||||
border: 1px solid #D9D9D9;
|
||||
border-radius: 3px;
|
||||
background: #fff;
|
||||
color: #000;
|
||||
padding: 5px;
|
||||
text-align: center;
|
||||
}
|
||||
.noUi-horizontal .noUi-tooltip {
|
||||
-webkit-transform: translate(-50%, 0);
|
||||
transform: translate(-50%, 0);
|
||||
left: 50%;
|
||||
bottom: 120%;
|
||||
}
|
||||
.noUi-vertical .noUi-tooltip {
|
||||
-webkit-transform: translate(0, -50%);
|
||||
transform: translate(0, -50%);
|
||||
top: 50%;
|
||||
right: 120%;
|
||||
}
|
||||
|
||||
|
||||
.slider {
|
||||
|
||||
&.slider-neutral{
|
||||
& .noUi-connect,
|
||||
&.noUi-connect{
|
||||
background-color: $white-color;
|
||||
}
|
||||
|
||||
&.noUi-target{
|
||||
background-color: rgba(255,255,255, .3);
|
||||
}
|
||||
|
||||
& .noUi-handle{
|
||||
background-color: $white-color;
|
||||
}
|
||||
}
|
||||
|
||||
&.slider-primary{
|
||||
& .noUi-connect,
|
||||
&.noUi-connect{
|
||||
background-color: $primary-color;
|
||||
}
|
||||
|
||||
&.noUi-target{
|
||||
background-color: $primary-color-opacity;
|
||||
}
|
||||
|
||||
& .noUi-handle{
|
||||
background-color: $brand-primary;
|
||||
}
|
||||
}
|
||||
|
||||
&.slider-info{
|
||||
& .noUi-connect,
|
||||
&.noUi-connect{
|
||||
background-color: $brand-info;
|
||||
}
|
||||
|
||||
&.noUi-target{
|
||||
background-color: $info-color-opacity;
|
||||
}
|
||||
|
||||
& .noUi-handle{
|
||||
background-color: $brand-info;
|
||||
}
|
||||
}
|
||||
&.slider-success{
|
||||
& .noUi-connect,
|
||||
&.noUi-connect{
|
||||
background-color: $brand-success;
|
||||
}
|
||||
|
||||
&.noUi-target{
|
||||
background-color: $success-color-opacity;
|
||||
}
|
||||
|
||||
& .noUi-handle{
|
||||
background-color: $brand-success;
|
||||
}
|
||||
}
|
||||
&.slider-warning{
|
||||
& .noUi-connect,
|
||||
&.noUi-connect{
|
||||
background-color: $brand-warning;
|
||||
}
|
||||
|
||||
&.noUi-target{
|
||||
background-color: $warning-color-opacity;
|
||||
}
|
||||
|
||||
& .noUi-handle{
|
||||
background-color: $brand-warning;
|
||||
}
|
||||
}
|
||||
&.slider-danger{
|
||||
& .noUi-connect,
|
||||
&.noUi-connect{
|
||||
background-color: $brand-danger;
|
||||
}
|
||||
|
||||
&.noUi-target{
|
||||
background-color: $danger-color-opacity;
|
||||
}
|
||||
|
||||
& .noUi-handle{
|
||||
background-color: $brand-danger;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -113,9 +113,11 @@ $.ccio.ws.on('f',function(d){
|
|||
console.log(d);
|
||||
switch(d.f){
|
||||
case'edit_sub_account':
|
||||
var account = $.ccio.subs[d.uid]
|
||||
$.each(d.form,function(n,v){
|
||||
$.ccio.subs[d.uid][n]=v;
|
||||
account[n]=v;
|
||||
});
|
||||
account.detailsJSON=JSON.parse(account.details);
|
||||
break;
|
||||
case'add_sub_account':
|
||||
$.ccio.tm(0,d,'#sub_accounts')
|
||||
|
|
@ -193,7 +195,7 @@ $.sU.e.on('click','.permission',function(e){
|
|||
$.pR={e:$('#permissions'),l:$('#permissionsLabel small')};$.pR.f=$.pR.e.find('form')
|
||||
$.pR.e.on('change','[detail="allmonitors"]',function(e){
|
||||
e.e=$(this),
|
||||
e.mon=$('#monitors_section,#monitors_edit_section,#video_delete_section')
|
||||
e.mon=$('.permission-view')
|
||||
e.details=$.pR.e.find('[name="details"]')
|
||||
e.json=JSON.parse(e.details.val())
|
||||
if(e.e.val()=='1'){
|
||||
|
|
|
|||
|
|
@ -0,0 +1,12 @@
|
|||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black">
|
||||
<meta name="apple-mobile-web-app-title" content="Shinobi">
|
||||
<link rel="apple-touch-icon" href="/apple-touch-icon.png" />
|
||||
<link rel="apple-touch-icon" sizes="57x57" href="libs/img/icon/apple-touch-icon-57x57.png" />
|
||||
<link rel="apple-touch-icon" sizes="72x72" href="libs/img/icon/apple-touch-icon-72x72.png" />
|
||||
<link rel="apple-touch-icon" sizes="76x76" href="libs/img/icon/apple-touch-icon-76x76.png" />
|
||||
<link rel="apple-touch-icon" sizes="114x114" href="libs/img/icon/apple-touch-icon-114x114.png" />
|
||||
<link rel="apple-touch-icon" sizes="120x120" href="libs/img/icon/apple-touch-icon-120x120.png" />
|
||||
<link rel="apple-touch-icon" sizes="144x144" href="libs/img/icon/apple-touch-icon-144x144.png" />
|
||||
<link rel="apple-touch-icon" sizes="152x152" href="libs/img/icon/apple-touch-icon-152x152.png" />
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="libs/img/icon/apple-touch-icon-180x180.png" />
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
<meta charset="utf-8">
|
||||
<meta name="ROBOTS" content="NOINDEX, NOFOLLOW">
|
||||
<meta name="viewport" content="width=device-width, maximum-scale=1, user-scalable=no" />
|
||||
<meta name="description" content="Shinobi, Open Source CCTV Technology">
|
||||
<meta name="author" content="Moe Alam, moeiscool on GitHub">
|
||||
|
|
@ -1,10 +1,6 @@
|
|||
<head>
|
||||
<title><%-lang.Shinobi%></title>
|
||||
<meta charset="utf-8">
|
||||
<meta name="ROBOTS" content="NOINDEX, NOFOLLOW">
|
||||
<meta name="viewport" content="width=device-width, maximum-scale=1, user-scalable=no" />
|
||||
<meta name="description" content="Shinobi, Open Source CCTV Technology">
|
||||
<meta name="author" content="Moe Alam, moeiscool on GitHub">
|
||||
<% include header-meta.ejs %>
|
||||
<meta http-equiv="content-type" content="text/html;charset=UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<link rel="stylesheet" href="libs/css/bootstrap.min.css">
|
||||
|
|
@ -14,18 +10,7 @@
|
|||
<meta name="mobile-web-app-capable" content="yes">
|
||||
<link rel="icon" href="libs/img/icon/favicon.ico" type="image/x-icon" />
|
||||
<link rel="shortcut icon" href="libs/img/icon/favicon.ico" type="image/x-icon" />
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black">
|
||||
<meta name="apple-mobile-web-app-title" content="Shinobi">
|
||||
<link rel="apple-touch-icon" href="/apple-touch-icon.png" />
|
||||
<link rel="apple-touch-icon" sizes="57x57" href="libs/img/icon/apple-touch-icon-57x57.png" />
|
||||
<link rel="apple-touch-icon" sizes="72x72" href="libs/img/icon/apple-touch-icon-72x72.png" />
|
||||
<link rel="apple-touch-icon" sizes="76x76" href="libs/img/icon/apple-touch-icon-76x76.png" />
|
||||
<link rel="apple-touch-icon" sizes="114x114" href="libs/img/icon/apple-touch-icon-114x114.png" />
|
||||
<link rel="apple-touch-icon" sizes="120x120" href="libs/img/icon/apple-touch-icon-120x120.png" />
|
||||
<link rel="apple-touch-icon" sizes="144x144" href="libs/img/icon/apple-touch-icon-144x144.png" />
|
||||
<link rel="apple-touch-icon" sizes="152x152" href="libs/img/icon/apple-touch-icon-152x152.png" />
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="libs/img/icon/apple-touch-icon-180x180.png" />
|
||||
<% include header-favicon.ejs %>
|
||||
<script src="libs/js/jquery.min.js"></script>
|
||||
<script src="libs/js/jquery-ui.min.js"></script>
|
||||
<script src="libs/js/jquery.serialize.js"></script>
|
||||
|
|
|
|||
|
|
@ -8,28 +8,42 @@
|
|||
</button>
|
||||
<h4 class="modal-title" id="logsLabel"><i class="fa fa-exclamation-triangle"></i> <%-lang.Logs%></h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="form-group">
|
||||
<label>
|
||||
<div>
|
||||
<select class="form-control" id="log_monitors">
|
||||
<option class="hard" value="all"><%-lang['All Logs']%></option>
|
||||
<option class="hard" value="$USER"><%-lang['For Group']%></option>
|
||||
</select>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>
|
||||
<input class="form-control search-controller" placeholder="<%-lang.Search%>">
|
||||
</label>
|
||||
</div>
|
||||
<table class="table table-striped">
|
||||
<tbody class="search-body"></tbody>
|
||||
</table>
|
||||
<div class="modal-body overflow-hidden">
|
||||
<div class="col-md-3">
|
||||
<div class="form-group">
|
||||
<label>
|
||||
<div>
|
||||
<select class="form-control" id="log_monitors">
|
||||
<option class="hard" value="all"><%-lang['All Logs']%></option>
|
||||
<option class="hard" value="$USER"><%-lang['For Group']%></option>
|
||||
</select>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label><div><span><%-lang.Search%></span></div>
|
||||
<div><input type="text" class="form-control search-controller" placeholder="<%-lang.Search%>" /></div>
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label><div><span><%-lang['Date Range']%></span></div>
|
||||
<div><input type="text" id="logs_daterange" class="form-control" value="" /></div>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-9">
|
||||
<div class="fixed-table-container">
|
||||
<div class="fixed-table-body">
|
||||
<table class="table table-striped">
|
||||
<tbody class="search-body"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default pull-left" data-dismiss="modal"><i class="fa fa-times"></i> <%-lang.Close%></button>
|
||||
<button download class="btn btn-info"><%-lang.Export%></button>
|
||||
<button onclick="$.log.lm.change()" class="btn btn-success"><%-lang.Check%></button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,19 +1,12 @@
|
|||
<!--Confirmation Window-->
|
||||
<div class="modal fade" id="add_edit" tabindex="-1" role="dialog" aria-labelledby="permissionsLabel" aria-hidden="true">
|
||||
<div class="modal fade full" id="add_edit" tabindex="-1" role="dialog" aria-labelledby="permissionsLabel" aria-hidden="true">
|
||||
<div class="modal-dialog" role="document">
|
||||
<form class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
<h4 class="modal-title" id="permissionsLabel"><i class="fa fa-lock"></i> <span id="title"></span>
|
||||
<div class="pull-right">
|
||||
<label class="mdl-switch mdl-js-switch mdl-js-ripple-effect" for="edit">
|
||||
<input type="checkbox" id="edit" value="1" class="mdl-switch__input">
|
||||
<span class="monospace mdl-switch__label"></span>
|
||||
</label>
|
||||
</div>
|
||||
</h4>
|
||||
<h4 class="modal-title" id="permissionsLabel"><i class="fa fa-lock"></i> <span id="title"></span></h4>
|
||||
</div>
|
||||
<div class="modal-body" style="max-height:600px;overflow:auto">
|
||||
<div class="form-group">
|
||||
|
|
@ -137,6 +130,12 @@
|
|||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default pull-left" data-dismiss="modal"><i class="fa fa-times"></i> <%-lang.Close%></button>
|
||||
|
||||
<div class="pull-left">
|
||||
<div class="marc-toggle display-inline">
|
||||
<input type="checkbox" id="edit"/><label for="edit">Add or Edit</label>
|
||||
</div>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-success"><i class="fa fa-check"></i> <%-lang.Save%></button>
|
||||
</div>
|
||||
<input type="hidden" name="details" value="{}">
|
||||
|
|
|
|||
|
|
@ -1308,30 +1308,6 @@
|
|||
<input type="hidden" detail="groups">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group-group green" section id="monSectionLogging">
|
||||
<h4><%-lang['Logging']%></h4>
|
||||
<div class="row">
|
||||
<div class="form-group col-md-12">
|
||||
<label><div><span><%-lang['Log Level']%></span></div>
|
||||
<div><select class="form-control" detail="loglevel">
|
||||
<option value="quiet"><%-lang['Silent']%></option>
|
||||
<option value="fatal"><%-lang['Fatal']%></option>
|
||||
<option value="error" selected><%-lang['on Error']%></option>
|
||||
<option value="warning"><%-lang['All Warnings']%></option>
|
||||
<option value="debug"><%-lang['Debug']%></option>
|
||||
</select></div>
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-group col-md-12">
|
||||
<label><div><span><%-lang['Save Log in SQL']%></span></div>
|
||||
<div><select class="form-control" detail="sqllog">
|
||||
<option value="0" selected><%-lang.No%></option>
|
||||
<option value="1"><%-lang.Yes%></option>
|
||||
</select></div>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group-group orange" section id="monSectionCopying">
|
||||
<h4><%-lang['Copy Settings']%></h4>
|
||||
<div class="form-group">
|
||||
|
|
@ -1435,6 +1411,32 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group-group green" section id="monSectionLogging">
|
||||
<h4><%-lang['Logging']%></h4>
|
||||
<div class="form-group">
|
||||
<label><div><span><%-lang['Log Level']%></span></div>
|
||||
<div><select class="form-control" detail="loglevel">
|
||||
<option value="quiet"><%-lang['Silent']%></option>
|
||||
<option value="fatal"><%-lang['Fatal']%></option>
|
||||
<option value="error" selected><%-lang['on Error']%></option>
|
||||
<option value="warning"><%-lang['All Warnings']%></option>
|
||||
<option value="debug"><%-lang['Debug']%></option>
|
||||
</select></div>
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label><div><span><%-lang['Save Log in SQL']%></span></div>
|
||||
<div><select class="form-control" detail="sqllog">
|
||||
<option value="0" selected><%-lang.No%></option>
|
||||
<option value="1"><%-lang.Yes%></option>
|
||||
</select></div>
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-group-group green">
|
||||
<h4><%-lang['Log Stream']%></h4>
|
||||
<div class="data-menu logs"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group" style="display:none">
|
||||
<input type="hidden" detail="detector_cascades">
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
</select></div>
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-group-group blue" id="monitors_section">
|
||||
<div class="form-group-group blue permission-view" id="monitors_section">
|
||||
<h4>
|
||||
<%-lang['Can View Monitor']%>
|
||||
<div class="pull-right">
|
||||
|
|
@ -37,7 +37,7 @@
|
|||
</div>
|
||||
<% }) %>
|
||||
</div>
|
||||
<div class="form-group-group forestgreen" id="monitors_edit_section">
|
||||
<div class="form-group-group forestgreen permission-view" id="monitors_edit_section">
|
||||
<h4>
|
||||
<%-lang['Can Edit Monitor']%>
|
||||
<div class="pull-right">
|
||||
|
|
@ -56,7 +56,7 @@
|
|||
</div>
|
||||
<% }) %>
|
||||
</div>
|
||||
<div class="form-group-group navy" id="video_view_section">
|
||||
<div class="form-group-group navy permission-view" id="video_view_section">
|
||||
<h4>
|
||||
<%-lang['Can View Videos and Events']%>
|
||||
<div class="pull-right">
|
||||
|
|
@ -75,7 +75,7 @@
|
|||
</div>
|
||||
<% }) %>
|
||||
</div>
|
||||
<div class="form-group-group red" id="video_delete_section">
|
||||
<div class="form-group-group red permission-view" id="video_delete_section">
|
||||
<h4>
|
||||
<%-lang['Can Delete Videos and Events']%>
|
||||
<div class="pull-right">
|
||||
|
|
|
|||
|
|
@ -8,10 +8,9 @@
|
|||
</button>
|
||||
<h4 class="modal-title" id="videos_viewerLabel"><i class="fa fa-film"></i> <%-lang.Videos%> <small> <span class="video_viewer_total"></span> <%-lang.total%></small></h4>
|
||||
</div>
|
||||
<div class="modal-body flex-container-modal-body">
|
||||
<div style="padding:20px 0" class="flex-block flex-modal-block">
|
||||
<div class="modal-body overflow-hidden">
|
||||
<div style="padding:20px 0">
|
||||
<div class="col-md-3">
|
||||
|
||||
<div class="form-group">
|
||||
<label><div><span><%-lang['Date Range']%></span></div>
|
||||
<div><input type="text" id="videos_viewer_daterange" class="form-control" value="" /></div>
|
||||
|
|
|
|||
|
|
@ -23,11 +23,16 @@ requires https or firefox
|
|||
<script src="libs/js/socket.io.js"></script>
|
||||
<script src="libs/js/menu.js"></script>
|
||||
<script>
|
||||
$.ccio={};$.ls=localStorage;
|
||||
$.ccio.ws=io(location.origin);
|
||||
$.ccio = {}
|
||||
$.ls = localStorage
|
||||
$.ccio.ws = io(location.origin)
|
||||
$.ccio.ws.on('connect',function (d){
|
||||
$(document).ready(function(e){
|
||||
$.ccio.cx=function(x){if(!x.ke){x.ke=$user.ke;};if(!x.uid){x.uid=$user.uid;};return $.ccio.ws.emit('r',x)}
|
||||
$.ccio.cx=function(x){
|
||||
if(!x.ke){x.ke=$user.ke;}
|
||||
if(!x.uid){x.uid=$user.uid;}
|
||||
return $.ccio.ws.emit('r',x)
|
||||
}
|
||||
console.log($user)
|
||||
$.ccio.cx({f:'init',ke:$user.ke,auth:$user.auth_token,uid:$user.uid})
|
||||
})
|
||||
|
|
@ -41,6 +46,16 @@ $.ccio.ws.on('f',function(d){
|
|||
$.ccio.mon[d.mid][n]=v;
|
||||
});
|
||||
break;
|
||||
case'disable_stream':
|
||||
$.ccio.mon[d.mid].allowStream = false
|
||||
if(d.mid === $.ccio.selected){
|
||||
$.ccio.stopSending()
|
||||
setTimeout($.ccio.startSending,2000)
|
||||
}
|
||||
break;
|
||||
case'enable_stream':
|
||||
$.ccio.mon[d.mid].allowStream = true
|
||||
break;
|
||||
}
|
||||
})
|
||||
function _base64ToArrayBuffer(base64) {
|
||||
|
|
@ -52,81 +67,95 @@ function _base64ToArrayBuffer(base64) {
|
|||
}
|
||||
return bytes.buffer;
|
||||
}
|
||||
|
||||
$.ccio.framerate=2;
|
||||
|
||||
$.ccio.stopSending=function(){
|
||||
$.ls.setItem('Shinobi_Dashcam_Started','0')
|
||||
$('#main').removeClass('recording');
|
||||
clearInterval($.ccio.cutChunk);
|
||||
clearTimeout($.ccio.sendCheckTimeout);
|
||||
try{
|
||||
mediaRecorder.stop()
|
||||
}catch(err){
|
||||
|
||||
}
|
||||
$('[record]').unbind('click').click($.ccio.startSending)
|
||||
}
|
||||
$.ccio.startSending=function(){
|
||||
if($.ccio.selected===null){return false;}
|
||||
$('#main').addClass('recording');
|
||||
if (typeof MediaRecorder.isTypeSupported == 'function'){
|
||||
/*
|
||||
MediaRecorder.isTypeSupported is a function announced in https://developers.google.com/web/updates/2016/01/mediarecorder and later introduced in the MediaRecorder API spec http://www.w3.org/TR/mediastream-recording/
|
||||
*/
|
||||
if (MediaRecorder.isTypeSupported('video/webm;codecs=vp9')) {
|
||||
var options = {mimeType: 'video/webm;codecs=vp9'};
|
||||
} else if (MediaRecorder.isTypeSupported('video/webm;codecs=h264')) {
|
||||
var options = {mimeType: 'video/webm;codecs=h264'};
|
||||
} else if (MediaRecorder.isTypeSupported('video/webm;codecs=vp8')) {
|
||||
var options = {mimeType: 'video/webm;codecs=vp8'};
|
||||
}
|
||||
log('Using '+options.mimeType);
|
||||
mediaRecorder = new MediaRecorder($.ccio.vid.stream, options);
|
||||
}else{
|
||||
log('Using default codecs for browser');
|
||||
mediaRecorder = new MediaRecorder($.ccio.vid.stream);
|
||||
}
|
||||
|
||||
mediaRecorder.start(10);
|
||||
$.ccio.chunker = function(){
|
||||
clearInterval($.ccio.cutChunk)
|
||||
$.ccio.cutChunk=setInterval(function(){
|
||||
mediaRecorder.stop()
|
||||
mediaRecorder.start()
|
||||
},5000)
|
||||
$.ccio.firstFrame = null
|
||||
$.ccio.startSending = function(){
|
||||
if($.ccio.selected === null){
|
||||
return false
|
||||
}
|
||||
mediaRecorder.ondataavailable = function(e) {
|
||||
//log('Data available...');
|
||||
//console.log(e.data);
|
||||
//console.log(e.data.type);
|
||||
//console.log(e);
|
||||
chunks.push(e.data);
|
||||
};
|
||||
$.ls.setItem('Shinobi_Dashcam_Started',1)
|
||||
$('#main').addClass('recording');
|
||||
if($.ccio.mon[$.ccio.selected].allowStream === true){
|
||||
if (typeof MediaRecorder.isTypeSupported == 'function'){
|
||||
var options = {
|
||||
audioBitsPerSecond : 128000,
|
||||
videoBitsPerSecond : 2500000,
|
||||
}
|
||||
if (MediaRecorder.isTypeSupported('video/webm;codecs=vp9')) {
|
||||
options.mimeType = 'video/webm;codecs=vp9'
|
||||
} else if (MediaRecorder.isTypeSupported('video/webm;codecs=h264')) {
|
||||
options.mimeType = 'video/webm;codecs=h264'
|
||||
} else if (MediaRecorder.isTypeSupported('video/webm;codecs=vp8')) {
|
||||
options.mimeType = 'video/webm;codecs=vp8'
|
||||
}
|
||||
console.log('Using '+options.mimeType);
|
||||
mediaRecorder = new MediaRecorder($.ccio.vid.stream, options);
|
||||
}else{
|
||||
console.log('Using default codecs for browser');
|
||||
mediaRecorder = new MediaRecorder($.ccio.vid.stream);
|
||||
}
|
||||
|
||||
mediaRecorder.onerror = function(e){
|
||||
clearInterval($.ccio.cutChunk)
|
||||
};
|
||||
mediaRecorder.start(10)
|
||||
|
||||
$.ccio.chunker = function(){
|
||||
clearInterval($.ccio.cutChunk)
|
||||
$.ccio.cutChunk=setInterval(function(){
|
||||
var blob = new Blob(chunks, {type: "video/webm"});
|
||||
$.ccio.cx({f:'monitor_chunk',chunk:blob,mid:$.ccio.selected});
|
||||
chunks = [];
|
||||
},1000/$.ccio.framerate)
|
||||
}
|
||||
var noFirstFrame = function(e){
|
||||
$.ccio.firstFrame = e.data
|
||||
chunks.push(e.data);
|
||||
mediaRecorder.ondataavailable = function(e) {
|
||||
chunks.push(e.data);
|
||||
}
|
||||
}
|
||||
mediaRecorder.ondataavailable = noFirstFrame
|
||||
|
||||
mediaRecorder.onerror = function(e){
|
||||
clearInterval($.ccio.cutChunk)
|
||||
}
|
||||
|
||||
|
||||
mediaRecorder.onstart = function(){
|
||||
$.ccio.chunker()
|
||||
};
|
||||
mediaRecorder.onstart = function(){
|
||||
if($.ccio.firstFrame){
|
||||
var blob = new Blob([$.ccio.firstFrame], {type: "video/webm"});
|
||||
$.ccio.cx({f:'monitor_chunk',chunk:blob,mid:$.ccio.selected});
|
||||
}
|
||||
$.ccio.chunker()
|
||||
}
|
||||
|
||||
mediaRecorder.onstop = function(){
|
||||
var blob = new Blob(chunks, {type: "video/webm"});
|
||||
$.ccio.cx({f:'monitor_chunk',chunk:blob,mid:$.ccio.selected});
|
||||
// var reader = new FileReader();
|
||||
// reader.addEventListener("loadend", function() {
|
||||
// console.log(reader.result)
|
||||
// });
|
||||
// reader.readAsArrayBuffer(blob);
|
||||
chunks = [];
|
||||
};
|
||||
mediaRecorder.onpause = function(){
|
||||
clearInterval($.ccio.cutChunk)
|
||||
}
|
||||
|
||||
mediaRecorder.onpause = function(){
|
||||
clearInterval($.ccio.cutChunk)
|
||||
}
|
||||
mediaRecorder.onresume = function(){
|
||||
$.ccio.chunker()
|
||||
}
|
||||
|
||||
mediaRecorder.onresume = function(){
|
||||
$.ccio.chunker()
|
||||
}
|
||||
|
||||
mediaRecorder.onwarning = function(e){
|
||||
clearInterval($.ccio.cutChunk)
|
||||
};
|
||||
mediaRecorder.onwarning = function(e){
|
||||
clearInterval($.ccio.cutChunk)
|
||||
}
|
||||
}else{
|
||||
clearTimeout($.ccio.sendCheckTimeout)
|
||||
$.ccio.sendCheckTimeout = setTimeout($.ccio.startSending,2000)
|
||||
}
|
||||
$('[record]').unbind('click').click($.ccio.stopSending)
|
||||
};
|
||||
function log(message){
|
||||
|
|
@ -138,9 +167,33 @@ function log(message){
|
|||
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
|
||||
window.URL = window.URL || window.webkitURL || window.mozURL || window.msURL;
|
||||
if(getBrowser() == "Chrome"){
|
||||
var constraints = {"audio": true, "video": { "mandatory": { "minWidth": 640, "maxWidth": 640, "minHeight": 480,"maxHeight": 480 }, "optional": [] } };//Chrome
|
||||
var constraints = {
|
||||
"audio": true,
|
||||
"video": {
|
||||
"mandatory": {
|
||||
"minWidth": 640,
|
||||
"maxWidth": 5000,
|
||||
"minHeight": 480,
|
||||
"maxHeight": 2500
|
||||
}, "optional": []
|
||||
}
|
||||
};
|
||||
}else if(getBrowser() == "Firefox"){
|
||||
var constraints = {audio: true,video: { width: { min: 640, ideal: 640, max: 640 }, height: { min: 480, ideal: 480, max: 480 }}}; //Firefox
|
||||
var constraints = {
|
||||
audio: true,
|
||||
video: {
|
||||
width: {
|
||||
min: 640,
|
||||
ideal: 640,
|
||||
max: 5000
|
||||
},
|
||||
height: {
|
||||
min: 480,
|
||||
ideal: 480,
|
||||
max: 2500
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
var mediaRecorder;
|
||||
var chunks = [];
|
||||
|
|
@ -149,8 +202,20 @@ var count = 0;
|
|||
$.ccio.vid = {element:$('#video')[0],canvas:$('#canvas')[0],data:$('#data')};
|
||||
$.ccio.vid.element.controls = false;
|
||||
navigator.getUserMedia(constraints,function(stream,fn) {
|
||||
$.ccio.vid.stream=stream;
|
||||
$.ccio.vid.stream = stream;
|
||||
$.ccio.vid.element.srcObject = stream;
|
||||
$('[record]').click($.ccio.startSending)
|
||||
////////
|
||||
if($user.mons.length>0&&$.ls.getItem('Shinobi_Dashcam')){
|
||||
$('[monitor="'+$.ls.getItem('Shinobi_Dashcam')+'"]').click()
|
||||
if($.ls.getItem('Shinobi_Dashcam_Started') === 1){
|
||||
setTimeout(function(){
|
||||
$('[record]').click()
|
||||
},3000)
|
||||
}
|
||||
}else{
|
||||
$.ccio.selected = null;
|
||||
}
|
||||
}, function(err){console.error('getUserMedia',err)});
|
||||
|
||||
|
||||
|
|
@ -187,8 +252,6 @@ navigator.getUserMedia(constraints,function(stream,fn) {
|
|||
})
|
||||
|
||||
|
||||
if($user.mons.length>0&&$.ls.getItem('Shinobi_Dashcam')){$('[monitor="'+$.ls.getItem('Shinobi_Dashcam')+'"]').click()}else{$.ccio.selected=null;}
|
||||
|
||||
$('body')
|
||||
.on('click','.logout',function(e){
|
||||
localStorage.removeItem('ShinobiLogin_'+location.host);location.href='/';
|
||||
|
|
@ -264,5 +327,6 @@ $('body')
|
|||
#main{text-align:center}
|
||||
#msg h2{margin-top:0}
|
||||
#img{border-radius:5px;overflow:hidden;max-width:100%;display:inline-block;margin-top: 30px}
|
||||
#video,#canvas{position: absolute;display:none}
|
||||
#canvas{position: absolute;display:none}
|
||||
#video{display:inline-block}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@
|
|||
<link rel="stylesheet" href="libs/css/vbox.css">
|
||||
<link rel="stylesheet" href="libs/css/daterangepicker.css">
|
||||
<link rel="stylesheet" href="libs/css/circles.css">
|
||||
<!--<link rel="stylesheet" href="libs/css/poseidon.css">-->
|
||||
<link rel="stylesheet" href="libs/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="libs/css/font-awesome.min.css">
|
||||
<link rel="stylesheet" href="libs/css/fullcalendar.min.css">
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ $.ccio.start=function(){
|
|||
$.ccio.cx({f:'monitor_frame',frame:ctx,mid:$.ccio.selected});
|
||||
delete(ctx);
|
||||
},1000/$.ccio.framerate);
|
||||
$('[record]').unbind('click').click($.ccio.end)
|
||||
$('[record]').unbind('click').click($.ccio.end)
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -74,7 +74,7 @@ $('[record]').unbind('click').click($.ccio.end)
|
|||
|
||||
$.ccio.vid = {e:$('#video'),c:$('#canvas')};
|
||||
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia||navigator.mediaDevices.getUserMedia;
|
||||
window.URL = window.URL || window.webkitURL || window.mozURL || window.msURL;
|
||||
window.URL = window.URL || window.webkitURL || window.mozURL || window.msURL;
|
||||
navigator.getUserMedia({video: true},function(stream,fn) {
|
||||
//set video element
|
||||
if ($.ccio.vid.e[0].mozSrcObject !== undefined) {
|
||||
|
|
|
|||
|
|
@ -1,95 +1,195 @@
|
|||
<% include blocks/header %>
|
||||
<link rel="stylesheet" href="libs/css/pnotify.custom.min.css">
|
||||
<link rel="stylesheet" href="libs/css/vbox.css">
|
||||
<link rel="stylesheet" href="libs/css/circles.css">
|
||||
<link rel="stylesheet" href="libs/css/material.min.css">
|
||||
<link rel="stylesheet" href="libs/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="libs/css/font-awesome.min.css">
|
||||
<link rel="stylesheet" href="libs/css/fullcalendar.min.css">
|
||||
<link rel="stylesheet" href="libs/css/bootstrap-table.min.css">
|
||||
<link rel="stylesheet" href="libs/css/main.dash2.css">
|
||||
<style>
|
||||
.form-group label>div:first-child{width:40%}
|
||||
</style>
|
||||
<body style="background:rgba(33,33,33,1);">
|
||||
<div class="container-fluid">
|
||||
<div class="container">
|
||||
<nav class="navbar navbar-default">
|
||||
<div class="container-fluid">
|
||||
<!-- Brand and toggle get grouped for better mobile display -->
|
||||
<div class="navbar-header">
|
||||
<a class="navbar-brand" href="/"><%-lang.superAdminTitle%></a>
|
||||
</div>
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
<!-- <li><a href="#">Link</a></li>-->
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"> <i class="fa fa-bars"></i> </a>
|
||||
<ul class="dropdown-menu">
|
||||
<!--
|
||||
<li><a href="#">Action</a></li>
|
||||
<li><a href="#">Another action</a></li>
|
||||
<li><a href="#">Something else here</a></li>
|
||||
<li role="separator" class="divider"></li>
|
||||
-->
|
||||
<li><a class="logout"><i class="fa fa-sign-out pull-right"></i> <%-lang.Logout%></a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div><!-- /.container-fluid -->
|
||||
</nav>
|
||||
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="form-group-group grey" id="accounts">
|
||||
<h4><%-lang.Accounts%><a class="pull-right add btn btn-success btn-xs"><i class="fa fa-plus"></i></a></h4>
|
||||
<table class="table table-striped"></table>
|
||||
</div>
|
||||
<div class="form-group-group primary no-padding" id="logs">
|
||||
<h4 class="no-margin"><%-lang['Logs']%><a class="pull-right delete btn btn-danger btn-xs"><i class="fa fa-trash-o"></i></a></h4>
|
||||
<div style="height:400px;overflow:auto">
|
||||
<table class="table table-striped"></table>
|
||||
</div>
|
||||
</div>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title><%-lang.Superuser%> - <%-lang.Shinobi%></title>
|
||||
<% include blocks/header-meta.ejs %>
|
||||
<% include blocks/header-favicon.ejs %>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
|
||||
<meta content='width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0, shrink-to-fit=no' name='viewport' />
|
||||
<!-- Fonts and icons -->
|
||||
<link href="https://fonts.googleapis.com/css?family=Montserrat:400,700,200" rel="stylesheet" />
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/latest/css/font-awesome.min.css" />
|
||||
<!-- CSS Files -->
|
||||
<link href="libs/css/bootstrap4.min.css" rel="stylesheet" />
|
||||
<link href="libs/css/main.dash2.css" rel="stylesheet" />
|
||||
<link rel="stylesheet" href="libs/css/pnotify.custom.min.css">
|
||||
<link href="libs/css/now-ui-kit.css?v=1.1.0" rel="stylesheet" />
|
||||
<script src="libs/js/jquery.min.js"></script>
|
||||
<script src="libs/js/jquery.serialize.js"></script>
|
||||
<script src="libs/js/pnotify.custom.min.js"></script>
|
||||
<script src="libs/js/popper.min.js" type="text/javascript"></script>
|
||||
<script src="libs/js/bootstrap4.min.js" type="text/javascript"></script>
|
||||
<style>
|
||||
.form-group label>div:first-child{width:40%}
|
||||
.list-group li .form-group {margin:0}
|
||||
a {cursor:pointer}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body class="index-page sidebar-collapse bg-hexagon">
|
||||
<!-- Navbar -->
|
||||
<nav id="main-nav" class="navbar navbar-expand-lg bg-primary fixed-top" color-on-scroll="400">
|
||||
<div class="container">
|
||||
<div class="navbar-translate">
|
||||
<a tabindex="1" class="navbar-brand logout" href="/" data-placement="bottom" target="_blank">
|
||||
<%-lang.superAdminTitle%>
|
||||
</a>
|
||||
<button class="navbar-toggler navbar-toggler" type="button" data-toggle="collapse" data-target="#navigation" aria-controls="navigation-index" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-bar bar1"></span>
|
||||
<span class="navbar-toggler-bar bar2"></span>
|
||||
<span class="navbar-toggler-bar bar3"></span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<form class="form-group-group red" id="conf_json">
|
||||
<h4><%-lang['Configuration']%> <small class="pull-right msg"></small></h4>
|
||||
<div class="form-group">
|
||||
<textarea name="json" style="height:300px;font-family: monospace;" class="form-control"></textarea>
|
||||
</div>
|
||||
<div>
|
||||
<div class="pull-right">
|
||||
<button type="submit" class="btn btn-success"><i class="fa fa-check"></i> <%-lang.Save%></button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<div class="form-group-group blue" id="system">
|
||||
<h4><%-lang['System']%> <small class="pull-right msg"></small></h4>
|
||||
<div class="btn-group btn-group-justified">
|
||||
<a restart="system" class="btn btn-danger"><i class="fa fa-retweet"></i> <%-lang['Restart Core']%></a>
|
||||
<a restart="cron" class="btn btn-danger"><i class="fa fa-retweet"></i> <%-lang['Restart CRON']%></a>
|
||||
<a restart="logs" class="btn btn-danger"><i class="fa fa-retweet"></i> <%-lang['Flush PM2 Logs']%></a>
|
||||
<div class="collapse navbar-collapse justify-content-end" id="navigation" data-nav-image="libs/img/blurred-image-1.jpg">
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
<li class="nav-item">
|
||||
<a href="javascript:location.href=location.pathname" class="nav-link" class="logout">
|
||||
<i class="fa fa-sign-out"></i>
|
||||
<p class="d-lg-none d-xl-none"><%-lang.Logout%></p>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
<!-- End Navbar -->
|
||||
<div class="wrapper">
|
||||
<div class="page-header clear-filter" filter-color="primary">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div id="main-card" class="card">
|
||||
<ul class="nav nav-tabs nav-tabs-neutral justify-content-center bg-primary" role="tablist">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" data-toggle="tab" href="#accounts" role="tab">Accounts</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" data-toggle="tab" href="#config" role="tab">Configuration</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" data-toggle="tab" href="#system" role="tab">Controls and Logs</a>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="card-body">
|
||||
<!-- Tab panes -->
|
||||
<div class="tab-content text-center">
|
||||
<div class="tab-pane active" id="accounts" role="tabpanel">
|
||||
<nav class="navbar navbar-rounded navbar-expand-lg bg-primary">
|
||||
<div class="container">
|
||||
<div class="collapse navbar-collapse">
|
||||
<ul class="navbar-nav">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link add">
|
||||
<p><i class="fa fa-plus-square-o"></i> Add Account</p>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
<table class="table table-striped"></table>
|
||||
</div>
|
||||
<div class="tab-pane" id="config" role="tabpanel">
|
||||
<small class="pull-right msg"></small>
|
||||
<nav class="navbar navbar-rounded navbar-expand-lg bg-success">
|
||||
<div class="container">
|
||||
<div class="collapse navbar-collapse">
|
||||
<ul class="navbar-nav">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link add" href="javascript:$.conf.e.submit()">
|
||||
<p><i class="fa fa-check"></i> <%-lang.Save%></p>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link add" href="javascript:$.conf.e.submit()">
|
||||
<p class="msg"></p>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
<form class="form-group-group red" id="conf_json">
|
||||
<small class="pull-right msg"></small>
|
||||
<div id="configForHumans"></div>
|
||||
<div class="form-group">
|
||||
<textarea name="json" style="height:300px;font-family: monospace;" class="form-control"></textarea>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="tab-pane" id="system" role="tabpanel">
|
||||
<nav class="navbar navbar-rounded navbar-expand-lg bg-primary">
|
||||
<div class="container">
|
||||
<div class="collapse navbar-collapse">
|
||||
<ul class="navbar-nav">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" system="deleteLogs">
|
||||
<p><i class="fa fa-trash-o"></i> Clear Logs</p>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" restart="system">
|
||||
<p><i class="fa fa-retweet"></i> <%-lang['Restart Core']%></p>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" restart="cron">
|
||||
<p><i class="fa fa-retweet"></i> <%-lang['Restart CRON']%></p>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" restart="logs">
|
||||
<p><i class="fa fa-retweet"></i> <%-lang['Flush PM2 Logs']%></p>
|
||||
</a>
|
||||
</li>
|
||||
<!--
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" system="update">
|
||||
<p><i class="fa fa-arrow-up"></i> <%-lang['Update']%></p>
|
||||
</a>
|
||||
</li>
|
||||
-->
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
<div id="logs" style="height:400px;overflow:auto">
|
||||
<table class="table table-striped"></table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% include blocks/confirm.ejs %>
|
||||
<div id="toast" class="mdl-js-snackbar mdl-snackbar">
|
||||
<div class="mdl-snackbar__text"></div>
|
||||
<button class="mdl-snackbar__action" type="button"></button>
|
||||
</div>
|
||||
</body>
|
||||
<script><% include ../libs/js/material.min.js %></script>
|
||||
<script><% include ../libs/js/pnotify.custom.min.js %></script>
|
||||
<% include blocks/confirm.ejs %>
|
||||
<script src="libs/js/pnotify.custom.min.js" type="text/javascript"></script>
|
||||
<script><% include ../libs/js/moment.js %></script>
|
||||
<script><% include ../libs/js/livestamp.min.js %></script>
|
||||
<script><% include ../libs/js/placeholder.js %></script>
|
||||
<script><% include ../libs/js/bootstrap.min.js %></script>
|
||||
<script><% include ../libs/js/bootstrap-table.min.js %></script>
|
||||
<script><% include ../libs/js/socket.io.js %></script>
|
||||
<script src="libs/js/livestamp.min.js" type="text/javascript"></script>
|
||||
<script src="libs/js/socket.io.js" type="text/javascript"></script>
|
||||
<script src="libs/js/placeholder.js" type="text/javascript"></script>
|
||||
<script src="libs/js/now-ui-kit.js?v=1.1.0" type="text/javascript"></script>
|
||||
<script type="text/javascript">
|
||||
PNotify.prototype.options.styling = "fontawesome";
|
||||
$(document).ready(function() {
|
||||
// the body of this function is in assets/js/now-ui-kit.js
|
||||
$('#main-card').css('margin-top',$('#main-nav').height() * 2)
|
||||
});
|
||||
|
||||
function scrollToDownload() {
|
||||
|
||||
if ($('.section-download').length != 0) {
|
||||
$("html, body").animate({
|
||||
scrollTop: $('.section-download').offset().top
|
||||
}, 1000);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<script>$user=<%-JSON.stringify($user)%></script>
|
||||
<script>
|
||||
$.ccio={accounts:{}};$.ls=localStorage;
|
||||
|
|
@ -117,7 +217,7 @@ $.ccio.ws.on('f',function(d){
|
|||
$.ccio.tm(4,d.log,'#logs table')
|
||||
break;
|
||||
case'save_configuration':
|
||||
$.conf.msg.html('Saved, Restart Shinobi to apply changes.')
|
||||
d.msg = 'Saved, Restart Shinobi to apply changes.'
|
||||
break;
|
||||
case'edit_account':
|
||||
d.msg='Account Edited';
|
||||
|
|
@ -135,7 +235,7 @@ $.ccio.ws.on('f',function(d){
|
|||
break;
|
||||
}
|
||||
if(d.msg&&typeof d.msg==='string'){
|
||||
$('#toast')[0].MaterialSnackbar.showSnackbar({message:d.msg})
|
||||
new PNotify({text:d.msg,type:'error'})
|
||||
}
|
||||
})
|
||||
|
||||
|
|
@ -146,12 +246,34 @@ $.ccio.tm=function(x,d,z,k){
|
|||
case 0://account row
|
||||
d.detailsJSON=JSON.parse(d.details);
|
||||
$.ccio.accounts[d.ke]=d;
|
||||
tmp+='<tr ke="'+d.ke+'"><td><b class="mail">'+d.mail+'</b></td><td>'+d.ke+'</td><td><a class="permission btn btn-xs btn-primary"><i class="fa fa-lock"></i></a></td><td><a class="delete btn btn-xs btn-danger"><i class="fa fa-trash-o"></i></a></td></tr>';
|
||||
tmp+='<tr ke="'+d.ke+'"><td><b class="mail">'+d.mail+'</b></td><td>'+d.ke+'</td><td><a tabindex="1" class="permission btn btn-xs btn-primary"><i class="fa fa-lock"></i></a></td><td><a tabindex="1" class="delete btn btn-xs btn-danger"><i class="fa fa-trash-o"></i></a></td></tr>';
|
||||
break;
|
||||
case 4://log row, draw to global and monitor
|
||||
if(!d.time){d.time=$.ccio.init('t')}
|
||||
tmp+='<tr class="search-row"><td><span title="'+d.time+'" class="livestamp"></span><br><small>'+d.time+'</small><br><small>'+d.mid+'</small></td><td></td><td><pre class="pre-inline">'+$.ccio.init('jsontoblock',JSON.parse(d.info))+'</pre></td></tr>'
|
||||
break;
|
||||
case 5://config element
|
||||
if(d.value instanceof Object){
|
||||
tmp += '<div class="form-group config-row" layer="'+d.layer+'">\
|
||||
<div><input class="form-control key" type="text" value="'+d.key+'"></div>\
|
||||
<ul class="list-group valueObject" style="margin:0">'
|
||||
++d.layer
|
||||
$.each(d.value,function(key,value){
|
||||
tmp += '<li class="list-group-item">'
|
||||
tmp += $.ccio.tm(5,{key:key,value:value,layer:d.layer})
|
||||
tmp += '</li>'
|
||||
})
|
||||
tmp += '</ul>'
|
||||
tmp += '</div>'
|
||||
}else{
|
||||
tmp += '<div class="form-group config-row" layer="'+d.layer+'">\
|
||||
<label>\
|
||||
<div><input class="form-control key" type="text" value="'+d.key+'"></div>\
|
||||
<div><input class="form-control value" type="text" value="'+d.value+'"></div>\
|
||||
</label>\
|
||||
</div>'
|
||||
}
|
||||
break;
|
||||
}
|
||||
if(z){
|
||||
$(z).prepend(tmp)
|
||||
|
|
@ -201,34 +323,40 @@ $.ccio.init=function(x,d,z,k){
|
|||
}
|
||||
//logs
|
||||
$.logs={e:$('#logs')}
|
||||
$.logs.e.find('.delete').click(function(e){
|
||||
$.confirm.e.modal('show');
|
||||
$.confirm.title.html('Delete Logs <small>'+e.u+'</small>')
|
||||
e.html='Do you want to delete these logs? User logs will <b>not</b> be deleted.'
|
||||
$.confirm.body.html(e.html)
|
||||
$.confirm.click({title:'Delete',class:'btn-danger'},function(){
|
||||
$.ccio.cx({f:'logs',ff:'delete',ke:'$'})
|
||||
$.logs.e.find('table').empty()
|
||||
});
|
||||
})
|
||||
//config editor
|
||||
$.conf={e:$('#conf_json')};$.conf.draw=$.conf.e.find('[name="json"]'),$.conf.msg=$.conf.e.find('.msg')
|
||||
<%
|
||||
var stringedConfig = JSON.stringify(plainConfig)
|
||||
%>
|
||||
var config = <%- JSON.stringify(plainConfig) || [] %>
|
||||
$.conf={e:$('#conf_json')};
|
||||
$.conf.configForHumans=$('#configForHumans')
|
||||
$.conf.draw=$.conf.e.find('[name="json"]')
|
||||
$.conf.msg=$.conf.e.find('.msg')
|
||||
$.conf.valid=1;
|
||||
$.conf.draw.val(JSON.stringify(<%-JSON.stringify(plainConfig)%>,null,3))
|
||||
$.conf.jsonToFields = function(){
|
||||
// var tmp = ''
|
||||
// $.each(config,function(key,value){
|
||||
// var layer = 0
|
||||
// tmp += $.ccio.tm(5,{key:key,value:value,layer:layer})
|
||||
// })
|
||||
// $.conf.configForHumans.html(tmp)
|
||||
}
|
||||
$.conf.draw.val(JSON.stringify(<%-stringedConfig%>,null,3))
|
||||
$.conf.draw.keyup(function(){
|
||||
var msg=''
|
||||
var color=''
|
||||
try{
|
||||
$.parseJSON($.conf.draw.val())
|
||||
msg='Valid JSON'
|
||||
color='success'
|
||||
$.conf.valid=1
|
||||
config = $.parseJSON($.conf.draw.val())
|
||||
msg = 'Valid JSON'
|
||||
color = 'success'
|
||||
$.conf.valid = 1
|
||||
$.conf.jsonToFields()
|
||||
}catch(er){
|
||||
msg='Not a valid JSON'
|
||||
color='danger'
|
||||
$.conf.valid=0
|
||||
msg = 'Not a valid JSON'
|
||||
color = 'danger'
|
||||
$.conf.valid = 0
|
||||
}
|
||||
$.conf.msg.text(msg).css('color',color)
|
||||
new PNotify({text:msg,type:color})
|
||||
})
|
||||
$.conf.e.submit(function(e){
|
||||
e.preventDefault()
|
||||
|
|
@ -242,22 +370,77 @@ $.conf.e.submit(function(e){
|
|||
$.ccio.cx({f:'system',ff:'configure',data:$.parseJSON($.conf.draw.val())})
|
||||
});
|
||||
}else{
|
||||
$.conf.msg.text('Invalid JSON Syntax, Cannot Save.')
|
||||
new PNotify({text:'Invalid JSON Syntax, Cannot Save.',type:'error'})
|
||||
}
|
||||
return false;
|
||||
})
|
||||
$.conf.e.on('keyup','.config-row input',function(){
|
||||
var newConfig = {}
|
||||
var checkRow = function(v,object){
|
||||
var _this = $(v)
|
||||
var key = _this.find('.key:first').val()
|
||||
var layer = parseInt(_this.attr('layer'))
|
||||
var list = _this.find('ul').first()
|
||||
var isObject = list.length > 0
|
||||
if(isObject){
|
||||
if(!object[key]){
|
||||
if(isNaN(key) === true){
|
||||
object[key] = {}
|
||||
}else{
|
||||
object[key] = []
|
||||
}
|
||||
}
|
||||
list.find('.config-row[layer="'+(layer+1)+'"]').each(function(n,v){
|
||||
checkRow(v,object[key])
|
||||
})
|
||||
}else{
|
||||
var value = _this.find('.value').val()
|
||||
switch(value){
|
||||
case'true':
|
||||
value = true
|
||||
break;
|
||||
case'false':
|
||||
value = false
|
||||
break;
|
||||
default:
|
||||
if(isNaN(value) === false){
|
||||
value = parseFloat(value)
|
||||
}
|
||||
break;
|
||||
}
|
||||
object[key] = value
|
||||
}
|
||||
|
||||
}
|
||||
$.conf.configForHumans.children('.config-row').each(function(n,v){
|
||||
checkRow(v,newConfig)
|
||||
})
|
||||
$.conf.draw.val(JSON.stringify(newConfig,null,3))
|
||||
console.log(newConfig)
|
||||
})
|
||||
$.conf.e.ready(function(){
|
||||
$.conf.jsonToFields()
|
||||
})
|
||||
//sys controls
|
||||
$.system={e:$('#system')}
|
||||
$.system.e.find('[system]').click(function(e){
|
||||
switch($(this).attr('system')){
|
||||
case'deleteLogs':
|
||||
$.confirm.e.modal('show');
|
||||
$.confirm.title.html('Delete Logs <small>'+e.u+'</small>')
|
||||
e.html='Do you want to delete these logs? User logs will <b>not</b> be deleted.'
|
||||
$.confirm.body.html(e.html)
|
||||
$.confirm.click({title:'Delete',class:'btn-danger'},function(){
|
||||
$.ccio.cx({f:'logs',ff:'delete',ke:'$'})
|
||||
$.logs.e.find('table').empty()
|
||||
});
|
||||
break;
|
||||
case'update':
|
||||
e.distro=$(this).attr('distro')
|
||||
if(!e.distro){e.distro='master'}
|
||||
$.confirm.e.modal('show')
|
||||
$.confirm.title.html('Update Shinobi?')
|
||||
$.confirm.body.html('Updating Shinobi means overwriting files. If you have modified any files yourself you should update Shinobi manually. The updater will download the latest '+e.distro+' from the <a href="https://github.com/ShinobiCCTV/Shinobi" target="_blank">Pro repository</a>.')
|
||||
$.confirm.body.html('Updating Shinobi means overwriting files. If you have modified any files yourself you should update Shinobi manually.')
|
||||
$.confirm.click({title:'Update',class:'btn-danger'},function(){
|
||||
$.ccio.cx({f:'system',ff:'update',distro:e.distro})
|
||||
$.ccio.cx({f:'system',ff:'update'})
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
|
@ -298,3 +481,4 @@ $('body')
|
|||
})
|
||||
</script>
|
||||
<% include blocks/mainpermissions.ejs %>
|
||||
</html>
|
||||
Loading…
Reference in New Issue