From ee569197478642fcfd929e5a3927aaa928711170 Mon Sep 17 00:00:00 2001 From: HFO4 <912394456@qq.com> Date: Sat, 7 Apr 2018 11:02:43 +0800 Subject: [PATCH 01/10] =?UTF-8?q?aria2=E4=B8=8B=E8=BD=BD=E5=A4=B1=E8=B4=A5?= =?UTF-8?q?=E5=BC=82=E5=B8=B8=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- application/config.php | 2 +- application/index/model/Aria2.php | 50 +++++++++++++++++++++++++++---- 2 files changed, 46 insertions(+), 6 deletions(-) diff --git a/application/config.php b/application/config.php index 38405e4a..fd8a9488 100644 --- a/application/config.php +++ b/application/config.php @@ -18,7 +18,7 @@ return [ // 应用命名空间 'app_namespace' => 'app', // 应用调试模式 - 'app_debug' => false, + 'app_debug' => true, // 应用Trace 'app_trace' => false, // 应用模式状态 diff --git a/application/index/model/Aria2.php b/application/index/model/Aria2.php index 8b7f57b0..ab6617cf 100644 --- a/application/index/model/Aria2.php +++ b/application/index/model/Aria2.php @@ -85,6 +85,7 @@ class Aria2 extends Model{ "downloadSpeed" => $respondData["result"]["downloadSpeed"], "errorMessage" => isset($respondData["result"]["errorMessage"]) ? $respondData["result"]["errorMessage"] : "", ]), + "msg" => isset($respondData["result"]["errorMessage"]) ? $respondData["result"]["errorMessage"] : "", ]); switch ($respondData["result"]["status"]) { case 'complete': @@ -98,7 +99,7 @@ class Aria2 extends Model{ }else{ $this->reqStatus = 0; $this->reqMsg = "空间容量不足"; - //取消离线下载 + $this->setError($respondData["result"],$downloadInfo,"空间容量不足"); return false; } }else{ @@ -110,7 +111,7 @@ class Aria2 extends Model{ private function setComplete($quenInfo,$sqlData){ if($this->policy["policy_type"] != "local"){ - //取消任务 + $this->setError($quenInfo,$sqlData,"您当前的上传策略无法使用离线下载"); return false; } $suffixTmp = explode('.', $quenInfo["dir"]); @@ -123,7 +124,7 @@ class Aria2 extends Model{ } if($sufficCheck){ //取消任务 - $this->setError(); + $this->setError($quenInfo,$sqlData,"文件类型不被允许"); return false; } if($this->policy['autoname']){ @@ -147,14 +148,53 @@ class Aria2 extends Model{ $addAction = FileManage::addFile($jsonData,$this->policy,$this->uid,$picInfo); if(!$addAction[0]){ //取消任务 - $this->setError(); + $this->setError($quenInfo,$sqlData,$addAction[1]); return false; } FileManage::storageCheckOut($this->uid,(int)$quenInfo["totalLength"]); } - private function setError(){ + private function setError($quenInfo,$sqlData,$msg,$status="error"){ + $this->Remove($sqlData["pid"],$sqlData); + $this->removeDownloadResult($sqlData["pid"],$sqlData); + if(file_exists($quenInfo["files"][0]["path"])){ + @unlink($quenInfo["files"][0]["path"]); + @unlink(dirname($quenInfo["files"][0]["path"])); + } + Db::name("download")->where("id",$sqlData["id"])->update([ + "msg" => $msg, + "status" => $status, + ]); + } + public function Remove($gid,$sqlData){ + $reqFileds = [ + "params" => ["token:".$this->authToken,$gid], + "jsonrpc" => "2.0", + "id" => uniqid(), + "method" => "aria2.remove" + ]; + $reqFileds = json_encode($reqFileds,JSON_OBJECT_AS_ARRAY); + $respondData = $this->sendReq($reqFileds); + if(isset($respondData["result"])){ + return true; + } + return false; + } + + public function removeDownloadResult($gid,$sqlData){ + $reqFileds = [ + "params" => ["token:".$this->authToken,$gid], + "jsonrpc" => "2.0", + "id" => uniqid(), + "method" => "aria2.removeDownloadResult" + ]; + $reqFileds = json_encode($reqFileds,JSON_OBJECT_AS_ARRAY); + $respondData = $this->sendReq($reqFileds); + if(isset($respondData["result"])){ + return true; + } + return false; } private function storageCheck($quenInfo,$sqlData){ From 1b87365b8a4e2108f51f57ad4b019949aee32ad7 Mon Sep 17 00:00:00 2001 From: HFO4 <912394456@qq.com> Date: Sat, 7 Apr 2018 15:16:57 +0800 Subject: [PATCH 02/10] =?UTF-8?q?aria2=20=E7=A7=8D=E5=AD=90=E4=B8=8B?= =?UTF-8?q?=E8=BD=BD=E5=8F=8A=E5=A4=9A=E6=96=87=E4=BB=B6=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../index/controller/RemoteDownload.php | 18 +++ application/index/model/Aria2.php | 107 +++++++++++++----- 2 files changed, 99 insertions(+), 26 deletions(-) diff --git a/application/index/controller/RemoteDownload.php b/application/index/controller/RemoteDownload.php index 04201747..1259d512 100644 --- a/application/index/controller/RemoteDownload.php +++ b/application/index/controller/RemoteDownload.php @@ -39,6 +39,8 @@ class RemoteDownload extends Controller{ "msg" => "", "info"=>"", "source" =>$url, + "file_index" => 0, + "is_single" => 1, ]); } @@ -57,6 +59,22 @@ class RemoteDownload extends Controller{ } } + public function AddTorrent(){ + $policyData = Db::name("policy")->where("id",$this->userObj->groupData["policy_name"])->find(); + if(!$this->checkPerimission(0) || $policyData["policy_type"] != "local"){ + return json(['error'=>1,'message'=>'您当前的无用户无法执行此操作']); + } + $aria2Options = Option::getValues(["aria2"]); + $aria2 = new Aria2($aria2Options); + $torrentObj = new \app\index\model\FileManage(input("post.path"),$this->userObj->uid); + $downloadStart = $aria2->addTorrent($torrentObj->signTmpUrl()); + if($aria2->reqStatus){ + $this->insertRecord($aria2,input("post.path")); + }else{ + return json(['error'=>1,'message'=>$aria2->reqMsg]); + } + } + public function FlushStatus(){ $aria2Options = Option::getValues(["aria2"]); $aria2 = new Aria2($aria2Options); diff --git a/application/index/model/Aria2.php b/application/index/model/Aria2.php index ab6617cf..b6c44481 100644 --- a/application/index/model/Aria2.php +++ b/application/index/model/Aria2.php @@ -46,6 +46,28 @@ class Aria2 extends Model{ } } + public function addTorrent($torrentUrl){ + $this->pathId = uniqid(); + $reqFileds = [ + "params" => ["token:".$this->authToken, + [$torrentUrl],["dir" => $this->savePath.$this->pathId], + ], + "jsonrpc" => "2.0", + "id" => $this->pathId, + "method" => "aria2.addUri" + ]; + $reqFileds["params"][2] = array_merge($reqFileds["params"][2],$this->saveOptions); + $reqFileds = json_encode($reqFileds,JSON_OBJECT_AS_ARRAY); + $respondData = $this->sendReq($reqFileds); + if(isset($respondData["result"])){ + $this->reqStatus = 1; + $this->pid = $respondData["result"]; + }else{ + $this->reqStatus = 0; + $this->reqMsg = $respondData["error"]["message"]; + } + } + public function flushStatus($id,$uid,$policy){ $this->uid = $uid; $this->policy = $policy; @@ -74,14 +96,25 @@ class Aria2 extends Model{ $respondData = $this->sendReq($reqFileds); if(isset($respondData["result"])){ if($this->storageCheck($respondData["result"],$downloadInfo)){ + if($downloadInfo["is_single"] && count($respondData["result"]["files"]) >1){ + $this->updateToMuiltpe($respondData["result"],$downloadInfo); + return false; + } + if(isset($respondData["result"]["followedBy"])){ + Db::name("download")->where("id",$id) + ->update([ + "pid" => $respondData["result"]["followedBy"][0], + ]); + return false; + } Db::name("download")->where("id",$id) ->update([ "status" => $respondData["result"]["status"], "last_update" => date("Y-m-d h:i:s"), "info" => json_encode([ - "completedLength" => $respondData["result"]["completedLength"], - "totalLength" => $respondData["result"]["totalLength"], - "dir" => $respondData["result"]["files"][0]["path"], + "completedLength" => $respondData["result"]["files"][$downloadInfo["file_index"]]["completedLength"], + "totalLength" => $respondData["result"]["files"][$downloadInfo["file_index"]]["length"], + "dir" => $respondData["result"]["files"][$downloadInfo["file_index"]]["path"], "downloadSpeed" => $respondData["result"]["downloadSpeed"], "errorMessage" => isset($respondData["result"]["errorMessage"]) ? $respondData["result"]["errorMessage"] : "", ]), @@ -105,10 +138,30 @@ class Aria2 extends Model{ }else{ $this->reqStatus = 0; $this->reqMsg = $respondData["error"]["message"]; + $this->setError($respondData,$downloadInfo,$respondData["error"]["message"],"error",false); + return false; } return true; } + private function updateToMuiltpe($quenInfo,$sqlData){ + foreach ($quenInfo["files"] as $key => $value) { + Db::name("download")->insert([ + "pid" => $sqlData["pid"], + "path_id" => $sqlData["path_id"], + "owner" => $sqlData["owner"], + "save_dir" => 1, + "status" => "ready", + "msg" => "", + "info"=>"", + "source" =>$sqlData["source"], + "file_index" => $key, + "is_single" => 0, + ]); + } + Db::name("download")->where("id",$sqlData["id"])->delete(); + } + private function setComplete($quenInfo,$sqlData){ if($this->policy["policy_type"] != "local"){ $this->setError($quenInfo,$sqlData,"您当前的上传策略无法使用离线下载"); @@ -128,20 +181,20 @@ class Aria2 extends Model{ return false; } if($this->policy['autoname']){ - $fileName = $uploadHandller->getObjName($this->policy['namerule'],"local",basename($quenInfo["files"][0]["path"])); + $fileName = $uploadHandller->getObjName($this->policy['namerule'],"local",basename($quenInfo["files"][$sqlData["file_index"]]["path"])); }else{ - $fileName = basename($quenInfo["files"][0]["path"]); + $fileName = basename($quenInfo["files"][$sqlData["file_index"]]["path"]); } $generatePath = $uploadHandller->getDirName($this->policy['dirrule']); $savePath = ROOT_PATH . 'public/uploads/'.$generatePath.DS.$fileName; is_dir(dirname($savePath))? :mkdir(dirname($savePath),0777,true); - rename($quenInfo["files"][0]["path"],$savePath); - @unlink(dirname($quenInfo["files"][0]["path"])); + rename($quenInfo["files"][$sqlData["file_index"]]["path"],$savePath); + @unlink(dirname($quenInfo["files"][$sqlData["file_index"]]["path"])); $jsonData = array( "path" => "", - "fname" => basename($quenInfo["files"][0]["path"]), + "fname" => basename($quenInfo["files"][$sqlData["file_index"]]["path"]), "objname" => $generatePath.DS.$fileName, - "fsize" => $quenInfo["totalLength"], + "fsize" => $quenInfo["files"][$sqlData["file_index"]]["length"], ); @list($width, $height, $type, $attr) = getimagesize($savePath); $picInfo = empty($width)?" ":$width.",".$height; @@ -151,15 +204,17 @@ class Aria2 extends Model{ $this->setError($quenInfo,$sqlData,$addAction[1]); return false; } - FileManage::storageCheckOut($this->uid,(int)$quenInfo["totalLength"]); + FileManage::storageCheckOut($this->uid,(int)$quenInfo["files"][$sqlData["file_index"]]["length"]); } - private function setError($quenInfo,$sqlData,$msg,$status="error"){ + private function setError($quenInfo,$sqlData,$msg,$status="error",$delete=true){ $this->Remove($sqlData["pid"],$sqlData); $this->removeDownloadResult($sqlData["pid"],$sqlData); - if(file_exists($quenInfo["files"][0]["path"])){ - @unlink($quenInfo["files"][0]["path"]); - @unlink(dirname($quenInfo["files"][0]["path"])); + if($delete){ + if(file_exists($quenInfo["files"][$sqlData["file_index"]]["path"])){ + @unlink($quenInfo["files"][$sqlData["file_index"]]["path"]); + @unlink(dirname($quenInfo["files"][$sqlData["file_index"]]["path"])); + } } Db::name("download")->where("id",$sqlData["id"])->update([ "msg" => $msg, @@ -209,18 +264,18 @@ class Aria2 extends Model{ private function sendReq($data){ $curl = curl_init(); - curl_setopt($curl, CURLOPT_URL, $this->apiUrl."jsonrpc"); - curl_setopt($curl, CURLOPT_POST, 1); - curl_setopt($curl, CURLOPT_POSTFIELDS, $data); - curl_setopt($curl, CURLOPT_TIMEOUT, 15); - curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); - $tmpInfo = curl_exec($curl); - if (curl_errno($curl)) { - $this->reqStatus = 0; - $this->reqMsg = "请求失败,".curl_error($curl); - } - curl_close($curl); - return json_decode($tmpInfo,true); + curl_setopt($curl, CURLOPT_URL, $this->apiUrl."jsonrpc"); + curl_setopt($curl, CURLOPT_POST, 1); + curl_setopt($curl, CURLOPT_POSTFIELDS, $data); + curl_setopt($curl, CURLOPT_TIMEOUT, 15); + curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); + $tmpInfo = curl_exec($curl); + if (curl_errno($curl)) { + $this->reqStatus = 0; + $this->reqMsg = "请求失败,".curl_error($curl); + } + curl_close($curl); + return json_decode($tmpInfo,true); } } From b8b63662eaa2bd8a33e691b16a6d3c3c5f753f05 Mon Sep 17 00:00:00 2001 From: HFO4 <912394456@qq.com> Date: Mon, 9 Apr 2018 22:04:56 +0800 Subject: [PATCH 03/10] =?UTF-8?q?=E7=A6=BB=E7=BA=BF=E4=B8=8B=E8=BD=BD?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0URL=E4=BA=A4=E4=BA=92=E7=95=8C=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../index/controller/RemoteDownload.php | 3 +- application/index/model/Aria2.php | 7 +++ application/index/view/home/home.html | 2 + static/js/angular-filemanager.min.js | 49 +++++++++++++++++-- static/js/home.js | 3 ++ 5 files changed, 59 insertions(+), 5 deletions(-) diff --git a/application/index/controller/RemoteDownload.php b/application/index/controller/RemoteDownload.php index 1259d512..98225cac 100644 --- a/application/index/controller/RemoteDownload.php +++ b/application/index/controller/RemoteDownload.php @@ -54,8 +54,9 @@ class RemoteDownload extends Controller{ $downloadStart = $aria2->addUrl(input("post.url")); if($aria2->reqStatus){ $this->insertRecord($aria2,input("post.url")); + return json(["result"=>['success'=>true,'error'=>null]]); }else{ - return json(['error'=>1,'message'=>$aria2->reqMsg]); + return json(["result"=>['success'=>false,'error'=>$aria2->reqMsg]]); } } diff --git a/application/index/model/Aria2.php b/application/index/model/Aria2.php index b6c44481..508bc919 100644 --- a/application/index/model/Aria2.php +++ b/application/index/model/Aria2.php @@ -129,6 +129,13 @@ class Aria2 extends Model{ # code... break; } + if(($respondData["result"]["files"][$downloadInfo["file_index"]]["completedLength"] == $respondData["result"]["files"][$downloadInfo["file_index"]]["length"]) && $respondData["result"]["status"]=="active"){ + $this->setComplete($respondData["result"],$downloadInfo); + Db::name("download")->where("id",$id) + ->update([ + "status" => "complete", + ]); + } }else{ $this->reqStatus = 0; $this->reqMsg = "空间容量不足"; diff --git a/application/index/view/home/home.html b/application/index/view/home/home.html index 593b101f..76332275 100644 --- a/application/index/view/home/home.html +++ b/application/index/view/home/home.html @@ -28,6 +28,8 @@ allowSource : "{$policyData.origin_link}", upUrl : "{$policyData.server}", allowShare:"{$groupData.allow_share}", + allowRemoteDownload:"{:explode(",",$groupData.aria2)[0]}", + allowTorrentDownload:"{:explode(",",$groupData.aria2)[1]}", }; diff --git a/static/js/angular-filemanager.min.js b/static/js/angular-filemanager.min.js index 25542c33..bb1c720d 100644 --- a/static/js/angular-filemanager.min.js +++ b/static/js/angular-filemanager.min.js @@ -323,6 +323,17 @@ function(e, r) { e.modal("move", !0) }) }, + e.startRemoteDownload = function(){ + if(e.temp['url'] == ""){ + return e.apiMiddleware.apiHandler.error = a.instant("下载URL不能为空"); + }else{ + e.apiMiddleware.apiHandler.error = !1; + return void e.apiMiddleware.startRemoteDownload(e.temp['url'],n.selectedModalPath).then(function() { + e.modal("remoteDownload", !0); + toastr["success"]("离线下载任务已创建"); + }) + } + } e.rename = function() { var r = e.singleSelection(), n = r.tempModel.name, @@ -456,6 +467,11 @@ function(e) { i = "/" + n.join("/"); return e.singleSelection() && !e.singleSelection().isFolder() && (i += "/" + e.singleSelection().tempModel.name), i.replace(/\/\//, "/") + }, + r.getSelectedPathForDownload = function() { + var path = r.selectedModalPath.filter(Boolean); + var result = '/' + path.join('/'); + return result.replace(/\/\//, '/'); } } ]) @@ -739,7 +755,7 @@ function(e) { e.module("FileManagerApp").provider("fileManagerConfig", function() { var r = { - appName: "angular-filemanager v1.5", + appName: "Cloudreve FileManager", defaultLang: "zh_cn", listUrl: "/File/ListFile", previewUrl:"/File/Preview", @@ -757,6 +773,7 @@ function(e) { extractUrl: "bridges/php/handler.php", permissionsUrl: "bridges/php/handler.php", sourceUrl:"/File/gerSource", + remoteDownloadUrl: "/RemoteDownload/addUrl", basePath: "/", searchForm: !0, sidebar: !0, @@ -778,7 +795,9 @@ function(e) { remove: !0, createFolder: !0, pickFiles: !1, - pickFolders: !1 + pickFolders: !1, + allowRemoteDownload: !1, + allowTorrentDownload: !1, }, multipleDownloadFileName: "angular-filemanager.zip", filterFileExtensions: [], @@ -994,6 +1013,25 @@ function(e, r) { }), s.promise }, + o.prototype.startRemoteDownload = function(api,url,path) { + var o = this, + s = n.defer(), + l = { + action: "remoteDownload", + path: path, + url:url + }; + return o.inprocess = !0, + o.error = "", + e.post(api, l).success(function(e, r) { + o.deferredHandler(e, s, r) + }).error(function(e, r) { + o.deferredHandler(e, s, r, a.instant("error_moving")) + })["finally"](function() { + o.inprocess = !1 + }), + s.promise + }, o.prototype.remove = function(r, i,dir) { var t = this, o = n.defer(), @@ -1307,6 +1345,9 @@ function(e) { var dirList = this.getFileList(dir); return this.apiHandler.move(r.moveUrl,dirList ,i, this.getPath(n)) }, + i.prototype.startRemoteDownload = function(url,path) { + return this.apiHandler.startRemoteDownload(r.remoteDownloadUrl,url ,this.getPath(path)) + }, i.prototype.remove = function(e,dir) { var n = this.getFileList(e); var dirList = this.getFileList(dir); @@ -1516,8 +1557,8 @@ angular.module("FileManagerApp").run(["$templateCache", e.put("src/templates/main-table-modal.html", '\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n
\r\n \r\n {{"name" | translate}}\r\n \r\n \r\n
\r\n
\r\n
\r\n {{"no_folders_in_folder" | translate}}...\r\n \r\n \r\n
\r\n {{ fileNavigator.error }}\r\n
\r\n \r\n \r\n {{item.model.name | strLimit : 32}}\r\n \r\n \r\n \r\n
'), e.put("src/templates/main-table.html", '\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n
\r\n \r\n {{"name" | translate}}\r\n \r\n \r\n
\r\n
\r\n
\r\n {{"no_files_in_folder" | translate}}...\r\n
\r\n {{ fileNavigator.error }}\r\n
\r\n \r\n \r\n \r\n {{item.model.name | strLimit : 64}}\r\n \r\n
\r\n'), e.put("src/templates/main.html", '
\r\n
\r\n\r\n
\r\n
\r\n\r\n \r\n\r\n
\r\n \r\n
\r\n
\r\n
\r\n\r\n
\r\n
\r\n
\r\n'), - e.put("src/templates/modals.html", '\r\n\r\n \r\n\r\n \r\n\r\n \r\n\r\n \r\n\r\n\r\n\r\n\r\n \r\n\r\n \r\n\r\n \r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n'), - e.put("src/templates/navbar.html", '\r\n'), + e.put("src/templates/modals.html", '\r\n\r\n \r\n\r\n \r\n\r\n \r\n\r\n \r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n \r\n\r\n \r\n\r\n \r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n'), + e.put("src/templates/navbar.html", '\r\n'), e.put("src/templates/sidebar.html", '\r\n\r\n'), e.put("src/templates/spinner.html", '
\r\n \r\n \r\n \r\n
') } diff --git a/static/js/home.js b/static/js/home.js index 21a300a1..70d02dee 100644 --- a/static/js/home.js +++ b/static/js/home.js @@ -49,6 +49,9 @@ changePermissions: false, upload: false, shareFile: uploadConfig.allowShare == "1" ? true : false, + allowRemoteDownload: uploadConfig.allowRemoteDownload, + allowTorrentDownload: uploadConfig.allowTorrentDownload, + }), }); }]); From ccbb6c7778754a16f80b996b33083f0e2fb718a0 Mon Sep 17 00:00:00 2001 From: HFO4 <912394456@qq.com> Date: Tue, 10 Apr 2018 22:28:17 +0800 Subject: [PATCH 04/10] =?UTF-8?q?=E7=A7=8D=E5=AD=90=E7=A6=BB=E7=BA=BF?= =?UTF-8?q?=E4=B8=8B=E8=BD=BD=E5=89=8D=E7=AB=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- static/js/angular-filemanager.min.js | 46 +++++++++++++++++++++++++--- 1 file changed, 41 insertions(+), 5 deletions(-) diff --git a/static/js/angular-filemanager.min.js b/static/js/angular-filemanager.min.js index bb1c720d..69c7a44e 100644 --- a/static/js/angular-filemanager.min.js +++ b/static/js/angular-filemanager.min.js @@ -332,8 +332,18 @@ function(e, r) { e.modal("remoteDownload", !0); toastr["success"]("离线下载任务已创建"); }) - } - } + } + }, + e.startTorrentDownload = function(){ + var r = e.singleSelection(); + console.log(r); + e.apiMiddleware.apiHandler.error = !1; + return void e.apiMiddleware.startTorrentDownload(r,n.selectedModalPath).then(function() { + e.modal("torrentDownload", !0); + toastr["success"]("离线下载任务已创建"); + }) + + }, e.rename = function() { var r = e.singleSelection(), n = r.tempModel.name, @@ -655,6 +665,9 @@ function(e) { }, i.prototype.isImage = function() { return r.isImageFilePattern.test(this.model.name) + }, + i.prototype.isTorrent = function() { + return r.isTorrentFilePattern.test(this.model.name) }, i.prototype.isVideo = function() { return r.isVideoFilePattern.test(this.model.name) @@ -812,6 +825,7 @@ function(e) { pickCallback: false, isEditableFilePattern: /\.(txt|diff?|patch|svg|asc|cnf|cfg|conf|html?|.html|cfm|cgi|aspx?|ini|pl|py|css|cs|js|jsp|log|htaccess|htpasswd|gitignore|gitattributes|env|json|atom|eml|rss|markdown|sql|xml|xslt?|sh|rb|as|bat|cmd|cob|for|ftn|frm|frx|inc|lisp|scm|coffee|php[3-6]?|java|c|cbl|go|h|scala|vb|tmpl|lock|go|yml|yaml|tsv|lst)$/i, isImageFilePattern: /\.(jpe?g|gif|bmp|png|tiff?)$/i, + isTorrentFilePattern: /\.(torrent)$/i, isVideoFilePattern:/\.(mp4|flv|avi|tff?)$/i, isAudioFilePattern:/\.(mp3|wav|ogg?)$/i, isMdFilePattern:/\.(md?)$/i, @@ -1032,6 +1046,25 @@ function(e, r) { }), s.promise }, + o.prototype.startTorrentDownload = function(api,fileId,path) { + var o = this, + s = n.defer(), + l = { + action: "torrentDownload", + path: path, + id:fileId + }; + return o.inprocess = !0, + o.error = "", + e.post(api, l).success(function(e, r) { + o.deferredHandler(e, s, r) + }).error(function(e, r) { + o.deferredHandler(e, s, r, a.instant("error_moving")) + })["finally"](function() { + o.inprocess = !1 + }), + s.promise + }, o.prototype.remove = function(r, i,dir) { var t = this, o = n.defer(), @@ -1348,6 +1381,9 @@ function(e) { i.prototype.startRemoteDownload = function(url,path) { return this.apiHandler.startRemoteDownload(r.remoteDownloadUrl,url ,this.getPath(path)) }, + i.prototype.startTorrentDownload = function(torrent,path) { + return this.apiHandler.startTorrentDownload(r.torrentDownloadUrl,torrent.model.fileId ,this.getPath(path)) + }, i.prototype.remove = function(e,dir) { var n = this.getFileList(e); var dirList = this.getFileList(dir); @@ -1552,12 +1588,12 @@ function(e) { angular.module("FileManagerApp").run(["$templateCache", function(e) { e.put("src/templates/current-folder-breadcrumb.html", ''), - e.put("src/templates/item-context-menu.html", ''), - e.put("src/templates/main-icons.html", '
\r\n
\r\n \r\n
\r\n\r\n
\r\n
\r\n
\r\n\r\n
\r\n {{"no_files_in_folder" | translate}}...\r\n
\r\n \r\n
\r\n {{ fileNavigator.error }}\r\n
\r\n
'), + e.put("src/templates/item-context-menu.html", ''), + e.put("src/templates/main-icons.html", '
\r\n
\r\n \r\n
\r\n\r\n
\r\n
\r\n
\r\n\r\n
\r\n {{"no_files_in_folder" | translate}}...\r\n
\r\n \r\n
\r\n {{ fileNavigator.error }}\r\n
\r\n
'), e.put("src/templates/main-table-modal.html", '\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n
\r\n \r\n {{"name" | translate}}\r\n \r\n \r\n
\r\n
\r\n
\r\n {{"no_folders_in_folder" | translate}}...\r\n \r\n \r\n
\r\n {{ fileNavigator.error }}\r\n
\r\n \r\n \r\n {{item.model.name | strLimit : 32}}\r\n \r\n \r\n \r\n
'), e.put("src/templates/main-table.html", '\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n
\r\n \r\n {{"name" | translate}}\r\n \r\n \r\n
\r\n
\r\n
\r\n {{"no_files_in_folder" | translate}}...\r\n
\r\n {{ fileNavigator.error }}\r\n
\r\n \r\n \r\n \r\n {{item.model.name | strLimit : 64}}\r\n \r\n
\r\n'), e.put("src/templates/main.html", '
\r\n
\r\n\r\n
\r\n
\r\n\r\n \r\n\r\n
\r\n \r\n
\r\n
\r\n
\r\n\r\n
\r\n
\r\n
\r\n'), - e.put("src/templates/modals.html", '\r\n\r\n \r\n\r\n \r\n\r\n \r\n\r\n \r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n \r\n\r\n \r\n\r\n \r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n'), + e.put("src/templates/modals.html", '\r\n\r\n \r\n\r\n \r\n\r\n \r\n\r\n \r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n \r\n\r\n \r\n\r\n \r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n'), e.put("src/templates/navbar.html", '\r\n'), e.put("src/templates/sidebar.html", '\r\n\r\n'), e.put("src/templates/spinner.html", '
\r\n \r\n \r\n \r\n
') From 6d9b67ac204916fc7346b129614800ce4f691d1b Mon Sep 17 00:00:00 2001 From: HFO4 <912394456@qq.com> Date: Mon, 16 Apr 2018 20:47:48 +0800 Subject: [PATCH 05/10] add torrent download support --- application/index/controller/Home.php | 12 ++- .../index/controller/RemoteDownload.php | 30 +++++-- application/index/model/Aria2.php | 4 +- application/index/model/FileManage.php | 17 ++-- application/index/view/home/Download.html | 79 +++++++++++++++++++ application/index/view/navbar_home.html | 5 ++ static/css/material.css | 10 ++- static/js/angular-filemanager.min.js | 3 +- static/js/remoteDownload.js | 9 +++ 9 files changed, 152 insertions(+), 17 deletions(-) create mode 100644 application/index/view/home/Download.html create mode 100644 static/js/remoteDownload.js diff --git a/application/index/controller/Home.php b/application/index/controller/Home.php index 5f9f78c8..f73650c0 100644 --- a/application/index/controller/Home.php +++ b/application/index/controller/Home.php @@ -38,6 +38,16 @@ class Home extends Controller{ ]); } + public function Download(){ + $userInfo = $this->userObj->getInfo(); + $groupData = $this->userObj->getGroupData(); + return view('download', [ + 'options' => Option::getValues(['basic','group_sell']), + 'userInfo' => $userInfo, + 'groupData' => $groupData, + ]); + } + public function Album(){ $userInfo = $this->userObj->getInfo(); $list = Db::name("files")->where("upload_user",$this->userObj->uid) @@ -60,7 +70,7 @@ class Home extends Controller{ $listData = $list->all(); $pageNow = input("?get.page")?input("get.page"):1; if($pageNow>$pageCount){ - $this->error('页面不存在',404,Option::getValues(['basic','group_sell'])); + $this->error('您当前没有上传任何图片',404,Option::getValues(['basic','group_sell'])); } return view('album', [ 'options' => Option::getValues(['basic','group_sell']), diff --git a/application/index/controller/RemoteDownload.php b/application/index/controller/RemoteDownload.php index 98225cac..1411b651 100644 --- a/application/index/controller/RemoteDownload.php +++ b/application/index/controller/RemoteDownload.php @@ -29,12 +29,12 @@ class RemoteDownload extends Controller{ return true; } - private function insertRecord($aria2,$url){ + private function insertRecord($aria2,$url,$path){ Db::name("download")->insert([ "pid" => $aria2->pid, "path_id" => $aria2->pathId, "owner" => $this->userObj->uid, - "save_dir" => 1, + "save_dir" => $path, "status" => "ready", "msg" => "", "info"=>"", @@ -53,7 +53,7 @@ class RemoteDownload extends Controller{ $aria2 = new Aria2($aria2Options); $downloadStart = $aria2->addUrl(input("post.url")); if($aria2->reqStatus){ - $this->insertRecord($aria2,input("post.url")); + $this->insertRecord($aria2,input("post.url"),input("post.path")); return json(["result"=>['success'=>true,'error'=>null]]); }else{ return json(["result"=>['success'=>false,'error'=>$aria2->reqMsg]]); @@ -67,12 +67,13 @@ class RemoteDownload extends Controller{ } $aria2Options = Option::getValues(["aria2"]); $aria2 = new Aria2($aria2Options); - $torrentObj = new \app\index\model\FileManage(input("post.path"),$this->userObj->uid); + $torrentObj = new \app\index\model\FileManage(input("post.id"),$this->userObj->uid,true); $downloadStart = $aria2->addTorrent($torrentObj->signTmpUrl()); if($aria2->reqStatus){ - $this->insertRecord($aria2,input("post.path")); + $this->insertRecord($aria2,input("post.id"),input("post.savePath")); + return json(["result"=>['success'=>true,'error'=>null]]); }else{ - return json(['error'=>1,'message'=>$aria2->reqMsg]); + return json(["result"=>['success'=>false,'error'=>$aria2->reqMsg]]); } } @@ -88,4 +89,21 @@ class RemoteDownload extends Controller{ } } + public function FlushUser(){ + $aria2Options = Option::getValues(["aria2"]); + $aria2 = new Aria2($aria2Options); + $toBeFlushed = Db::name("download") + ->where("owner",$this->userObj->uid) + ->where("status","<>","complete") + ->where("status","<>","error") + ->select(); + foreach ($toBeFlushed as $key => $value) { + $aria2->flushStatus($value["id"],$this->userObj->uid,$this->userObj->getPolicy()); + } + } + + public function ListDownloading(){ + return json(["s"=>"s"]); + } + } \ No newline at end of file diff --git a/application/index/model/Aria2.php b/application/index/model/Aria2.php index 508bc919..dac3d7a4 100644 --- a/application/index/model/Aria2.php +++ b/application/index/model/Aria2.php @@ -157,7 +157,7 @@ class Aria2 extends Model{ "pid" => $sqlData["pid"], "path_id" => $sqlData["path_id"], "owner" => $sqlData["owner"], - "save_dir" => 1, + "save_dir" => $sqlData["save_dir"], "status" => "ready", "msg" => "", "info"=>"", @@ -198,7 +198,7 @@ class Aria2 extends Model{ rename($quenInfo["files"][$sqlData["file_index"]]["path"],$savePath); @unlink(dirname($quenInfo["files"][$sqlData["file_index"]]["path"])); $jsonData = array( - "path" => "", + "path" => ltrim(str_replace("/", ",", $sqlData["save_dir"]),","), "fname" => basename($quenInfo["files"][$sqlData["file_index"]]["path"]), "objname" => $generatePath.DS.$fileName, "fsize" => $quenInfo["files"][$sqlData["file_index"]]["length"], diff --git a/application/index/model/FileManage.php b/application/index/model/FileManage.php index ba639c38..9bd26255 100644 --- a/application/index/model/FileManage.php +++ b/application/index/model/FileManage.php @@ -22,12 +22,17 @@ class FileManage extends Model{ public $policyData; public $deleteStatus = true; - public function __construct($path,$uid){ - $this->filePath = $path; - $fileInfo = $this->getFileName($path); - $fileName = $fileInfo[0]; - $path = $fileInfo[1]; - $fileRecord = Db::name('files')->where('upload_user',$uid)->where('orign_name',$fileName)->where('dir',$path)->find(); + public function __construct($path,$uid,$byId=false){ + if($byId){ + $fileRecord = Db::name('files')->where('id',$path)->find(); + $this->filePath = rtrim($fileRecord["dir"],"/")."/".$fileRecord["orign_name"]; + }else{ + $this->filePath = $path; + $fileInfo = $this->getFileName($path); + $fileName = $fileInfo[0]; + $path = $fileInfo[1]; + $fileRecord = Db::name('files')->where('upload_user',$uid)->where('orign_name',$fileName)->where('dir',$path)->find(); + } if (empty($fileRecord)){ die('{ "result": { "success": false, "error": "文件不存在" } }'); } diff --git a/application/index/view/home/Download.html b/application/index/view/home/Download.html new file mode 100644 index 00000000..a24692bc --- /dev/null +++ b/application/index/view/home/Download.html @@ -0,0 +1,79 @@ +{extend name="header_home" /} +{block name="title"}离线下载管理- {$options.siteName}{/block} +{block name="content"} + + + + +
+ {include file="navbar_home" /} + +
+

离线下载管理

+
+
+ + +
+
+
+
正在进行中
+
+ 更新状态数据中... +
+ +
+
+ +
+
+
+ + + + {$options.js_code} + + {/block} \ No newline at end of file diff --git a/application/index/view/navbar_home.html b/application/index/view/navbar_home.html index 8a7526ae..bc315807 100644 --- a/application/index/view/navbar_home.html +++ b/application/index/view/navbar_home.html @@ -129,6 +129,11 @@     图片集 + {eq name=':(explode(",",$groupData.aria2)[0] OR explode(",",$groupData.aria2)[1])' value="1"} + +     离线下载 + + {/eq}
li>a{color:inherit;padding-top:20px;padding-bottom:20px}.navbar .navbar-nav>li>a:focus,.navbar .navbar-nav>li>a:hover{color:inherit;background-color:transparent}.navbar .navbar-nav>.active>a,.navbar .navbar-nav>.active>a:focus,.navbar .navbar-nav>.active>a:hover{color:inherit;background-color:rgba(255,255,255,.1)}.navbar .navbar-nav>.disabled>a,.navbar .navbar-nav>.disabled>a:focus,.navbar .navbar-nav>.disabled>a:hover{color:inherit;background-color:transparent;opacity:.9}.navbar .navbar-toggle{border:0}.navbar .navbar-toggle:focus,.navbar .navbar-toggle:hover{background-color:transparent}.navbar .navbar-toggle .icon-bar{background-color:inherit;border:1px solid}.navbar .navbar-default .navbar-toggle,.navbar .navbar-inverse .navbar-toggle{border-color:transparent}.navbar .navbar-collapse,.navbar .navbar-form{border-color:rgba(0,0,0,.1)}.navbar .navbar-nav>.open>a,.navbar .navbar-nav>.open>a:focus,.navbar .navbar-nav>.open>a:hover{background-color:transparent;color:inherit}@media (max-width:767px){.navbar .navbar-nav .navbar-text{color:inherit;margin-top:15px;margin-bottom:15px}.navbar .navbar-nav .open .dropdown-menu>.dropdown-header{border:0;color:inherit}.navbar .navbar-nav .open .dropdown-menu .divider{border-bottom:1px solid;opacity:.08}.navbar .navbar-nav .open .dropdown-menu>li>a{color:inherit}.navbar .navbar-nav .open .dropdown-menu>li>a:focus,.navbar .navbar-nav .open .dropdown-menu>li>a:hover{color:inherit;background-color:transparent}.navbar .navbar-nav .open .dropdown-menu>.active>a,.navbar .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar .navbar-nav .open .dropdown-menu>.active>a:hover{color:inherit;background-color:transparent}.navbar .navbar-nav .open .dropdown-menu>.disabled>a,.navbar .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:inherit;background-color:transparent}}.navbar .navbar-link{color:inherit}.navbar .navbar-link:hover{color:inherit}.navbar .btn-link{color:inherit}.navbar .btn-link:focus,.navbar .btn-link:hover{color:inherit}.navbar .btn-link[disabled]:focus,.navbar .btn-link[disabled]:hover,fieldset[disabled] .navbar .btn-link:focus,fieldset[disabled] .navbar .btn-link:hover{color:inherit}.navbar .navbar-form{margin-top:16px}.navbar .navbar-form .form-group{margin:0;padding:0}.navbar .navbar-form .form-group .material-input:before,.navbar .navbar-form .form-group.is-focused .material-input:after{background-color:inherit}.navbar .navbar-form .form-control,.navbar .navbar-form .form-group .form-control{border-color:inherit;color:inherit;padding:0;margin:0;height:28px;font-size:14px;line-height:1.42857143}.navbar,.navbar.navbar-default{background-color:#009688;color:rgba(255,255,255,.84)}.navbar .navbar-form .form-group input.form-control::-moz-placeholder,.navbar .navbar-form input.form-control::-moz-placeholder,.navbar.navbar-default .navbar-form .form-group input.form-control::-moz-placeholder,.navbar.navbar-default .navbar-form input.form-control::-moz-placeholder{color:rgba(255,255,255,.84)}.navbar .navbar-form .form-group input.form-control:-ms-input-placeholder,.navbar .navbar-form input.form-control:-ms-input-placeholder,.navbar.navbar-default .navbar-form .form-group input.form-control:-ms-input-placeholder,.navbar.navbar-default .navbar-form input.form-control:-ms-input-placeholder{color:rgba(255,255,255,.84)}.navbar .navbar-form .form-group input.form-control::-webkit-input-placeholder,.navbar .navbar-form input.form-control::-webkit-input-placeholder,.navbar.navbar-default .navbar-form .form-group input.form-control::-webkit-input-placeholder,.navbar.navbar-default .navbar-form input.form-control::-webkit-input-placeholder{color:rgba(255,255,255,.84)}.navbar .dropdown-menu,.navbar.navbar-default .dropdown-menu{border-radius:2px}.navbar .dropdown-menu li>a,.navbar.navbar-default .dropdown-menu li>a{font-size:16px;padding:13px 16px}.navbar .dropdown-menu li>a:focus,.navbar .dropdown-menu li>a:hover,.navbar.navbar-default .dropdown-menu li>a:focus,.navbar.navbar-default .dropdown-menu li>a:hover{color:#5B6BC2;background-color:#eee}.navbar .dropdown-menu .active>a,.navbar.navbar-default .dropdown-menu .active>a{background-color:#5B6BC2;color:rgba(255,255,255,.84)}.navbar .dropdown-menu .active>a:focus,.navbar .dropdown-menu .active>a:hover,.navbar.navbar-default .dropdown-menu .active>a:focus,.navbar.navbar-default .dropdown-menu .active>a:hover{color:rgba(255,255,255,.84)}.navbar.navbar-inverse{background-color:#3f51b5;color:#fff}.navbar.navbar-inverse .navbar-form .form-group input.form-control::-moz-placeholder,.navbar.navbar-inverse .navbar-form input.form-control::-moz-placeholder{color:#fff}.navbar.navbar-inverse .navbar-form .form-group input.form-control:-ms-input-placeholder,.navbar.navbar-inverse .navbar-form input.form-control:-ms-input-placeholder{color:#fff}.navbar.navbar-inverse .navbar-form .form-group input.form-control::-webkit-input-placeholder,.navbar.navbar-inverse .navbar-form input.form-control::-webkit-input-placeholder{color:#fff}.navbar.navbar-inverse .dropdown-menu{border-radius:2px}.navbar.navbar-inverse .dropdown-menu li>a{font-size:16px;padding:13px 16px}.navbar.navbar-inverse .dropdown-menu li>a:focus,.navbar.navbar-inverse .dropdown-menu li>a:hover{color:#3f51b5;background-color:#eee}.navbar.navbar-inverse .dropdown-menu .active>a{background-color:#3f51b5;color:#fff}.navbar.navbar-inverse .dropdown-menu .active>a:focus,.navbar.navbar-inverse .dropdown-menu .active>a:hover{color:#fff}.navbar.navbar-primary{background-color:#009688;color:rgba(255,255,255,.84)}.navbar.navbar-primary .navbar-form .form-group input.form-control::-moz-placeholder,.navbar.navbar-primary .navbar-form input.form-control::-moz-placeholder{color:rgba(255,255,255,.84)}.navbar.navbar-primary .navbar-form .form-group input.form-control:-ms-input-placeholder,.navbar.navbar-primary .navbar-form input.form-control:-ms-input-placeholder{color:rgba(255,255,255,.84)}.navbar.navbar-primary .navbar-form .form-group input.form-control::-webkit-input-placeholder,.navbar.navbar-primary .navbar-form input.form-control::-webkit-input-placeholder{color:rgba(255,255,255,.84)}.navbar.navbar-primary .dropdown-menu{border-radius:2px}.navbar.navbar-primary .dropdown-menu li>a{font-size:16px;padding:13px 16px}.navbar.navbar-primary .dropdown-menu li>a:focus,.navbar.navbar-primary .dropdown-menu li>a:hover{color:#009688;background-color:#eee}.navbar.navbar-primary .dropdown-menu .active>a{background-color:#009688;color:rgba(255,255,255,.84)}.navbar.navbar-primary .dropdown-menu .active>a:focus,.navbar.navbar-primary .dropdown-menu .active>a:hover{color:rgba(255,255,255,.84)}.navbar.navbar-success{background-color:#4caf50;color:rgba(255,255,255,.84)}.navbar.navbar-success .navbar-form .form-group input.form-control::-moz-placeholder,.navbar.navbar-success .navbar-form input.form-control::-moz-placeholder{color:rgba(255,255,255,.84)}.navbar.navbar-success .navbar-form .form-group input.form-control:-ms-input-placeholder,.navbar.navbar-success .navbar-form input.form-control:-ms-input-placeholder{color:rgba(255,255,255,.84)}.navbar.navbar-success .navbar-form .form-group input.form-control::-webkit-input-placeholder,.navbar.navbar-success .navbar-form input.form-control::-webkit-input-placeholder{color:rgba(255,255,255,.84)}.navbar.navbar-success .dropdown-menu{border-radius:2px}.navbar.navbar-success .dropdown-menu li>a{font-size:16px;padding:13px 16px}.navbar.navbar-success .dropdown-menu li>a:focus,.navbar.navbar-success .dropdown-menu li>a:hover{color:#4caf50;background-color:#eee}.navbar.navbar-success .dropdown-menu .active>a{background-color:#4caf50;color:rgba(255,255,255,.84)}.navbar.navbar-success .dropdown-menu .active>a:focus,.navbar.navbar-success .dropdown-menu .active>a:hover{color:rgba(255,255,255,.84)}.navbar.navbar-info{background-color:#03a9f4;color:rgba(255,255,255,.84)}.navbar.navbar-info .navbar-form .form-group input.form-control::-moz-placeholder,.navbar.navbar-info .navbar-form input.form-control::-moz-placeholder{color:rgba(255,255,255,.84)}.navbar.navbar-info .navbar-form .form-group input.form-control:-ms-input-placeholder,.navbar.navbar-info .navbar-form input.form-control:-ms-input-placeholder{color:rgba(255,255,255,.84)}.navbar.navbar-info .navbar-form .form-group input.form-control::-webkit-input-placeholder,.navbar.navbar-info .navbar-form input.form-control::-webkit-input-placeholder{color:rgba(255,255,255,.84)}.navbar.navbar-info .dropdown-menu{border-radius:2px}.navbar.navbar-info .dropdown-menu li>a{font-size:16px;padding:13px 16px}.navbar.navbar-info .dropdown-menu li>a:focus,.navbar.navbar-info .dropdown-menu li>a:hover{color:#03a9f4;background-color:#eee}.navbar.navbar-info .dropdown-menu .active>a{background-color:#03a9f4;color:rgba(255,255,255,.84)}.navbar.navbar-info .dropdown-menu .active>a:focus,.navbar.navbar-info .dropdown-menu .active>a:hover{color:rgba(255,255,255,.84)}.navbar.navbar-warning{background-color:#ff5722;color:rgba(255,255,255,.84)}.navbar.navbar-warning .navbar-form .form-group input.form-control::-moz-placeholder,.navbar.navbar-warning .navbar-form input.form-control::-moz-placeholder{color:rgba(255,255,255,.84)}.navbar.navbar-warning .navbar-form .form-group input.form-control:-ms-input-placeholder,.navbar.navbar-warning .navbar-form input.form-control:-ms-input-placeholder{color:rgba(255,255,255,.84)}.navbar.navbar-warning .navbar-form .form-group input.form-control::-webkit-input-placeholder,.navbar.navbar-warning .navbar-form input.form-control::-webkit-input-placeholder{color:rgba(255,255,255,.84)}.navbar.navbar-warning .dropdown-menu{border-radius:2px}.navbar.navbar-warning .dropdown-menu li>a{font-size:16px;padding:13px 16px}.navbar.navbar-warning .dropdown-menu li>a:focus,.navbar.navbar-warning .dropdown-menu li>a:hover{color:#ff5722;background-color:#eee}.navbar.navbar-warning .dropdown-menu .active>a{background-color:#ff5722;color:rgba(255,255,255,.84)}.navbar.navbar-warning .dropdown-menu .active>a:focus,.navbar.navbar-warning .dropdown-menu .active>a:hover{color:rgba(255,255,255,.84)}.navbar.navbar-danger{background-color:#f44336;color:rgba(255,255,255,.84)}.navbar.navbar-danger .navbar-form .form-group input.form-control::-moz-placeholder,.navbar.navbar-danger .navbar-form input.form-control::-moz-placeholder{color:rgba(255,255,255,.84)}.navbar.navbar-danger .navbar-form .form-group input.form-control:-ms-input-placeholder,.navbar.navbar-danger .navbar-form input.form-control:-ms-input-placeholder{color:rgba(255,255,255,.84)}.navbar.navbar-danger .navbar-form .form-group input.form-control::-webkit-input-placeholder,.navbar.navbar-danger .navbar-form input.form-control::-webkit-input-placeholder{color:rgba(255,255,255,.84)}.navbar.navbar-danger .dropdown-menu{border-radius:2px}.navbar.navbar-danger .dropdown-menu li>a{font-size:16px;padding:13px 16px}.navbar.navbar-danger .dropdown-menu li>a:focus,.navbar.navbar-danger .dropdown-menu li>a:hover{color:#f44336;background-color:#eee}.navbar.navbar-danger .dropdown-menu .active>a{background-color:#f44336;color:rgba(255,255,255,.84)}.navbar.navbar-danger .dropdown-menu .active>a:focus,.navbar.navbar-danger .dropdown-menu .active>a:hover{color:rgba(255,255,255,.84)}.navbar-inverse{background-color:#3f51b5}@media (max-width:1199px){.navbar .navbar-brand{height:50px;padding:10px 15px}.navbar .navbar-form{margin-top:10px}.navbar .navbar-nav>li>a{padding-top:15px;padding-bottom:15px}}.dropdown-menu{border:0;-webkit-box-shadow:0 2px 5px 0 rgba(0,0,0,.26);box-shadow:0 2px 5px 0 rgba(0,0,0,.26)}.dropdown-menu .divider{background-color:rgba(0,0,0,.12)}.dropdown-menu li{overflow:hidden;position:relative}.dropdown-menu li a:hover{background-color:transparent;color:#009688}.alert{border:0;border-radius:0}.alert,.alert.alert-default{background-color:rgba(255,255,255,.84);color:rgba(255,255,255,.84)}.alert .alert-link,.alert a,.alert.alert-default .alert-link,.alert.alert-default a{color:rgba(255,255,255,.84)}.alert.alert-inverse{background-color:#3f51b5;color:#fff}.alert.alert-inverse .alert-link,.alert.alert-inverse a{color:#fff}.alert.alert-primary{background-color:#009688;color:rgba(255,255,255,.84)}.alert.alert-primary .alert-link,.alert.alert-primary a{color:rgba(255,255,255,.84)}.alert.alert-success{background-color:#4caf50;color:rgba(255,255,255,.84)}.alert.alert-success .alert-link,.alert.alert-success a{color:rgba(255,255,255,.84)}.alert.alert-info{background-color:#03a9f4;color:rgba(255,255,255,.84)}.alert.alert-info .alert-link,.alert.alert-info a{color:rgba(255,255,255,.84)}.alert.alert-warning{background-color:#ff5722;color:rgba(255,255,255,.84)}.alert.alert-warning .alert-link,.alert.alert-warning a{color:rgba(255,255,255,.84)}.alert.alert-danger{background-color:#f44336;color:rgba(255,255,255,.84)}.alert.alert-danger .alert-link,.alert.alert-danger a{color:rgba(255,255,255,.84)}.alert-danger,.alert-info,.alert-success,.alert-warning{color:rgba(255,255,255,.84)}.alert-default .alert-link,.alert-default a{color:rgba(0,0,0,.87)}.progress{height:4px;border-radius:0;-webkit-box-shadow:none;box-shadow:none;background:#c8c8c8}.progress .progress-bar{-webkit-box-shadow:none;box-shadow:none}.progress .progress-bar,.progress .progress-bar.progress-bar-default{background-color:#009688}.progress .progress-bar.progress-bar-inverse{background-color:#3f51b5}.progress .progress-bar.progress-bar-primary{background-color:#009688}.progress .progress-bar.progress-bar-success{background-color:#4caf50}.progress .progress-bar.progress-bar-info{background-color:#03a9f4}.progress .progress-bar.progress-bar-warning{background-color:#ff5722}.progress .progress-bar.progress-bar-danger{background-color:#f44336}.text-warning{color:#ff5722}.text-primary{color:#009688}.text-danger{color:#f44336}.text-success{color:#4caf50}.text-info{color:#03a9f4}.nav-tabs{background:#009688}.nav-tabs>li>a{color:#FFF;border:0;margin:0}.nav-tabs>li>a:hover{background-color:transparent;border:0}.nav-tabs>li>a,.nav-tabs>li>a:focus,.nav-tabs>li>a:hover{background-color:transparent!important;border:0!important;color:#FFF!important;font-weight:500}.nav-tabs>li.disabled>a,.nav-tabs>li.disabled>a:hover{color:rgba(255,255,255,.5)}.popover,.tooltip-inner{color:#ececec;line-height:1em;background:rgba(101,101,101,.9);border:none;border-radius:2px;-webkit-box-shadow:0 1px 6px 0 rgba(0,0,0,.12),0 1px 6px 0 rgba(0,0,0,.12);box-shadow:0 1px 6px 0 rgba(0,0,0,.12),0 1px 6px 0 rgba(0,0,0,.12)}.tooltip,.tooltip.in{opacity:1}.popover .arrow,.popover .tooltip-arrow,.tooltip .arrow,.tooltip .tooltip-arrow{display:none}.card{display:inline-block;position:relative;width:100%;border-radius:2px;color:rgba(0,0,0,.87);background:#fff;-webkit-box-shadow:0 8px 17px 0 rgba(0,0,0,.2),0 6px 20px 0 rgba(0,0,0,.19);box-shadow:0 8px 17px 0 rgba(0,0,0,.2),0 6px 20px 0 rgba(0,0,0,.19)}.card .card-height-indicator{margin-top:100%}.card .card-content{position:absolute;top:0;bottom:0;left:0;right:0}.card .card-image{height:60%;position:relative;overflow:hidden}.card .card-image img{width:100%;height:100%;border-top-left-radius:2px;border-top-right-radius:2px;pointer-events:none}.card .card-image .card-image-headline{position:absolute;bottom:16px;left:18px;color:#fff;font-size:2em}.card .card-body{height:30%;padding:18px}.card .card-footer{height:10%;padding:18px}.card .card-footer a,.card .card-footer button{margin:0!important;position:relative;bottom:25px;width:auto}.card .card-footer a:first-child,.card .card-footer button:first-child{left:-15px}.modal-content{-webkit-box-shadow:0 27px 24px 0 rgba(0,0,0,.2),0 40px 77px 0 rgba(0,0,0,.22);box-shadow:0 27px 24px 0 rgba(0,0,0,.2),0 40px 77px 0 rgba(0,0,0,.22);border-radius:2px;border:none}.modal-content .modal-header{border-bottom:none;padding-top:24px;padding-right:24px;padding-bottom:0;padding-left:24px}.modal-content .modal-body{padding-top:24px;padding-right:24px;padding-bottom:16px;padding-left:24px}.modal-content .modal-footer{border-top:none;padding:7px}.modal-content .modal-footer button{margin:0;padding-left:16px;padding-right:16px;width:auto}.modal-content .modal-footer button.pull-left{padding-left:5px;padding-right:5px;position:relative;left:-5px}.modal-content .modal-footer button+button{margin-bottom:16px}.modal-content .modal-body+.modal-footer{padding-top:0}.modal-backdrop{background:rgba(0,0,0,.3)}.panel{border-radius:2px;border:0;-webkit-box-shadow:0 1px 6px 0 rgba(0,0,0,.12),0 1px 6px 0 rgba(0,0,0,.12);box-shadow:0 1px 6px 0 rgba(0,0,0,.12),0 1px 6px 0 rgba(0,0,0,.12)}.panel.panel-default>.panel-heading,.panel>.panel-heading{background-color:#eee}.panel.panel-inverse>.panel-heading{background-color:#3f51b5}.panel.panel-primary>.panel-heading{background-color:#009688}.panel.panel-success>.panel-heading{background-color:#4caf50}.panel.panel-info>.panel-heading{background-color:#03a9f4}.panel.panel-warning>.panel-heading{background-color:#ff5722}.panel.panel-danger>.panel-heading{background-color:#f44336}[class*=panel-]>.panel-heading{color:rgba(255,255,255,.84);border:0}.panel-default>.panel-heading,.panel:not([class*=panel-])>.panel-heading{color:rgba(0,0,0,.87)}.panel-footer{background-color:#eee}hr.on-dark{color:#1a1a1a}hr.on-light{color:#fff}@media (-webkit-min-device-pixel-ratio:0.75),(min--moz-device-pixel-ratio:0.75),(-o-device-pixel-ratio:3/4),(min-device-pixel-ratio:0.75),(-o-min-device-pixel-ratio:3/4),(min-resolution:0.75dppx),(-webkit-min-device-pixel-ratio:1.25),(-o-min-device-pixel-ratio:5/4),(min-resolution:120dpi){hr{height:.75px}}@media (-webkit-min-device-pixel-ratio:1),(min--moz-device-pixel-ratio:1),(-o-device-pixel-ratio:1),(min-device-pixel-ratio:1),(-o-min-device-pixel-ratio:1/1),(min-resolution:1dppx),(-webkit-min-device-pixel-ratio:1.6666666666666667),(-o-min-device-pixel-ratio:5/3),(min-resolution:160dpi){hr{height:1px}}@media (-webkit-min-device-pixel-ratio:1.33),(min--moz-device-pixel-ratio:1.33),(-o-device-pixel-ratio:133/100),(min-device-pixel-ratio:1.33),(-o-min-device-pixel-ratio:133/100),(min-resolution:1.33dppx),(-webkit-min-device-pixel-ratio:2.21875),(-o-min-device-pixel-ratio:71/32),(min-resolution:213dpi){hr{height:1.33px}}@media (-webkit-min-device-pixel-ratio:1.5),(min--moz-device-pixel-ratio:1.5),(-o-device-pixel-ratio:3/2),(min-device-pixel-ratio:1.5),(-o-min-device-pixel-ratio:3/2),(min-resolution:1.5dppx),(-webkit-min-device-pixel-ratio:2.5),(-o-min-device-pixel-ratio:5/2),(min-resolution:240dpi){hr{height:1.5px}}@media (-webkit-min-device-pixel-ratio:2),(min--moz-device-pixel-ratio:2),(-o-device-pixel-ratio:2/1),(min-device-pixel-ratio:2),(-o-min-device-pixel-ratio:2/1),(min-resolution:2dppx),(-webkit-min-device-pixel-ratio:3.9583333333333335),(-o-min-device-pixel-ratio:95/24),(min-resolution:380dpi){hr{height:2px}}@media (-webkit-min-device-pixel-ratio:3),(min--moz-device-pixel-ratio:3),(-o-device-pixel-ratio:3/1),(min-device-pixel-ratio:3),(-o-min-device-pixel-ratio:3/1),(min-resolution:3dppx),(-webkit-min-device-pixel-ratio:5),(-o-min-device-pixel-ratio:5/1),(min-resolution:480dpi){hr{height:3px}}@media (-webkit-min-device-pixel-ratio:4),(min--moz-device-pixel-ratio:4),(-o-device-pixel-ratio:4/1),(min-device-pixel-ratio:3),(-o-min-device-pixel-ratio:4/1),(min-resolution:4dppx),(-webkit-min-device-pixel-ratio:6.666666666666667),(-o-min-device-pixel-ratio:20/3),(min-resolution:640dpi){hr{height:4px}}*{-webkit-tap-highlight-color:rgba(255,255,255,0);-webkit-tap-highlight-color:transparent}:focus{outline:0}.snackbar{background-color:#323232;color:rgba(255,255,255,.84);font-size:14px;border-radius:2px;-webkit-box-shadow:0 1px 6px 0 rgba(0,0,0,.12),0 1px 6px 0 rgba(0,0,0,.12);box-shadow:0 1px 6px 0 rgba(0,0,0,.12),0 1px 6px 0 rgba(0,0,0,.12);height:0;-webkit-transition:-webkit-transform .2s ease-in-out,opacity .2s ease-in,height 0s linear .2s,padding 0s linear .2s,height 0s linear .2s;-o-transition:-o-transform .2s ease-in-out,opacity .2s ease-in,height 0s linear .2s,padding 0s linear .2s,height 0s linear .2s;transition:transform .2s ease-in-out,opacity .2s ease-in,height 0s linear .2s,padding 0s linear .2s,height 0s linear .2s;-webkit-transform:translateY(200%);-ms-transform:translateY(200%);-o-transform:translateY(200%);transform:translateY(200%)}.snackbar.snackbar-opened{padding:14px 15px;margin-bottom:20px;height:auto;-webkit-transition:-webkit-transform .2s ease-in-out,opacity .2s ease-in,height 0s linear .2s,height 0s linear .2s;-o-transition:-o-transform .2s ease-in-out,opacity .2s ease-in,height 0s linear .2s,height 0s linear .2s;transition:transform .2s ease-in-out,opacity .2s ease-in,height 0s linear .2s,height 0s linear .2s;-webkit-transform:none;-ms-transform:none;-o-transform:none;transform:none}.snackbar.toast{border-radius:200px}.noUi-target,.noUi-target *{-webkit-touch-callout:none;-ms-touch-action:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.noUi-base{width:100%;height:100%;position:relative}.noUi-origin{position:absolute;right:0;top:0;left:0;bottom:0}.noUi-handle{position:relative;z-index:1;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.noUi-stacking .noUi-handle{z-index:10}.noUi-state-tap .noUi-origin{-webkit-transition:left .3s,top .3s;-o-transition:left .3s,top .3s;transition:left .3s,top .3s}.noUi-state-drag *{cursor:inherit!important}.noUi-horizontal{height:10px}.noUi-handle{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;width:12px;height:12px;left:-10px;top:-5px;cursor:ew-resize;border-radius:100%;-webkit-transition:all .2s ease-out;-o-transition:all .2s ease-out;transition:all .2s ease-out;border:1px solid}.noUi-vertical .noUi-handle{margin-left:5px;cursor:ns-resize}.noUi-horizontal.noUi-extended{padding:0 15px}.noUi-horizontal.noUi-extended .noUi-origin{right:-15px}.noUi-background{height:2px;margin:20px 0}.noUi-origin{margin:0;border-radius:0;height:2px;background:#c8c8c8}.noUi-origin[style^="left: 0"] .noUi-handle{background-color:#fff;border:2px solid #c8c8c8}.noUi-origin[style^="left: 0"] .noUi-handle.noUi-active{border-width:1px}.noUi-target{border-radius:2px}.noUi-horizontal{height:2px;margin:15px 0}.noUi-vertical{height:100%;width:2px;margin:0 15px;display:inline-block}.noUi-handle.noUi-active{-webkit-transform:scale3d(2.5,2.5,1);transform:scale3d(2.5,2.5,1)}[disabled].noUi-slider{opacity:.5}[disabled] .noUi-handle{cursor:not-allowed}.slider{background:#c8c8c8}.slider.noUi-connect,.slider.slider-default.noUi-connect{background-color:#009688}.slider.slider-inverse.noUi-connect{background-color:#3f51b5}.slider.slider-primary.noUi-connect{background-color:#009688}.slider.slider-success.noUi-connect{background-color:#4caf50}.slider.slider-info.noUi-connect{background-color:#03a9f4}.slider.slider-warning.noUi-connect{background-color:#ff5722}.slider.slider-danger.noUi-connect{background-color:#f44336}.slider .noUi-connect,.slider.slider-default .noUi-connect{background-color:#009688}.slider.slider-inverse .noUi-connect{background-color:#3f51b5}.slider.slider-primary .noUi-connect{background-color:#009688}.slider.slider-success .noUi-connect{background-color:#4caf50}.slider.slider-info .noUi-connect{background-color:#03a9f4}.slider.slider-warning .noUi-connect{background-color:#ff5722}.slider.slider-danger .noUi-connect{background-color:#f44336}.slider .noUi-handle,.slider.slider-default .noUi-handle{background-color:#009688}.slider.slider-inverse .noUi-handle{background-color:#3f51b5}.slider.slider-primary .noUi-handle{background-color:#009688}.slider.slider-success .noUi-handle{background-color:#4caf50}.slider.slider-info .noUi-handle{background-color:#03a9f4}.slider.slider-warning .noUi-handle{background-color:#ff5722}.slider.slider-danger .noUi-handle{background-color:#f44336}.slider .noUi-handle,.slider.slider-default .noUi-handle{border-color:#009688}.slider.slider-inverse .noUi-handle{border-color:#3f51b5}.slider.slider-primary .noUi-handle{border-color:#009688}.slider.slider-success .noUi-handle{border-color:#4caf50}.slider.slider-info .noUi-handle{border-color:#03a9f4}.slider.slider-warning .noUi-handle{border-color:#ff5722}.slider.slider-danger .noUi-handle{border-color:#f44336}.selectize-control.multi,.selectize-control.single{padding:0}.selectize-control.multi .selectize-input,.selectize-control.multi .selectize-input.input-active,.selectize-control.single .selectize-input,.selectize-control.single .selectize-input.input-active{cursor:text;background:0 0;-webkit-box-shadow:none;box-shadow:none;border:0;padding:0;height:100%;font-size:14px;line-height:30px}.selectize-control.multi .selectize-input .has-items,.selectize-control.multi .selectize-input.input-active .has-items,.selectize-control.single .selectize-input .has-items,.selectize-control.single .selectize-input.input-active .has-items{padding:0}.selectize-control.multi .selectize-input.input-active:after,.selectize-control.multi .selectize-input:after,.selectize-control.single .selectize-input.input-active:after,.selectize-control.single .selectize-input:after{right:5px;position:absolute;font-size:25px;content:"\e5c5";font-family:'Material Icons';speak:none;font-style:normal;font-weight:400;font-variant:normal;text-transform:none;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.selectize-control.multi .selectize-input input,.selectize-control.multi .selectize-input.input-active input,.selectize-control.single .selectize-input input,.selectize-control.single .selectize-input.input-active input{font-size:14px;outline:0;border:0;background:0 0}.selectize-control.multi .selectize-input.input-active.label-floating-fix input,.selectize-control.multi .selectize-input.label-floating-fix input,.selectize-control.single .selectize-input.input-active.label-floating-fix input,.selectize-control.single .selectize-input.label-floating-fix input{opacity:0}.selectize-control.multi .selectize-input.input-active>.item,.selectize-control.multi .selectize-input.input-active>div,.selectize-control.multi .selectize-input>.item,.selectize-control.multi .selectize-input>div,.selectize-control.single .selectize-input.input-active>.item,.selectize-control.single .selectize-input.input-active>div,.selectize-control.single .selectize-input>.item,.selectize-control.single .selectize-input>div{display:inline-block;margin:0 8px 3px 0;padding:0;background:0 0;border:0}.selectize-control.multi .selectize-input.input-active>.item:after,.selectize-control.multi .selectize-input.input-active>div:after,.selectize-control.multi .selectize-input>.item:after,.selectize-control.multi .selectize-input>div:after,.selectize-control.single .selectize-input.input-active>.item:after,.selectize-control.single .selectize-input.input-active>div:after,.selectize-control.single .selectize-input>.item:after,.selectize-control.single .selectize-input>div:after{content:","}.selectize-control.multi .selectize-input.input-active>.item:last-of-type:after,.selectize-control.multi .selectize-input.input-active>div:last-of-type:after,.selectize-control.multi .selectize-input>.item:last-of-type:after,.selectize-control.multi .selectize-input>div:last-of-type:after,.selectize-control.single .selectize-input.input-active>.item:last-of-type:after,.selectize-control.single .selectize-input.input-active>div:last-of-type:after,.selectize-control.single .selectize-input>.item:last-of-type:after,.selectize-control.single .selectize-input>div:last-of-type:after{content:""}.selectize-control.multi .selectize-input.input-active>.item.active,.selectize-control.multi .selectize-input.input-active>div.active,.selectize-control.multi .selectize-input>.item.active,.selectize-control.multi .selectize-input>div.active,.selectize-control.single .selectize-input.input-active>.item.active,.selectize-control.single .selectize-input.input-active>div.active,.selectize-control.single .selectize-input>.item.active,.selectize-control.single .selectize-input>div.active{font-weight:700;background:0 0;border:0}.selectize-control.multi .selectize-dropdown,.selectize-control.single .selectize-dropdown{position:absolute;z-index:1000;border:0;width:100%!important;left:0!important;height:auto;background-color:#FFF;-webkit-box-shadow:0 1px 3px rgba(0,0,0,.12),0 1px 2px rgba(0,0,0,.24);box-shadow:0 1px 3px rgba(0,0,0,.12),0 1px 2px rgba(0,0,0,.24);border-radius:2px;padding:0;margin-top:3px}.selectize-control.multi .selectize-dropdown .active,.selectize-control.single .selectize-dropdown .active{background-color:inherit}.selectize-control.multi .selectize-dropdown .highlight,.selectize-control.single .selectize-dropdown .highlight{background-color:#d5d8ff}.selectize-control.multi .selectize-dropdown .selected,.selectize-control.multi .selectize-dropdown .selected.active,.selectize-control.single .selectize-dropdown .selected,.selectize-control.single .selectize-dropdown .selected.active{background-color:#EEE}.selectize-control.multi .selectize-dropdown .optgroup-header,.selectize-control.multi .selectize-dropdown [data-selectable],.selectize-control.single .selectize-dropdown .optgroup-header,.selectize-control.single .selectize-dropdown [data-selectable]{padding:10px 20px;cursor:pointer}.selectize-control.multi .dropdown-active~.selectize-dropdown,.selectize-control.single .dropdown-active~.selectize-dropdown{display:block}.dropdownjs::after{right:5px;top:3px;font-size:25px;position:absolute;font-family:'Material Icons';font-style:normal;font-weight:400;content:"\e5c5";pointer-events:none;color:#757575}.navbar-brand{background-position:10px;background-size:192px 50px;background-image:url(/static/img/logo_s.png);width:200px;background-repeat:no-repeat}.wave_hide{overflow:initial}@media (min-width:768px){.avatar-a{padding-top:15px!important;padding-bottom:15px!important}.avatar-s{width:30px!important}} \ No newline at end of file +body{background-color:#EEE}body.inverse{background:#333}body.inverse,body.inverse .form-control{color:rgba(255,255,255,.84)}body.inverse .card,body.inverse .card .form-control,body.inverse .modal,body.inverse .modal .form-control,body.inverse .panel-default,body.inverse .panel-default .form-control{background-color:initial;color:initial}.h1,.h2,.h3,.h4,body,h1,h2,h3,h4,h5,h6{font-weight:300}h5,h6{font-weight:400}a,a:focus,a:hover{color:#3F51B5}a .material-icons,a:focus .material-icons,a:hover .material-icons{vertical-align:middle}.form-horizontal .checkbox,.form-horizontal .checkbox-inline,.form-horizontal .radio,.form-horizontal .radio-inline{padding-top:0}.form-horizontal .radio{margin-bottom:10px}.form-horizontal label{text-align:right}.form-horizontal label.control-label{margin:0}body .container .well.well-sm,body .container-fluid .well.well-sm{padding:10px}body .container .well.well-lg,body .container-fluid .well.well-lg{padding:26px}body .container .jumbotron,body .container .well,body .container-fluid .jumbotron,body .container-fluid .well{background-color:#fff;padding:19px;margin-bottom:20px;-webkit-box-shadow:0 8px 17px 0 rgba(0,0,0,.2),0 6px 20px 0 rgba(0,0,0,.19);box-shadow:0 8px 17px 0 rgba(0,0,0,.2),0 6px 20px 0 rgba(0,0,0,.19);border-radius:2px;border:0}body .container .jumbotron p,body .container .well p,body .container-fluid .jumbotron p,body .container-fluid .well p{font-weight:300}body .container .jumbotron,body .container .jumbotron-default,body .container .well,body .container .well-default,body .container-fluid .jumbotron,body .container-fluid .jumbotron-default,body .container-fluid .well,body .container-fluid .well-default{background-color:#fff}body .container .jumbotron-inverse,body .container .well-inverse,body .container-fluid .jumbotron-inverse,body .container-fluid .well-inverse{background-color:#3f51b5}body .container .jumbotron-primary,body .container .well-primary,body .container-fluid .jumbotron-primary,body .container-fluid .well-primary{background-color:#009688}body .container .jumbotron-success,body .container .well-success,body .container-fluid .jumbotron-success,body .container-fluid .well-success{background-color:#4caf50}body .container .jumbotron-info,body .container .well-info,body .container-fluid .jumbotron-info,body .container-fluid .well-info{background-color:#03a9f4}body .container .jumbotron-warning,body .container .well-warning,body .container-fluid .jumbotron-warning,body .container-fluid .well-warning{background-color:#ff5722}body .container .jumbotron-danger,body .container .well-danger,body .container-fluid .jumbotron-danger,body .container-fluid .well-danger{background-color:#f44336}.btn,.input-group-btn .btn{border:none;border-radius:2px;position:relative;padding:8px 30px;margin:10px 1px;font-size:14px;font-weight:500;text-transform:uppercase;letter-spacing:0;will-change:box-shadow,transform;-webkit-transition:-webkit-box-shadow .2s cubic-bezier(.4,0,1,1),background-color .2s cubic-bezier(.4,0,.2,1),color .2s cubic-bezier(.4,0,.2,1);-o-transition:box-shadow .2s cubic-bezier(.4,0,1,1),background-color .2s cubic-bezier(.4,0,.2,1),color .2s cubic-bezier(.4,0,.2,1);transition:box-shadow .2s cubic-bezier(.4,0,1,1),background-color .2s cubic-bezier(.4,0,.2,1),color .2s cubic-bezier(.4,0,.2,1);outline:0;cursor:pointer;text-decoration:none;background:0 0}.btn::-moz-focus-inner,.input-group-btn .btn::-moz-focus-inner{border:0}.btn:not(.btn-raised),.input-group-btn .btn:not(.btn-raised){-webkit-box-shadow:none;box-shadow:none}.btn:not(.btn-raised),.btn:not(.btn-raised).btn-default,.input-group-btn .btn:not(.btn-raised),.input-group-btn .btn:not(.btn-raised).btn-default{color:rgba(0,0,0,.87)}.btn:not(.btn-raised).btn-inverse,.input-group-btn .btn:not(.btn-raised).btn-inverse{color:#3f51b5}.btn:not(.btn-raised).btn-primary,.input-group-btn .btn:not(.btn-raised).btn-primary{color:#3F51B5}.btn:not(.btn-raised).btn-success,.input-group-btn .btn:not(.btn-raised).btn-success{color:#4caf50}.btn:not(.btn-raised).btn-info,.input-group-btn .btn:not(.btn-raised).btn-info{color:#03a9f4}.btn:not(.btn-raised).btn-warning,.input-group-btn .btn:not(.btn-raised).btn-warning{color:#ff5722}.btn:not(.btn-raised).btn-danger,.input-group-btn .btn:not(.btn-raised).btn-danger{color:#f44336}.btn:not(.btn-raised):not(.btn-link):focus,.btn:not(.btn-raised):not(.btn-link):hover,.input-group-btn .btn:not(.btn-raised):not(.btn-link):focus,.input-group-btn .btn:not(.btn-raised):not(.btn-link):hover{background-color:rgba(153,153,153,.2)}.theme-dark .btn:not(.btn-raised):not(.btn-link):focus,.theme-dark .btn:not(.btn-raised):not(.btn-link):hover,.theme-dark .input-group-btn .btn:not(.btn-raised):not(.btn-link):focus,.theme-dark .input-group-btn .btn:not(.btn-raised):not(.btn-link):hover{background-color:rgba(204,204,204,.15)}.btn-group-raised .btn,.btn-group-raised .btn.btn-default,.btn-group-raised .input-group-btn .btn,.btn-group-raised .input-group-btn .btn.btn-default,.btn.btn-fab,.btn.btn-fab.btn-default,.btn.btn-raised,.btn.btn-raised.btn-default,.input-group-btn .btn.btn-fab,.input-group-btn .btn.btn-fab.btn-default,.input-group-btn .btn.btn-raised,.input-group-btn .btn.btn-raised.btn-default{background-color:#EEE;color:rgba(0,0,0,.87)}.btn-group-raised .btn.btn-inverse,.btn-group-raised .input-group-btn .btn.btn-inverse,.btn.btn-fab.btn-inverse,.btn.btn-raised.btn-inverse,.input-group-btn .btn.btn-fab.btn-inverse,.input-group-btn .btn.btn-raised.btn-inverse{background-color:#3f51b5;color:#fff}.btn-group-raised .btn.btn-primary,.btn-group-raised .input-group-btn .btn.btn-primary,.btn.btn-fab.btn-primary,.btn.btn-raised.btn-primary,.input-group-btn .btn.btn-fab.btn-primary,.input-group-btn .btn.btn-raised.btn-primary{background-color:#3F51B5;color:rgba(255,255,255,.84)}.btn-group-raised .btn.btn-success,.btn-group-raised .input-group-btn .btn.btn-success,.btn.btn-fab.btn-success,.btn.btn-raised.btn-success,.input-group-btn .btn.btn-fab.btn-success,.input-group-btn .btn.btn-raised.btn-success{background-color:#4caf50;color:rgba(255,255,255,.84)}.btn-group-raised .btn.btn-info,.btn-group-raised .input-group-btn .btn.btn-info,.btn.btn-fab.btn-info,.btn.btn-raised.btn-info,.input-group-btn .btn.btn-fab.btn-info,.input-group-btn .btn.btn-raised.btn-info{background-color:#03a9f4;color:rgba(255,255,255,.84)}.btn-group-raised .btn.btn-warning,.btn-group-raised .input-group-btn .btn.btn-warning,.btn.btn-fab.btn-warning,.btn.btn-raised.btn-warning,.input-group-btn .btn.btn-fab.btn-warning,.input-group-btn .btn.btn-raised.btn-warning{background-color:#ff5722;color:rgba(255,255,255,.84)}.btn-group-raised .btn.btn-danger,.btn-group-raised .input-group-btn .btn.btn-danger,.btn.btn-fab.btn-danger,.btn.btn-raised.btn-danger,.input-group-btn .btn.btn-fab.btn-danger,.input-group-btn .btn.btn-raised.btn-danger{background-color:#f44336;color:rgba(255,255,255,.84)}.btn-group-raised .btn:not(.btn-link),.btn-group-raised .input-group-btn .btn:not(.btn-link),.btn.btn-raised:not(.btn-link),.input-group-btn .btn.btn-raised:not(.btn-link){-webkit-box-shadow:0 2px 2px 0 rgba(0,0,0,.14),0 3px 1px -2px rgba(0,0,0,.2),0 1px 5px 0 rgba(0,0,0,.12);box-shadow:0 2px 2px 0 rgba(0,0,0,.14),0 3px 1px -2px rgba(0,0,0,.2),0 1px 5px 0 rgba(0,0,0,.12)}.btn-group-raised .btn:not(.btn-link).active,.btn-group-raised .btn:not(.btn-link):active,.btn-group-raised .btn:not(.btn-link):focus,.btn-group-raised .btn:not(.btn-link):hover,.btn-group-raised .input-group-btn .btn:not(.btn-link).active,.btn-group-raised .input-group-btn .btn:not(.btn-link):active,.btn-group-raised .input-group-btn .btn:not(.btn-link):focus,.btn-group-raised .input-group-btn .btn:not(.btn-link):hover,.btn.btn-raised:not(.btn-link).active,.btn.btn-raised:not(.btn-link):active,.btn.btn-raised:not(.btn-link):focus,.btn.btn-raised:not(.btn-link):hover,.input-group-btn .btn.btn-raised:not(.btn-link).active,.input-group-btn .btn.btn-raised:not(.btn-link):active,.input-group-btn .btn.btn-raised:not(.btn-link):focus,.input-group-btn .btn.btn-raised:not(.btn-link):hover{outline:0}.btn-group-raised .btn:not(.btn-link).active,.btn-group-raised .btn:not(.btn-link).active.btn-default,.btn-group-raised .btn:not(.btn-link):active,.btn-group-raised .btn:not(.btn-link):active.btn-default,.btn-group-raised .btn:not(.btn-link):focus,.btn-group-raised .btn:not(.btn-link):focus.btn-default,.btn-group-raised .btn:not(.btn-link):hover,.btn-group-raised .btn:not(.btn-link):hover.btn-default,.btn-group-raised .input-group-btn .btn:not(.btn-link).active,.btn-group-raised .input-group-btn .btn:not(.btn-link).active.btn-default,.btn-group-raised .input-group-btn .btn:not(.btn-link):active,.btn-group-raised .input-group-btn .btn:not(.btn-link):active.btn-default,.btn-group-raised .input-group-btn .btn:not(.btn-link):focus,.btn-group-raised .input-group-btn .btn:not(.btn-link):focus.btn-default,.btn-group-raised .input-group-btn .btn:not(.btn-link):hover,.btn-group-raised .input-group-btn .btn:not(.btn-link):hover.btn-default,.btn.btn-raised:not(.btn-link).active,.btn.btn-raised:not(.btn-link).active.btn-default,.btn.btn-raised:not(.btn-link):active,.btn.btn-raised:not(.btn-link):active.btn-default,.btn.btn-raised:not(.btn-link):focus,.btn.btn-raised:not(.btn-link):focus.btn-default,.btn.btn-raised:not(.btn-link):hover,.btn.btn-raised:not(.btn-link):hover.btn-default,.input-group-btn .btn.btn-raised:not(.btn-link).active,.input-group-btn .btn.btn-raised:not(.btn-link).active.btn-default,.input-group-btn .btn.btn-raised:not(.btn-link):active,.input-group-btn .btn.btn-raised:not(.btn-link):active.btn-default,.input-group-btn .btn.btn-raised:not(.btn-link):focus,.input-group-btn .btn.btn-raised:not(.btn-link):focus.btn-default,.input-group-btn .btn.btn-raised:not(.btn-link):hover,.input-group-btn .btn.btn-raised:not(.btn-link):hover.btn-default{background-color:#e4e4e4}.btn-group-raised .btn:not(.btn-link).active.btn-inverse,.btn-group-raised .btn:not(.btn-link):active.btn-inverse,.btn-group-raised .btn:not(.btn-link):focus.btn-inverse,.btn-group-raised .btn:not(.btn-link):hover.btn-inverse,.btn-group-raised .input-group-btn .btn:not(.btn-link).active.btn-inverse,.btn-group-raised .input-group-btn .btn:not(.btn-link):active.btn-inverse,.btn-group-raised .input-group-btn .btn:not(.btn-link):focus.btn-inverse,.btn-group-raised .input-group-btn .btn:not(.btn-link):hover.btn-inverse,.btn.btn-raised:not(.btn-link).active.btn-inverse,.btn.btn-raised:not(.btn-link):active.btn-inverse,.btn.btn-raised:not(.btn-link):focus.btn-inverse,.btn.btn-raised:not(.btn-link):hover.btn-inverse,.input-group-btn .btn.btn-raised:not(.btn-link).active.btn-inverse,.input-group-btn .btn.btn-raised:not(.btn-link):active.btn-inverse,.input-group-btn .btn.btn-raised:not(.btn-link):focus.btn-inverse,.input-group-btn .btn.btn-raised:not(.btn-link):hover.btn-inverse{background-color:#495bc0}.btn-group-raised .btn:not(.btn-link).active.btn-primary,.btn-group-raised .btn:not(.btn-link):active.btn-primary,.btn-group-raised .btn:not(.btn-link):focus.btn-primary,.btn-group-raised .btn:not(.btn-link):hover.btn-primary,.btn-group-raised .input-group-btn .btn:not(.btn-link).active.btn-primary,.btn-group-raised .input-group-btn .btn:not(.btn-link):active.btn-primary,.btn-group-raised .input-group-btn .btn:not(.btn-link):focus.btn-primary,.btn-group-raised .input-group-btn .btn:not(.btn-link):hover.btn-primary,.btn.btn-raised:not(.btn-link).active.btn-primary,.btn.btn-raised:not(.btn-link):active.btn-primary,.btn.btn-raised:not(.btn-link):focus.btn-primary,.btn.btn-raised:not(.btn-link):hover.btn-primary,.input-group-btn .btn.btn-raised:not(.btn-link).active.btn-primary,.input-group-btn .btn.btn-raised:not(.btn-link):active.btn-primary,.input-group-btn .btn.btn-raised:not(.btn-link):focus.btn-primary,.input-group-btn .btn.btn-raised:not(.btn-link):hover.btn-primary{background-color:#3F51B5}.btn-group-raised .btn:not(.btn-link).active.btn-success,.btn-group-raised .btn:not(.btn-link):active.btn-success,.btn-group-raised .btn:not(.btn-link):focus.btn-success,.btn-group-raised .btn:not(.btn-link):hover.btn-success,.btn-group-raised .input-group-btn .btn:not(.btn-link).active.btn-success,.btn-group-raised .input-group-btn .btn:not(.btn-link):active.btn-success,.btn-group-raised .input-group-btn .btn:not(.btn-link):focus.btn-success,.btn-group-raised .input-group-btn .btn:not(.btn-link):hover.btn-success,.btn.btn-raised:not(.btn-link).active.btn-success,.btn.btn-raised:not(.btn-link):active.btn-success,.btn.btn-raised:not(.btn-link):focus.btn-success,.btn.btn-raised:not(.btn-link):hover.btn-success,.input-group-btn .btn.btn-raised:not(.btn-link).active.btn-success,.input-group-btn .btn.btn-raised:not(.btn-link):active.btn-success,.input-group-btn .btn.btn-raised:not(.btn-link):focus.btn-success,.input-group-btn .btn.btn-raised:not(.btn-link):hover.btn-success{background-color:#59b75c}.btn-group-raised .btn:not(.btn-link).active.btn-info,.btn-group-raised .btn:not(.btn-link):active.btn-info,.btn-group-raised .btn:not(.btn-link):focus.btn-info,.btn-group-raised .btn:not(.btn-link):hover.btn-info,.btn-group-raised .input-group-btn .btn:not(.btn-link).active.btn-info,.btn-group-raised .input-group-btn .btn:not(.btn-link):active.btn-info,.btn-group-raised .input-group-btn .btn:not(.btn-link):focus.btn-info,.btn-group-raised .input-group-btn .btn:not(.btn-link):hover.btn-info,.btn.btn-raised:not(.btn-link).active.btn-info,.btn.btn-raised:not(.btn-link):active.btn-info,.btn.btn-raised:not(.btn-link):focus.btn-info,.btn.btn-raised:not(.btn-link):hover.btn-info,.input-group-btn .btn.btn-raised:not(.btn-link).active.btn-info,.input-group-btn .btn.btn-raised:not(.btn-link):active.btn-info,.input-group-btn .btn.btn-raised:not(.btn-link):focus.btn-info,.input-group-btn .btn.btn-raised:not(.btn-link):hover.btn-info{background-color:#0fb2fc}.btn-group-raised .btn:not(.btn-link).active.btn-warning,.btn-group-raised .btn:not(.btn-link):active.btn-warning,.btn-group-raised .btn:not(.btn-link):focus.btn-warning,.btn-group-raised .btn:not(.btn-link):hover.btn-warning,.btn-group-raised .input-group-btn .btn:not(.btn-link).active.btn-warning,.btn-group-raised .input-group-btn .btn:not(.btn-link):active.btn-warning,.btn-group-raised .input-group-btn .btn:not(.btn-link):focus.btn-warning,.btn-group-raised .input-group-btn .btn:not(.btn-link):hover.btn-warning,.btn.btn-raised:not(.btn-link).active.btn-warning,.btn.btn-raised:not(.btn-link):active.btn-warning,.btn.btn-raised:not(.btn-link):focus.btn-warning,.btn.btn-raised:not(.btn-link):hover.btn-warning,.input-group-btn .btn.btn-raised:not(.btn-link).active.btn-warning,.input-group-btn .btn.btn-raised:not(.btn-link):active.btn-warning,.input-group-btn .btn.btn-raised:not(.btn-link):focus.btn-warning,.input-group-btn .btn.btn-raised:not(.btn-link):hover.btn-warning{background-color:#ff6736}.btn-group-raised .btn:not(.btn-link).active.btn-danger,.btn-group-raised .btn:not(.btn-link):active.btn-danger,.btn-group-raised .btn:not(.btn-link):focus.btn-danger,.btn-group-raised .btn:not(.btn-link):hover.btn-danger,.btn-group-raised .input-group-btn .btn:not(.btn-link).active.btn-danger,.btn-group-raised .input-group-btn .btn:not(.btn-link):active.btn-danger,.btn-group-raised .input-group-btn .btn:not(.btn-link):focus.btn-danger,.btn-group-raised .input-group-btn .btn:not(.btn-link):hover.btn-danger,.btn.btn-raised:not(.btn-link).active.btn-danger,.btn.btn-raised:not(.btn-link):active.btn-danger,.btn.btn-raised:not(.btn-link):focus.btn-danger,.btn.btn-raised:not(.btn-link):hover.btn-danger,.input-group-btn .btn.btn-raised:not(.btn-link).active.btn-danger,.input-group-btn .btn.btn-raised:not(.btn-link):active.btn-danger,.input-group-btn .btn.btn-raised:not(.btn-link):focus.btn-danger,.input-group-btn .btn.btn-raised:not(.btn-link):hover.btn-danger{background-color:#f55549}.btn-group-raised .btn:not(.btn-link).active,.btn-group-raised .btn:not(.btn-link).active:hover,.btn-group-raised .btn:not(.btn-link):active,.btn-group-raised .btn:not(.btn-link):active:hover,.btn-group-raised .input-group-btn .btn:not(.btn-link).active,.btn-group-raised .input-group-btn .btn:not(.btn-link).active:hover,.btn-group-raised .input-group-btn .btn:not(.btn-link):active,.btn-group-raised .input-group-btn .btn:not(.btn-link):active:hover,.btn.btn-raised:not(.btn-link).active,.btn.btn-raised:not(.btn-link).active:hover,.btn.btn-raised:not(.btn-link):active,.btn.btn-raised:not(.btn-link):active:hover,.input-group-btn .btn.btn-raised:not(.btn-link).active,.input-group-btn .btn.btn-raised:not(.btn-link).active:hover,.input-group-btn .btn.btn-raised:not(.btn-link):active,.input-group-btn .btn.btn-raised:not(.btn-link):active:hover{-webkit-box-shadow:0 4px 5px 0 rgba(0,0,0,.14),0 1px 10px 0 rgba(0,0,0,.12),0 2px 4px -1px rgba(0,0,0,.2);box-shadow:0 4px 5px 0 rgba(0,0,0,.14),0 1px 10px 0 rgba(0,0,0,.12),0 2px 4px -1px rgba(0,0,0,.2)}.btn-group-raised .btn:not(.btn-link):focus,.btn-group-raised .btn:not(.btn-link):focus.active,.btn-group-raised .btn:not(.btn-link):focus.active:hover,.btn-group-raised .btn:not(.btn-link):focus:active,.btn-group-raised .btn:not(.btn-link):focus:active:hover,.btn-group-raised .btn:not(.btn-link):focus:hover,.btn-group-raised .input-group-btn .btn:not(.btn-link):focus,.btn-group-raised .input-group-btn .btn:not(.btn-link):focus.active,.btn-group-raised .input-group-btn .btn:not(.btn-link):focus.active:hover,.btn-group-raised .input-group-btn .btn:not(.btn-link):focus:active,.btn-group-raised .input-group-btn .btn:not(.btn-link):focus:active:hover,.btn-group-raised .input-group-btn .btn:not(.btn-link):focus:hover,.btn.btn-raised:not(.btn-link):focus,.btn.btn-raised:not(.btn-link):focus.active,.btn.btn-raised:not(.btn-link):focus.active:hover,.btn.btn-raised:not(.btn-link):focus:active,.btn.btn-raised:not(.btn-link):focus:active:hover,.btn.btn-raised:not(.btn-link):focus:hover,.input-group-btn .btn.btn-raised:not(.btn-link):focus,.input-group-btn .btn.btn-raised:not(.btn-link):focus.active,.input-group-btn .btn.btn-raised:not(.btn-link):focus.active:hover,.input-group-btn .btn.btn-raised:not(.btn-link):focus:active,.input-group-btn .btn.btn-raised:not(.btn-link):focus:active:hover,.input-group-btn .btn.btn-raised:not(.btn-link):focus:hover{-webkit-box-shadow:0 0 8px rgba(0,0,0,.18),0 8px 16px rgba(0,0,0,.36);box-shadow:0 0 8px rgba(0,0,0,.18),0 8px 16px rgba(0,0,0,.36)}.btn.btn-fab,.input-group-btn .btn.btn-fab{border-radius:50%;font-size:24px;height:56px;margin:auto;min-width:56px;width:56px;padding:0;overflow:hidden;-webkit-box-shadow:0 1px 1.5px 0 rgba(0,0,0,.12),0 1px 1px 0 rgba(0,0,0,.24);box-shadow:0 1px 1.5px 0 rgba(0,0,0,.12),0 1px 1px 0 rgba(0,0,0,.24);position:relative;line-height:normal}.btn.btn-fab .ripple-container,.input-group-btn .btn.btn-fab .ripple-container{border-radius:50%}.btn-group-sm .btn.btn-fab,.btn-group-sm .input-group-btn .btn.btn-fab,.btn.btn-fab.btn-fab-mini,.input-group-btn .btn.btn-fab.btn-fab-mini{height:40px;min-width:40px;width:40px}.btn-group-sm .btn.btn-fab.material-icons,.btn-group-sm .input-group-btn .btn.btn-fab.material-icons,.btn.btn-fab.btn-fab-mini.material-icons,.input-group-btn .btn.btn-fab.btn-fab-mini.material-icons{top:0;left:0}.btn.btn-fab i.material-icons,.input-group-btn .btn.btn-fab i.material-icons{position:absolute;top:50%;left:50%;-webkit-transform:translate(-12px,-12px);-ms-transform:translate(-12px,-12px);-o-transform:translate(-12px,-12px);transform:translate(-12px,-12px);line-height:24px;width:24px}.btn i.material-icons,.input-group-btn .btn i.material-icons{vertical-align:middle}.btn-group-lg .btn,.btn-group-lg .input-group-btn .btn,.btn.btn-lg,.input-group-btn .btn.btn-lg{font-size:16px}.btn-group-sm .btn,.btn-group-sm .input-group-btn .btn,.btn.btn-sm,.input-group-btn .btn.btn-sm{padding:5px 20px;font-size:12px}.btn-group-xs .btn,.btn-group-xs .input-group-btn .btn,.btn.btn-xs,.input-group-btn .btn.btn-xs{padding:4px 15px;font-size:10px}.btn-group-vertical.disabled,.btn-group-vertical:disabled,.btn-group-vertical[disabled][disabled],.btn-group.disabled,.btn-group:disabled,.btn-group[disabled][disabled],.btn.disabled,.btn:disabled,.btn[disabled][disabled],.input-group-btn .btn.disabled,.input-group-btn .btn:disabled,.input-group-btn .btn[disabled][disabled],fieldset[disabled][disabled] .btn,fieldset[disabled][disabled] .btn-group,fieldset[disabled][disabled] .btn-group-vertical,fieldset[disabled][disabled] .input-group-btn .btn{color:rgba(0,0,0,.26);background:0 0}.theme-dark .btn-group-vertical.disabled,.theme-dark .btn-group-vertical:disabled,.theme-dark .btn-group-vertical[disabled][disabled],.theme-dark .btn-group.disabled,.theme-dark .btn-group:disabled,.theme-dark .btn-group[disabled][disabled],.theme-dark .btn.disabled,.theme-dark .btn:disabled,.theme-dark .btn[disabled][disabled],.theme-dark .input-group-btn .btn.disabled,.theme-dark .input-group-btn .btn:disabled,.theme-dark .input-group-btn .btn[disabled][disabled],.theme-dark fieldset[disabled][disabled] .btn,.theme-dark fieldset[disabled][disabled] .btn-group,.theme-dark fieldset[disabled][disabled] .btn-group-vertical,.theme-dark fieldset[disabled][disabled] .input-group-btn .btn{color:rgba(255,255,255,.3)}.btn-group-vertical.disabled.btn-group-raised,.btn-group-vertical.disabled.btn-group-raised.active,.btn-group-vertical.disabled.btn-group-raised:active,.btn-group-vertical.disabled.btn-group-raised:focus:not(:active),.btn-group-vertical.disabled.btn-raised,.btn-group-vertical.disabled.btn-raised.active,.btn-group-vertical.disabled.btn-raised:active,.btn-group-vertical.disabled.btn-raised:focus:not(:active),.btn-group-vertical:disabled.btn-group-raised,.btn-group-vertical:disabled.btn-group-raised.active,.btn-group-vertical:disabled.btn-group-raised:active,.btn-group-vertical:disabled.btn-group-raised:focus:not(:active),.btn-group-vertical:disabled.btn-raised,.btn-group-vertical:disabled.btn-raised.active,.btn-group-vertical:disabled.btn-raised:active,.btn-group-vertical:disabled.btn-raised:focus:not(:active),.btn-group-vertical[disabled][disabled].btn-group-raised,.btn-group-vertical[disabled][disabled].btn-group-raised.active,.btn-group-vertical[disabled][disabled].btn-group-raised:active,.btn-group-vertical[disabled][disabled].btn-group-raised:focus:not(:active),.btn-group-vertical[disabled][disabled].btn-raised,.btn-group-vertical[disabled][disabled].btn-raised.active,.btn-group-vertical[disabled][disabled].btn-raised:active,.btn-group-vertical[disabled][disabled].btn-raised:focus:not(:active),.btn-group.disabled.btn-group-raised,.btn-group.disabled.btn-group-raised.active,.btn-group.disabled.btn-group-raised:active,.btn-group.disabled.btn-group-raised:focus:not(:active),.btn-group.disabled.btn-raised,.btn-group.disabled.btn-raised.active,.btn-group.disabled.btn-raised:active,.btn-group.disabled.btn-raised:focus:not(:active),.btn-group:disabled.btn-group-raised,.btn-group:disabled.btn-group-raised.active,.btn-group:disabled.btn-group-raised:active,.btn-group:disabled.btn-group-raised:focus:not(:active),.btn-group:disabled.btn-raised,.btn-group:disabled.btn-raised.active,.btn-group:disabled.btn-raised:active,.btn-group:disabled.btn-raised:focus:not(:active),.btn-group[disabled][disabled].btn-group-raised,.btn-group[disabled][disabled].btn-group-raised.active,.btn-group[disabled][disabled].btn-group-raised:active,.btn-group[disabled][disabled].btn-group-raised:focus:not(:active),.btn-group[disabled][disabled].btn-raised,.btn-group[disabled][disabled].btn-raised.active,.btn-group[disabled][disabled].btn-raised:active,.btn-group[disabled][disabled].btn-raised:focus:not(:active),.btn.disabled.btn-group-raised,.btn.disabled.btn-group-raised.active,.btn.disabled.btn-group-raised:active,.btn.disabled.btn-group-raised:focus:not(:active),.btn.disabled.btn-raised,.btn.disabled.btn-raised.active,.btn.disabled.btn-raised:active,.btn.disabled.btn-raised:focus:not(:active),.btn:disabled.btn-group-raised,.btn:disabled.btn-group-raised.active,.btn:disabled.btn-group-raised:active,.btn:disabled.btn-group-raised:focus:not(:active),.btn:disabled.btn-raised,.btn:disabled.btn-raised.active,.btn:disabled.btn-raised:active,.btn:disabled.btn-raised:focus:not(:active),.btn[disabled][disabled].btn-group-raised,.btn[disabled][disabled].btn-group-raised.active,.btn[disabled][disabled].btn-group-raised:active,.btn[disabled][disabled].btn-group-raised:focus:not(:active),.btn[disabled][disabled].btn-raised,.btn[disabled][disabled].btn-raised.active,.btn[disabled][disabled].btn-raised:active,.btn[disabled][disabled].btn-raised:focus:not(:active),.input-group-btn .btn.disabled.btn-group-raised,.input-group-btn .btn.disabled.btn-group-raised.active,.input-group-btn .btn.disabled.btn-group-raised:active,.input-group-btn .btn.disabled.btn-group-raised:focus:not(:active),.input-group-btn .btn.disabled.btn-raised,.input-group-btn .btn.disabled.btn-raised.active,.input-group-btn .btn.disabled.btn-raised:active,.input-group-btn .btn.disabled.btn-raised:focus:not(:active),.input-group-btn .btn:disabled.btn-group-raised,.input-group-btn .btn:disabled.btn-group-raised.active,.input-group-btn .btn:disabled.btn-group-raised:active,.input-group-btn .btn:disabled.btn-group-raised:focus:not(:active),.input-group-btn .btn:disabled.btn-raised,.input-group-btn .btn:disabled.btn-raised.active,.input-group-btn .btn:disabled.btn-raised:active,.input-group-btn .btn:disabled.btn-raised:focus:not(:active),.input-group-btn .btn[disabled][disabled].btn-group-raised,.input-group-btn .btn[disabled][disabled].btn-group-raised.active,.input-group-btn .btn[disabled][disabled].btn-group-raised:active,.input-group-btn .btn[disabled][disabled].btn-group-raised:focus:not(:active),.input-group-btn .btn[disabled][disabled].btn-raised,.input-group-btn .btn[disabled][disabled].btn-raised.active,.input-group-btn .btn[disabled][disabled].btn-raised:active,.input-group-btn .btn[disabled][disabled].btn-raised:focus:not(:active),fieldset[disabled][disabled] .btn-group-vertical.btn-group-raised,fieldset[disabled][disabled] .btn-group-vertical.btn-group-raised.active,fieldset[disabled][disabled] .btn-group-vertical.btn-group-raised:active,fieldset[disabled][disabled] .btn-group-vertical.btn-group-raised:focus:not(:active),fieldset[disabled][disabled] .btn-group-vertical.btn-raised,fieldset[disabled][disabled] .btn-group-vertical.btn-raised.active,fieldset[disabled][disabled] .btn-group-vertical.btn-raised:active,fieldset[disabled][disabled] .btn-group-vertical.btn-raised:focus:not(:active),fieldset[disabled][disabled] .btn-group.btn-group-raised,fieldset[disabled][disabled] .btn-group.btn-group-raised.active,fieldset[disabled][disabled] .btn-group.btn-group-raised:active,fieldset[disabled][disabled] .btn-group.btn-group-raised:focus:not(:active),fieldset[disabled][disabled] .btn-group.btn-raised,fieldset[disabled][disabled] .btn-group.btn-raised.active,fieldset[disabled][disabled] .btn-group.btn-raised:active,fieldset[disabled][disabled] .btn-group.btn-raised:focus:not(:active),fieldset[disabled][disabled] .btn.btn-group-raised,fieldset[disabled][disabled] .btn.btn-group-raised.active,fieldset[disabled][disabled] .btn.btn-group-raised:active,fieldset[disabled][disabled] .btn.btn-group-raised:focus:not(:active),fieldset[disabled][disabled] .btn.btn-raised,fieldset[disabled][disabled] .btn.btn-raised.active,fieldset[disabled][disabled] .btn.btn-raised:active,fieldset[disabled][disabled] .btn.btn-raised:focus:not(:active),fieldset[disabled][disabled] .input-group-btn .btn.btn-group-raised,fieldset[disabled][disabled] .input-group-btn .btn.btn-group-raised.active,fieldset[disabled][disabled] .input-group-btn .btn.btn-group-raised:active,fieldset[disabled][disabled] .input-group-btn .btn.btn-group-raised:focus:not(:active),fieldset[disabled][disabled] .input-group-btn .btn.btn-raised,fieldset[disabled][disabled] .input-group-btn .btn.btn-raised.active,fieldset[disabled][disabled] .input-group-btn .btn.btn-raised:active,fieldset[disabled][disabled] .input-group-btn .btn.btn-raised:focus:not(:active){-webkit-box-shadow:none;box-shadow:none}.btn-group,.btn-group-vertical{position:relative;margin:10px 1px}.btn-group-vertical.open>.dropdown-toggle.btn,.btn-group-vertical.open>.dropdown-toggle.btn.btn-default,.btn-group.open>.dropdown-toggle.btn,.btn-group.open>.dropdown-toggle.btn.btn-default{background-color:#EEE}.btn-group-vertical.open>.dropdown-toggle.btn.btn-inverse,.btn-group.open>.dropdown-toggle.btn.btn-inverse{background-color:#3f51b5}.btn-group-vertical.open>.dropdown-toggle.btn.btn-primary,.btn-group.open>.dropdown-toggle.btn.btn-primary{background-color:#009688}.btn-group-vertical.open>.dropdown-toggle.btn.btn-success,.btn-group.open>.dropdown-toggle.btn.btn-success{background-color:#4caf50}.btn-group-vertical.open>.dropdown-toggle.btn.btn-info,.btn-group.open>.dropdown-toggle.btn.btn-info{background-color:#03a9f4}.btn-group-vertical.open>.dropdown-toggle.btn.btn-warning,.btn-group.open>.dropdown-toggle.btn.btn-warning{background-color:#ff5722}.btn-group-vertical.open>.dropdown-toggle.btn.btn-danger,.btn-group.open>.dropdown-toggle.btn.btn-danger{background-color:#f44336}.btn-group .dropdown-menu,.btn-group-vertical .dropdown-menu{border-radius:0 0 2px 2px}.btn-group-vertical.btn-group-raised,.btn-group.btn-group-raised{-webkit-box-shadow:0 2px 2px 0 rgba(0,0,0,.14),0 3px 1px -2px rgba(0,0,0,.2),0 1px 5px 0 rgba(0,0,0,.12);box-shadow:0 2px 2px 0 rgba(0,0,0,.14),0 3px 1px -2px rgba(0,0,0,.2),0 1px 5px 0 rgba(0,0,0,.12)}.btn-group .btn,.btn-group .btn+.btn,.btn-group .btn-group,.btn-group .btn:active,.btn-group-vertical .btn,.btn-group-vertical .btn+.btn,.btn-group-vertical .btn-group,.btn-group-vertical .btn:active{margin:0}.checkbox label,label.checkbox-inline{cursor:pointer;padding-left:0;color:rgba(0,0,0,.26)}.form-group.is-focused .checkbox label,.form-group.is-focused label.checkbox-inline{color:rgba(0,0,0,.26)}.form-group.is-focused .checkbox label:focus,.form-group.is-focused .checkbox label:hover,.form-group.is-focused label.checkbox-inline:focus,.form-group.is-focused label.checkbox-inline:hover{color:rgba(0,0,0,.54)}fieldset[disabled] .form-group.is-focused .checkbox label,fieldset[disabled] .form-group.is-focused label.checkbox-inline{color:rgba(0,0,0,.26)}.checkbox input[type=checkbox],label.checkbox-inline input[type=checkbox]{opacity:0;position:absolute;margin:0;z-index:-1;width:0;height:0;overflow:hidden;left:0;pointer-events:none}.checkbox .checkbox-material,label.checkbox-inline .checkbox-material{vertical-align:middle;position:relative;top:3px}.checkbox .checkbox-material:before,label.checkbox-inline .checkbox-material:before{display:block;position:absolute;top:-5px;left:0;content:"";background-color:rgba(0,0,0,.84);height:20px;width:20px;border-radius:100%;z-index:1;opacity:0;margin:0;-webkit-transform:scale3d(2.3,2.3,1);transform:scale3d(2.3,2.3,1)}.checkbox .checkbox-material .check,label.checkbox-inline .checkbox-material .check{position:relative;display:inline-block;width:20px;height:20px;border:2px solid rgba(0,0,0,.54);border-radius:2px;overflow:hidden;z-index:1}.checkbox .checkbox-material .check:before,label.checkbox-inline .checkbox-material .check:before{position:absolute;content:"";-webkit-transform:rotate(45deg);-ms-transform:rotate(45deg);-o-transform:rotate(45deg);transform:rotate(45deg);display:block;margin-top:-4px;margin-left:6px;width:0;height:0;-webkit-box-shadow:0 0 0 0,0 0 0 0,0 0 0 0,0 0 0 0,0 0 0 0,0 0 0 0,0 0 0 0 inset;box-shadow:0 0 0 0,0 0 0 0,0 0 0 0,0 0 0 0,0 0 0 0,0 0 0 0,0 0 0 0 inset}.checkbox input[type=checkbox]:focus+.checkbox-material .check:after,label.checkbox-inline input[type=checkbox]:focus+.checkbox-material .check:after{opacity:.2}.checkbox input[type=checkbox]:focus:checked+.checkbox-material:before,label.checkbox-inline input[type=checkbox]:focus:checked+.checkbox-material:before{-webkit-animation:rippleOn .5s;-o-animation:rippleOn .5s;animation:rippleOn .5s}.checkbox input[type=checkbox]:focus:checked+.checkbox-material .check:before,label.checkbox-inline input[type=checkbox]:focus:checked+.checkbox-material .check:before{-webkit-animation:checkbox-on .3s forwards;-o-animation:checkbox-on .3s forwards;animation:checkbox-on .3s forwards}.checkbox input[type=checkbox]:focus:checked+.checkbox-material .check:after,label.checkbox-inline input[type=checkbox]:focus:checked+.checkbox-material .check:after{-webkit-animation:rippleOn .5s forwards;-o-animation:rippleOn .5s forwards;animation:rippleOn .5s forwards}.checkbox input[type=checkbox]:focus:not(:checked)+.checkbox-material:before,label.checkbox-inline input[type=checkbox]:focus:not(:checked)+.checkbox-material:before{-webkit-animation:rippleOff .5s;-o-animation:rippleOff .5s;animation:rippleOff .5s}.checkbox input[type=checkbox]:focus:not(:checked)+.checkbox-material .check:before,label.checkbox-inline input[type=checkbox]:focus:not(:checked)+.checkbox-material .check:before{-webkit-animation:checkbox-off .3s forwards;-o-animation:checkbox-off .3s forwards;animation:checkbox-off .3s forwards}.checkbox input[type=checkbox]:focus:not(:checked)+.checkbox-material .check:after,label.checkbox-inline input[type=checkbox]:focus:not(:checked)+.checkbox-material .check:after{-webkit-animation:rippleOff .5s forwards;-o-animation:rippleOff .5s forwards;animation:rippleOff .5s forwards}.checkbox input[type=checkbox]:checked+.checkbox-material .check,label.checkbox-inline input[type=checkbox]:checked+.checkbox-material .check{color:#009688;border-color:#009688}.checkbox input[type=checkbox]:checked+.checkbox-material .check:before,label.checkbox-inline input[type=checkbox]:checked+.checkbox-material .check:before{color:#009688;-webkit-box-shadow:0 0 0 10px,10px -10px 0 10px,32px 0 0 20px,0 32px 0 20px,-5px 5px 0 10px,20px -12px 0 11px;box-shadow:0 0 0 10px,10px -10px 0 10px,32px 0 0 20px,0 32px 0 20px,-5px 5px 0 10px,20px -12px 0 11px}.checkbox input[type=checkbox][disabled]+.circle,.checkbox input[type=checkbox][disabled]:not(:checked)~.checkbox-material .check,.checkbox input[type=checkbox][disabled]:not(:checked)~.checkbox-material .check:before,fieldset[disabled] .checkbox,fieldset[disabled] .checkbox input[type=checkbox],fieldset[disabled] label.checkbox-inline,fieldset[disabled] label.checkbox-inline input[type=checkbox],label.checkbox-inline input[type=checkbox][disabled]+.circle,label.checkbox-inline input[type=checkbox][disabled]:not(:checked)~.checkbox-material .check,label.checkbox-inline input[type=checkbox][disabled]:not(:checked)~.checkbox-material .check:before{opacity:.5}.checkbox input[type=checkbox][disabled]+.checkbox-material .check:after,label.checkbox-inline input[type=checkbox][disabled]+.checkbox-material .check:after{background-color:rgba(0,0,0,.87);-webkit-transform:rotate(-45deg);-ms-transform:rotate(-45deg);-o-transform:rotate(-45deg);transform:rotate(-45deg)}@-webkit-keyframes checkbox-on{0%{-webkit-box-shadow:0 0 0 10px,10px -10px 0 10px,32px 0 0 20px,0 32px 0 20px,-5px 5px 0 10px,15px 2px 0 11px;box-shadow:0 0 0 10px,10px -10px 0 10px,32px 0 0 20px,0 32px 0 20px,-5px 5px 0 10px,15px 2px 0 11px}50%{-webkit-box-shadow:0 0 0 10px,10px -10px 0 10px,32px 0 0 20px,0 32px 0 20px,-5px 5px 0 10px,20px 2px 0 11px;box-shadow:0 0 0 10px,10px -10px 0 10px,32px 0 0 20px,0 32px 0 20px,-5px 5px 0 10px,20px 2px 0 11px}100%{-webkit-box-shadow:0 0 0 10px,10px -10px 0 10px,32px 0 0 20px,0 32px 0 20px,-5px 5px 0 10px,20px -12px 0 11px;box-shadow:0 0 0 10px,10px -10px 0 10px,32px 0 0 20px,0 32px 0 20px,-5px 5px 0 10px,20px -12px 0 11px}}@-o-keyframes checkbox-on{0%{box-shadow:0 0 0 10px,10px -10px 0 10px,32px 0 0 20px,0 32px 0 20px,-5px 5px 0 10px,15px 2px 0 11px}50%{box-shadow:0 0 0 10px,10px -10px 0 10px,32px 0 0 20px,0 32px 0 20px,-5px 5px 0 10px,20px 2px 0 11px}100%{box-shadow:0 0 0 10px,10px -10px 0 10px,32px 0 0 20px,0 32px 0 20px,-5px 5px 0 10px,20px -12px 0 11px}}@keyframes checkbox-on{0%{-webkit-box-shadow:0 0 0 10px,10px -10px 0 10px,32px 0 0 20px,0 32px 0 20px,-5px 5px 0 10px,15px 2px 0 11px;box-shadow:0 0 0 10px,10px -10px 0 10px,32px 0 0 20px,0 32px 0 20px,-5px 5px 0 10px,15px 2px 0 11px}50%{-webkit-box-shadow:0 0 0 10px,10px -10px 0 10px,32px 0 0 20px,0 32px 0 20px,-5px 5px 0 10px,20px 2px 0 11px;box-shadow:0 0 0 10px,10px -10px 0 10px,32px 0 0 20px,0 32px 0 20px,-5px 5px 0 10px,20px 2px 0 11px}100%{-webkit-box-shadow:0 0 0 10px,10px -10px 0 10px,32px 0 0 20px,0 32px 0 20px,-5px 5px 0 10px,20px -12px 0 11px;box-shadow:0 0 0 10px,10px -10px 0 10px,32px 0 0 20px,0 32px 0 20px,-5px 5px 0 10px,20px -12px 0 11px}}@-webkit-keyframes checkbox-off{0%{-webkit-box-shadow:0 0 0 10px,10px -10px 0 10px,32px 0 0 20px,0 32px 0 20px,-5px 5px 0 10px,20px -12px 0 11px,0 0 0 0 inset;box-shadow:0 0 0 10px,10px -10px 0 10px,32px 0 0 20px,0 32px 0 20px,-5px 5px 0 10px,20px -12px 0 11px,0 0 0 0 inset}25%{-webkit-box-shadow:0 0 0 10px,10px -10px 0 10px,32px 0 0 20px,0 32px 0 20px,-5px 5px 0 10px,20px -12px 0 11px,0 0 0 0 inset;box-shadow:0 0 0 10px,10px -10px 0 10px,32px 0 0 20px,0 32px 0 20px,-5px 5px 0 10px,20px -12px 0 11px,0 0 0 0 inset}50%{-webkit-transform:rotate(45deg);transform:rotate(45deg);margin-top:-4px;margin-left:6px;width:0;height:0;-webkit-box-shadow:0 0 0 10px,10px -10px 0 10px,32px 0 0 20px,0 32px 0 20px,-5px 5px 0 10px,15px 2px 0 11px,0 0 0 0 inset;box-shadow:0 0 0 10px,10px -10px 0 10px,32px 0 0 20px,0 32px 0 20px,-5px 5px 0 10px,15px 2px 0 11px,0 0 0 0 inset}51%{-webkit-transform:rotate(0);transform:rotate(0);margin-top:-2px;margin-left:-2px;width:20px;height:20px;-webkit-box-shadow:0 0 0 0,0 0 0 0,0 0 0 0,0 0 0 0,0 0 0 0,0 0 0 0,0 0 0 10px inset;box-shadow:0 0 0 0,0 0 0 0,0 0 0 0,0 0 0 0,0 0 0 0,0 0 0 0,0 0 0 10px inset}100%{-webkit-transform:rotate(0);transform:rotate(0);margin-top:-2px;margin-left:-2px;width:20px;height:20px;-webkit-box-shadow:0 0 0 0,0 0 0 0,0 0 0 0,0 0 0 0,0 0 0 0,0 0 0 0,0 0 0 0 inset;box-shadow:0 0 0 0,0 0 0 0,0 0 0 0,0 0 0 0,0 0 0 0,0 0 0 0,0 0 0 0 inset}}@-o-keyframes checkbox-off{0%{box-shadow:0 0 0 10px,10px -10px 0 10px,32px 0 0 20px,0 32px 0 20px,-5px 5px 0 10px,20px -12px 0 11px,0 0 0 0 inset}25%{box-shadow:0 0 0 10px,10px -10px 0 10px,32px 0 0 20px,0 32px 0 20px,-5px 5px 0 10px,20px -12px 0 11px,0 0 0 0 inset}50%{-o-transform:rotate(45deg);transform:rotate(45deg);margin-top:-4px;margin-left:6px;width:0;height:0;box-shadow:0 0 0 10px,10px -10px 0 10px,32px 0 0 20px,0 32px 0 20px,-5px 5px 0 10px,15px 2px 0 11px,0 0 0 0 inset}51%{-o-transform:rotate(0);transform:rotate(0);margin-top:-2px;margin-left:-2px;width:20px;height:20px;box-shadow:0 0 0 0,0 0 0 0,0 0 0 0,0 0 0 0,0 0 0 0,0 0 0 0,0 0 0 10px inset}100%{-o-transform:rotate(0);transform:rotate(0);margin-top:-2px;margin-left:-2px;width:20px;height:20px;box-shadow:0 0 0 0,0 0 0 0,0 0 0 0,0 0 0 0,0 0 0 0,0 0 0 0,0 0 0 0 inset}}@keyframes checkbox-off{0%{-webkit-box-shadow:0 0 0 10px,10px -10px 0 10px,32px 0 0 20px,0 32px 0 20px,-5px 5px 0 10px,20px -12px 0 11px,0 0 0 0 inset;box-shadow:0 0 0 10px,10px -10px 0 10px,32px 0 0 20px,0 32px 0 20px,-5px 5px 0 10px,20px -12px 0 11px,0 0 0 0 inset}25%{-webkit-box-shadow:0 0 0 10px,10px -10px 0 10px,32px 0 0 20px,0 32px 0 20px,-5px 5px 0 10px,20px -12px 0 11px,0 0 0 0 inset;box-shadow:0 0 0 10px,10px -10px 0 10px,32px 0 0 20px,0 32px 0 20px,-5px 5px 0 10px,20px -12px 0 11px,0 0 0 0 inset}50%{-webkit-transform:rotate(45deg);-o-transform:rotate(45deg);transform:rotate(45deg);margin-top:-4px;margin-left:6px;width:0;height:0;-webkit-box-shadow:0 0 0 10px,10px -10px 0 10px,32px 0 0 20px,0 32px 0 20px,-5px 5px 0 10px,15px 2px 0 11px,0 0 0 0 inset;box-shadow:0 0 0 10px,10px -10px 0 10px,32px 0 0 20px,0 32px 0 20px,-5px 5px 0 10px,15px 2px 0 11px,0 0 0 0 inset}51%{-webkit-transform:rotate(0);-o-transform:rotate(0);transform:rotate(0);margin-top:-2px;margin-left:-2px;width:20px;height:20px;-webkit-box-shadow:0 0 0 0,0 0 0 0,0 0 0 0,0 0 0 0,0 0 0 0,0 0 0 0,0 0 0 10px inset;box-shadow:0 0 0 0,0 0 0 0,0 0 0 0,0 0 0 0,0 0 0 0,0 0 0 0,0 0 0 10px inset}100%{-webkit-transform:rotate(0);-o-transform:rotate(0);transform:rotate(0);margin-top:-2px;margin-left:-2px;width:20px;height:20px;-webkit-box-shadow:0 0 0 0,0 0 0 0,0 0 0 0,0 0 0 0,0 0 0 0,0 0 0 0,0 0 0 0 inset;box-shadow:0 0 0 0,0 0 0 0,0 0 0 0,0 0 0 0,0 0 0 0,0 0 0 0,0 0 0 0 inset}}@-webkit-keyframes rippleOn{0%{opacity:0}50%{opacity:.2}100%{opacity:0}}@-o-keyframes rippleOn{0%{opacity:0}50%{opacity:.2}100%{opacity:0}}@keyframes rippleOn{0%{opacity:0}50%{opacity:.2}100%{opacity:0}}@-webkit-keyframes rippleOff{0%{opacity:0}50%{opacity:.2}100%{opacity:0}}@-o-keyframes rippleOff{0%{opacity:0}50%{opacity:.2}100%{opacity:0}}@keyframes rippleOff{0%{opacity:0}50%{opacity:.2}100%{opacity:0}}.togglebutton{vertical-align:middle}.togglebutton,.togglebutton .toggle,.togglebutton input,.togglebutton label{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.togglebutton label{cursor:pointer;color:rgba(0,0,0,.26)}.form-group.is-focused .togglebutton label{color:rgba(0,0,0,.26)}.form-group.is-focused .togglebutton label:focus,.form-group.is-focused .togglebutton label:hover{color:rgba(0,0,0,.54)}fieldset[disabled] .form-group.is-focused .togglebutton label{color:rgba(0,0,0,.26)}.togglebutton label input[type=checkbox]{opacity:0;width:0;height:0}.togglebutton label .toggle{text-align:left}.togglebutton label .toggle,.togglebutton label input[type=checkbox][disabled]+.toggle{content:"";display:inline-block;width:30px;height:15px;background-color:rgba(80,80,80,.7);border-radius:15px;margin-right:15px;-webkit-transition:background .3s ease;-o-transition:background .3s ease;transition:background .3s ease;vertical-align:middle}.togglebutton label .toggle:after{content:"";display:inline-block;width:20px;height:20px;background-color:#F1F1F1;border-radius:20px;position:relative;-webkit-box-shadow:0 1px 3px 1px rgba(0,0,0,.4);box-shadow:0 1px 3px 1px rgba(0,0,0,.4);left:-5px;top:-2px;-webkit-transition:left .3s ease,background .3s ease,-webkit-box-shadow .1s ease;-o-transition:left .3s ease,background .3s ease,box-shadow .1s ease;transition:left .3s ease,background .3s ease,box-shadow .1s ease}.togglebutton label input[type=checkbox][disabled]+.toggle:after,.togglebutton label input[type=checkbox][disabled]:checked+.toggle:after{background-color:#BDBDBD}.togglebutton label input[type=checkbox]+.toggle:active:after,.togglebutton label input[type=checkbox][disabled]+.toggle:active:after{-webkit-box-shadow:0 1px 3px 1px rgba(0,0,0,.4),0 0 0 15px rgba(0,0,0,.1);box-shadow:0 1px 3px 1px rgba(0,0,0,.4),0 0 0 15px rgba(0,0,0,.1)}.togglebutton label input[type=checkbox]:checked+.toggle:after{left:15px}.togglebutton label input[type=checkbox]:checked+.toggle{background-color:hsla(231,48%,48%,.5)}.togglebutton label input[type=checkbox]:checked+.toggle:after{background-color:#3f51b5}.togglebutton label input[type=checkbox]:checked+.toggle:active:after{-webkit-box-shadow:0 1px 3px 1px rgba(0,0,0,.4),0 0 0 15px rgba(0,150,136,.1);box-shadow:0 1px 3px 1px rgba(0,0,0,.4),0 0 0 15px rgba(0,150,136,.1)}.radio label,label.radio-inline{cursor:pointer;padding-left:45px;position:relative;color:rgba(0,0,0,.26)}.form-group.is-focused .radio label,.form-group.is-focused label.radio-inline{color:rgba(0,0,0,.26)}.form-group.is-focused .radio label:focus,.form-group.is-focused .radio label:hover,.form-group.is-focused label.radio-inline:focus,.form-group.is-focused label.radio-inline:hover{color:rgba(0,0,0,.54)}fieldset[disabled] .form-group.is-focused .radio label,fieldset[disabled] .form-group.is-focused label.radio-inline{color:rgba(0,0,0,.26)}.radio span,label.radio-inline span{display:block;position:absolute;left:10px;top:2px;-webkit-transition-duration:.2s;-o-transition-duration:.2s;transition-duration:.2s}.radio .circle,label.radio-inline .circle{border:2px solid rgba(0,0,0,.54);height:15px;width:15px;border-radius:100%}.radio .check,label.radio-inline .check{height:15px;width:15px;border-radius:100%;background-color:#009688;-webkit-transform:scale3d(0,0,0);transform:scale3d(0,0,0)}.radio .check:after,label.radio-inline .check:after{display:block;position:absolute;content:"";background-color:rgba(0,0,0,.87);left:-18px;top:-18px;height:50px;width:50px;border-radius:100%;z-index:1;opacity:0;margin:0;-webkit-transform:scale3d(1.5,1.5,1);transform:scale3d(1.5,1.5,1)}.radio input[type=radio]:focus:not(:checked)~.check:after,label.radio-inline input[type=radio]:focus:not(:checked)~.check:after{-webkit-animation:rippleOff .5s;-o-animation:rippleOff .5s;animation:rippleOff .5s}.radio input[type=radio]:focus:checked~.check:after,label.radio-inline input[type=radio]:focus:checked~.check:after{-webkit-animation:rippleOn .5s;-o-animation:rippleOn .5s;animation:rippleOn .5s}.radio input[type=radio],label.radio-inline input[type=radio]{opacity:0;height:0;width:0;overflow:hidden}.radio input[type=radio]:checked~.check,.radio input[type=radio]:checked~.circle,label.radio-inline input[type=radio]:checked~.check,label.radio-inline input[type=radio]:checked~.circle{opacity:1}.radio input[type=radio]:checked~.check,label.radio-inline input[type=radio]:checked~.check{background-color:#009688}.radio input[type=radio]:checked~.circle,label.radio-inline input[type=radio]:checked~.circle{border-color:#009688}.radio input[type=radio]:checked~.check,label.radio-inline input[type=radio]:checked~.check{-webkit-transform:scale3d(.55,.55,1);transform:scale3d(.55,.55,1)}.radio input[type=radio][disabled]~.check,.radio input[type=radio][disabled]~.circle,label.radio-inline input[type=radio][disabled]~.check,label.radio-inline input[type=radio][disabled]~.circle{opacity:.26}.radio input[type=radio][disabled]~.check,label.radio-inline input[type=radio][disabled]~.check{background-color:#000}.radio input[type=radio][disabled]~.circle,label.radio-inline input[type=radio][disabled]~.circle{border-color:#000}.theme-dark .radio input[type=radio][disabled]~.check,.theme-dark .radio input[type=radio][disabled]~.circle,.theme-dark label.radio-inline input[type=radio][disabled]~.check,.theme-dark label.radio-inline input[type=radio][disabled]~.circle{opacity:.3}.theme-dark .radio input[type=radio][disabled]~.check,.theme-dark label.radio-inline input[type=radio][disabled]~.check{background-color:#fff}.theme-dark .radio input[type=radio][disabled]~.circle,.theme-dark label.radio-inline input[type=radio][disabled]~.circle{border-color:#fff}@keyframes rippleOn{0%{opacity:0}50%{opacity:.2}100%{opacity:0}}@keyframes rippleOff{0%{opacity:0}50%{opacity:.2}100%{opacity:0}}legend{margin-bottom:22px;font-size:24px}output{padding-top:8px;font-size:16px;line-height:1.42857143}.form-control{height:38px;padding:7px 0;font-size:16px;line-height:1.42857143}@media screen and (-webkit-min-device-pixel-ratio:0){input[type=date].form-control,input[type=time].form-control,input[type=datetime-local].form-control,input[type=month].form-control{line-height:38px}.input-group-sm input[type=date],.input-group-sm input[type=time],.input-group-sm input[type=datetime-local],.input-group-sm input[type=month],input[type=date].input-sm,input[type=time].input-sm,input[type=datetime-local].input-sm,input[type=month].input-sm{line-height:24px}.input-group-lg input[type=date],.input-group-lg input[type=time],.input-group-lg input[type=datetime-local],.input-group-lg input[type=month],input[type=date].input-lg,input[type=time].input-lg,input[type=datetime-local].input-lg,input[type=month].input-lg{line-height:44px}}.checkbox label,.radio label{min-height:22px}.form-control-static{padding-top:8px;padding-bottom:8px;min-height:38px}.input-sm .input-sm{height:24px;padding:3px 0;font-size:11px;line-height:1.5;border-radius:0}.input-sm select.input-sm{height:24px;line-height:24px}.input-sm select[multiple].input-sm,.input-sm textarea.input-sm{height:auto}.form-group-sm .form-control{height:24px;padding:3px 0;font-size:11px;line-height:1.5}.form-group-sm select.form-control{height:24px;line-height:24px}.form-group-sm select[multiple].form-control,.form-group-sm textarea.form-control{height:auto}.form-group-sm .form-control-static{height:24px;min-height:33px;padding:4px 0;font-size:11px;line-height:1.5}.input-lg .input-lg{height:44px;padding:9px 0;font-size:18px;line-height:1.3333333;border-radius:0}.input-lg select.input-lg{height:44px;line-height:44px}.input-lg select[multiple].input-lg,.input-lg textarea.input-lg{height:auto}.form-group-lg .form-control{height:44px;padding:9px 0;font-size:18px;line-height:1.3333333}.form-group-lg select.form-control{height:44px;line-height:44px}.form-group-lg select[multiple].form-control,.form-group-lg textarea.form-control{height:auto}.form-group-lg .form-control-static{height:44px;min-height:40px;padding:10px 0;font-size:18px;line-height:1.3333333}.form-horizontal .checkbox,.form-horizontal .checkbox-inline,.form-horizontal .radio,.form-horizontal .radio-inline{padding-top:8px}.form-horizontal .checkbox,.form-horizontal .radio{min-height:30px}@media (min-width:768px){.form-horizontal .control-label{padding-top:8px}}@media (min-width:768px){.form-horizontal .form-group-lg .control-label{padding-top:13px;font-size:18px}}@media (min-width:768px){.form-horizontal .form-group-sm .control-label{padding-top:4px;font-size:11px}}.label{border-radius:1px;padding:.3em .6em}.label,.label.label-default{background-color:#9e9e9e}.label.label-inverse{background-color:#3f51b5}.label.label-primary{background-color:#009688}.label.label-success{background-color:#4caf50}.label.label-info{background-color:#03a9f4}.label.label-warning{background-color:#ff5722}.label.label-danger{background-color:#f44336}.form-control,.form-group .form-control{border:0;background-image:-webkit-gradient(linear,left top,left bottom,from(#009688),to(#009688)),-webkit-gradient(linear,left top,left bottom,from(#D2D2D2),to(#D2D2D2));background-image:-webkit-linear-gradient(#009688,#009688),-webkit-linear-gradient(#D2D2D2,#D2D2D2);background-image:-o-linear-gradient(#009688,#009688),-o-linear-gradient(#D2D2D2,#D2D2D2);background-image:linear-gradient(#009688,#009688),linear-gradient(#D2D2D2,#D2D2D2);-webkit-background-size:0 2px,100% 1px;background-size:0 2px,100% 1px;background-repeat:no-repeat;background-position:center bottom,center -webkit-calc(100% - 1px);background-position:center bottom,center calc(100% - 1px);background-color:rgba(0,0,0,0);-webkit-transition:background 0s ease-out;-o-transition:background 0s ease-out;transition:background 0s ease-out;float:none;-webkit-box-shadow:none;box-shadow:none;border-radius:0}.form-control::-moz-placeholder,.form-group .form-control::-moz-placeholder{color:#BDBDBD;font-weight:400}.form-control:-ms-input-placeholder,.form-group .form-control:-ms-input-placeholder{color:#BDBDBD;font-weight:400}.form-control::-webkit-input-placeholder,.form-group .form-control::-webkit-input-placeholder{color:#BDBDBD;font-weight:400}.form-control[disabled],.form-control[readonly],.form-group .form-control[disabled],.form-group .form-control[readonly],fieldset[disabled] .form-control,fieldset[disabled] .form-group .form-control{background-color:rgba(0,0,0,0)}.form-control[disabled],.form-group .form-control[disabled],fieldset[disabled] .form-control,fieldset[disabled] .form-group .form-control{background-image:none;border-bottom:1px dotted #D2D2D2}.form-group{position:relative}.form-group.label-floating label.control-label,.form-group.label-placeholder label.control-label,.form-group.label-static label.control-label{position:absolute;pointer-events:none;-webkit-transition:.3s ease all;-o-transition:.3s ease all;transition:.3s ease all}.form-group.label-floating label.control-label{will-change:left,top,contents}.form-group.label-placeholder:not(.is-empty) label.control-label{display:none}.form-group .help-block{position:absolute;display:none}.form-group.is-focused .form-control{outline:0;background-image:-webkit-gradient(linear,left top,left bottom,from(#009688),to(#009688)),-webkit-gradient(linear,left top,left bottom,from(#D2D2D2),to(#D2D2D2));background-image:-webkit-linear-gradient(#009688,#009688),-webkit-linear-gradient(#D2D2D2,#D2D2D2);background-image:-o-linear-gradient(#009688,#009688),-o-linear-gradient(#D2D2D2,#D2D2D2);background-image:linear-gradient(#3f51b5,#3f51b5),linear-gradient(#D2D2D2,#D2D2D2);-webkit-background-size:100% 2px,100% 1px;background-size:100% 2px,100% 1px;-webkit-box-shadow:none;box-shadow:none;-webkit-transition-duration:.3s;-o-transition-duration:.3s;transition-duration:.3s}.form-group.is-focused .form-control .material-input:after{background-color:#009688}.form-group.is-focused label,.form-group.is-focused label.control-label{color:#009688}.form-group.is-focused.label-placeholder label,.form-group.is-focused.label-placeholder label.control-label{color:#BDBDBD}.form-group.is-focused .help-block{display:block}.form-group.has-warning .form-control{-webkit-box-shadow:none;box-shadow:none}.form-group.has-warning.is-focused .form-control{background-image:-webkit-gradient(linear,left top,left bottom,from(#ff5722),to(#ff5722)),-webkit-gradient(linear,left top,left bottom,from(#D2D2D2),to(#D2D2D2));background-image:-webkit-linear-gradient(#ff5722,#ff5722),-webkit-linear-gradient(#D2D2D2,#D2D2D2);background-image:-o-linear-gradient(#ff5722,#ff5722),-o-linear-gradient(#D2D2D2,#D2D2D2);background-image:linear-gradient(#ff5722,#ff5722),linear-gradient(#D2D2D2,#D2D2D2)}.form-group.has-warning .help-block,.form-group.has-warning label.control-label{color:#ff5722}.form-group.has-error .form-control{-webkit-box-shadow:none;box-shadow:none}.form-group.has-error.is-focused .form-control{background-image:-webkit-gradient(linear,left top,left bottom,from(#f44336),to(#f44336)),-webkit-gradient(linear,left top,left bottom,from(#D2D2D2),to(#D2D2D2));background-image:-webkit-linear-gradient(#f44336,#f44336),-webkit-linear-gradient(#D2D2D2,#D2D2D2);background-image:-o-linear-gradient(#f44336,#f44336),-o-linear-gradient(#D2D2D2,#D2D2D2);background-image:linear-gradient(#f44336,#f44336),linear-gradient(#D2D2D2,#D2D2D2)}.form-group.has-error .help-block,.form-group.has-error label.control-label{color:#f44336}.form-group.has-success .form-control{-webkit-box-shadow:none;box-shadow:none}.form-group.has-success.is-focused .form-control{background-image:-webkit-gradient(linear,left top,left bottom,from(#4caf50),to(#4caf50)),-webkit-gradient(linear,left top,left bottom,from(#D2D2D2),to(#D2D2D2));background-image:-webkit-linear-gradient(#4caf50,#4caf50),-webkit-linear-gradient(#D2D2D2,#D2D2D2);background-image:-o-linear-gradient(#4caf50,#4caf50),-o-linear-gradient(#D2D2D2,#D2D2D2);background-image:linear-gradient(#4caf50,#4caf50),linear-gradient(#D2D2D2,#D2D2D2)}.form-group.has-success .help-block,.form-group.has-success label.control-label{color:#4caf50}.form-group.has-info .form-control{-webkit-box-shadow:none;box-shadow:none}.form-group.has-info.is-focused .form-control{background-image:-webkit-gradient(linear,left top,left bottom,from(#03a9f4),to(#03a9f4)),-webkit-gradient(linear,left top,left bottom,from(#D2D2D2),to(#D2D2D2));background-image:-webkit-linear-gradient(#03a9f4,#03a9f4),-webkit-linear-gradient(#D2D2D2,#D2D2D2);background-image:-o-linear-gradient(#03a9f4,#03a9f4),-o-linear-gradient(#D2D2D2,#D2D2D2);background-image:linear-gradient(#03a9f4,#03a9f4),linear-gradient(#D2D2D2,#D2D2D2)}.form-group.has-info .help-block,.form-group.has-info label.control-label{color:#03a9f4}.form-group textarea{resize:none}.form-group textarea~.form-control-highlight{margin-top:-11px}.form-group select{-webkit-appearance:none;-moz-appearance:none;appearance:none}.form-group select~.material-input:after{display:none}.form-control{margin-bottom:7px}.form-control::-moz-placeholder{font-size:16px;line-height:1.42857143;color:#BDBDBD;font-weight:400}.form-control:-ms-input-placeholder{font-size:16px;line-height:1.42857143;color:#BDBDBD;font-weight:400}.form-control::-webkit-input-placeholder{font-size:16px;line-height:1.42857143;color:#BDBDBD;font-weight:400}.checkbox label,.radio label,label{font-size:16px;line-height:1.42857143;color:#BDBDBD;font-weight:400}label.control-label{font-size:12px;line-height:1.07142857;font-weight:400;margin:16px 0 0 0}.help-block{margin-top:0;font-size:12px}.form-group{padding-bottom:7px;margin:28px 0 0 0}.form-group .form-control{margin-bottom:7px}.form-group .form-control::-moz-placeholder{font-size:16px;line-height:1.42857143;color:#BDBDBD;font-weight:400}.form-group .form-control:-ms-input-placeholder{font-size:16px;line-height:1.42857143;color:#BDBDBD;font-weight:400}.form-group .form-control::-webkit-input-placeholder{font-size:16px;line-height:1.42857143;color:#BDBDBD;font-weight:400}.form-group .checkbox label,.form-group .radio label,.form-group label{font-size:16px;line-height:1.42857143;color:#BDBDBD;font-weight:400}.form-group label.control-label{font-size:12px;line-height:1.07142857;font-weight:400;margin:16px 0 0 0}.form-group .help-block{margin-top:0;font-size:12px}.form-group.label-floating label.control-label,.form-group.label-placeholder label.control-label{top:-7px;font-size:16px;line-height:1.42857143}.form-group.label-floating.is-focused label.control-label,.form-group.label-floating:not(.is-empty) label.control-label,.form-group.label-static label.control-label{top:-30px;left:0;font-size:12px;line-height:1.07142857}.form-group.label-floating input.form-control:-webkit-autofill~label.control-label label.control-label{top:-30px;left:0;font-size:12px;line-height:1.07142857}.form-group.form-group-sm{padding-bottom:3px;margin:21px 0 0 0}.form-group.form-group-sm .form-control{margin-bottom:3px}.form-group.form-group-sm .form-control::-moz-placeholder{font-size:11px;line-height:1.5;color:#BDBDBD;font-weight:400}.form-group.form-group-sm .form-control:-ms-input-placeholder{font-size:11px;line-height:1.5;color:#BDBDBD;font-weight:400}.form-group.form-group-sm .form-control::-webkit-input-placeholder{font-size:11px;line-height:1.5;color:#BDBDBD;font-weight:400}.form-group.form-group-sm .checkbox label,.form-group.form-group-sm .radio label,.form-group.form-group-sm label{font-size:11px;line-height:1.5;color:#BDBDBD;font-weight:400}.form-group.form-group-sm label.control-label{font-size:9px;line-height:1.125;font-weight:400;margin:16px 0 0 0}.form-group.form-group-sm .help-block{margin-top:0;font-size:9px}.form-group.form-group-sm.label-floating label.control-label,.form-group.form-group-sm.label-placeholder label.control-label{top:-11px;font-size:11px;line-height:1.5}.form-group.form-group-sm.label-floating.is-focused label.control-label,.form-group.form-group-sm.label-floating:not(.is-empty) label.control-label,.form-group.form-group-sm.label-static label.control-label{top:-25px;left:0;font-size:9px;line-height:1.125}.form-group.form-group-sm.label-floating input.form-control:-webkit-autofill~label.control-label label.control-label{top:-25px;left:0;font-size:9px;line-height:1.125}.form-group.form-group-lg{padding-bottom:9px;margin:30px 0 0 0}.form-group.form-group-lg .form-control{margin-bottom:9px}.form-group.form-group-lg .form-control::-moz-placeholder{font-size:18px;line-height:1.3333333;color:#BDBDBD;font-weight:400}.form-group.form-group-lg .form-control:-ms-input-placeholder{font-size:18px;line-height:1.3333333;color:#BDBDBD;font-weight:400}.form-group.form-group-lg .form-control::-webkit-input-placeholder{font-size:18px;line-height:1.3333333;color:#BDBDBD;font-weight:400}.form-group.form-group-lg .checkbox label,.form-group.form-group-lg .radio label,.form-group.form-group-lg label{font-size:18px;line-height:1.3333333;color:#BDBDBD;font-weight:400}.form-group.form-group-lg label.control-label{font-size:14px;line-height:.99999998;font-weight:400;margin:16px 0 0 0}.form-group.form-group-lg .help-block{margin-top:0;font-size:14px}.form-group.form-group-lg.label-floating label.control-label,.form-group.form-group-lg.label-placeholder label.control-label{top:-5px;font-size:18px;line-height:1.3333333}.form-group.form-group-lg.label-floating.is-focused label.control-label,.form-group.form-group-lg.label-floating:not(.is-empty) label.control-label,.form-group.form-group-lg.label-static label.control-label{top:-32px;left:0;font-size:14px;line-height:.99999998}.form-group.form-group-lg.label-floating input.form-control:-webkit-autofill~label.control-label label.control-label{top:-32px;left:0;font-size:14px;line-height:.99999998}select.form-control{border:0;-webkit-box-shadow:none;box-shadow:none;border-radius:0}.form-group.is-focused select.form-control{-webkit-box-shadow:none;box-shadow:none;border-color:#D2D2D2}.form-group.is-focused select.form-control[multiple],select.form-control[multiple]{height:85px}.input-group-btn .btn{margin:0 0 7px 0}.form-group.form-group-sm .input-group-btn .btn{margin:0 0 3px 0}.form-group.form-group-lg .input-group-btn .btn{margin:0 0 9px 0}.input-group .input-group-btn{padding:0 12px}.input-group .input-group-addon{border:0;background:0 0}.form-group input[type=file]{opacity:0;position:absolute;top:0;right:0;bottom:0;left:0;width:100%;height:100%;z-index:100}legend{border-bottom:0}.list-group{border-radius:0}.list-group .list-group-item{background-color:transparent;overflow:hidden;border:0;border-radius:0}.list-group .list-group-item.baseline{border-bottom:1px solid #cecece}.list-group .list-group-item.baseline:last-child{border-bottom:none}.list-group .list-group-item .row-action-primary,.list-group .list-group-item .row-picture{display:inline-block;padding-right:16px}.list-group .list-group-item .row-action-primary i,.list-group .list-group-item .row-action-primary img,.list-group .list-group-item .row-action-primary label,.list-group .list-group-item .row-picture i,.list-group .list-group-item .row-picture img,.list-group .list-group-item .row-picture label{display:block;width:56px;height:56px}.list-group .list-group-item .row-action-primary img,.list-group .list-group-item .row-picture img{background:rgba(0,0,0,.1);padding:1px}.list-group .list-group-item .row-action-primary img.circle,.list-group .list-group-item .row-picture img.circle{border-radius:100%}.list-group .list-group-item .row-action-primary i,.list-group .list-group-item .row-picture i{background:rgba(0,0,0,.25);border-radius:100%;text-align:center;line-height:56px;font-size:20px;color:#fff}.list-group .list-group-item .row-action-primary label,.list-group .list-group-item .row-picture label{margin-left:7px;margin-right:-7px;margin-top:5px;margin-bottom:-5px}.list-group .list-group-item .row-action-primary label .checkbox-material,.list-group .list-group-item .row-picture label .checkbox-material{left:-10px}.list-group .list-group-item .row-content{display:inline-block;width:-webkit-calc(100% - 92px);width:calc(100% - 92px);min-height:66px}.list-group .list-group-item .row-content .action-secondary{position:absolute;right:16px;top:16px}.list-group .list-group-item .row-content .action-secondary i{font-size:20px;color:rgba(0,0,0,.25);cursor:pointer}.list-group .list-group-item .row-content .action-secondary~*{max-width:-webkit-calc(100% - 30px);max-width:calc(100% - 30px)}.list-group .list-group-item .row-content .least-content{position:absolute;right:16px;top:0;color:rgba(0,0,0,.54);font-size:14px}.list-group .list-group-item .list-group-item-heading{color:rgba(0,0,0,.77);font-size:20px;line-height:29px}.list-group .list-group-item.active:focus,.list-group .list-group-item.active:hover{background:rgba(0,0,0,.15);outline:10px solid rgba(0,0,0,.15)}.list-group .list-group-item.active .list-group-item-heading,.list-group .list-group-item.active .list-group-item-text{color:rgba(0,0,0,.87)}.list-group .list-group-separator{clear:both;overflow:hidden;margin-top:10px;margin-bottom:10px}.list-group .list-group-separator:before{content:"";width:-webkit-calc(100% - 90px);width:calc(100% - 90px);border-bottom:1px solid rgba(0,0,0,.1);float:right}.navbar{background-color:#009688;border:0;border-radius:0}.navbar .navbar-brand{position:relative;height:60px;line-height:30px;color:inherit}.navbar .navbar-brand:focus,.navbar .navbar-brand:hover{color:inherit;background-color:transparent}.navbar .navbar-text{color:inherit;margin-top:20px;margin-bottom:20px}.navbar .navbar-nav>li>a{color:inherit;padding-top:20px;padding-bottom:20px}.navbar .navbar-nav>li>a:focus,.navbar .navbar-nav>li>a:hover{color:inherit;background-color:transparent}.navbar .navbar-nav>.active>a,.navbar .navbar-nav>.active>a:focus,.navbar .navbar-nav>.active>a:hover{color:inherit;background-color:rgba(255,255,255,.1)}.navbar .navbar-nav>.disabled>a,.navbar .navbar-nav>.disabled>a:focus,.navbar .navbar-nav>.disabled>a:hover{color:inherit;background-color:transparent;opacity:.9}.navbar .navbar-toggle{border:0}.navbar .navbar-toggle:focus,.navbar .navbar-toggle:hover{background-color:transparent}.navbar .navbar-toggle .icon-bar{background-color:inherit;border:1px solid}.navbar .navbar-default .navbar-toggle,.navbar .navbar-inverse .navbar-toggle{border-color:transparent}.navbar .navbar-collapse,.navbar .navbar-form{border-color:rgba(0,0,0,.1)}.navbar .navbar-nav>.open>a,.navbar .navbar-nav>.open>a:focus,.navbar .navbar-nav>.open>a:hover{background-color:transparent;color:inherit}@media (max-width:767px){.navbar .navbar-nav .navbar-text{color:inherit;margin-top:15px;margin-bottom:15px}.navbar .navbar-nav .open .dropdown-menu>.dropdown-header{border:0;color:inherit}.navbar .navbar-nav .open .dropdown-menu .divider{border-bottom:1px solid;opacity:.08}.navbar .navbar-nav .open .dropdown-menu>li>a{color:inherit}.navbar .navbar-nav .open .dropdown-menu>li>a:focus,.navbar .navbar-nav .open .dropdown-menu>li>a:hover{color:inherit;background-color:transparent}.navbar .navbar-nav .open .dropdown-menu>.active>a,.navbar .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar .navbar-nav .open .dropdown-menu>.active>a:hover{color:inherit;background-color:transparent}.navbar .navbar-nav .open .dropdown-menu>.disabled>a,.navbar .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:inherit;background-color:transparent}}.navbar .navbar-link{color:inherit}.navbar .navbar-link:hover{color:inherit}.navbar .btn-link{color:inherit}.navbar .btn-link:focus,.navbar .btn-link:hover{color:inherit}.navbar .btn-link[disabled]:focus,.navbar .btn-link[disabled]:hover,fieldset[disabled] .navbar .btn-link:focus,fieldset[disabled] .navbar .btn-link:hover{color:inherit}.navbar .navbar-form{margin-top:16px}.navbar .navbar-form .form-group{margin:0;padding:0}.navbar .navbar-form .form-group .material-input:before,.navbar .navbar-form .form-group.is-focused .material-input:after{background-color:inherit}.navbar .navbar-form .form-control,.navbar .navbar-form .form-group .form-control{border-color:inherit;color:inherit;padding:0;margin:0;height:28px;font-size:14px;line-height:1.42857143}.navbar,.navbar.navbar-default{background-color:#009688;color:rgba(255,255,255,.84)}.navbar .navbar-form .form-group input.form-control::-moz-placeholder,.navbar .navbar-form input.form-control::-moz-placeholder,.navbar.navbar-default .navbar-form .form-group input.form-control::-moz-placeholder,.navbar.navbar-default .navbar-form input.form-control::-moz-placeholder{color:rgba(255,255,255,.84)}.navbar .navbar-form .form-group input.form-control:-ms-input-placeholder,.navbar .navbar-form input.form-control:-ms-input-placeholder,.navbar.navbar-default .navbar-form .form-group input.form-control:-ms-input-placeholder,.navbar.navbar-default .navbar-form input.form-control:-ms-input-placeholder{color:rgba(255,255,255,.84)}.navbar .navbar-form .form-group input.form-control::-webkit-input-placeholder,.navbar .navbar-form input.form-control::-webkit-input-placeholder,.navbar.navbar-default .navbar-form .form-group input.form-control::-webkit-input-placeholder,.navbar.navbar-default .navbar-form input.form-control::-webkit-input-placeholder{color:rgba(255,255,255,.84)}.navbar .dropdown-menu,.navbar.navbar-default .dropdown-menu{border-radius:2px}.navbar .dropdown-menu li>a,.navbar.navbar-default .dropdown-menu li>a{font-size:16px;padding:13px 16px}.navbar .dropdown-menu li>a:focus,.navbar .dropdown-menu li>a:hover,.navbar.navbar-default .dropdown-menu li>a:focus,.navbar.navbar-default .dropdown-menu li>a:hover{color:#5B6BC2;background-color:#eee}.navbar .dropdown-menu .active>a,.navbar.navbar-default .dropdown-menu .active>a{background-color:#5B6BC2;color:rgba(255,255,255,.84)}.navbar .dropdown-menu .active>a:focus,.navbar .dropdown-menu .active>a:hover,.navbar.navbar-default .dropdown-menu .active>a:focus,.navbar.navbar-default .dropdown-menu .active>a:hover{color:rgba(255,255,255,.84)}.navbar.navbar-inverse{background-color:#3f51b5;color:#fff}.navbar.navbar-inverse .navbar-form .form-group input.form-control::-moz-placeholder,.navbar.navbar-inverse .navbar-form input.form-control::-moz-placeholder{color:#fff}.navbar.navbar-inverse .navbar-form .form-group input.form-control:-ms-input-placeholder,.navbar.navbar-inverse .navbar-form input.form-control:-ms-input-placeholder{color:#fff}.navbar.navbar-inverse .navbar-form .form-group input.form-control::-webkit-input-placeholder,.navbar.navbar-inverse .navbar-form input.form-control::-webkit-input-placeholder{color:#fff}.navbar.navbar-inverse .dropdown-menu{border-radius:2px}.navbar.navbar-inverse .dropdown-menu li>a{font-size:16px;padding:13px 16px}.navbar.navbar-inverse .dropdown-menu li>a:focus,.navbar.navbar-inverse .dropdown-menu li>a:hover{color:#3f51b5;background-color:#eee}.navbar.navbar-inverse .dropdown-menu .active>a{background-color:#3f51b5;color:#fff}.navbar.navbar-inverse .dropdown-menu .active>a:focus,.navbar.navbar-inverse .dropdown-menu .active>a:hover{color:#fff}.navbar.navbar-primary{background-color:#009688;color:rgba(255,255,255,.84)}.navbar.navbar-primary .navbar-form .form-group input.form-control::-moz-placeholder,.navbar.navbar-primary .navbar-form input.form-control::-moz-placeholder{color:rgba(255,255,255,.84)}.navbar.navbar-primary .navbar-form .form-group input.form-control:-ms-input-placeholder,.navbar.navbar-primary .navbar-form input.form-control:-ms-input-placeholder{color:rgba(255,255,255,.84)}.navbar.navbar-primary .navbar-form .form-group input.form-control::-webkit-input-placeholder,.navbar.navbar-primary .navbar-form input.form-control::-webkit-input-placeholder{color:rgba(255,255,255,.84)}.navbar.navbar-primary .dropdown-menu{border-radius:2px}.navbar.navbar-primary .dropdown-menu li>a{font-size:16px;padding:13px 16px}.navbar.navbar-primary .dropdown-menu li>a:focus,.navbar.navbar-primary .dropdown-menu li>a:hover{color:#009688;background-color:#eee}.navbar.navbar-primary .dropdown-menu .active>a{background-color:#009688;color:rgba(255,255,255,.84)}.navbar.navbar-primary .dropdown-menu .active>a:focus,.navbar.navbar-primary .dropdown-menu .active>a:hover{color:rgba(255,255,255,.84)}.navbar.navbar-success{background-color:#4caf50;color:rgba(255,255,255,.84)}.navbar.navbar-success .navbar-form .form-group input.form-control::-moz-placeholder,.navbar.navbar-success .navbar-form input.form-control::-moz-placeholder{color:rgba(255,255,255,.84)}.navbar.navbar-success .navbar-form .form-group input.form-control:-ms-input-placeholder,.navbar.navbar-success .navbar-form input.form-control:-ms-input-placeholder{color:rgba(255,255,255,.84)}.navbar.navbar-success .navbar-form .form-group input.form-control::-webkit-input-placeholder,.navbar.navbar-success .navbar-form input.form-control::-webkit-input-placeholder{color:rgba(255,255,255,.84)}.navbar.navbar-success .dropdown-menu{border-radius:2px}.navbar.navbar-success .dropdown-menu li>a{font-size:16px;padding:13px 16px}.navbar.navbar-success .dropdown-menu li>a:focus,.navbar.navbar-success .dropdown-menu li>a:hover{color:#4caf50;background-color:#eee}.navbar.navbar-success .dropdown-menu .active>a{background-color:#4caf50;color:rgba(255,255,255,.84)}.navbar.navbar-success .dropdown-menu .active>a:focus,.navbar.navbar-success .dropdown-menu .active>a:hover{color:rgba(255,255,255,.84)}.navbar.navbar-info{background-color:#03a9f4;color:rgba(255,255,255,.84)}.navbar.navbar-info .navbar-form .form-group input.form-control::-moz-placeholder,.navbar.navbar-info .navbar-form input.form-control::-moz-placeholder{color:rgba(255,255,255,.84)}.navbar.navbar-info .navbar-form .form-group input.form-control:-ms-input-placeholder,.navbar.navbar-info .navbar-form input.form-control:-ms-input-placeholder{color:rgba(255,255,255,.84)}.navbar.navbar-info .navbar-form .form-group input.form-control::-webkit-input-placeholder,.navbar.navbar-info .navbar-form input.form-control::-webkit-input-placeholder{color:rgba(255,255,255,.84)}.navbar.navbar-info .dropdown-menu{border-radius:2px}.navbar.navbar-info .dropdown-menu li>a{font-size:16px;padding:13px 16px}.navbar.navbar-info .dropdown-menu li>a:focus,.navbar.navbar-info .dropdown-menu li>a:hover{color:#03a9f4;background-color:#eee}.navbar.navbar-info .dropdown-menu .active>a{background-color:#03a9f4;color:rgba(255,255,255,.84)}.navbar.navbar-info .dropdown-menu .active>a:focus,.navbar.navbar-info .dropdown-menu .active>a:hover{color:rgba(255,255,255,.84)}.navbar.navbar-warning{background-color:#ff5722;color:rgba(255,255,255,.84)}.navbar.navbar-warning .navbar-form .form-group input.form-control::-moz-placeholder,.navbar.navbar-warning .navbar-form input.form-control::-moz-placeholder{color:rgba(255,255,255,.84)}.navbar.navbar-warning .navbar-form .form-group input.form-control:-ms-input-placeholder,.navbar.navbar-warning .navbar-form input.form-control:-ms-input-placeholder{color:rgba(255,255,255,.84)}.navbar.navbar-warning .navbar-form .form-group input.form-control::-webkit-input-placeholder,.navbar.navbar-warning .navbar-form input.form-control::-webkit-input-placeholder{color:rgba(255,255,255,.84)}.navbar.navbar-warning .dropdown-menu{border-radius:2px}.navbar.navbar-warning .dropdown-menu li>a{font-size:16px;padding:13px 16px}.navbar.navbar-warning .dropdown-menu li>a:focus,.navbar.navbar-warning .dropdown-menu li>a:hover{color:#ff5722;background-color:#eee}.navbar.navbar-warning .dropdown-menu .active>a{background-color:#ff5722;color:rgba(255,255,255,.84)}.navbar.navbar-warning .dropdown-menu .active>a:focus,.navbar.navbar-warning .dropdown-menu .active>a:hover{color:rgba(255,255,255,.84)}.navbar.navbar-danger{background-color:#f44336;color:rgba(255,255,255,.84)}.navbar.navbar-danger .navbar-form .form-group input.form-control::-moz-placeholder,.navbar.navbar-danger .navbar-form input.form-control::-moz-placeholder{color:rgba(255,255,255,.84)}.navbar.navbar-danger .navbar-form .form-group input.form-control:-ms-input-placeholder,.navbar.navbar-danger .navbar-form input.form-control:-ms-input-placeholder{color:rgba(255,255,255,.84)}.navbar.navbar-danger .navbar-form .form-group input.form-control::-webkit-input-placeholder,.navbar.navbar-danger .navbar-form input.form-control::-webkit-input-placeholder{color:rgba(255,255,255,.84)}.navbar.navbar-danger .dropdown-menu{border-radius:2px}.navbar.navbar-danger .dropdown-menu li>a{font-size:16px;padding:13px 16px}.navbar.navbar-danger .dropdown-menu li>a:focus,.navbar.navbar-danger .dropdown-menu li>a:hover{color:#f44336;background-color:#eee}.navbar.navbar-danger .dropdown-menu .active>a{background-color:#f44336;color:rgba(255,255,255,.84)}.navbar.navbar-danger .dropdown-menu .active>a:focus,.navbar.navbar-danger .dropdown-menu .active>a:hover{color:rgba(255,255,255,.84)}.navbar-inverse{background-color:#3f51b5}@media (max-width:1199px){.navbar .navbar-brand{height:50px;padding:10px 15px}.navbar .navbar-form{margin-top:10px}.navbar .navbar-nav>li>a{padding-top:15px;padding-bottom:15px}}.dropdown-menu{border:0;-webkit-box-shadow:0 2px 5px 0 rgba(0,0,0,.26);box-shadow:0 2px 5px 0 rgba(0,0,0,.26)}.dropdown-menu .divider{background-color:rgba(0,0,0,.12)}.dropdown-menu li{overflow:hidden;position:relative}.dropdown-menu li a:hover{background-color:transparent;color:#009688}.alert{border:0;border-radius:0}.alert,.alert.alert-default{background-color:rgba(255,255,255,.84);color:rgba(255,255,255,.84)}.alert .alert-link,.alert a,.alert.alert-default .alert-link,.alert.alert-default a{color:rgba(255,255,255,.84)}.alert.alert-inverse{background-color:#3f51b5;color:#fff}.alert.alert-inverse .alert-link,.alert.alert-inverse a{color:#fff}.alert.alert-primary{background-color:#009688;color:rgba(255,255,255,.84)}.alert.alert-primary .alert-link,.alert.alert-primary a{color:rgba(255,255,255,.84)}.alert.alert-success{background-color:#4caf50;color:rgba(255,255,255,.84)}.alert.alert-success .alert-link,.alert.alert-success a{color:rgba(255,255,255,.84)}.alert.alert-info{background-color:#03a9f4;color:rgba(255,255,255,.84)}.alert.alert-info .alert-link,.alert.alert-info a{color:rgba(255,255,255,.84)}.alert.alert-warning{background-color:#ff5722;color:rgba(255,255,255,.84)}.alert.alert-warning .alert-link,.alert.alert-warning a{color:rgba(255,255,255,.84)}.alert.alert-danger{background-color:#f44336;color:rgba(255,255,255,.84)}.alert.alert-danger .alert-link,.alert.alert-danger a{color:rgba(255,255,255,.84)}.alert-danger,.alert-info,.alert-success,.alert-warning{color:rgba(255,255,255,.84)}.alert-default .alert-link,.alert-default a{color:rgba(0,0,0,.87)}.progress{height:4px;border-radius:0;-webkit-box-shadow:none;box-shadow:none;background:#c8c8c8}.progress .progress-bar{-webkit-box-shadow:none;box-shadow:none}.progress .progress-bar,.progress .progress-bar.progress-bar-default{background-color:#009688}.progress .progress-bar.progress-bar-inverse{background-color:#3f51b5}.progress .progress-bar.progress-bar-primary{background-color:#009688}.progress .progress-bar.progress-bar-success{background-color:#4caf50}.progress .progress-bar.progress-bar-info{background-color:#03a9f4}.progress .progress-bar.progress-bar-warning{background-color:#ff5722}.progress .progress-bar.progress-bar-danger{background-color:#f44336}.text-warning{color:#ff5722}.text-primary{color:#009688}.text-danger{color:#f44336}.text-success{color:#4caf50}.text-info{color:#03a9f4}.nav-tabs{background:#009688}.nav-tabs>li>a{color:#FFF;border:0;margin:0}.nav-tabs>li>a:hover{background-color:transparent;border:0}.nav-tabs>li>a,.nav-tabs>li>a:focus,.nav-tabs>li>a:hover{background-color:transparent!important;border:0!important;color:#FFF!important;font-weight:500}.nav-tabs>li.disabled>a,.nav-tabs>li.disabled>a:hover{color:rgba(255,255,255,.5)}.popover,.tooltip-inner{color:#ececec;line-height:1em;background:rgba(101,101,101,.9);border:none;border-radius:2px;-webkit-box-shadow:0 1px 6px 0 rgba(0,0,0,.12),0 1px 6px 0 rgba(0,0,0,.12);box-shadow:0 1px 6px 0 rgba(0,0,0,.12),0 1px 6px 0 rgba(0,0,0,.12)}.tooltip,.tooltip.in{opacity:1}.popover .arrow,.popover .tooltip-arrow,.tooltip .arrow,.tooltip .tooltip-arrow{display:none}.card{display:inline-block;position:relative;width:100%;border-radius:2px;color:rgba(0,0,0,.87);background:#fff;-webkit-box-shadow:0 8px 17px 0 rgba(0,0,0,.2),0 6px 20px 0 rgba(0,0,0,.19);box-shadow:0 8px 17px 0 rgba(0,0,0,.2),0 6px 20px 0 rgba(0,0,0,.19)}.card .card-height-indicator{margin-top:100%}.card .card-content{position:absolute;top:0;bottom:0;left:0;right:0}.card .card-image{height:60%;position:relative;overflow:hidden}.card .card-image img{width:100%;height:100%;border-top-left-radius:2px;border-top-right-radius:2px;pointer-events:none}.card .card-image .card-image-headline{position:absolute;bottom:16px;left:18px;color:#fff;font-size:2em}.card .card-body{height:30%;padding:18px}.card .card-footer{height:10%;padding:18px}.card .card-footer a,.card .card-footer button{margin:0!important;position:relative;bottom:25px;width:auto}.card .card-footer a:first-child,.card .card-footer button:first-child{left:-15px}.modal-content{-webkit-box-shadow:0 27px 24px 0 rgba(0,0,0,.2),0 40px 77px 0 rgba(0,0,0,.22);box-shadow:0 27px 24px 0 rgba(0,0,0,.2),0 40px 77px 0 rgba(0,0,0,.22);border-radius:2px;border:none}.modal-content .modal-header{border-bottom:none;padding-top:24px;padding-right:24px;padding-bottom:0;padding-left:24px}.modal-content .modal-body{padding-top:24px;padding-right:24px;padding-bottom:16px;padding-left:24px}.modal-content .modal-footer{border-top:none;padding:7px}.modal-content .modal-footer button{margin:0;padding-left:16px;padding-right:16px;width:auto}.modal-content .modal-footer button.pull-left{padding-left:5px;padding-right:5px;position:relative;left:-5px}.modal-content .modal-footer button+button{margin-bottom:16px}.modal-content .modal-body+.modal-footer{padding-top:0}.modal-backdrop{background:rgba(0,0,0,.3)}.panel{border-radius:2px;border:0;-webkit-box-shadow:0 1px 6px 0 rgba(0,0,0,.12),0 1px 6px 0 rgba(0,0,0,.12);box-shadow:0 1px 6px 0 rgba(0,0,0,.12),0 1px 6px 0 rgba(0,0,0,.12)}.panel.panel-default>.panel-heading,.panel>.panel-heading{background-color:#eee}.panel.panel-inverse>.panel-heading{background-color:#3f51b5}.panel.panel-primary>.panel-heading{background-color:#3f51b5}.panel.panel-success>.panel-heading{background-color:#4caf50}.panel.panel-info>.panel-heading{background-color:#03a9f4}.panel.panel-warning>.panel-heading{background-color:#ff5722}.panel.panel-danger>.panel-heading{background-color:#f44336}[class*=panel-]>.panel-heading{color:rgba(255,255,255,.84);border:0}.panel-default>.panel-heading,.panel:not([class*=panel-])>.panel-heading{color:rgba(0,0,0,.87)}.panel-footer{background-color:#eee}hr.on-dark{color:#1a1a1a}hr.on-light{color:#fff}@media (-webkit-min-device-pixel-ratio:0.75),(min--moz-device-pixel-ratio:0.75),(-o-device-pixel-ratio:3/4),(min-device-pixel-ratio:0.75),(-o-min-device-pixel-ratio:3/4),(min-resolution:0.75dppx),(-webkit-min-device-pixel-ratio:1.25),(-o-min-device-pixel-ratio:5/4),(min-resolution:120dpi){hr{height:.75px}}@media (-webkit-min-device-pixel-ratio:1),(min--moz-device-pixel-ratio:1),(-o-device-pixel-ratio:1),(min-device-pixel-ratio:1),(-o-min-device-pixel-ratio:1/1),(min-resolution:1dppx),(-webkit-min-device-pixel-ratio:1.6666666666666667),(-o-min-device-pixel-ratio:5/3),(min-resolution:160dpi){hr{height:1px}}@media (-webkit-min-device-pixel-ratio:1.33),(min--moz-device-pixel-ratio:1.33),(-o-device-pixel-ratio:133/100),(min-device-pixel-ratio:1.33),(-o-min-device-pixel-ratio:133/100),(min-resolution:1.33dppx),(-webkit-min-device-pixel-ratio:2.21875),(-o-min-device-pixel-ratio:71/32),(min-resolution:213dpi){hr{height:1.33px}}@media (-webkit-min-device-pixel-ratio:1.5),(min--moz-device-pixel-ratio:1.5),(-o-device-pixel-ratio:3/2),(min-device-pixel-ratio:1.5),(-o-min-device-pixel-ratio:3/2),(min-resolution:1.5dppx),(-webkit-min-device-pixel-ratio:2.5),(-o-min-device-pixel-ratio:5/2),(min-resolution:240dpi){hr{height:1.5px}}@media (-webkit-min-device-pixel-ratio:2),(min--moz-device-pixel-ratio:2),(-o-device-pixel-ratio:2/1),(min-device-pixel-ratio:2),(-o-min-device-pixel-ratio:2/1),(min-resolution:2dppx),(-webkit-min-device-pixel-ratio:3.9583333333333335),(-o-min-device-pixel-ratio:95/24),(min-resolution:380dpi){hr{height:2px}}@media (-webkit-min-device-pixel-ratio:3),(min--moz-device-pixel-ratio:3),(-o-device-pixel-ratio:3/1),(min-device-pixel-ratio:3),(-o-min-device-pixel-ratio:3/1),(min-resolution:3dppx),(-webkit-min-device-pixel-ratio:5),(-o-min-device-pixel-ratio:5/1),(min-resolution:480dpi){hr{height:3px}}@media (-webkit-min-device-pixel-ratio:4),(min--moz-device-pixel-ratio:4),(-o-device-pixel-ratio:4/1),(min-device-pixel-ratio:3),(-o-min-device-pixel-ratio:4/1),(min-resolution:4dppx),(-webkit-min-device-pixel-ratio:6.666666666666667),(-o-min-device-pixel-ratio:20/3),(min-resolution:640dpi){hr{height:4px}}*{-webkit-tap-highlight-color:rgba(255,255,255,0);-webkit-tap-highlight-color:transparent}:focus{outline:0}.snackbar{background-color:#323232;color:rgba(255,255,255,.84);font-size:14px;border-radius:2px;-webkit-box-shadow:0 1px 6px 0 rgba(0,0,0,.12),0 1px 6px 0 rgba(0,0,0,.12);box-shadow:0 1px 6px 0 rgba(0,0,0,.12),0 1px 6px 0 rgba(0,0,0,.12);height:0;-webkit-transition:-webkit-transform .2s ease-in-out,opacity .2s ease-in,height 0s linear .2s,padding 0s linear .2s,height 0s linear .2s;-o-transition:-o-transform .2s ease-in-out,opacity .2s ease-in,height 0s linear .2s,padding 0s linear .2s,height 0s linear .2s;transition:transform .2s ease-in-out,opacity .2s ease-in,height 0s linear .2s,padding 0s linear .2s,height 0s linear .2s;-webkit-transform:translateY(200%);-ms-transform:translateY(200%);-o-transform:translateY(200%);transform:translateY(200%)}.snackbar.snackbar-opened{padding:14px 15px;margin-bottom:20px;height:auto;-webkit-transition:-webkit-transform .2s ease-in-out,opacity .2s ease-in,height 0s linear .2s,height 0s linear .2s;-o-transition:-o-transform .2s ease-in-out,opacity .2s ease-in,height 0s linear .2s,height 0s linear .2s;transition:transform .2s ease-in-out,opacity .2s ease-in,height 0s linear .2s,height 0s linear .2s;-webkit-transform:none;-ms-transform:none;-o-transform:none;transform:none}.snackbar.toast{border-radius:200px}.noUi-target,.noUi-target *{-webkit-touch-callout:none;-ms-touch-action:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.noUi-base{width:100%;height:100%;position:relative}.noUi-origin{position:absolute;right:0;top:0;left:0;bottom:0}.noUi-handle{position:relative;z-index:1;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.noUi-stacking .noUi-handle{z-index:10}.noUi-state-tap .noUi-origin{-webkit-transition:left .3s,top .3s;-o-transition:left .3s,top .3s;transition:left .3s,top .3s}.noUi-state-drag *{cursor:inherit!important}.noUi-horizontal{height:10px}.noUi-handle{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;width:12px;height:12px;left:-10px;top:-5px;cursor:ew-resize;border-radius:100%;-webkit-transition:all .2s ease-out;-o-transition:all .2s ease-out;transition:all .2s ease-out;border:1px solid}.noUi-vertical .noUi-handle{margin-left:5px;cursor:ns-resize}.noUi-horizontal.noUi-extended{padding:0 15px}.noUi-horizontal.noUi-extended .noUi-origin{right:-15px}.noUi-background{height:2px;margin:20px 0}.noUi-origin{margin:0;border-radius:0;height:2px;background:#c8c8c8}.noUi-origin[style^="left: 0"] .noUi-handle{background-color:#fff;border:2px solid #c8c8c8}.noUi-origin[style^="left: 0"] .noUi-handle.noUi-active{border-width:1px}.noUi-target{border-radius:2px}.noUi-horizontal{height:2px;margin:15px 0}.noUi-vertical{height:100%;width:2px;margin:0 15px;display:inline-block}.noUi-handle.noUi-active{-webkit-transform:scale3d(2.5,2.5,1);transform:scale3d(2.5,2.5,1)}[disabled].noUi-slider{opacity:.5}[disabled] .noUi-handle{cursor:not-allowed}.slider{background:#c8c8c8}.slider.noUi-connect,.slider.slider-default.noUi-connect{background-color:#009688}.slider.slider-inverse.noUi-connect{background-color:#3f51b5}.slider.slider-primary.noUi-connect{background-color:#009688}.slider.slider-success.noUi-connect{background-color:#4caf50}.slider.slider-info.noUi-connect{background-color:#03a9f4}.slider.slider-warning.noUi-connect{background-color:#ff5722}.slider.slider-danger.noUi-connect{background-color:#f44336}.slider .noUi-connect,.slider.slider-default .noUi-connect{background-color:#009688}.slider.slider-inverse .noUi-connect{background-color:#3f51b5}.slider.slider-primary .noUi-connect{background-color:#009688}.slider.slider-success .noUi-connect{background-color:#4caf50}.slider.slider-info .noUi-connect{background-color:#03a9f4}.slider.slider-warning .noUi-connect{background-color:#ff5722}.slider.slider-danger .noUi-connect{background-color:#f44336}.slider .noUi-handle,.slider.slider-default .noUi-handle{background-color:#009688}.slider.slider-inverse .noUi-handle{background-color:#3f51b5}.slider.slider-primary .noUi-handle{background-color:#009688}.slider.slider-success .noUi-handle{background-color:#4caf50}.slider.slider-info .noUi-handle{background-color:#03a9f4}.slider.slider-warning .noUi-handle{background-color:#ff5722}.slider.slider-danger .noUi-handle{background-color:#f44336}.slider .noUi-handle,.slider.slider-default .noUi-handle{border-color:#009688}.slider.slider-inverse .noUi-handle{border-color:#3f51b5}.slider.slider-primary .noUi-handle{border-color:#009688}.slider.slider-success .noUi-handle{border-color:#4caf50}.slider.slider-info .noUi-handle{border-color:#03a9f4}.slider.slider-warning .noUi-handle{border-color:#ff5722}.slider.slider-danger .noUi-handle{border-color:#f44336}.selectize-control.multi,.selectize-control.single{padding:0}.selectize-control.multi .selectize-input,.selectize-control.multi .selectize-input.input-active,.selectize-control.single .selectize-input,.selectize-control.single .selectize-input.input-active{cursor:text;background:0 0;-webkit-box-shadow:none;box-shadow:none;border:0;padding:0;height:100%;font-size:14px;line-height:30px}.selectize-control.multi .selectize-input .has-items,.selectize-control.multi .selectize-input.input-active .has-items,.selectize-control.single .selectize-input .has-items,.selectize-control.single .selectize-input.input-active .has-items{padding:0}.selectize-control.multi .selectize-input.input-active:after,.selectize-control.multi .selectize-input:after,.selectize-control.single .selectize-input.input-active:after,.selectize-control.single .selectize-input:after{right:5px;position:absolute;font-size:25px;content:"\e5c5";font-family:'Material Icons';speak:none;font-style:normal;font-weight:400;font-variant:normal;text-transform:none;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.selectize-control.multi .selectize-input input,.selectize-control.multi .selectize-input.input-active input,.selectize-control.single .selectize-input input,.selectize-control.single .selectize-input.input-active input{font-size:14px;outline:0;border:0;background:0 0}.selectize-control.multi .selectize-input.input-active.label-floating-fix input,.selectize-control.multi .selectize-input.label-floating-fix input,.selectize-control.single .selectize-input.input-active.label-floating-fix input,.selectize-control.single .selectize-input.label-floating-fix input{opacity:0}.selectize-control.multi .selectize-input.input-active>.item,.selectize-control.multi .selectize-input.input-active>div,.selectize-control.multi .selectize-input>.item,.selectize-control.multi .selectize-input>div,.selectize-control.single .selectize-input.input-active>.item,.selectize-control.single .selectize-input.input-active>div,.selectize-control.single .selectize-input>.item,.selectize-control.single .selectize-input>div{display:inline-block;margin:0 8px 3px 0;padding:0;background:0 0;border:0}.selectize-control.multi .selectize-input.input-active>.item:after,.selectize-control.multi .selectize-input.input-active>div:after,.selectize-control.multi .selectize-input>.item:after,.selectize-control.multi .selectize-input>div:after,.selectize-control.single .selectize-input.input-active>.item:after,.selectize-control.single .selectize-input.input-active>div:after,.selectize-control.single .selectize-input>.item:after,.selectize-control.single .selectize-input>div:after{content:","}.selectize-control.multi .selectize-input.input-active>.item:last-of-type:after,.selectize-control.multi .selectize-input.input-active>div:last-of-type:after,.selectize-control.multi .selectize-input>.item:last-of-type:after,.selectize-control.multi .selectize-input>div:last-of-type:after,.selectize-control.single .selectize-input.input-active>.item:last-of-type:after,.selectize-control.single .selectize-input.input-active>div:last-of-type:after,.selectize-control.single .selectize-input>.item:last-of-type:after,.selectize-control.single .selectize-input>div:last-of-type:after{content:""}.selectize-control.multi .selectize-input.input-active>.item.active,.selectize-control.multi .selectize-input.input-active>div.active,.selectize-control.multi .selectize-input>.item.active,.selectize-control.multi .selectize-input>div.active,.selectize-control.single .selectize-input.input-active>.item.active,.selectize-control.single .selectize-input.input-active>div.active,.selectize-control.single .selectize-input>.item.active,.selectize-control.single .selectize-input>div.active{font-weight:700;background:0 0;border:0}.selectize-control.multi .selectize-dropdown,.selectize-control.single .selectize-dropdown{position:absolute;z-index:1000;border:0;width:100%!important;left:0!important;height:auto;background-color:#FFF;-webkit-box-shadow:0 1px 3px rgba(0,0,0,.12),0 1px 2px rgba(0,0,0,.24);box-shadow:0 1px 3px rgba(0,0,0,.12),0 1px 2px rgba(0,0,0,.24);border-radius:2px;padding:0;margin-top:3px}.selectize-control.multi .selectize-dropdown .active,.selectize-control.single .selectize-dropdown .active{background-color:inherit}.selectize-control.multi .selectize-dropdown .highlight,.selectize-control.single .selectize-dropdown .highlight{background-color:#d5d8ff}.selectize-control.multi .selectize-dropdown .selected,.selectize-control.multi .selectize-dropdown .selected.active,.selectize-control.single .selectize-dropdown .selected,.selectize-control.single .selectize-dropdown .selected.active{background-color:#EEE}.selectize-control.multi .selectize-dropdown .optgroup-header,.selectize-control.multi .selectize-dropdown [data-selectable],.selectize-control.single .selectize-dropdown .optgroup-header,.selectize-control.single .selectize-dropdown [data-selectable]{padding:10px 20px;cursor:pointer}.selectize-control.multi .dropdown-active~.selectize-dropdown,.selectize-control.single .dropdown-active~.selectize-dropdown{display:block}.dropdownjs::after{right:5px;top:3px;font-size:25px;position:absolute;font-family:'Material Icons';font-style:normal;font-weight:400;content:"\e5c5";pointer-events:none;color:#757575}.navbar-brand{background-position:10px;background-size:192px 50px;background-image:url(/static/img/logo_s.png);width:200px;background-repeat:no-repeat}.wave_hide{overflow:initial}@media (min-width:768px){.avatar-a{padding-top:15px!important;padding-bottom:15px!important}.avatar-s{width:30px!important}} +.centerTable{ + text-align:center; + text-align:center; +} +.tr-bar { + background-image: -webkit-gradient(linear, left top, right top, from(#ecefff), to(white), color-stop(0.5, #ecefff), color-stop(0.5, white)); + background-image: -moz-linear-gradient(0, #ecefff 0%, #ecefff 50%, white 50%, white 100%); + } \ No newline at end of file diff --git a/static/js/angular-filemanager.min.js b/static/js/angular-filemanager.min.js index 69c7a44e..a9fbb63d 100644 --- a/static/js/angular-filemanager.min.js +++ b/static/js/angular-filemanager.min.js @@ -787,6 +787,7 @@ function(e) { permissionsUrl: "bridges/php/handler.php", sourceUrl:"/File/gerSource", remoteDownloadUrl: "/RemoteDownload/addUrl", + torrentDownloadUrl: "/RemoteDownload/AddTorrent", basePath: "/", searchForm: !0, sidebar: !0, @@ -1051,7 +1052,7 @@ function(e, r) { s = n.defer(), l = { action: "torrentDownload", - path: path, + savePath: path, id:fileId }; return o.inprocess = !0, diff --git a/static/js/remoteDownload.js b/static/js/remoteDownload.js new file mode 100644 index 00000000..144ce569 --- /dev/null +++ b/static/js/remoteDownload.js @@ -0,0 +1,9 @@ +$.get("/RemoteDownload/FlushUser", function(){ + $("#loadStatus").html("加载下载列表中"); + loadDownloadingList(); +}) +function loadDownloadingList(){ + $.getJSON("/RemoteDownload/ListDownloading", function(data){ + console.log(data); + }) +} \ No newline at end of file From 3326c9232e2667e5e51cffd676678728eb1eef7d Mon Sep 17 00:00:00 2001 From: HFO4 <912394456@qq.com> Date: Tue, 17 Apr 2018 19:59:13 +0800 Subject: [PATCH 06/10] add download task list and optimize temp file recovery --- .../index/controller/RemoteDownload.php | 38 ++++++++++- application/index/model/Aria2.php | 47 ++++++++++++- application/index/view/home/Download.html | 25 +------ static/js/remoteDownload.js | 68 +++++++++++++++++-- 4 files changed, 146 insertions(+), 32 deletions(-) diff --git a/application/index/controller/RemoteDownload.php b/application/index/controller/RemoteDownload.php index 1411b651..b9076321 100644 --- a/application/index/controller/RemoteDownload.php +++ b/application/index/controller/RemoteDownload.php @@ -96,14 +96,50 @@ class RemoteDownload extends Controller{ ->where("owner",$this->userObj->uid) ->where("status","<>","complete") ->where("status","<>","error") + ->where("status","<>","canceled") + //取消的 ->select(); foreach ($toBeFlushed as $key => $value) { $aria2->flushStatus($value["id"],$this->userObj->uid,$this->userObj->getPolicy()); } } + public function Cancel(){ + $aria2Options = Option::getValues(["aria2"]); + $aria2 = new Aria2($aria2Options); + $downloadItem = Db::name("download")->where("owner",$this->userObj->uid)->where("id",input("post.id"))->find(); + if(empty($downloadItem)){ + return json(['error'=>1,'message'=>"未找到下载记录"]); + } + if($aria2->Remove($downloadItem["pid"],"")){ + return json(['error'=>0,'message'=>"下载已取消"]); + }else{ + return json(['error'=>1,'message'=>"取消失败"]); + } + } + public function ListDownloading(){ - return json(["s"=>"s"]); + $downloadItems = Db::name("download")->where("owner",$this->userObj->uid)->where("status","in",["active","ready"])->order('id desc')->select(); + foreach ($downloadItems as $key => $value) { + $connectInfo = json_decode($value["info"],true); + if(isset($connectInfo["dir"])){ + $downloadItems[$key]["fileName"] = basename($connectInfo["dir"]); + $downloadItems[$key]["completedLength"] = $connectInfo["completedLength"]; + $downloadItems[$key]["totalLength"] = $connectInfo["totalLength"]; + $downloadItems[$key]["downloadSpeed"] = $connectInfo["downloadSpeed"]; + }else{ + if(floor($value["source"])==$value["source"]){ + $downloadItems[$key]["fileName"] = Db::name("files")->where("id",$value["source"])->column("orign_name"); + }else{ + $downloadItems[$key]["fileName"] = $value["source"]; + } + $downloadItems[$key]["completedLength"] = 0; + $downloadItems[$key]["totalLength"] = 0; + $downloadItems[$key]["downloadSpeed"] = 0; + } + } + return json($downloadItems); } + } \ No newline at end of file diff --git a/application/index/model/Aria2.php b/application/index/model/Aria2.php index dac3d7a4..4798a612 100644 --- a/application/index/model/Aria2.php +++ b/application/index/model/Aria2.php @@ -124,7 +124,9 @@ class Aria2 extends Model{ case 'complete': $this->setComplete($respondData["result"],$downloadInfo); break; - + case 'removed': + $this->setCanceled($respondData["result"],$downloadInfo); + break; default: # code... break; @@ -151,6 +153,31 @@ class Aria2 extends Model{ return true; } + private function setCanceled($quenInfo,$sqlData){ + @self::remove_directory(ROOT_PATH."public".DS."downloads".DS.$sqlData["path_id"]); + if(!is_dir(ROOT_PATH."public".DS."downloads".DS.$sqlData["path_id"])){ + Db::name("download")->where("id",$sqlData["id"])->update([ + "status" => "canceled", + ]); + } + } + + static function remove_directory($dir){ + if($handle=opendir("$dir")){ + while(false!==($item=readdir($handle))){ + if($item!="."&&$item!=".."){ + if(is_dir("$dir/$item")){ + self::remove_directory("$dir/$item"); + }else{ + unlink("$dir/$item"); + } + } + } + closedir($handle); + rmdir($dir); + } + } + private function updateToMuiltpe($quenInfo,$sqlData){ foreach ($quenInfo["files"] as $key => $value) { Db::name("download")->insert([ @@ -174,6 +201,7 @@ class Aria2 extends Model{ $this->setError($quenInfo,$sqlData,"您当前的上传策略无法使用离线下载"); return false; } + $this->forceRemove($sqlData["pid"]); $suffixTmp = explode('.', $quenInfo["dir"]); $fileSuffix = array_pop($suffixTmp); $uploadHandller = new UploadHandler($this->policy["id"],$this->uid); @@ -220,7 +248,7 @@ class Aria2 extends Model{ if($delete){ if(file_exists($quenInfo["files"][$sqlData["file_index"]]["path"])){ @unlink($quenInfo["files"][$sqlData["file_index"]]["path"]); - @unlink(dirname($quenInfo["files"][$sqlData["file_index"]]["path"])); + @self::remove_directory(dirname($quenInfo["files"][$sqlData["file_index"]]["path"])); } } Db::name("download")->where("id",$sqlData["id"])->update([ @@ -259,6 +287,21 @@ class Aria2 extends Model{ return false; } + public function forceRemove($gid){ + $reqFileds = [ + "params" => ["token:".$this->authToken,$gid], + "jsonrpc" => "2.0", + "id" => uniqid(), + "method" => "aria2.forceRemove" + ]; + $reqFileds = json_encode($reqFileds,JSON_OBJECT_AS_ARRAY); + $respondData = $this->sendReq($reqFileds); + if(isset($respondData["result"])){ + return true; + } + return false; + } + private function storageCheck($quenInfo,$sqlData){ if(!FileManage::sotrageCheck($this->uid,(int)$quenInfo["totalLength"])){ return false; diff --git a/application/index/view/home/Download.html b/application/index/view/home/Download.html index a24692bc..1bcdd4b3 100644 --- a/application/index/view/home/Download.html +++ b/application/index/view/home/Download.html @@ -34,32 +34,13 @@ 文件名 大小 储存位置 + 下载速度 进度 操作 - - - 1 - Mark - Otto - @mdo the Bird - @twitter - - - 2 - Jacob - Thornton - @fat the Bird - @twitter - - - 3 - Larry - the Bird - @twitter the Bird - @twitter - + +
diff --git a/static/js/remoteDownload.js b/static/js/remoteDownload.js index 144ce569..29b97003 100644 --- a/static/js/remoteDownload.js +++ b/static/js/remoteDownload.js @@ -1,9 +1,63 @@ -$.get("/RemoteDownload/FlushUser", function(){ - $("#loadStatus").html("加载下载列表中"); +$.get("/RemoteDownload/FlushUser", function() { + $("#loadStatus").html("加载下载列表中..."); loadDownloadingList(); }) -function loadDownloadingList(){ - $.getJSON("/RemoteDownload/ListDownloading", function(data){ - console.log(data); - }) -} \ No newline at end of file + +function loadDownloadingList() { + $.getJSON("/RemoteDownload/ListDownloading", function(data) { + $("#itemContent").html(); + if(data.length == 0){ + $("#loadStatus").html("下载列表为空"); + } + data.forEach(function(e) { + $("#itemContent").append(function() { + var row = '' + e["id"] + '' + e["fileName"] + ''; + row = row + '' + bytesToSize(e["totalLength"]) + ''; + row = row + '' + e["save_dir"] + ''; + if (e["downloadSpeed"] == "0") { + row = row + '-'; + } else { + row = row + '' + bytesToSize(e["downloadSpeed"]) + '/s'; + } + row = row + '' + GetPercent(e["completedLength"], e["totalLength"]) + '' + row = row + '取消' + return row + ""; + }); + $("#i-" + e["id"]).css({ + "background-image": "-webkit-gradient(linear, left top, right top, from(#ecefff), to(white), color-stop("+e["completedLength"]/e["totalLength"]+", #ecefff), color-stop("+e["completedLength"]/e["totalLength"]+", white))", + + }); + $(".table-responsive").slideDown(); + $("#loadStatus").slideUp(); + }); + }) + } + + function bytesToSize(bytes) { + if (bytes === 0) return '0 B'; + var k = 1000, // or 1024 + sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'], + i = Math.floor(Math.log(bytes) / Math.log(k)); + + return (bytes / Math.pow(k, i)).toPrecision(3) + ' ' + sizes[i]; + } + + function GetPercent(num, total) { + num = parseFloat(num); + total = parseFloat(total); + if (isNaN(num) || isNaN(total)) { + return "-"; + } + return total <= 0 ? "0%" : (Math.round(num / total * 10000) / 100.00 + "%"); + } + + function cancel(id){ + $.post("/RemoteDownload/Cancel", {id:id}, function(data){ + console.log(data); + if(data.error){ + toastr["warning"](data.message); + }else{ + toastr["success"](data.message); + } + }) + } \ No newline at end of file From 412541a5402b66f9e9bff3d469b1ade5c690af1a Mon Sep 17 00:00:00 2001 From: HFO4 <912394456@qq.com> Date: Wed, 18 Apr 2018 20:31:24 +0800 Subject: [PATCH 07/10] add list for completed remote download and fix storage check before starting downloading --- .../index/controller/RemoteDownload.php | 34 +++++ application/index/model/Aria2.php | 8 +- application/index/view/home/Download.html | 127 +++++++++++------- static/css/material.css | 14 ++ static/js/remoteDownload.js | 82 ++++++++++- 5 files changed, 207 insertions(+), 58 deletions(-) diff --git a/application/index/controller/RemoteDownload.php b/application/index/controller/RemoteDownload.php index b9076321..d09d0f77 100644 --- a/application/index/controller/RemoteDownload.php +++ b/application/index/controller/RemoteDownload.php @@ -41,6 +41,7 @@ class RemoteDownload extends Controller{ "source" =>$url, "file_index" => 0, "is_single" => 1, + "total_size" => 0, ]); } @@ -65,6 +66,15 @@ class RemoteDownload extends Controller{ if(!$this->checkPerimission(0) || $policyData["policy_type"] != "local"){ return json(['error'=>1,'message'=>'您当前的无用户无法执行此操作']); } + $downloadingLength = Db::name("download") + ->where("owner",$this->userObj->uid) + ->where("status","<>","complete") + ->where("status","<>","error") + ->where("status","<>","canceled") + ->sum("total_size"); + if(!\app\index\model\FileManage::sotrageCheck($this->userObj->uid,$downloadingLength)){ + return json(["result"=>['success'=>false,'error'=>"容量不足"]]); + } $aria2Options = Option::getValues(["aria2"]); $aria2 = new Aria2($aria2Options); $torrentObj = new \app\index\model\FileManage(input("post.id"),$this->userObj->uid,true); @@ -141,5 +151,29 @@ class RemoteDownload extends Controller{ return json($downloadItems); } + public function ListFinished(){ + $page = input("get.page"); + $downloadItems = Db::name("download")->where("owner",$this->userObj->uid)->where("status","not in",["active","ready"])->order('id desc')->page($page.',10')->select(); + foreach ($downloadItems as $key => $value) { + $connectInfo = json_decode($value["info"],true); + if(isset($connectInfo["dir"])){ + $downloadItems[$key]["fileName"] = basename($connectInfo["dir"]); + $downloadItems[$key]["completedLength"] = $connectInfo["completedLength"]; + $downloadItems[$key]["totalLength"] = $connectInfo["totalLength"]; + $downloadItems[$key]["downloadSpeed"] = $connectInfo["downloadSpeed"]; + }else{ + if(floor($value["source"])==$value["source"]){ + $downloadItems[$key]["fileName"] = Db::name("files")->where("id",$value["source"])->column("orign_name"); + }else{ + $downloadItems[$key]["fileName"] = $value["source"]; + } + $downloadItems[$key]["completedLength"] = 0; + $downloadItems[$key]["totalLength"] = 0; + $downloadItems[$key]["downloadSpeed"] = 0; + } + } + return json($downloadItems); + } + } \ No newline at end of file diff --git a/application/index/model/Aria2.php b/application/index/model/Aria2.php index 4798a612..4fa1745b 100644 --- a/application/index/model/Aria2.php +++ b/application/index/model/Aria2.php @@ -119,6 +119,7 @@ class Aria2 extends Model{ "errorMessage" => isset($respondData["result"]["errorMessage"]) ? $respondData["result"]["errorMessage"] : "", ]), "msg" => isset($respondData["result"]["errorMessage"]) ? $respondData["result"]["errorMessage"] : "", + "total_size" => $respondData["result"]["files"][$downloadInfo["file_index"]]["length"], ]); switch ($respondData["result"]["status"]) { case 'complete': @@ -191,6 +192,7 @@ class Aria2 extends Model{ "source" =>$sqlData["source"], "file_index" => $key, "is_single" => 0, + "total_size" => 0, ]); } Db::name("download")->where("id",$sqlData["id"])->delete(); @@ -239,7 +241,7 @@ class Aria2 extends Model{ $this->setError($quenInfo,$sqlData,$addAction[1]); return false; } - FileManage::storageCheckOut($this->uid,(int)$quenInfo["files"][$sqlData["file_index"]]["length"]); + FileManage::storageCheckOut($this->uid,$quenInfo["files"][$sqlData["file_index"]]["length"]); } private function setError($quenInfo,$sqlData,$msg,$status="error",$delete=true){ @@ -303,10 +305,10 @@ class Aria2 extends Model{ } private function storageCheck($quenInfo,$sqlData){ - if(!FileManage::sotrageCheck($this->uid,(int)$quenInfo["totalLength"])){ + if(!FileManage::sotrageCheck($this->uid,$quenInfo["totalLength"])){ return false; } - if(!FileManage::sotrageCheck($this->uid,(int)$quenInfo["completedLength"])){ + if(!FileManage::sotrageCheck($this->uid,$quenInfo["completedLength"])){ return false; } return true; diff --git a/application/index/view/home/Download.html b/application/index/view/home/Download.html index 1bcdd4b3..02d58c0d 100644 --- a/application/index/view/home/Download.html +++ b/application/index/view/home/Download.html @@ -1,60 +1,83 @@ {extend name="header_home" /} {block name="title"}离线下载管理- {$options.siteName}{/block} {block name="content"} - - - - -
- {include file="navbar_home" /} + + + + +
+ {include file="navbar_home" /} + +
+

离线下载管理

+
+
-
-

离线下载管理

-
-
- - -
-
-
-
正在进行中
-
- 更新状态数据中... -
- + +
+
+
+
正在进行中
+
+ 更新状态数据中... +
+
-
-
+
+
+
已完成
+
+ + + + + + + + + + + + + +
#文件名大小储存位置状态操作
+
+
+ +
- - - - {$options.js_code} - - {/block} \ No newline at end of file +
+ +
+
+
+ + + + {$options.js_code} + +{/block} \ No newline at end of file diff --git a/static/css/material.css b/static/css/material.css index 8f01348d..0fd61a47 100644 --- a/static/css/material.css +++ b/static/css/material.css @@ -6,4 +6,18 @@ body{background-color:#EEE}body.inverse{background:#333}body.inverse,body.invers .tr-bar { background-image: -webkit-gradient(linear, left top, right top, from(#ecefff), to(white), color-stop(0.5, #ecefff), color-stop(0.5, white)); background-image: -moz-linear-gradient(0, #ecefff 0%, #ecefff 50%, white 50%, white 100%); + } + .download-error{ + color: #F44336; + font-weight: 700; + } + .td-error{ + background-color:#ffebea; + } + .download-success{ + color:#009688; + font-weight: 700; + } + .td-success{ + background-color:#edffee; } \ No newline at end of file diff --git a/static/js/remoteDownload.js b/static/js/remoteDownload.js index 29b97003..d8e7643b 100644 --- a/static/js/remoteDownload.js +++ b/static/js/remoteDownload.js @@ -1,17 +1,83 @@ +function getMemory() { + $.get("/Member/Memory", function(data) { + var dataObj = eval("(" + data + ")"); + if (dataObj.rate >= 100) { + $("#memory_bar").css("width", "100%"); + $("#memory_bar").addClass("progress-bar-warning"); + toastr["error"]("您的已用容量已超过容量配额,请尽快删除多余文件或购买容量"); + + } else { + $("#memory_bar").css("width", dataObj.rate + "%"); + } + $("#used").html(dataObj.used); + $("#total").html(dataObj.total); + }); +} + +page = 1; +window.onload = function() { + $.material.init(); + + getMemory(); +} +$(function() { + $("#loadFinished").click(function(){ + $.getJSON("/RemoteDownload/ListFinished?page="+page, function(data) { + if(data.length == 0){ + $("#loadFinished").html("已加载全部"); + $("#loadFinished").attr("disabled","true"); + }else{ + $("#loadFinished").html("继续加载"); + } + data.forEach(function(e) { + $("#completeItemContent").append(function() { + var row = '' + e["id"] + '' + e["fileName"] + ''; + row = row + '' + bytesToSize(e["totalLength"]) + ''; + row = row + '' + e["save_dir"] + ''; + switch(e["status"]){ + case "error": + row = row +'失败' + break; + case "canceled": + row = row +'取消' + break; + case "canceled": + row = row +'取消' + break; + case "complete": + row = row +'完成' + break; + } + row = row + '删除记录' + return row + ""; + }); + switch(e["status"]){ + case "error": + $("#i-" + e["id"]).addClass("td-error"); + $('[data-toggle="tooltip"]').tooltip() + break; + case "complete": + $("#i-" + e["id"]).addClass("td-success"); + break; + } + }); + page++; + }) + }) +}) $.get("/RemoteDownload/FlushUser", function() { $("#loadStatus").html("加载下载列表中..."); loadDownloadingList(); }) - function loadDownloadingList() { + $("#itemContent").html(""); $.getJSON("/RemoteDownload/ListDownloading", function(data) { - $("#itemContent").html(); if(data.length == 0){ $("#loadStatus").html("下载列表为空"); } data.forEach(function(e) { $("#itemContent").append(function() { - var row = '' + e["id"] + '' + e["fileName"] + ''; + var row = '' + e["id"] + '' + e["fileName"] + ''; row = row + '' + bytesToSize(e["totalLength"]) + ''; row = row + '' + e["save_dir"] + ''; if (e["downloadSpeed"] == "0") { @@ -57,7 +123,17 @@ function loadDownloadingList() { if(data.error){ toastr["warning"](data.message); }else{ + var pid = $("#i-"+id).attr("data-pid"); + $("[data-pid='"+pid+"'").remove(); toastr["success"](data.message); + } }) + } + + function refresh(){ + $.get("/RemoteDownload/FlushUser?i="+Math.random(), function() { + $("#loadStatus").html("加载下载列表中..."); + loadDownloadingList(); + }) } \ No newline at end of file From 334d25833c5eb8360c3aca4cbe31bd3e185050dc Mon Sep 17 00:00:00 2001 From: HFO4 <912394456@qq.com> Date: Wed, 18 Apr 2018 20:37:20 +0800 Subject: [PATCH 08/10] Fix #62 --- application/index/model/Directory.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/application/index/model/Directory.php b/application/index/model/Directory.php index 5880b38e..a1badc21 100644 --- a/application/index/model/Directory.php +++ b/application/index/model/Directory.php @@ -47,7 +47,7 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota{ } $fileSize = fstat($data)["size"]; if(empty($fileSize)){ - $fileSize = 0; + $fileSize = -1; } if($fileSize>$policyData["max_size"]){ throw new DAV\Exception\InsufficientStorage('File is to large'); @@ -66,6 +66,9 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota{ mkdir($savePath,0777,true); } file_put_contents($savePath."/".$fileName, $data); + if($fileSize<=0){ + $fileSize = filesize($savePath."/".$fileName); + } $jsonData = array( "path" => str_replace("/",",",ltrim($this->myPath,"/")), "fname" => $name, From 36e6526259a5838833e83dd190b2aa5f5582d9f1 Mon Sep 17 00:00:00 2001 From: HFO4 <912394456@qq.com> Date: Thu, 19 Apr 2018 19:07:22 +0800 Subject: [PATCH 09/10] complete remote download based on aria2 --- README.md | 1 + application/index/controller/Admin.php | 31 +++++ .../index/controller/RemoteDownload.php | 4 +- application/index/model/AdminHandler.php | 45 +++++++ application/index/model/Aria2.php | 13 +- application/index/model/CronHandler.php | 22 ++++ application/index/view/admin/add_group.html | 12 ++ application/index/view/admin/download.html | 122 ++++++++++++++++++ application/index/view/admin/edit_group.html | 17 +++ application/index/view/header_admin.html | 6 + application/index/view/home/Download.html | 1 - mysql.sql | 40 ++++-- static/css/sb-admin.css | 2 +- static/js/admin/aria2.js | 34 +++++ static/js/remoteDownload.js | 4 +- 15 files changed, 335 insertions(+), 19 deletions(-) create mode 100644 application/index/view/admin/download.html create mode 100644 static/js/admin/aria2.js diff --git a/README.md b/README.md index a10a7d1d..e3a1f367 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,7 @@ Cloudreve - Make the cloud easy for everyone * 快速对接多家云存储,支持七牛、又拍云、阿里云OSS、AWS S3、自建远程服务器,当然,还有本地存储 * 可限制单文件最大大小、MIMEType、文件后缀、用户可用容量 +* 基于Aria2的离线下载 * 图片、音频、视频、文本、Markdown、Ofiice文档 在线预览 * 移动端全站响应式布局 * 文件、目录分享系统,可创建私有分享或公开分享链接 diff --git a/application/index/controller/Admin.php b/application/index/controller/Admin.php index f7380f13..0a2c52f5 100644 --- a/application/index/controller/Admin.php +++ b/application/index/controller/Admin.php @@ -248,6 +248,10 @@ class Admin extends Controller{ return $this->adminObj->saveMailSetting(input('post.')); } + public function SaveAria2Setting(){ + return $this->adminObj->saveAria2Setting(input('post.')); + } + public function SendTestMail(){ return $this->adminObj->sendTestMail(input('post.')); } @@ -482,5 +486,32 @@ class Admin extends Controller{ 'policy' => $this->adminObj->getAvaliablePolicy(), ]); } + + public function RemoteDownload(){ + $this->adminObj->listDownloads(); + return view('download', [ + 'options' => $this->siteOptions, + 'optionsForSet' => Option::getValues(["aria2"]), + 'list' => $this->adminObj->pageData, + 'originList' => $this->adminObj->listData, + 'pageNow' => $this->adminObj->pageNow, + 'pageTotal' => $this->adminObj->pageTotal, + 'dataTotal' => $this->adminObj->dataTotal, + ]); + } + + public function CancelDownload(){ + $aria2Options = Option::getValues(["aria2"]); + $aria2 = new \app\index\model\Aria2($aria2Options); + $downloadItem = Db::name("download")->where("id",input("post.id"))->find(); + if(empty($downloadItem)){ + return json(['error'=>1,'message'=>"未找到下载记录"]); + } + if($aria2->Remove($downloadItem["pid"],"")){ + return json(['error'=>0,'message'=>"下载已取消"]); + }else{ + return json(['error'=>1,'message'=>"取消失败"]); + } + } } diff --git a/application/index/controller/RemoteDownload.php b/application/index/controller/RemoteDownload.php index d09d0f77..e16a1c53 100644 --- a/application/index/controller/RemoteDownload.php +++ b/application/index/controller/RemoteDownload.php @@ -129,7 +129,7 @@ class RemoteDownload extends Controller{ } public function ListDownloading(){ - $downloadItems = Db::name("download")->where("owner",$this->userObj->uid)->where("status","in",["active","ready"])->order('id desc')->select(); + $downloadItems = Db::name("download")->where("owner",$this->userObj->uid)->where("status","in",["active","ready","waiting"])->order('id desc')->select(); foreach ($downloadItems as $key => $value) { $connectInfo = json_decode($value["info"],true); if(isset($connectInfo["dir"])){ @@ -153,7 +153,7 @@ class RemoteDownload extends Controller{ public function ListFinished(){ $page = input("get.page"); - $downloadItems = Db::name("download")->where("owner",$this->userObj->uid)->where("status","not in",["active","ready"])->order('id desc')->page($page.',10')->select(); + $downloadItems = Db::name("download")->where("owner",$this->userObj->uid)->where("status","not in",["active","ready","waiting"])->order('id desc')->page($page.',10')->select(); foreach ($downloadItems as $key => $value) { $connectInfo = json_decode($value["info"],true); if(isset($connectInfo["dir"])){ diff --git a/application/index/model/AdminHandler.php b/application/index/model/AdminHandler.php index 0fa28a24..733d3b67 100644 --- a/application/index/model/AdminHandler.php +++ b/application/index/model/AdminHandler.php @@ -104,6 +104,10 @@ class AdminHandler extends Model{ return $this->saveOptions($options); } + public function saveAria2Setting($options){ + return $this->saveOptions($options); + } + public function saveMailTemplate($options){ return $this->saveOptions($options); } @@ -113,6 +117,7 @@ class AdminHandler extends Model{ unset($options["sizeTimes"]); $options["grade_policy"] = 0; $options["policy_list"] = $options["policy_name"]; + $options["aria2"] = $options["aria2"] ? "1,1,1" : "0,0,0"; try { Db::name("groups")->insert($options); } catch (Exception $e) { @@ -347,6 +352,46 @@ class AdminHandler extends Model{ return $userData; } + public function listDownloads(){ + $pageSize = 10; + $this->pageData = Db::name("download") + ->order("id desc") + ->paginate($pageSize); + $this->dataTotal = Db::name("download") + ->order("id desc") + ->count(); + $this->pageTotal = ceil($this->dataTotal/$pageSize); + $this->listData = $this->pageData->all(); + $userCache=[]; + $userCacheList=[]; + foreach ($this->listData as $key => $value) { + if(in_array($value["owner"], $userCacheList)){ + $this->listData[$key]["user"] = $userCache[$value["owner"]]; + }else{ + $this->listData[$key]["user"] = Db::name("users")->where("id",$value["owner"])->find(); + array_push($userCacheList,$value["owner"]); + $userCache[$value["owner"]] = $this->listData[$key]["user"]; + } + $connectInfo = json_decode($value["info"],true); + if(isset($connectInfo["dir"])){ + $this->listData[$key]["fileName"] = basename($connectInfo["dir"]); + $this->listData[$key]["completedLength"] = $connectInfo["completedLength"]; + $this->listData[$key]["totalLength"] = $connectInfo["totalLength"]; + $this->listData[$key]["downloadSpeed"] = $connectInfo["downloadSpeed"]; + }else{ + if(floor($value["source"])==$value["source"]){ + $this->listData[$key]["fileName"] = Db::name("files")->where("id",$value["source"])->column("orign_name")[0]; + }else{ + $this->listData[$key]["fileName"] = $value["source"]; + } + $this->listData[$key]["completedLength"] = 0; + $this->listData[$key]["totalLength"] = 0; + $this->listData[$key]["downloadSpeed"] = 0; + } + } + $this->pageNow = input("?get.page")?input("get.page"):1; + } + public function listFile(){ $pageSize = !cookie('?pageSize') ? 10 : cookie('pageSize'); $orderType = empty(cookie('orderMethodFile')) ? "id DESC" : cookie('orderMethodFile'); diff --git a/application/index/model/Aria2.php b/application/index/model/Aria2.php index 4fa1745b..88b571f4 100644 --- a/application/index/model/Aria2.php +++ b/application/index/model/Aria2.php @@ -42,7 +42,7 @@ class Aria2 extends Model{ $this->pid = $respondData["result"]; }else{ $this->reqStatus = 0; - $this->reqMsg = $respondData["error"]["message"]; + $this->reqMsg = isset($respondData["error"]["message"]) ? $respondData["error"]["message"] : $this->reqMsg; } } @@ -70,6 +70,11 @@ class Aria2 extends Model{ public function flushStatus($id,$uid,$policy){ $this->uid = $uid; + if(empty($policy)){ + $user = Db::name("users")->where("id",$uid)->find(); + $group = Db::name("groups")->where("id",$user["user_group"])->find(); + $policy = Db::name("policy")->where("id",$group["policy_name"])->find(); + } $this->policy = $policy; $downloadInfo = Db::name("download")->where("id",$id)->find(); if(empty($downloadInfo)){ @@ -148,15 +153,15 @@ class Aria2 extends Model{ }else{ $this->reqStatus = 0; $this->reqMsg = $respondData["error"]["message"]; - $this->setError($respondData,$downloadInfo,$respondData["error"]["message"],"error",false); + $this->setError($respondData,$downloadInfo,$respondData["error"]["message"],"error",true); return false; } return true; } private function setCanceled($quenInfo,$sqlData){ - @self::remove_directory(ROOT_PATH."public".DS."downloads".DS.$sqlData["path_id"]); - if(!is_dir(ROOT_PATH."public".DS."downloads".DS.$sqlData["path_id"])){ + @self::remove_directory($this->savePath.$sqlData["path_id"]); + if(!is_dir($this->savePath.$sqlData["path_id"])){ Db::name("download")->where("id",$sqlData["id"])->update([ "status" => "canceled", ]); diff --git a/application/index/model/CronHandler.php b/application/index/model/CronHandler.php index d57314d7..64263a46 100644 --- a/application/index/model/CronHandler.php +++ b/application/index/model/CronHandler.php @@ -7,6 +7,7 @@ use \think\Session; use \app\index\model\FileManage; use \app\index\model\Option; use \app\index\model\Mail; +use \app\index\model\Aria2; class CronHandler extends Model{ @@ -40,6 +41,11 @@ class CronHandler extends Model{ $this->deleteCallbackData($value["interval_s"]); } break; + case 'flush_aria2': + if($this->checkInterval($value["interval_s"],$value["last_excute"])){ + $this->flushAria2($value["interval_s"]); + } + break; default: # code... break; @@ -69,5 +75,21 @@ class CronHandler extends Model{ $this->setComplete("delete_callback_data"); } + public function flushAria2($interval){ + echo("flushingAria2Status..."); + $aria2Options = Option::getValues(["aria2"]); + $aria2 = new Aria2($aria2Options); + $toBeFlushed = Db::name("download") + ->where("status","<>","complete") + ->where("status","<>","error") + ->where("status","<>","canceled") + ->select(); + foreach ($toBeFlushed as $key => $value) { + $aria2->flushStatus($value["id"],$value["owner"],null); + } + echo("Complete
"); + $this->setComplete("flush_aria2"); + } + } ?> \ No newline at end of file diff --git a/application/index/view/admin/add_group.html b/application/index/view/admin/add_group.html index 7e190809..b4c2aee8 100644 --- a/application/index/view/admin/add_group.html +++ b/application/index/view/admin/add_group.html @@ -113,6 +113,18 @@
是否允许用户使用WebDAV协议同步文件。目前此功能仅支持本地上传方案
+
+
+ +
+
+ +     + +
+
是否允许用户使用离线下载。此功能仅支持本地存储策略,开启前需要到离线下载管理页面设置Aria2接口
+
+
diff --git a/application/index/view/admin/download.html b/application/index/view/admin/download.html new file mode 100644 index 00000000..1f28fe5b --- /dev/null +++ b/application/index/view/admin/download.html @@ -0,0 +1,122 @@ +{extend name="header_admin" /} +{block name="title"}离线下载 - {$options.siteName}{/block} +{block name="content"} +
+
+ + + + +
+
+

离线下载

+
+
+
+ +
+
+
+
+
+
+
+ +
+
+
aria2的RPC服务器地址,请在aria2的配置文件中启用RPC服务。例如:http://127.0.0.1:6800/
+
+
+
+ +
+
+
在配置文件中设置的RPC服务的Token
+
+
+
+ +
+
+
下载文件数据的临时存放目录,请确保PHP对该目录拥有读写权限
+
+
+
+ +
+
+
aria2启动下载的其他附带参数,请以json格式书写。你可也可以将这些设置写在aria2配置文件里。可用参数请查阅官方文档
+
+
+
+
+
+
+


+
+
+
+ +
+ + + + + + + + + + + + + + {volist name='list' id='download'} + + + + + + + + + + {/volist} + + +
#文件名创建者文件大小状态进度操作
{$download.id}{:$originList[$key]['fileName']}{:$originList[$key]['user']["user_nick"]}{:countSize($download.total_size)}{$download.status}{:floor($originList[$key]['completedLength']/$originList[$key]['totalLength']*10000)/100}%{eq name="download.status" value="active"}取消任务{else/} - {/eq}
+ {$list->render()} +
+
+ ddd +
+
+
+

+ +
+
+ + +
+ +
+{/block} +{block name="js"} + + + +{/block} \ No newline at end of file diff --git a/application/index/view/admin/edit_group.html b/application/index/view/admin/edit_group.html index 56a625cc..9706123b 100644 --- a/application/index/view/admin/edit_group.html +++ b/application/index/view/admin/edit_group.html @@ -114,6 +114,18 @@
是否允许用户使用WebDAV协议同步文件。目前此功能仅支持本地上传方案
+
+
+ +
+
+ +     + +
+
是否允许用户使用离线下载。此功能仅支持本地存储策略,开启前需要到离线下载管理页面设置Aria2接口
+
+
@@ -167,5 +179,10 @@ $("input[name='range_transfer'][value='{$group.range_transfer}']").attr("checked $("input[name='allow_share'][value='{$group.allow_share}']").attr("checked",true); $("input[name='color'][value='{$group.color}']").attr("checked",true); $("input[name='webdav'][value='{$group.webdav}']").attr("checked",true); +if('{$group.aria2}'=="1,1,1"){ + $("input[name='aria2'][value='1']").attr("checked",true); +}else{ + $("input[name='aria2'][value='0']").attr("checked",true); +} {/block} \ No newline at end of file diff --git a/application/index/view/header_admin.html b/application/index/view/header_admin.html index e6803ffc..cc0fb556 100644 --- a/application/index/view/header_admin.html +++ b/application/index/view/header_admin.html @@ -76,6 +76,12 @@ 分享 +