From ca1cbb0e064a630bcdb5e6b7bd800140d045b615 Mon Sep 17 00:00:00 2001 From: Exodus4D Date: Sun, 23 Oct 2016 20:08:10 +0200 Subject: [PATCH] - new UI option for "delete expired connections", #219 - new cronjob for "delete expired connections", #219 - fixed "not updating" map changes, closed #357 - improved caching strategy for DB models (file cache) - improved "map sharing" --- app/config.ini | 3 + app/cron.ini | 18 ++- app/lib/db/cortex.php | 15 ++- app/main/controller/api/map.php | 115 ++++++++++-------- app/main/cron/mapupdate.php | 44 ++++++- app/main/model/alliancemapmodel.php | 4 +- app/main/model/alliancemodel.php | 2 +- app/main/model/basicmodel.php | 56 ++++++--- app/main/model/characterlogmodel.php | 47 +++++-- app/main/model/charactermapmodel.php | 4 +- app/main/model/charactermodel.php | 50 +++++++- app/main/model/connectionmodel.php | 12 +- app/main/model/corporationmapmodel.php | 4 +- app/main/model/corporationmodel.php | 2 +- app/main/model/mapmodel.php | 37 +++++- app/main/model/systemmodel.php | 14 +-- app/main/model/systemsignaturemodel.php | 6 - app/pathfinder.ini | 2 + js/app/map/map.js | 2 +- js/app/page.js | 6 +- js/app/ui/dialog/map_settings.js | 26 +++- js/app/ui/form_element.js | 6 +- js/app/util.js | 5 +- public/css/pathfinder.css | 2 +- public/js/v1.1.7/app/map/map.js | 2 +- public/js/v1.1.7/app/page.js | 6 +- .../js/v1.1.7/app/ui/dialog/map_settings.js | 26 +++- public/js/v1.1.7/app/ui/form_element.js | 6 +- public/js/v1.1.7/app/util.js | 5 +- public/templates/dialog/map.html | 19 ++- public/templates/dialog/map_info.html | 2 +- public/templates/dialog/map_manual.html | 4 +- .../select2/theme/pathfinder/_layout.scss | 1 + 33 files changed, 396 insertions(+), 157 deletions(-) diff --git a/app/config.ini b/app/config.ini index 35714b33..cc4bbf54 100644 --- a/app/config.ini +++ b/app/config.ini @@ -1,5 +1,8 @@ ; Global Framework Config +[SERVER] +SERVER_NAME = PATHFINDER + [globals] ; Default Verbosity level of the stack trace. ; Assign values between 0 to 3 for increasing verbosity levels. Check (environment.ini) config for overwriting diff --git a/app/cron.ini b/app/cron.ini index 123aab6e..9eb31085 100644 --- a/app/cron.ini +++ b/app/cron.ini @@ -5,20 +5,26 @@ web = TRUE [CRON.presets] ; run every minute -instant = * * * * * +instant = * * * * * -; run on EVE downtime 11:00 GMT/UTC -downtime = 0 11 * * * +; 12 times per hour (each 5min) +fiveMinutes = */5 * * * * ; 6 times per hour (each 10min) -sixthHour = */10 * * * * +tenMinutes = */10 * * * * ; 2 times per hour (each 30min) -halfHour = */30 * * * * +halfHour = */30 * * * * + +; run on EVE downtime 11:00 GMT/UTC +downtime = 0 11 * * * [CRON.jobs] +; delete expired connections (e.g. EOL) +deleteConnections = Cron\MapUpdate->deleteConnections, @fiveMinutes + ; delete character log data -deleteLogData = Cron\CharacterUpdate->deleteLogData, @sixthHour +deleteLogData = Cron\CharacterUpdate->deleteLogData, @tenMinutes ; delete expired signatures deleteSignatures = Cron\MapUpdate->deleteSignatures, @halfHour diff --git a/app/lib/db/cortex.php b/app/lib/db/cortex.php index cfc9a138..78f035fb 100644 --- a/app/lib/db/cortex.php +++ b/app/lib/db/cortex.php @@ -1074,11 +1074,16 @@ class Cortex extends Cursor { if ($this->emit('beforeerase')===false) return false; if ($this->fieldConf) { - foreach($this->fieldConf as $field => $conf) - if (isset($conf['has-many']) && - $conf['has-many']['hasRel']=='has-many') - $this->set($field,null); - $this->save(); + $changed = false; + foreach($this->fieldConf as $field => $conf){ + if (isset($conf['has-many']) && $conf['has-many']['hasRel']=='has-many'){ + $this->set($field,null); + $changed = true; + } + } + if($changed){ + $this->save(); + } } $this->mapper->erase(); $this->emit('aftererase'); diff --git a/app/main/controller/api/map.php b/app/main/controller/api/map.php index 08850a10..22dd3afa 100644 --- a/app/main/controller/api/map.php +++ b/app/main/controller/api/map.php @@ -374,28 +374,34 @@ class Map extends Controller\AccessController { // share map between characters -> set access if(isset($formData['mapCharacters'])){ + // remove character corporation (re-add later) + $accessCharacters = array_diff($formData['mapCharacters'], [$activeCharacter->_id]); + // avoid abuse -> respect share limits - $accessCharacters = array_slice( $formData['mapCharacters'], 0, $f3->get('PATHFINDER.MAP.PRIVATE.MAX_SHARED') ); + $maxShared = max($f3->get('PATHFINDER.MAP.PRIVATE.MAX_SHARED') - 1, 0); + $accessCharacters = array_slice($accessCharacters, 0, $maxShared); - // clear map access. In case something has removed from access list - $map->clearAccess(); + if($accessCharacters){ + // clear map access. In case something has removed from access list + $map->clearAccess(); - /** - * @var $tempCharacter Model\CharacterModel - */ - $tempCharacter = Model\BasicModel::getNew('CharacterModel'); + /** + * @var $tempCharacter Model\CharacterModel + */ + $tempCharacter = Model\BasicModel::getNew('CharacterModel'); - foreach($accessCharacters as $characterId){ - $tempCharacter->getById( (int)$characterId ); + foreach($accessCharacters as $characterId){ + $tempCharacter->getById( (int)$characterId ); - if( - !$tempCharacter->dry() && - $tempCharacter->shared == 1 // check if map shared is enabled - ){ - $map->setAccess($tempCharacter); + if( + !$tempCharacter->dry() && + $tempCharacter->shared == 1 // check if map shared is enabled + ){ + $map->setAccess($tempCharacter); + } + + $tempCharacter->reset(); } - - $tempCharacter->reset(); } } @@ -411,28 +417,34 @@ class Map extends Controller\AccessController { // share map between corporations -> set access if(isset($formData['mapCorporations'])){ + // remove character corporation (re-add later) + $accessCorporations = array_diff($formData['mapCorporations'], [$corporation->_id]); + // avoid abuse -> respect share limits - $accessCorporations = array_slice( $formData['mapCorporations'], 0, $f3->get('PATHFINDER.MAP.CORPORATION.MAX_SHARED') ); + $maxShared = max($f3->get('PATHFINDER.MAP.CORPORATION.MAX_SHARED') - 1, 0); + $accessCorporations = array_slice($accessCorporations, 0, $maxShared); - // clear map access. In case something has removed from access list - $map->clearAccess(); + if($accessCorporations){ + // clear map access. In case something has removed from access list + $map->clearAccess(); - /** - * @var $tempCorporation Model\CorporationModel - */ - $tempCorporation = Model\BasicModel::getNew('CorporationModel'); + /** + * @var $tempCorporation Model\CorporationModel + */ + $tempCorporation = Model\BasicModel::getNew('CorporationModel'); - foreach($accessCorporations as $corporationId){ - $tempCorporation->getById( (int)$corporationId ); + foreach($accessCorporations as $corporationId){ + $tempCorporation->getById( (int)$corporationId ); - if( - !$tempCorporation->dry() && - $tempCorporation->shared == 1 // check if map shared is enabled - ){ - $map->setAccess($tempCorporation); + if( + !$tempCorporation->dry() && + $tempCorporation->shared == 1 // check if map shared is enabled + ){ + $map->setAccess($tempCorporation); + } + + $tempCorporation->reset(); } - - $tempCorporation->reset(); } } @@ -448,30 +460,35 @@ class Map extends Controller\AccessController { // share map between alliances -> set access if(isset($formData['mapAlliances'])){ + // remove character alliance (re-add later) + $accessAlliances = array_diff($formData['mapAlliances'], [$alliance->_id]); + // avoid abuse -> respect share limits - $accessAlliances = array_slice( $formData['mapAlliances'], 0, $f3->get('PATHFINDER.MAP.ALLIANCE.MAX_SHARED') ); + $maxShared = max($f3->get('PATHFINDER.MAP.ALLIANCE.MAX_SHARED') - 1, 0); + $accessAlliances = array_slice($accessAlliances, 0, $maxShared); - // clear map access. In case something has removed from access list - $map->clearAccess(); + if($accessAlliances){ + // clear map access. In case something has removed from access list + $map->clearAccess(); - /** - * @var $tempAlliance Model\AllianceModel - */ - $tempAlliance = Model\BasicModel::getNew('AllianceModel'); + /** + * @var $tempAlliance Model\AllianceModel + */ + $tempAlliance = Model\BasicModel::getNew('AllianceModel'); - foreach($accessAlliances as $allianceId){ - $tempAlliance->getById( (int)$allianceId ); + foreach($accessAlliances as $allianceId){ + $tempAlliance->getById( (int)$allianceId ); - if( - !$tempAlliance->dry() && - $tempAlliance->shared == 1 // check if map shared is enabled - ){ - $map->setAccess($tempAlliance); + if( + !$tempAlliance->dry() && + $tempAlliance->shared == 1 // check if map shared is enabled + ){ + $map->setAccess($tempAlliance); + } + + $tempAlliance->reset(); } - - $tempAlliance->reset(); } - } // the alliance of the current user should always have access diff --git a/app/main/cron/mapupdate.php b/app/main/cron/mapupdate.php index 6ca8912f..39dc5cfd 100644 --- a/app/main/cron/mapupdate.php +++ b/app/main/cron/mapupdate.php @@ -8,6 +8,7 @@ namespace cron; use DB; +use Model; class MapUpdate { @@ -62,6 +63,48 @@ class MapUpdate { $log->write( sprintf(self::LOG_TEXT_MAPS, __FUNCTION__, $deletedMapsCount) ); } + /** + * delete expired connections (EOL connections) + * >> php index.php "/cron/deleteConnections" + * @param \Base $f3 + */ + function deleteConnections(\Base $f3){ + $eolExpire = (int)$f3->get('PATHFINDER.CACHE.EXPIRE_CONNECTIONS_EOL'); + + if($eolExpire > 0){ + $pfDB = DB\Database::instance()->getDB('PF'); + + $sql = "SELECT + `con`.`id` + FROM + `connection` `con` INNER JOIN + `map` ON + `map`.`id` = `con`.`mapId` + WHERE + `map`.`deleteExpiredConnections` = :deleteExpiredConnections AND + TIMESTAMPDIFF(SECOND, `con`.`eolUpdated`, NOW() ) > :expire_time + "; + + $connectionsData = $pfDB->exec($sql, [ + 'deleteExpiredConnections' => 1, + 'expire_time' => $eolExpire + ]); + + if($connectionsData){ + /** + * @var $connection Model\ConnectionModel + */ + $connection = Model\BasicModel::getNew('ConnectionModel'); + foreach($connectionsData as $data){ + $connection->getById( (int)$data['id'] ); + if( !$connection->dry() ){ + $connection->erase(); + } + } + } + } + } + /** * delete all expired signatures on "inactive" systems * >> php index.php "/cron/deleteSignatures" @@ -84,7 +127,6 @@ class MapUpdate { $pfDB->exec($sqlDeleteExpiredSignatures, ['lifetime' => $signatureExpire]); } - } } \ No newline at end of file diff --git a/app/main/model/alliancemapmodel.php b/app/main/model/alliancemapmodel.php index 9cb3a89e..f8e29c5d 100644 --- a/app/main/model/alliancemapmodel.php +++ b/app/main/model/alliancemapmodel.php @@ -49,9 +49,7 @@ class AllianceMapModel extends BasicModel { * see parent */ public function clearCacheData(){ - parent::clearCacheData(); - - // clear map cache as well + // clear map cache $this->mapId->clearCacheData(); } diff --git a/app/main/model/alliancemodel.php b/app/main/model/alliancemodel.php index 76f414e6..b762fa49 100644 --- a/app/main/model/alliancemodel.php +++ b/app/main/model/alliancemodel.php @@ -41,7 +41,7 @@ class AllianceModel extends BasicModel { /** * get all alliance data - * @return array + * @return \stdClass */ public function getData(){ $allianceData = (object) []; diff --git a/app/main/model/basicmodel.php b/app/main/model/basicmodel.php index 959d0f98..ca541765 100644 --- a/app/main/model/basicmodel.php +++ b/app/main/model/basicmodel.php @@ -92,6 +92,11 @@ abstract class BasicModel extends \DB\Cortex { */ protected $fieldChanges = []; + /** + * default TTL for getData(); cache + */ + const DEFAULT_CACHE_TTL = 120; + public function __construct($db = NULL, $table = NULL, $fluid = NULL, $ttl = 0){ $this->addStaticFieldConfig(); @@ -105,7 +110,6 @@ abstract class BasicModel extends \DB\Cortex { $this->afterinsert(function($self, $pkeys){ $self->afterInsertEvent($self, $pkeys); - $self->clearCacheData(); }); // update events ------------------------------------------------------------------------------------ @@ -115,7 +119,6 @@ abstract class BasicModel extends \DB\Cortex { $this->afterupdate( function($self, $pkeys){ $self->afterUpdateEvent($self, $pkeys); - $self->clearCacheData(); }); // erase events ------------------------------------------------------------------------------------- @@ -318,6 +321,14 @@ abstract class BasicModel extends \DB\Cortex { return $valid; } + /** + * get key for for all objects in this table + * @return string + */ + private function getTableCacheKey(){ + return $this->dataCacheKeyPrefix .'.' . strtoupper($this->table); + } + /** * get the cache key for this model * ->do not set a key if the model is not saved! @@ -329,14 +340,12 @@ abstract class BasicModel extends \DB\Cortex { // set a model unique cache key if the model is saved if( $this->id > 0){ + $cacheKey = $this->getTableCacheKey(); + // check if there is a given key prefix // -> if not, use the standard key. // this is useful for caching multiple data sets according to one row entry - - $cacheKey = $this->dataCacheKeyPrefix; - $cacheKey .= '.' . strtoupper($this->table); - - if($dataCacheTableKeyPrefix){ + if( !empty($dataCacheTableKeyPrefix) ){ $cacheKey .= '.' . $dataCacheTableKeyPrefix . '_'; }else{ $cacheKey .= '.ID_'; @@ -353,13 +362,14 @@ abstract class BasicModel extends \DB\Cortex { * @return \stdClass|null */ protected function getCacheData($dataCacheKeyPrefix = ''){ - - $cacheKey = $this->getCacheKey($dataCacheKeyPrefix); $cacheData = null; + // table cache exists + // -> check cache for this row data + $cacheKey = $this->getCacheKey($dataCacheKeyPrefix); + if( !is_null($cacheKey) ){ $f3 = self::getF3(); - if( $f3->exists($cacheKey) ){ $cacheData = $f3->get( $cacheKey ); } @@ -374,15 +384,14 @@ abstract class BasicModel extends \DB\Cortex { * @param string $dataCacheKeyPrefix * @param int $data_ttl */ - public function updateCacheData($cacheData, $dataCacheKeyPrefix = '', $data_ttl = 300){ - + public function updateCacheData($cacheData, $dataCacheKeyPrefix = '', $data_ttl = self::DEFAULT_CACHE_TTL){ $cacheDataTmp = (array)$cacheData; // check if data should be cached // and cacheData is not empty if( $data_ttl > 0 && - !empty( $cacheDataTmp ) + !empty($cacheDataTmp) ){ $cacheKey = $this->getCacheKey($dataCacheKeyPrefix); @@ -394,13 +403,30 @@ abstract class BasicModel extends \DB\Cortex { /** * unset the getData() cache for this object + * -> see also clearCacheDataWithPrefix(), for more information */ public function clearCacheData(){ $cacheKey = $this->getCacheKey(); + $this->clearCache($cacheKey); + } - if( !is_null($cacheKey) ){ + /** + * unset object cached data by prefix + * -> primarily used by object cache with multiple data caches + * @param string $dataCacheKeyPrefix + */ + public function clearCacheDataWithPrefix($dataCacheKeyPrefix = ''){ + $cacheKey = $this->getCacheKey($dataCacheKeyPrefix); + $this->clearCache($cacheKey); + } + + /** + * unset object cached data (if exists) + * @param $cacheKey + */ + private function clearCache($cacheKey){ + if( !empty($cacheKey) ){ $f3 = self::getF3(); - if( $f3->exists($cacheKey) ){ $f3->clear($cacheKey); } diff --git a/app/main/model/characterlogmodel.php b/app/main/model/characterlogmodel.php index 2d9b8dc2..dc6e0cb8 100644 --- a/app/main/model/characterlogmodel.php +++ b/app/main/model/characterlogmodel.php @@ -16,14 +16,6 @@ class CharacterLogModel extends BasicModel { protected $table = 'character_log'; - /** - * caching for relational data - * -> 5s matches REST API - Expire: Header-Data - * for "Location" calls - * @var int - */ - protected $rel_ttl = 5; - protected $fieldConf = [ 'active' => [ 'type' => Schema::DT_BOOL, @@ -203,6 +195,45 @@ class CharacterLogModel extends BasicModel { return $systemId; } + /** + * Event "Hook" function + * return false will stop any further action + * @param self $self + * @param $pkeys + */ + public function afterInsertEvent($self, $pkeys){ + $self->clearCacheData(); + } + + /** + * Event "Hook" function + * return false will stop any further action + * @param self $self + * @param $pkeys + */ + public function afterUpdateEvent($self, $pkeys){ + $self->clearCacheData(); + } + + /** + * Event "Hook" function + * can be overwritten + * @param self $self + * @param $pkeys + */ + public function afterEraseEvent($self, $pkeys){ + $self->clearCacheData(); + } + + /** + * see parent + */ + public function clearCacheData(){ + // clear character "LOG" cache + // -> character data without "LOG" has not changed! + $this->characterId->clearCacheDataWithPrefix(CharacterModel::DATA_CACHE_KEY_LOG); + } + /** * update session data for active character * @param int $systemId diff --git a/app/main/model/charactermapmodel.php b/app/main/model/charactermapmodel.php index fadb8793..1ca0366f 100644 --- a/app/main/model/charactermapmodel.php +++ b/app/main/model/charactermapmodel.php @@ -49,9 +49,7 @@ class CharacterMapModel extends BasicModel { * see parent */ public function clearCacheData(){ - parent::clearCacheData(); - - // clear map cache as well + // clear map cache $this->mapId->clearCacheData(); } diff --git a/app/main/model/charactermodel.php b/app/main/model/charactermodel.php index b81089b5..caf68659 100644 --- a/app/main/model/charactermodel.php +++ b/app/main/model/charactermodel.php @@ -16,6 +16,11 @@ class CharacterModel extends BasicModel { protected $table = 'character'; + /** + * cache key prefix for getData(); result WITH log data + */ + const DATA_CACHE_KEY_LOG = 'LOG'; + protected $fieldConf = [ 'lastLogin' => [ 'type' => Schema::DT_TIMESTAMP, @@ -107,15 +112,15 @@ class CharacterModel extends BasicModel { $cacheKeyModifier = ''; // check if there is cached data + // -> IMPORTANT: $addCharacterLogData is optional! -> therefore we need 2 cache keys! if($addCharacterLogData){ - $cacheKeyModifier = strtoupper($this->table) . '_LOG'; + $cacheKeyModifier = self::DATA_CACHE_KEY_LOG; } - $characterData = $this->getCacheData($cacheKeyModifier); if(is_null($characterData)){ - // no cached character data found + $characterData = (object) []; $characterData->id = $this->id; $characterData->name = $this->name; @@ -140,7 +145,7 @@ class CharacterModel extends BasicModel { // max caching time for a system // the cached date has to be cleared manually on any change // this includes system, connection,... changes (all dependencies) - $this->updateCacheData($characterData, $cacheKeyModifier, 10); + $this->updateCacheData($characterData, $cacheKeyModifier); } return $characterData; @@ -180,6 +185,43 @@ class CharacterModel extends BasicModel { return $accessToken; } + /** + * Event "Hook" function + * @param self $self + * @param $pkeys + */ + public function afterInsertEvent($self, $pkeys){ + $self->clearCacheData(); + } + + /** + * Event "Hook" function + * @param self $self + * @param $pkeys + */ + public function afterUpdateEvent($self, $pkeys){ + $self->clearCacheData(); + } + + /** + * Event "Hook" function + * @param self $self + * @param $pkeys + */ + public function afterEraseEvent($self, $pkeys){ + $self->clearCacheData(); + } + + /** + * see parent + */ + public function clearCacheData(){ + parent::clearCacheData(); + + // clear data with "log" as well! + parent::clearCacheDataWithPrefix(self::DATA_CACHE_KEY_LOG); + } + /** * check whether this character has already a user assigned to it * @return bool diff --git a/app/main/model/connectionmodel.php b/app/main/model/connectionmodel.php index 70a6abe6..0b50281c 100644 --- a/app/main/model/connectionmodel.php +++ b/app/main/model/connectionmodel.php @@ -224,8 +224,7 @@ class ConnectionModel extends BasicModel{ * @param $pkeys */ public function afterInsertEvent($self, $pkeys){ - parent::afterInsertEvent($self, $pkeys); - + $self->clearCacheData(); $self->logActivity('connectionCreate'); } @@ -236,8 +235,7 @@ class ConnectionModel extends BasicModel{ * @param $pkeys */ public function afterUpdateEvent($self, $pkeys){ - parent::afterUpdateEvent($self, $pkeys); - + $self->clearCacheData(); $self->logActivity('connectionUpdate'); } @@ -248,8 +246,7 @@ class ConnectionModel extends BasicModel{ * @param $pkeys */ public function afterEraseEvent($self, $pkeys){ - parent::afterUpdateEvent($self, $pkeys); - + $self->clearCacheData(); $self->logActivity('connectionDelete'); } @@ -302,9 +299,6 @@ class ConnectionModel extends BasicModel{ * see parent */ public function clearCacheData(){ - parent::clearCacheData(); - - // clear map cache as well $this->mapId->clearCacheData(); } diff --git a/app/main/model/corporationmapmodel.php b/app/main/model/corporationmapmodel.php index 0cac06d2..35a16e50 100644 --- a/app/main/model/corporationmapmodel.php +++ b/app/main/model/corporationmapmodel.php @@ -49,9 +49,7 @@ class CorporationMapModel extends BasicModel { * see parent */ public function clearCacheData(){ - parent::clearCacheData(); - - // clear map cache as well + // clear map cache $this->mapId->clearCacheData(); } diff --git a/app/main/model/corporationmodel.php b/app/main/model/corporationmodel.php index e9148021..240f8158 100644 --- a/app/main/model/corporationmodel.php +++ b/app/main/model/corporationmodel.php @@ -46,7 +46,7 @@ class CorporationModel extends BasicModel { /** * get all cooperation data - * @return array + * @return \stdClass */ public function getData(){ $cooperationData = (object) []; diff --git a/app/main/model/mapmodel.php b/app/main/model/mapmodel.php index 0293444f..ecf672cf 100644 --- a/app/main/model/mapmodel.php +++ b/app/main/model/mapmodel.php @@ -55,6 +55,11 @@ class MapModel extends BasicModel { 'nullable' => false, 'default' => '' ], + 'deleteExpiredConnections' => [ + 'type' => Schema::DT_BOOL, + 'nullable' => false, + 'default' => 1 + ], 'systems' => [ 'has-many' => ['Model\SystemModel', 'mapId'] ], @@ -134,6 +139,7 @@ class MapModel extends BasicModel { $mapData->id = $this->id; $mapData->name = $this->name; $mapData->icon = $this->icon; + $mapData->deleteExpiredConnections = $this->deleteExpiredConnections; $mapData->created = strtotime($this->created); $mapData->updated = strtotime($this->updated); @@ -194,12 +200,39 @@ class MapModel extends BasicModel { // max caching time for a map // the cached date has to be cleared manually on any change // this includes system, connection,... changes (all dependencies) - $this->updateCacheData($mapDataAll, '', 300); + $this->updateCacheData($mapDataAll); } return $mapDataAll; } + /** + * Event "Hook" function + * @param self $self + * @param $pkeys + */ + public function afterInsertEvent($self, $pkeys){ + $self->clearCacheData(); + } + + /** + * Event "Hook" function + * @param self $self + * @param $pkeys + */ + public function afterUpdateEvent($self, $pkeys){ + $self->clearCacheData(); + } + + /** + * Event "Hook" function + * @param self $self + * @param $pkeys + */ + public function afterEraseEvent($self, $pkeys){ + $self->clearCacheData(); + } + /** * get blank system model pre-filled with default SDE data * -> check for "inactive" systems on this map first! @@ -531,7 +564,7 @@ class MapModel extends BasicModel { /** * get data for all characters that are currently online "viewing" this map - * -> the result of this function is cached! + * -> The result of this function is cached! * @return \stdClass[] */ private function getCharactersData(){ diff --git a/app/main/model/systemmodel.php b/app/main/model/systemmodel.php index a5708fc6..c6213cb6 100644 --- a/app/main/model/systemmodel.php +++ b/app/main/model/systemmodel.php @@ -277,7 +277,7 @@ class SystemModel extends BasicModel { // max caching time for a system // the cached date has to be cleared manually on any change // this includes system, connection,... changes (all dependencies) - $this->updateCacheData($systemData, '', 300); + $this->updateCacheData($systemData); } return $systemData; @@ -358,19 +358,16 @@ class SystemModel extends BasicModel { /** * Event "Hook" function - * return false will stop any further action * @param self $self * @param $pkeys */ public function afterInsertEvent($self, $pkeys){ - parent::afterInsertEvent($self, $pkeys); - + $self->clearCacheData(); $self->logActivity('systemCreate'); } /** * Event "Hook" function - * can be overwritten * return false will stop any further action * @param self $self * @param $pkeys @@ -397,12 +394,11 @@ class SystemModel extends BasicModel { /** * Event "Hook" function - * return false will stop any further action * @param self $self * @param $pkeys */ public function afterUpdateEvent($self, $pkeys){ - parent::afterUpdateEvent($self, $pkeys); + $self->clearCacheData(); // check if rally point mail should be send if( @@ -418,13 +414,11 @@ class SystemModel extends BasicModel { /** * Event "Hook" function - * can be overwritten * @param self $self * @param $pkeys */ public function afterEraseEvent($self, $pkeys){ - parent::afterUpdateEvent($self, $pkeys); - + $self->clearCacheData(); $self->logActivity('systemDelete'); } diff --git a/app/main/model/systemsignaturemodel.php b/app/main/model/systemsignaturemodel.php index be5baa0e..44385146 100644 --- a/app/main/model/systemsignaturemodel.php +++ b/app/main/model/systemsignaturemodel.php @@ -183,8 +183,6 @@ class SystemSignatureModel extends BasicModel { * @param $pkeys */ public function afterInsertEvent($self, $pkeys){ - parent::afterInsertEvent($self, $pkeys); - $self->logActivity('signatureCreate'); } @@ -195,8 +193,6 @@ class SystemSignatureModel extends BasicModel { * @param $pkeys */ public function afterUpdateEvent($self, $pkeys){ - parent::afterUpdateEvent($self, $pkeys); - $self->logActivity('signatureUpdate'); } @@ -207,8 +203,6 @@ class SystemSignatureModel extends BasicModel { * @param $pkeys */ public function afterEraseEvent($self, $pkeys){ - parent::afterUpdateEvent($self, $pkeys); - $self->logActivity('signatureDelete'); } diff --git a/app/pathfinder.ini b/app/pathfinder.ini index 1098f0c3..5409a6de 100644 --- a/app/pathfinder.ini +++ b/app/pathfinder.ini @@ -119,6 +119,8 @@ CHARACTER_LOG = 300 CONSTELLATION_SYSTEMS = 1728000 ; max expire time. Expired cache files will be deleted by cronjob (seconds) (default: 10d) EXPIRE_MAX = 864000 +; expire time for EOL (end of life) connections (seconds) (default: 4h + 15min) +EXPIRE_CONNECTIONS_EOL = 15300 ; expire time for signatures (inactive systems) (seconds) (default 3d) EXPIRE_SIGNATURES = 259200 diff --git a/js/app/map/map.js b/js/app/map/map.js index 71d2f228..290626f2 100644 --- a/js/app/map/map.js +++ b/js/app/map/map.js @@ -1406,7 +1406,7 @@ define([ var moduleData = { id: config.mapContextMenuId, items: [ - {icon: 'fa-info', action: 'info', text: 'info'}, + {icon: 'fa-street-view', action: 'info', text: 'information'}, {icon: 'fa-plus', action: 'add_system', text: 'add system'}, {icon: 'fa-object-ungroup', action: 'select_all', text: 'select all'}, {icon: 'fa-filter', action: 'filter_scope', text: 'filter scope', subitems: [ diff --git a/js/app/page.js b/js/app/page.js index 55dbc220..da6e900b 100644 --- a/js/app/page.js +++ b/js/app/page.js @@ -279,9 +279,9 @@ define([ $('', { class: 'list-group-item', href: '#' - }).html('  Status').prepend( + }).html('  Information').prepend( $('',{ - class: 'fa fa-info fa-fw' + class: 'fa fa-street-view fa-fw' }) ).on('click', function(){ $(document).triggerMenuEvent('ShowMapInfo'); @@ -292,7 +292,7 @@ define([ $('', { class: 'list-group-item', href: '#' - }).html('  Map config').prepend( + }).html('  Configuration').prepend( $('',{ class: 'fa fa-gears fa-fw' }) diff --git a/js/app/ui/dialog/map_settings.js b/js/app/ui/dialog/map_settings.js index 1d492c64..2191fd76 100644 --- a/js/app/ui/dialog/map_settings.js +++ b/js/app/ui/dialog/map_settings.js @@ -20,6 +20,8 @@ define([ dialogMapSettingsContainerId: 'pf-map-dialog-settings', // id for the "settings" container dialogMapDownloadContainerId: 'pf-map-dialog-download', // id for the "download" container + deleteExpiredConnectionsId: 'pf-map-dialog-delete-connections', // id for "deleteExpiredConnections" checkbox + characterSelectId: 'pf-map-dialog-character-select', // id for "character" select corporationSelectId: 'pf-map-dialog-corporation-select', // id for "corporation" select allianceSelectId: 'pf-map-dialog-alliance-select', // id for "alliance" select @@ -103,6 +105,7 @@ define([ var accessCharacter = []; var accessCorporation = []; var accessAlliance = []; + var deleteExpiredConnections = true; if(mapData !== false){ // set current map information @@ -115,6 +118,8 @@ define([ accessCharacter = mapData.config.access.character; accessCorporation = mapData.config.access.corporation; accessAlliance = mapData.config.access.alliance; + + deleteExpiredConnections = mapData.config.deleteExpiredConnections; } // render main dialog ----------------------------------------------------- @@ -144,6 +149,9 @@ define([ hideDownloadTab: hideDownloadTab, // settings tab -------------- + deleteExpiredConnectionsId : config.deleteExpiredConnectionsId, + deleteExpiredConnections: deleteExpiredConnections, + characterSelectId: config.characterSelectId, corporationSelectId: config.corporationSelectId, allianceSelectId: config.allianceSelectId, @@ -207,10 +215,10 @@ define([ var selectField = $(this); var selectValues = selectField.val(); - if(selectValues === null){ - selectField.parents('.form-group').addClass('has-error'); - }else{ + if(selectValues.length > 0){ selectField.parents('.form-group').removeClass('has-error'); + }else{ + selectField.parents('.form-group').addClass('has-error'); } }); @@ -223,12 +231,20 @@ define([ var dialogContent = mapInfoDialog.find('.modal-content'); dialogContent.showLoadingAnimation(); - var newMapData = {formData: form.getFormValues()}; + // get form data + var formData = form.getFormValues(); + + // checkbox fix -> settings tab + if( form.find('#' + config.deleteExpiredConnectionsId).length ){ + formData.deleteExpiredConnections = formData.hasOwnProperty('deleteExpiredConnections') ? parseInt( formData.deleteExpiredConnections ) : 0; + } + + var requestData = {formData: formData}; $.ajax({ type: 'POST', url: Init.path.saveMap, - data: newMapData, + data: requestData, dataType: 'json' }).done(function(responseData){ diff --git a/js/app/ui/form_element.js b/js/app/ui/form_element.js index 665eb33b..36b6cfe8 100644 --- a/js/app/ui/form_element.js +++ b/js/app/ui/form_element.js @@ -139,7 +139,7 @@ define([ placeholder: 'System name', allowClear: true, maximumSelectionLength: options.maxSelectionLength, - escapeMarkup: function (markup) { + escapeMarkup: function(markup){ // let our custom formatter work return markup; } @@ -257,12 +257,12 @@ define([ dropdownParent: selectElement.parents('.modal-body'), theme: 'pathfinder', minimumInputLength: 3, - placeholder: '', + placeholder: options.type + ' names', allowClear: false, maximumSelectionLength: options.maxSelectionLength, templateResult: formatResultData, templateSelection: formatSelectionData, - escapeMarkup: function (markup) { + escapeMarkup: function(markup){ // let our custom formatter work return markup; } diff --git a/js/app/util.js b/js/app/util.js index 25d41582..3618a524 100644 --- a/js/app/util.js +++ b/js/app/util.js @@ -1469,7 +1469,10 @@ define([ var currentMapUserData = false; - if( mapId === parseInt(mapId, 10) ){ + if( + mapId === parseInt(mapId, 10) && + Init.currentMapUserData + ){ // search for a specific map for(var i = 0; i < Init.currentMapUserData.length; i++){ if(Init.currentMapUserData[i].config.id === mapId){ diff --git a/public/css/pathfinder.css b/public/css/pathfinder.css index 791dd464..74a098d9 100644 --- a/public/css/pathfinder.css +++ b/public/css/pathfinder.css @@ -32,7 +32,7 @@ * Licensed under the Apache License v2.0 * http://www.apache.org/licenses/LICENSE-2.0 * - */.datepicker{padding:4px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;direction:ltr}.datepicker-inline{width:220px}.datepicker.datepicker-rtl{direction:rtl}.datepicker.datepicker-rtl table tr td span{float:right}.datepicker-dropdown{top:0;left:0}.datepicker-dropdown:before{content:'';display:inline-block;border-left:7px solid transparent;border-right:7px solid transparent;border-bottom:7px solid #ccc;border-bottom-color:rgba(0,0,0,0.2);position:absolute;top:-7px;left:6px}.datepicker-dropdown:after{content:'';display:inline-block;border-left:6px solid transparent;border-right:6px solid transparent;border-bottom:6px solid #ffffff;position:absolute;top:-6px;left:7px}.datepicker>div{display:none}.datepicker.days div.datepicker-days{display:block}.datepicker.months div.datepicker-months{display:block}.datepicker.years div.datepicker-years{display:block}.datepicker table{margin:0}.datepicker td,.datepicker th{text-align:center;width:20px;height:20px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;border:none}.table-striped .datepicker table tr td,.table-striped .datepicker table tr th{background-color:transparent}.datepicker table tr td.day:hover{background:#eeeeee;cursor:pointer}.datepicker table tr td.old,.datepicker table tr td.new{color:#999999}.datepicker table tr td.disabled,.datepicker table tr td.disabled:hover{background:none;color:#999999;cursor:default}.datepicker table tr td.today,.datepicker table tr td.today:hover,.datepicker table tr td.today.disabled,.datepicker table tr td.today.disabled:hover{background-color:#fde19a;background-image:-moz-linear-gradient(top, #fdd49a, #fdf59a);background-image:-ms-linear-gradient(top, #fdd49a, #fdf59a);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#fdd49a), to(#fdf59a));background-image:-webkit-linear-gradient(top, #fdd49a, #fdf59a);background-image:-o-linear-gradient(top, #fdd49a, #fdf59a);background-image:linear-gradient(to bottom, #fdd49a,#fdf59a);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fdd49a', endColorstr='#fdf59a', GradientType=0);border-color:#fdf59a #fdf59a #fbed50;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);color:#000}.datepicker table tr td.today:hover,.datepicker table tr td.today:hover:hover,.datepicker table tr td.today.disabled:hover,.datepicker table tr td.today.disabled:hover:hover,.datepicker table tr td.today:active,.datepicker table tr td.today:hover:active,.datepicker table tr td.today.disabled:active,.datepicker table tr td.today.disabled:hover:active,.datepicker table tr td.today.active,.datepicker table tr td.today:hover.active,.datepicker table tr td.today.disabled.active,.datepicker table tr td.today.disabled:hover.active,.datepicker table tr td.today.disabled,.datepicker table tr td.today:hover.disabled,.datepicker table tr td.today.disabled.disabled,.datepicker table tr td.today.disabled:hover.disabled,.datepicker table tr td.today[disabled],.datepicker table tr td.today:hover[disabled],.datepicker table tr td.today.disabled[disabled],.datepicker table tr td.today.disabled:hover[disabled]{background-color:#fdf59a}.datepicker table tr td.today:active,.datepicker table tr td.today:hover:active,.datepicker table tr td.today.disabled:active,.datepicker table tr td.today.disabled:hover:active,.datepicker table tr td.today.active,.datepicker table tr td.today:hover.active,.datepicker table tr td.today.disabled.active,.datepicker table tr td.today.disabled:hover.active{background-color:#fbf069 \9}.datepicker table tr td.today:hover:hover{color:#000}.datepicker table tr td.today.active:hover{color:#fff}.datepicker table tr td.range,.datepicker table tr td.range:hover,.datepicker table tr td.range.disabled,.datepicker table tr td.range.disabled:hover{background:#eeeeee;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.datepicker table tr td.range.today,.datepicker table tr td.range.today:hover,.datepicker table tr td.range.today.disabled,.datepicker table tr td.range.today.disabled:hover{background-color:#f3d17a;background-image:-moz-linear-gradient(top, #f3c17a, #f3e97a);background-image:-ms-linear-gradient(top, #f3c17a, #f3e97a);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#f3c17a), to(#f3e97a));background-image:-webkit-linear-gradient(top, #f3c17a, #f3e97a);background-image:-o-linear-gradient(top, #f3c17a, #f3e97a);background-image:linear-gradient(to bottom, #f3c17a,#f3e97a);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#f3c17a', endColorstr='#f3e97a', GradientType=0);border-color:#f3e97a #f3e97a #edde34;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.datepicker table tr td.range.today:hover,.datepicker table tr td.range.today:hover:hover,.datepicker table tr td.range.today.disabled:hover,.datepicker table tr td.range.today.disabled:hover:hover,.datepicker table tr td.range.today:active,.datepicker table tr td.range.today:hover:active,.datepicker table tr td.range.today.disabled:active,.datepicker table tr td.range.today.disabled:hover:active,.datepicker table tr td.range.today.active,.datepicker table tr td.range.today:hover.active,.datepicker table tr td.range.today.disabled.active,.datepicker table tr td.range.today.disabled:hover.active,.datepicker table tr td.range.today.disabled,.datepicker table tr td.range.today:hover.disabled,.datepicker table tr td.range.today.disabled.disabled,.datepicker table tr td.range.today.disabled:hover.disabled,.datepicker table tr td.range.today[disabled],.datepicker table tr td.range.today:hover[disabled],.datepicker table tr td.range.today.disabled[disabled],.datepicker table tr td.range.today.disabled:hover[disabled]{background-color:#f3e97a}.datepicker table tr td.range.today:active,.datepicker table tr td.range.today:hover:active,.datepicker table tr td.range.today.disabled:active,.datepicker table tr td.range.today.disabled:hover:active,.datepicker table tr td.range.today.active,.datepicker table tr td.range.today:hover.active,.datepicker table tr td.range.today.disabled.active,.datepicker table tr td.range.today.disabled:hover.active{background-color:#efe24b \9}.datepicker table tr td.selected,.datepicker table tr td.selected:hover,.datepicker table tr td.selected.disabled,.datepicker table tr td.selected.disabled:hover{background-color:#9e9e9e;background-image:-moz-linear-gradient(top, #b3b3b3, gray);background-image:-ms-linear-gradient(top, #b3b3b3, gray);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#b3b3b3), to(gray));background-image:-webkit-linear-gradient(top, #b3b3b3, gray);background-image:-o-linear-gradient(top, #b3b3b3, gray);background-image:linear-gradient(to bottom, #b3b3b3,#808080);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#b3b3b3', endColorstr='#808080', GradientType=0);border-color:#808080 #808080 #595959;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25)}.datepicker table tr td.selected:hover,.datepicker table tr td.selected:hover:hover,.datepicker table tr td.selected.disabled:hover,.datepicker table tr td.selected.disabled:hover:hover,.datepicker table tr td.selected:active,.datepicker table tr td.selected:hover:active,.datepicker table tr td.selected.disabled:active,.datepicker table tr td.selected.disabled:hover:active,.datepicker table tr td.selected.active,.datepicker table tr td.selected:hover.active,.datepicker table tr td.selected.disabled.active,.datepicker table tr td.selected.disabled:hover.active,.datepicker table tr td.selected.disabled,.datepicker table tr td.selected:hover.disabled,.datepicker table tr td.selected.disabled.disabled,.datepicker table tr td.selected.disabled:hover.disabled,.datepicker table tr td.selected[disabled],.datepicker table tr td.selected:hover[disabled],.datepicker table tr td.selected.disabled[disabled],.datepicker table tr td.selected.disabled:hover[disabled]{background-color:#808080}.datepicker table tr td.selected:active,.datepicker table tr td.selected:hover:active,.datepicker table tr td.selected.disabled:active,.datepicker table tr td.selected.disabled:hover:active,.datepicker table tr td.selected.active,.datepicker table tr td.selected:hover.active,.datepicker table tr td.selected.disabled.active,.datepicker table tr td.selected.disabled:hover.active{background-color:#666666 \9}.datepicker table tr td.active,.datepicker table tr td.active:hover,.datepicker table tr td.active.disabled,.datepicker table tr td.active.disabled:hover{background-color:#006dcc;background-image:-moz-linear-gradient(top, #08c, #04c);background-image:-ms-linear-gradient(top, #08c, #04c);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#08c), to(#04c));background-image:-webkit-linear-gradient(top, #08c, #04c);background-image:-o-linear-gradient(top, #08c, #04c);background-image:linear-gradient(to bottom, #0088cc,#0044cc);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc', endColorstr='#0044cc', GradientType=0);border-color:#0044cc #0044cc #002a80;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25)}.datepicker table tr td.active:hover,.datepicker table tr td.active:hover:hover,.datepicker table tr td.active.disabled:hover,.datepicker table tr td.active.disabled:hover:hover,.datepicker table tr td.active:active,.datepicker table tr td.active:hover:active,.datepicker table tr td.active.disabled:active,.datepicker table tr td.active.disabled:hover:active,.datepicker table tr td.active.active,.datepicker table tr td.active:hover.active,.datepicker table tr td.active.disabled.active,.datepicker table tr td.active.disabled:hover.active,.datepicker table tr td.active.disabled,.datepicker table tr td.active:hover.disabled,.datepicker table tr td.active.disabled.disabled,.datepicker table tr td.active.disabled:hover.disabled,.datepicker table tr td.active[disabled],.datepicker table tr td.active:hover[disabled],.datepicker table tr td.active.disabled[disabled],.datepicker table tr td.active.disabled:hover[disabled]{background-color:#0044cc}.datepicker table tr td.active:active,.datepicker table tr td.active:hover:active,.datepicker table tr td.active.disabled:active,.datepicker table tr td.active.disabled:hover:active,.datepicker table tr td.active.active,.datepicker table tr td.active:hover.active,.datepicker table tr td.active.disabled.active,.datepicker table tr td.active.disabled:hover.active{background-color:#003399 \9}.datepicker table tr td span{display:block;width:23%;height:54px;line-height:54px;float:left;margin:1%;cursor:pointer;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.datepicker table tr td span:hover{background:#eeeeee}.datepicker table tr td span.disabled,.datepicker table tr td span.disabled:hover{background:none;color:#999999;cursor:default}.datepicker table tr td span.active,.datepicker table tr td span.active:hover,.datepicker table tr td span.active.disabled,.datepicker table tr td span.active.disabled:hover{background-color:#006dcc;background-image:-moz-linear-gradient(top, #08c, #04c);background-image:-ms-linear-gradient(top, #08c, #04c);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#08c), to(#04c));background-image:-webkit-linear-gradient(top, #08c, #04c);background-image:-o-linear-gradient(top, #08c, #04c);background-image:linear-gradient(to bottom, #0088cc,#0044cc);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc', endColorstr='#0044cc', GradientType=0);border-color:#0044cc #0044cc #002a80;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25)}.datepicker table tr td span.active:hover,.datepicker table tr td span.active:hover:hover,.datepicker table tr td span.active.disabled:hover,.datepicker table tr td span.active.disabled:hover:hover,.datepicker table tr td span.active:active,.datepicker table tr td span.active:hover:active,.datepicker table tr td span.active.disabled:active,.datepicker table tr td span.active.disabled:hover:active,.datepicker table tr td span.active.active,.datepicker table tr td span.active:hover.active,.datepicker table tr td span.active.disabled.active,.datepicker table tr td span.active.disabled:hover.active,.datepicker table tr td span.active.disabled,.datepicker table tr td span.active:hover.disabled,.datepicker table tr td span.active.disabled.disabled,.datepicker table tr td span.active.disabled:hover.disabled,.datepicker table tr td span.active[disabled],.datepicker table tr td span.active:hover[disabled],.datepicker table tr td span.active.disabled[disabled],.datepicker table tr td span.active.disabled:hover[disabled]{background-color:#0044cc}.datepicker table tr td span.active:active,.datepicker table tr td span.active:hover:active,.datepicker table tr td span.active.disabled:active,.datepicker table tr td span.active.disabled:hover:active,.datepicker table tr td span.active.active,.datepicker table tr td span.active:hover.active,.datepicker table tr td span.active.disabled.active,.datepicker table tr td span.active.disabled:hover.active{background-color:#003399 \9}.datepicker table tr td span.old,.datepicker table tr td span.new{color:#999999}.datepicker th.datepicker-switch{width:145px}.datepicker thead tr:first-child th,.datepicker tfoot tr th{cursor:pointer}.datepicker thead tr:first-child th:hover,.datepicker tfoot tr th:hover{background:#eeeeee}.datepicker .cw{font-size:10px;width:12px;padding:0 2px 0 5px;vertical-align:middle}.datepicker thead tr:first-child th.cw{cursor:default;background-color:transparent}.input-append.date .add-on i,.input-prepend.date .add-on i{display:block;cursor:pointer;width:16px;height:16px}.input-daterange input{text-align:center}.input-daterange input:first-child{-webkit-border-radius:3px 0 0 3px;-moz-border-radius:3px 0 0 3px;border-radius:3px 0 0 3px}.input-daterange input:last-child{-webkit-border-radius:0 3px 3px 0;-moz-border-radius:0 3px 3px 0;border-radius:0 3px 3px 0}.input-daterange .add-on{display:inline-block;width:auto;min-width:16px;height:18px;padding:4px 5px;font-weight:normal;line-height:18px;text-align:center;text-shadow:0 1px 0 #ffffff;vertical-align:middle;background-color:#eeeeee;border:1px solid #ccc;margin-left:-5px;margin-right:-5px}.ui-pnotify{top:36px;right:36px;position:absolute;height:auto;z-index:2}body>.ui-pnotify{position:fixed;z-index:100040}.ui-pnotify-modal-overlay{background-color:rgba(0,0,0,0.4);top:0;left:0;position:absolute;height:100%;width:100%;z-index:1}body>.ui-pnotify-modal-overlay{position:fixed;z-index:100039}.ui-pnotify.ui-pnotify-in{display:block !important}.ui-pnotify.ui-pnotify-move{transition:left .5s ease, top .5s ease, right .5s ease, bottom .5s ease}.ui-pnotify.ui-pnotify-fade-slow{transition:opacity .6s linear;opacity:0}.ui-pnotify.ui-pnotify-fade-slow.ui-pnotify.ui-pnotify-move{transition:opacity .6s linear, left .5s ease, top .5s ease, right .5s ease, bottom .5s ease}.ui-pnotify.ui-pnotify-fade-normal{transition:opacity .4s linear;opacity:0}.ui-pnotify.ui-pnotify-fade-normal.ui-pnotify.ui-pnotify-move{transition:opacity .4s linear, left .5s ease, top .5s ease, right .5s ease, bottom .5s ease}.ui-pnotify.ui-pnotify-fade-fast{transition:opacity .2s linear;opacity:0}.ui-pnotify.ui-pnotify-fade-fast.ui-pnotify.ui-pnotify-move{transition:opacity .2s linear, left .5s ease, top .5s ease, right .5s ease, bottom .5s ease}.ui-pnotify.ui-pnotify-fade-in{opacity:1}.ui-pnotify .ui-pnotify-shadow{-webkit-box-shadow:0px 6px 28px 0px rgba(0,0,0,0.1);-moz-box-shadow:0px 6px 28px 0px rgba(0,0,0,0.1);box-shadow:0px 6px 28px 0px rgba(0,0,0,0.1)}.ui-pnotify-container{background-position:0 0;padding:.8em;height:100%;margin:0}.ui-pnotify-container:after{content:" ";visibility:hidden;display:block;height:0;clear:both}.ui-pnotify-container.ui-pnotify-sharp{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.ui-pnotify-title{display:block;margin-bottom:.4em;margin-top:0}.ui-pnotify-text{display:block}.ui-pnotify-icon,.ui-pnotify-icon span{display:block;float:left;margin-right:.2em}.ui-pnotify.stack-topleft,.ui-pnotify.stack-bottomleft{left:25px;right:auto}.ui-pnotify.stack-bottomright,.ui-pnotify.stack-bottomleft{bottom:25px;top:auto}.ui-pnotify.stack-modal{left:50%;right:auto;margin-left:-150px}.ui-pnotify.ui-pnotify-nonblock-fade{opacity:.2}.ui-pnotify.ui-pnotify-nonblock-hide{display:none !important}.ui-pnotify.stack-bar-bottom{margin-left:15%;margin-bottom:25px;right:auto;bottom:0;top:auto;left:auto}html,body,#sb-site,.sb-site-container,.sb-slidebar{margin:0;padding:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html,body{width:100%;overflow-x:hidden}html{height:100%}body{min-height:100%;height:auto;position:relative}html.sb-scroll-lock.sb-active:not(.sb-static){overflow:hidden}#sb-site,.sb-site-container{width:100%;position:relative;z-index:1;background:url("../img/pf-bg.jpg") #05050a;background-repeat:no-repeat}.sb-slidebar{height:100%;overflow-y:auto;position:fixed;top:0;z-index:0;display:none;background-color:#313335;-webkit-transform:translate(0px)}.sb-left{left:0;-webkit-box-shadow:inset -5px 0px 10px 0px rgba(0,0,0,0.4);box-shadow:inset -5px 0px 10px 0px rgba(0,0,0,0.4)}.sb-right{right:0;-webkit-box-shadow:inset 5px 0px 10px 0px rgba(0,0,0,0.4);box-shadow:inset 5px 0px 10px 0px rgba(0,0,0,0.4)}html.sb-static .sb-slidebar,.sb-slidebar.sb-static{position:absolute}.sb-slidebar.sb-active{display:block}.sb-style-overlay{z-index:9999}.sb-momentum-scrolling{-webkit-overflow-scrolling:touch}.sb-slidebar{width:30%}.sb-width-thin{width:15%}.sb-width-wide{width:45%}@media (max-width: 480px){.sb-slidebar{width:70%}.sb-width-thin{width:55%}.sb-width-wide{width:85%}}@media (min-width: 481px){.sb-slidebar{width:55%}.sb-width-thin{width:40%}.sb-width-wide{width:70%}}@media (min-width: 768px){.sb-slidebar{width:40%}.sb-width-thin{width:25%}.sb-width-wide{width:55%}}@media (min-width: 992px){.sb-slidebar{width:30%}.sb-width-thin{width:15%}.sb-width-wide{width:45%}}@media (min-width: 1200px){.sb-slidebar{width:20%}.sb-width-thin{width:5%}.sb-width-wide{width:35%}}.sb-slide,#sb-site,.sb-site-container,.sb-slidebar{-webkit-transition:transform 180ms ease-out;transition:transform 180ms ease-out;-webkit-transition-property:-webkit-transform, left, right;-webkit-backface-visibility:hidden}.sb-hide{display:none}.pf-pie-chart{position:relative;display:table-cell;text-align:center;vertical-align:middle}.pf-pie-chart span{display:inline-block}.pf-pie-chart canvas{position:absolute;top:0;left:0}.pf-pie-chart-map-timer{width:36px;height:36px;margin:3px}.pf-pie-chart-map-timer canvas{top:3px;left:3px}.pf-pie-chart-map-timer span{font-size:10px}.pf-pie-chart-map-timer span:after{content:'s';margin-left:1px}div.pf-map-drag-to-select{background:#375959 !important;display:block;visibility:hidden;opacity:0;z-index:9000;border:1px dashed #adadad;will-change:left, top, width, height, opacity;-moz-border-radius:5px;-webkit-border-radius:5px;border-radius:5px;-webkit-transition:opacity 0.15s linear;transition:opacity 0.15s linear}div.pf-map-drag-to-select.active{visibility:visible;opacity:0.3}.select2-container{box-sizing:border-box;display:inline-block;margin:0;position:relative;vertical-align:middle}.select2-container .select2-selection--single{box-sizing:border-box;cursor:pointer;display:block;height:28px;user-select:none;-webkit-user-select:none}.select2-container .select2-selection--single .select2-selection__rendered{display:block;padding-left:8px;padding-right:20px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.select2-container[dir="rtl"] .select2-selection--single .select2-selection__rendered{padding-right:8px;padding-left:20px}.select2-container .select2-selection--multiple{box-sizing:border-box;cursor:pointer;display:block;min-height:32px;user-select:none;-webkit-user-select:none}.select2-container .select2-selection--multiple .select2-selection__rendered{display:inline-block;overflow:hidden;padding-left:8px;text-overflow:ellipsis;white-space:nowrap}.select2-container .select2-search--inline{float:left}.select2-container .select2-search--inline .select2-search__field{box-sizing:border-box;border:none;font-size:100%;margin-top:5px}.select2-container .select2-search--inline .select2-search__field::-webkit-search-cancel-button{-webkit-appearance:none}.select2-dropdown{background-color:white;border:1px solid #aaa;border-radius:4px;box-sizing:border-box;display:block;position:absolute;left:-100000px;width:100%;z-index:1051}.select2-results{display:block}.select2-results__options{list-style:none;margin:0;padding:0}.select2-results__option{padding:6px;color:#adadad;user-select:none;-webkit-user-select:none}.select2-results__option[aria-selected]{cursor:pointer}.select2-container--open .select2-dropdown{left:0}.select2-container--open .select2-dropdown--above{border-bottom:none;border-bottom-left-radius:0;border-bottom-right-radius:0}.select2-container--open .select2-dropdown--below{border-top:none;border-top-left-radius:0;border-top-right-radius:0}.select2-search--dropdown{display:block;padding:4px}.select2-search--dropdown .select2-search__field{padding:4px;width:100%;box-sizing:border-box}.select2-search--dropdown .select2-search__field::-webkit-search-cancel-button{-webkit-appearance:none}.select2-search--dropdown.select2-search--hide{display:none}.select2-close-mask{border:0;margin:0;padding:0;display:block;position:fixed;left:0;top:0;min-height:100%;min-width:100%;height:auto;width:auto;opacity:0;z-index:99;background-color:#fff;filter:alpha(opacity=0)}.select2-hidden-accessible{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.select2-container--pathfinder .select2-selection--single{background-color:#313335;border:1px solid #63676a;border-radius:0px;outline:0}.select2-container--pathfinder .select2-selection--single:focus{border:1px solid #568a89}.select2-container--pathfinder .select2-selection--single .select2-selection__rendered{color:#adadad;line-height:28px}.select2-container--pathfinder .select2-selection--single .select2-selection__clear{color:#a52521;cursor:pointer;float:right;font-weight:bold;margin-right:3px;margin-left:10px}.select2-container--pathfinder .select2-selection--single .select2-selection__clear:hover{color:#58100d}.select2-container--pathfinder .select2-selection--single .select2-selection__placeholder{color:#63676a}.select2-container--pathfinder .select2-selection--single .select2-selection__arrow{background-color:#313335;border:none;border-left:none;border-top-right-radius:0px;border-bottom-right-radius:0px;height:26px;position:absolute;top:1px;right:1px;width:20px}.select2-container--pathfinder .select2-selection--single .select2-selection__arrow b{border-color:#888 transparent transparent transparent;border-style:solid;border-width:5px 4px 0 4px;height:0;left:50%;margin-left:-4px;margin-top:-2px;position:absolute;top:50%;width:0}.select2-container--pathfinder[dir="rtl"] .select2-selection--single .select2-selection__clear{float:left}.select2-container--pathfinder[dir="rtl"] .select2-selection--single .select2-selection__arrow{border:none;border-right:1px solid #63676a;border-radius:0;border-top-left-radius:0px;border-bottom-left-radius:0px;left:1px;right:auto}.select2-container--pathfinder.select2-container--open .select2-selection--single{border:1px solid #568a89}.select2-container--pathfinder.select2-container--open .select2-selection--single .select2-selection__arrow{background:transparent;border:none}.select2-container--pathfinder.select2-container--open .select2-selection--single .select2-selection__arrow b{border-color:transparent transparent #888 transparent;border-width:0 4px 5px 4px}.select2-container--pathfinder.select2-container--open.select2-container--above .select2-selection--single{border-top:none;border-top-left-radius:0;border-top-right-radius:0}.select2-container--pathfinder.select2-container--open.select2-container--below .select2-selection--single{border-bottom:none;border-bottom-left-radius:0;border-bottom-right-radius:0}.select2-container--pathfinder .select2-selection--multiple{background-color:#313335;color:#313335;border:1px solid #63676a;border-radius:0px;cursor:text;outline:0}.select2-container--pathfinder .select2-selection--multiple:focus{border:1px solid #568a89}.select2-container--pathfinder .select2-selection--multiple .select2-selection__rendered{list-style:none;margin:0;padding:0 5px;width:100%}.select2-container--pathfinder .select2-selection--multiple .select2-selection__clear{display:none}.select2-container--pathfinder .select2-selection--multiple .select2-selection__choice{background-color:#adadad;border:1px solid #63676a;border-radius:4px;cursor:default;float:left;margin-right:5px;margin-top:5px;padding:0 5px}.select2-container--pathfinder .select2-selection--multiple .select2-selection__choice__remove{color:#a52521;cursor:pointer;display:inline-block;font-weight:bold;margin-right:2px}.select2-container--pathfinder .select2-selection--multiple .select2-selection__choice__remove:hover{color:#58100d}.select2-container--pathfinder .select2-selection--multiple .select2-selection__placeholder{color:#63676a}.select2-container--pathfinder[dir="rtl"] .select2-selection--multiple .select2-selection__choice{float:right}.select2-container--pathfinder[dir="rtl"] .select2-selection--multiple .select2-selection__choice{margin-left:5px;margin-right:auto}.select2-container--pathfinder[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove{margin-left:2px;margin-right:auto}.select2-container--pathfinder.select2-container--open .select2-selection--multiple{border:1px solid #568a89}.select2-container--pathfinder.select2-container--open.select2-container--above .select2-selection--multiple{border-top:none;border-top-left-radius:0;border-top-right-radius:0}.select2-container--pathfinder.select2-container--open.select2-container--below .select2-selection--multiple{border-bottom:none;border-bottom-left-radius:0;border-bottom-right-radius:0}.select2-container--pathfinder .select2-search--dropdown .select2-search__field{border:1px solid #63676a;outline:0}.select2-container--pathfinder .select2-search--inline .select2-search__field{outline:0}.select2-container--pathfinder .select2-dropdown{background-color:#313335;border:1px solid transparent;overflow:hidden;-webkit-box-shadow:0 6px 12px rgba(0,0,0,0.3);box-shadow:0 6px 12px rgba(0,0,0,0.3)}.select2-container--pathfinder .select2-dropdown--above{border-bottom:none}.select2-container--pathfinder .select2-dropdown--below{border-top:none}.select2-container--pathfinder .select2-results>.select2-results__options{max-height:200px;overflow-y:auto}.select2-container--pathfinder .select2-results__option[role=group]{padding:0}.select2-container--pathfinder .select2-results__option[aria-disabled=true],.select2-container--pathfinder .select2-results__option[aria-selected=true]{color:#63676a;background-color:#3c3f41}.select2-container--pathfinder .select2-results__option[aria-disabled=true] .pf-select-item-anchor:before,.select2-container--pathfinder .select2-results__option[aria-selected=true] .pf-select-item-anchor:before{content:"\f05e";font-family:FontAwesome;font-size:9px;position:absolute;left:0;top:0;color:#63676a}.select2-container--pathfinder .select2-results__option--highlighted[aria-selected]{background-color:#adadad;color:#313335}.select2-container--pathfinder .select2-results__group{cursor:default;display:block;padding:6px}.select2-container--pathfinder.select2-container--open .select2-dropdown{border-color:#568a89}select.select2-hidden-accessible{-moz-appearance:none;-webkit-appearance:none}.blueimp-gallery,.blueimp-gallery>.slides>.slide>.slide-content{position:absolute;top:0;right:0;bottom:0;left:0;-moz-backface-visibility:hidden}.blueimp-gallery>.slides>.slide>.slide-content{margin:auto;width:auto;height:auto;max-width:100%;max-height:100%;opacity:1}.blueimp-gallery{position:fixed;z-index:999999;overflow:hidden;background:#000;background:rgba(0,0,0,0.9);opacity:0;display:none;direction:ltr;-ms-touch-action:none;touch-action:none}.blueimp-gallery-carousel{position:relative;z-index:auto;margin:1em auto;padding-bottom:56.25%;-webkit-box-shadow:0 4px 10px rgba(0,0,0,0.4);box-shadow:0 4px 10px rgba(0,0,0,0.4);-moz-border-radius:5px;-webkit-border-radius:5px;border-radius:5px;-ms-touch-action:pan-y;touch-action:pan-y}.blueimp-gallery-display{display:block;opacity:1}.blueimp-gallery>.slides{position:relative;height:100%;overflow:hidden}.blueimp-gallery-carousel>.slides{position:absolute}.blueimp-gallery>.slides>.slide{position:relative;float:left;height:100%;text-align:center;will-change:all;-webkit-transition-timing-function:cubic-bezier(0.645, 0.045, 0.355, 1);-moz-transition-timing-function:cubic-bezier(0.645, 0.045, 0.355, 1);-ms-transition-timing-function:cubic-bezier(0.645, 0.045, 0.355, 1);-o-transition-timing-function:cubic-bezier(0.645, 0.045, 0.355, 1);transition-timing-function:cubic-bezier(0.645, 0.045, 0.355, 1)}.blueimp-gallery,.blueimp-gallery>.slides>.slide>.slide-content{-webkit-transition:opacity 0.5s linear;-moz-transition:opacity 0.5s linear;-ms-transition:opacity 0.5s linear;-o-transition:opacity 0.5s linear;transition:opacity 0.5s linear}.blueimp-gallery>.slides>.slide-loading{background-size:64px 64px}.blueimp-gallery>.slides>.slide-loading>.slide-content{opacity:0}.blueimp-gallery>.slides>.slide-error>.slide-content{display:none}.blueimp-gallery>.prev,.blueimp-gallery>.next{position:absolute;top:50%;left:15px;width:35px;height:35px;margin-top:-17px;font-size:22px;line-height:35px;color:#63676a;text-decoration:none;text-align:center;background:rgba(0,0,0,0.2);-moz-border-radius:5px;-webkit-border-radius:5px;border-radius:5px;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-transition:color 0.09s linear;transition:color 0.09s linear;will-change:color;opacity:1;cursor:pointer;display:none}.blueimp-gallery>.next{left:auto;right:15px}.blueimp-gallery>.close,.blueimp-gallery>.title{position:absolute;bottom:15px;left:15px;margin:0 40px 0 0;font-size:14px;line-height:14px;font-font:"Oxygen Bold","Helvetica Neue",Helvetica,Arial,sans-serif;color:#63676a;text-shadow:0 1px 3px #1d1d1d;opacity:1;display:none}.blueimp-gallery>.title{margin-left:20px}.blueimp-gallery>.title:before{content:'\f101';font-family:'FontAwesome';position:absolute;top:-1px;left:-20px;height:14px;width:14px}.blueimp-gallery>.close{padding:15px;right:15px;left:auto;margin:-15px;font-size:30px;text-decoration:none;cursor:pointer}.blueimp-gallery>.play-pause{position:absolute;right:15px;bottom:15px;width:35px;height:35px;font-size:22px;line-height:35px;text-align:center;background:rgba(0,0,0,0.2);-moz-border-radius:5px;-webkit-border-radius:5px;border-radius:5px;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-transition:color 0.09s linear;transition:color 0.09s linear;will-change:color;color:#e28a0d;cursor:pointer;opacity:1;display:none}.blueimp-gallery-playing>.play-pause{color:#2b2b2b}.blueimp-gallery>.prev:hover,.blueimp-gallery>.next:hover,.blueimp-gallery>.close:hover,.blueimp-gallery>.play-pause:hover{color:#e28a0d}.blueimp-gallery-controls>.prev,.blueimp-gallery-controls>.next,.blueimp-gallery-controls>.close,.blueimp-gallery-controls>.title,.blueimp-gallery-controls>.play-pause{display:block;-webkit-transform:translateZ(0);-moz-transform:translateZ(0);-ms-transform:translateZ(0);-o-transform:translateZ(0);transform:translateZ(0)}.blueimp-gallery-single>.prev,.blueimp-gallery-left>.prev,.blueimp-gallery-single>.next,.blueimp-gallery-right>.next,.blueimp-gallery-single>.play-pause{display:none}.blueimp-gallery>.slides>.slide>.slide-content,.blueimp-gallery>.prev,.blueimp-gallery>.next,.blueimp-gallery>.close,.blueimp-gallery>.play-pause{-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}body:last-child .blueimp-gallery-playing>.play-pause{background-position:-20px 0}*+html .blueimp-gallery>.slides>.slide{min-height:300px}*+html .blueimp-gallery>.slides>.slide>.slide-content{position:relative}.blueimp-gallery>.slides>.slide>.text-content{overflow:auto;margin:0 auto;overflow:hidden;text-align:left}.blueimp-gallery .modal-body{position:relative;text-align:center;padding:0 0 56.25% 0;overflow:hidden;cursor:pointer}.blueimp-gallery .modal-footer{margin:0}.blueimp-gallery .modal-body img,.blueimp-gallery .modal-body .video-content video,.blueimp-gallery .modal-body .video-content iframe,.blueimp-gallery .modal-body .video-content a{max-width:100%;max-height:100%;margin:auto;position:absolute;top:0;right:0;bottom:0;left:0}.blueimp-gallery .modal-body .video-content video{display:none}.blueimp-gallery .modal-body .video-playing video{display:block}.blueimp-gallery .modal-body .video-content iframe{width:100%;height:100%;border:none;left:100%}.blueimp-gallery .modal-body .video-playing iframe{left:0}.blueimp-gallery .modal-body .video-playing img,.blueimp-gallery .modal-body .video-playing a{display:none}.blueimp-gallery .modal-body .video-content a{cursor:pointer}.blueimp-gallery .modal-body .video-content a:after{font-family:"Glyphicons Halflings";-webkit-font-smoothing:antialiased;content:"\e029";font-size:64px;line-height:64px;width:64px;height:64px;position:absolute;top:50%;margin:-32px 0 0 -32px}.blueimp-gallery .modal-body .video-loading a{background:url(../img/loading.gif) center no-repeat;background-size:64px 64px}.blueimp-gallery .modal-body .video-loading a:after{content:none}@media screen and (min-width: 768px){.blueimp-gallery .modal-dialog{right:auto;left:auto;width:auto;max-width:1200px;padding-left:5%;padding-right:5%}}/*! ======================================================================== + */.datepicker{padding:4px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;direction:ltr}.datepicker-inline{width:220px}.datepicker.datepicker-rtl{direction:rtl}.datepicker.datepicker-rtl table tr td span{float:right}.datepicker-dropdown{top:0;left:0}.datepicker-dropdown:before{content:'';display:inline-block;border-left:7px solid transparent;border-right:7px solid transparent;border-bottom:7px solid #ccc;border-bottom-color:rgba(0,0,0,0.2);position:absolute;top:-7px;left:6px}.datepicker-dropdown:after{content:'';display:inline-block;border-left:6px solid transparent;border-right:6px solid transparent;border-bottom:6px solid #ffffff;position:absolute;top:-6px;left:7px}.datepicker>div{display:none}.datepicker.days div.datepicker-days{display:block}.datepicker.months div.datepicker-months{display:block}.datepicker.years div.datepicker-years{display:block}.datepicker table{margin:0}.datepicker td,.datepicker th{text-align:center;width:20px;height:20px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;border:none}.table-striped .datepicker table tr td,.table-striped .datepicker table tr th{background-color:transparent}.datepicker table tr td.day:hover{background:#eeeeee;cursor:pointer}.datepicker table tr td.old,.datepicker table tr td.new{color:#999999}.datepicker table tr td.disabled,.datepicker table tr td.disabled:hover{background:none;color:#999999;cursor:default}.datepicker table tr td.today,.datepicker table tr td.today:hover,.datepicker table tr td.today.disabled,.datepicker table tr td.today.disabled:hover{background-color:#fde19a;background-image:-moz-linear-gradient(top, #fdd49a, #fdf59a);background-image:-ms-linear-gradient(top, #fdd49a, #fdf59a);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#fdd49a), to(#fdf59a));background-image:-webkit-linear-gradient(top, #fdd49a, #fdf59a);background-image:-o-linear-gradient(top, #fdd49a, #fdf59a);background-image:linear-gradient(to bottom, #fdd49a,#fdf59a);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fdd49a', endColorstr='#fdf59a', GradientType=0);border-color:#fdf59a #fdf59a #fbed50;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);color:#000}.datepicker table tr td.today:hover,.datepicker table tr td.today:hover:hover,.datepicker table tr td.today.disabled:hover,.datepicker table tr td.today.disabled:hover:hover,.datepicker table tr td.today:active,.datepicker table tr td.today:hover:active,.datepicker table tr td.today.disabled:active,.datepicker table tr td.today.disabled:hover:active,.datepicker table tr td.today.active,.datepicker table tr td.today:hover.active,.datepicker table tr td.today.disabled.active,.datepicker table tr td.today.disabled:hover.active,.datepicker table tr td.today.disabled,.datepicker table tr td.today:hover.disabled,.datepicker table tr td.today.disabled.disabled,.datepicker table tr td.today.disabled:hover.disabled,.datepicker table tr td.today[disabled],.datepicker table tr td.today:hover[disabled],.datepicker table tr td.today.disabled[disabled],.datepicker table tr td.today.disabled:hover[disabled]{background-color:#fdf59a}.datepicker table tr td.today:active,.datepicker table tr td.today:hover:active,.datepicker table tr td.today.disabled:active,.datepicker table tr td.today.disabled:hover:active,.datepicker table tr td.today.active,.datepicker table tr td.today:hover.active,.datepicker table tr td.today.disabled.active,.datepicker table tr td.today.disabled:hover.active{background-color:#fbf069 \9}.datepicker table tr td.today:hover:hover{color:#000}.datepicker table tr td.today.active:hover{color:#fff}.datepicker table tr td.range,.datepicker table tr td.range:hover,.datepicker table tr td.range.disabled,.datepicker table tr td.range.disabled:hover{background:#eeeeee;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.datepicker table tr td.range.today,.datepicker table tr td.range.today:hover,.datepicker table tr td.range.today.disabled,.datepicker table tr td.range.today.disabled:hover{background-color:#f3d17a;background-image:-moz-linear-gradient(top, #f3c17a, #f3e97a);background-image:-ms-linear-gradient(top, #f3c17a, #f3e97a);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#f3c17a), to(#f3e97a));background-image:-webkit-linear-gradient(top, #f3c17a, #f3e97a);background-image:-o-linear-gradient(top, #f3c17a, #f3e97a);background-image:linear-gradient(to bottom, #f3c17a,#f3e97a);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#f3c17a', endColorstr='#f3e97a', GradientType=0);border-color:#f3e97a #f3e97a #edde34;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.datepicker table tr td.range.today:hover,.datepicker table tr td.range.today:hover:hover,.datepicker table tr td.range.today.disabled:hover,.datepicker table tr td.range.today.disabled:hover:hover,.datepicker table tr td.range.today:active,.datepicker table tr td.range.today:hover:active,.datepicker table tr td.range.today.disabled:active,.datepicker table tr td.range.today.disabled:hover:active,.datepicker table tr td.range.today.active,.datepicker table tr td.range.today:hover.active,.datepicker table tr td.range.today.disabled.active,.datepicker table tr td.range.today.disabled:hover.active,.datepicker table tr td.range.today.disabled,.datepicker table tr td.range.today:hover.disabled,.datepicker table tr td.range.today.disabled.disabled,.datepicker table tr td.range.today.disabled:hover.disabled,.datepicker table tr td.range.today[disabled],.datepicker table tr td.range.today:hover[disabled],.datepicker table tr td.range.today.disabled[disabled],.datepicker table tr td.range.today.disabled:hover[disabled]{background-color:#f3e97a}.datepicker table tr td.range.today:active,.datepicker table tr td.range.today:hover:active,.datepicker table tr td.range.today.disabled:active,.datepicker table tr td.range.today.disabled:hover:active,.datepicker table tr td.range.today.active,.datepicker table tr td.range.today:hover.active,.datepicker table tr td.range.today.disabled.active,.datepicker table tr td.range.today.disabled:hover.active{background-color:#efe24b \9}.datepicker table tr td.selected,.datepicker table tr td.selected:hover,.datepicker table tr td.selected.disabled,.datepicker table tr td.selected.disabled:hover{background-color:#9e9e9e;background-image:-moz-linear-gradient(top, #b3b3b3, gray);background-image:-ms-linear-gradient(top, #b3b3b3, gray);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#b3b3b3), to(gray));background-image:-webkit-linear-gradient(top, #b3b3b3, gray);background-image:-o-linear-gradient(top, #b3b3b3, gray);background-image:linear-gradient(to bottom, #b3b3b3,#808080);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#b3b3b3', endColorstr='#808080', GradientType=0);border-color:#808080 #808080 #595959;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25)}.datepicker table tr td.selected:hover,.datepicker table tr td.selected:hover:hover,.datepicker table tr td.selected.disabled:hover,.datepicker table tr td.selected.disabled:hover:hover,.datepicker table tr td.selected:active,.datepicker table tr td.selected:hover:active,.datepicker table tr td.selected.disabled:active,.datepicker table tr td.selected.disabled:hover:active,.datepicker table tr td.selected.active,.datepicker table tr td.selected:hover.active,.datepicker table tr td.selected.disabled.active,.datepicker table tr td.selected.disabled:hover.active,.datepicker table tr td.selected.disabled,.datepicker table tr td.selected:hover.disabled,.datepicker table tr td.selected.disabled.disabled,.datepicker table tr td.selected.disabled:hover.disabled,.datepicker table tr td.selected[disabled],.datepicker table tr td.selected:hover[disabled],.datepicker table tr td.selected.disabled[disabled],.datepicker table tr td.selected.disabled:hover[disabled]{background-color:#808080}.datepicker table tr td.selected:active,.datepicker table tr td.selected:hover:active,.datepicker table tr td.selected.disabled:active,.datepicker table tr td.selected.disabled:hover:active,.datepicker table tr td.selected.active,.datepicker table tr td.selected:hover.active,.datepicker table tr td.selected.disabled.active,.datepicker table tr td.selected.disabled:hover.active{background-color:#666666 \9}.datepicker table tr td.active,.datepicker table tr td.active:hover,.datepicker table tr td.active.disabled,.datepicker table tr td.active.disabled:hover{background-color:#006dcc;background-image:-moz-linear-gradient(top, #08c, #04c);background-image:-ms-linear-gradient(top, #08c, #04c);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#08c), to(#04c));background-image:-webkit-linear-gradient(top, #08c, #04c);background-image:-o-linear-gradient(top, #08c, #04c);background-image:linear-gradient(to bottom, #0088cc,#0044cc);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc', endColorstr='#0044cc', GradientType=0);border-color:#0044cc #0044cc #002a80;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25)}.datepicker table tr td.active:hover,.datepicker table tr td.active:hover:hover,.datepicker table tr td.active.disabled:hover,.datepicker table tr td.active.disabled:hover:hover,.datepicker table tr td.active:active,.datepicker table tr td.active:hover:active,.datepicker table tr td.active.disabled:active,.datepicker table tr td.active.disabled:hover:active,.datepicker table tr td.active.active,.datepicker table tr td.active:hover.active,.datepicker table tr td.active.disabled.active,.datepicker table tr td.active.disabled:hover.active,.datepicker table tr td.active.disabled,.datepicker table tr td.active:hover.disabled,.datepicker table tr td.active.disabled.disabled,.datepicker table tr td.active.disabled:hover.disabled,.datepicker table tr td.active[disabled],.datepicker table tr td.active:hover[disabled],.datepicker table tr td.active.disabled[disabled],.datepicker table tr td.active.disabled:hover[disabled]{background-color:#0044cc}.datepicker table tr td.active:active,.datepicker table tr td.active:hover:active,.datepicker table tr td.active.disabled:active,.datepicker table tr td.active.disabled:hover:active,.datepicker table tr td.active.active,.datepicker table tr td.active:hover.active,.datepicker table tr td.active.disabled.active,.datepicker table tr td.active.disabled:hover.active{background-color:#003399 \9}.datepicker table tr td span{display:block;width:23%;height:54px;line-height:54px;float:left;margin:1%;cursor:pointer;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.datepicker table tr td span:hover{background:#eeeeee}.datepicker table tr td span.disabled,.datepicker table tr td span.disabled:hover{background:none;color:#999999;cursor:default}.datepicker table tr td span.active,.datepicker table tr td span.active:hover,.datepicker table tr td span.active.disabled,.datepicker table tr td span.active.disabled:hover{background-color:#006dcc;background-image:-moz-linear-gradient(top, #08c, #04c);background-image:-ms-linear-gradient(top, #08c, #04c);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#08c), to(#04c));background-image:-webkit-linear-gradient(top, #08c, #04c);background-image:-o-linear-gradient(top, #08c, #04c);background-image:linear-gradient(to bottom, #0088cc,#0044cc);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc', endColorstr='#0044cc', GradientType=0);border-color:#0044cc #0044cc #002a80;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25)}.datepicker table tr td span.active:hover,.datepicker table tr td span.active:hover:hover,.datepicker table tr td span.active.disabled:hover,.datepicker table tr td span.active.disabled:hover:hover,.datepicker table tr td span.active:active,.datepicker table tr td span.active:hover:active,.datepicker table tr td span.active.disabled:active,.datepicker table tr td span.active.disabled:hover:active,.datepicker table tr td span.active.active,.datepicker table tr td span.active:hover.active,.datepicker table tr td span.active.disabled.active,.datepicker table tr td span.active.disabled:hover.active,.datepicker table tr td span.active.disabled,.datepicker table tr td span.active:hover.disabled,.datepicker table tr td span.active.disabled.disabled,.datepicker table tr td span.active.disabled:hover.disabled,.datepicker table tr td span.active[disabled],.datepicker table tr td span.active:hover[disabled],.datepicker table tr td span.active.disabled[disabled],.datepicker table tr td span.active.disabled:hover[disabled]{background-color:#0044cc}.datepicker table tr td span.active:active,.datepicker table tr td span.active:hover:active,.datepicker table tr td span.active.disabled:active,.datepicker table tr td span.active.disabled:hover:active,.datepicker table tr td span.active.active,.datepicker table tr td span.active:hover.active,.datepicker table tr td span.active.disabled.active,.datepicker table tr td span.active.disabled:hover.active{background-color:#003399 \9}.datepicker table tr td span.old,.datepicker table tr td span.new{color:#999999}.datepicker th.datepicker-switch{width:145px}.datepicker thead tr:first-child th,.datepicker tfoot tr th{cursor:pointer}.datepicker thead tr:first-child th:hover,.datepicker tfoot tr th:hover{background:#eeeeee}.datepicker .cw{font-size:10px;width:12px;padding:0 2px 0 5px;vertical-align:middle}.datepicker thead tr:first-child th.cw{cursor:default;background-color:transparent}.input-append.date .add-on i,.input-prepend.date .add-on i{display:block;cursor:pointer;width:16px;height:16px}.input-daterange input{text-align:center}.input-daterange input:first-child{-webkit-border-radius:3px 0 0 3px;-moz-border-radius:3px 0 0 3px;border-radius:3px 0 0 3px}.input-daterange input:last-child{-webkit-border-radius:0 3px 3px 0;-moz-border-radius:0 3px 3px 0;border-radius:0 3px 3px 0}.input-daterange .add-on{display:inline-block;width:auto;min-width:16px;height:18px;padding:4px 5px;font-weight:normal;line-height:18px;text-align:center;text-shadow:0 1px 0 #ffffff;vertical-align:middle;background-color:#eeeeee;border:1px solid #ccc;margin-left:-5px;margin-right:-5px}.ui-pnotify{top:36px;right:36px;position:absolute;height:auto;z-index:2}body>.ui-pnotify{position:fixed;z-index:100040}.ui-pnotify-modal-overlay{background-color:rgba(0,0,0,0.4);top:0;left:0;position:absolute;height:100%;width:100%;z-index:1}body>.ui-pnotify-modal-overlay{position:fixed;z-index:100039}.ui-pnotify.ui-pnotify-in{display:block !important}.ui-pnotify.ui-pnotify-move{transition:left .5s ease, top .5s ease, right .5s ease, bottom .5s ease}.ui-pnotify.ui-pnotify-fade-slow{transition:opacity .6s linear;opacity:0}.ui-pnotify.ui-pnotify-fade-slow.ui-pnotify.ui-pnotify-move{transition:opacity .6s linear, left .5s ease, top .5s ease, right .5s ease, bottom .5s ease}.ui-pnotify.ui-pnotify-fade-normal{transition:opacity .4s linear;opacity:0}.ui-pnotify.ui-pnotify-fade-normal.ui-pnotify.ui-pnotify-move{transition:opacity .4s linear, left .5s ease, top .5s ease, right .5s ease, bottom .5s ease}.ui-pnotify.ui-pnotify-fade-fast{transition:opacity .2s linear;opacity:0}.ui-pnotify.ui-pnotify-fade-fast.ui-pnotify.ui-pnotify-move{transition:opacity .2s linear, left .5s ease, top .5s ease, right .5s ease, bottom .5s ease}.ui-pnotify.ui-pnotify-fade-in{opacity:1}.ui-pnotify .ui-pnotify-shadow{-webkit-box-shadow:0px 6px 28px 0px rgba(0,0,0,0.1);-moz-box-shadow:0px 6px 28px 0px rgba(0,0,0,0.1);box-shadow:0px 6px 28px 0px rgba(0,0,0,0.1)}.ui-pnotify-container{background-position:0 0;padding:.8em;height:100%;margin:0}.ui-pnotify-container:after{content:" ";visibility:hidden;display:block;height:0;clear:both}.ui-pnotify-container.ui-pnotify-sharp{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.ui-pnotify-title{display:block;margin-bottom:.4em;margin-top:0}.ui-pnotify-text{display:block}.ui-pnotify-icon,.ui-pnotify-icon span{display:block;float:left;margin-right:.2em}.ui-pnotify.stack-topleft,.ui-pnotify.stack-bottomleft{left:25px;right:auto}.ui-pnotify.stack-bottomright,.ui-pnotify.stack-bottomleft{bottom:25px;top:auto}.ui-pnotify.stack-modal{left:50%;right:auto;margin-left:-150px}.ui-pnotify.ui-pnotify-nonblock-fade{opacity:.2}.ui-pnotify.ui-pnotify-nonblock-hide{display:none !important}.ui-pnotify.stack-bar-bottom{margin-left:15%;margin-bottom:25px;right:auto;bottom:0;top:auto;left:auto}html,body,#sb-site,.sb-site-container,.sb-slidebar{margin:0;padding:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html,body{width:100%;overflow-x:hidden}html{height:100%}body{min-height:100%;height:auto;position:relative}html.sb-scroll-lock.sb-active:not(.sb-static){overflow:hidden}#sb-site,.sb-site-container{width:100%;position:relative;z-index:1;background:url("../img/pf-bg.jpg") #05050a;background-repeat:no-repeat}.sb-slidebar{height:100%;overflow-y:auto;position:fixed;top:0;z-index:0;display:none;background-color:#313335;-webkit-transform:translate(0px)}.sb-left{left:0;-webkit-box-shadow:inset -5px 0px 10px 0px rgba(0,0,0,0.4);box-shadow:inset -5px 0px 10px 0px rgba(0,0,0,0.4)}.sb-right{right:0;-webkit-box-shadow:inset 5px 0px 10px 0px rgba(0,0,0,0.4);box-shadow:inset 5px 0px 10px 0px rgba(0,0,0,0.4)}html.sb-static .sb-slidebar,.sb-slidebar.sb-static{position:absolute}.sb-slidebar.sb-active{display:block}.sb-style-overlay{z-index:9999}.sb-momentum-scrolling{-webkit-overflow-scrolling:touch}.sb-slidebar{width:30%}.sb-width-thin{width:15%}.sb-width-wide{width:45%}@media (max-width: 480px){.sb-slidebar{width:70%}.sb-width-thin{width:55%}.sb-width-wide{width:85%}}@media (min-width: 481px){.sb-slidebar{width:55%}.sb-width-thin{width:40%}.sb-width-wide{width:70%}}@media (min-width: 768px){.sb-slidebar{width:40%}.sb-width-thin{width:25%}.sb-width-wide{width:55%}}@media (min-width: 992px){.sb-slidebar{width:30%}.sb-width-thin{width:15%}.sb-width-wide{width:45%}}@media (min-width: 1200px){.sb-slidebar{width:20%}.sb-width-thin{width:5%}.sb-width-wide{width:35%}}.sb-slide,#sb-site,.sb-site-container,.sb-slidebar{-webkit-transition:transform 180ms ease-out;transition:transform 180ms ease-out;-webkit-transition-property:-webkit-transform, left, right;-webkit-backface-visibility:hidden}.sb-hide{display:none}.pf-pie-chart{position:relative;display:table-cell;text-align:center;vertical-align:middle}.pf-pie-chart span{display:inline-block}.pf-pie-chart canvas{position:absolute;top:0;left:0}.pf-pie-chart-map-timer{width:36px;height:36px;margin:3px}.pf-pie-chart-map-timer canvas{top:3px;left:3px}.pf-pie-chart-map-timer span{font-size:10px}.pf-pie-chart-map-timer span:after{content:'s';margin-left:1px}div.pf-map-drag-to-select{background:#375959 !important;display:block;visibility:hidden;opacity:0;z-index:9000;border:1px dashed #adadad;will-change:left, top, width, height, opacity;-moz-border-radius:5px;-webkit-border-radius:5px;border-radius:5px;-webkit-transition:opacity 0.15s linear;transition:opacity 0.15s linear}div.pf-map-drag-to-select.active{visibility:visible;opacity:0.3}.select2-container{box-sizing:border-box;display:inline-block;margin:0;position:relative;vertical-align:middle}.select2-container .select2-selection--single{box-sizing:border-box;cursor:pointer;display:block;height:28px;user-select:none;-webkit-user-select:none}.select2-container .select2-selection--single .select2-selection__rendered{display:block;padding-left:8px;padding-right:20px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.select2-container[dir="rtl"] .select2-selection--single .select2-selection__rendered{padding-right:8px;padding-left:20px}.select2-container .select2-selection--multiple{box-sizing:border-box;cursor:pointer;display:block;min-height:32px;user-select:none;-webkit-user-select:none}.select2-container .select2-selection--multiple .select2-selection__rendered{display:inline-block;overflow:hidden;padding-left:8px;text-overflow:ellipsis;white-space:nowrap}.select2-container .select2-search--inline{float:left}.select2-container .select2-search--inline .select2-search__field{box-sizing:border-box;border:none;font-size:100%;margin-top:5px}.select2-container .select2-search--inline .select2-search__field::-webkit-search-cancel-button{-webkit-appearance:none}.select2-dropdown{background-color:white;border:1px solid #aaa;border-radius:4px;box-sizing:border-box;display:block;position:absolute;left:-100000px;width:100%;z-index:1051}.select2-results{display:block}.select2-results__options{list-style:none;margin:0;padding:0}.select2-results__option{padding:6px;color:#adadad;user-select:none;-webkit-user-select:none}.select2-results__option[aria-selected]{cursor:pointer}.select2-container--open .select2-dropdown{left:0}.select2-container--open .select2-dropdown--above{border-bottom:none;border-bottom-left-radius:0;border-bottom-right-radius:0}.select2-container--open .select2-dropdown--below{border-top:none;border-top-left-radius:0;border-top-right-radius:0}.select2-search--dropdown{display:block;padding:4px}.select2-search--dropdown .select2-search__field{padding:4px;width:100%;box-sizing:border-box}.select2-search--dropdown .select2-search__field::-webkit-search-cancel-button{-webkit-appearance:none}.select2-search--dropdown.select2-search--hide{display:none}.select2-close-mask{border:0;margin:0;padding:0;display:block;position:fixed;left:0;top:0;min-height:100%;min-width:100%;height:auto;width:auto;opacity:0;z-index:99;background-color:#fff;filter:alpha(opacity=0)}.select2-hidden-accessible{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.select2-container--pathfinder .select2-selection--single{background-color:#313335;border:1px solid #63676a;border-radius:0px;outline:0}.select2-container--pathfinder .select2-selection--single:focus{border:1px solid #568a89}.select2-container--pathfinder .select2-selection--single .select2-selection__rendered{color:#adadad;line-height:28px}.select2-container--pathfinder .select2-selection--single .select2-selection__clear{color:#a52521;cursor:pointer;float:right;font-weight:bold;margin-right:3px;margin-left:10px}.select2-container--pathfinder .select2-selection--single .select2-selection__clear:hover{color:#58100d}.select2-container--pathfinder .select2-selection--single .select2-selection__placeholder{color:#63676a}.select2-container--pathfinder .select2-selection--single .select2-selection__arrow{background-color:#313335;border:none;border-left:none;border-top-right-radius:0px;border-bottom-right-radius:0px;height:26px;position:absolute;top:1px;right:1px;width:20px}.select2-container--pathfinder .select2-selection--single .select2-selection__arrow b{border-color:#888 transparent transparent transparent;border-style:solid;border-width:5px 4px 0 4px;height:0;left:50%;margin-left:-4px;margin-top:-2px;position:absolute;top:50%;width:0}.select2-container--pathfinder[dir="rtl"] .select2-selection--single .select2-selection__clear{float:left}.select2-container--pathfinder[dir="rtl"] .select2-selection--single .select2-selection__arrow{border:none;border-right:1px solid #63676a;border-radius:0;border-top-left-radius:0px;border-bottom-left-radius:0px;left:1px;right:auto}.select2-container--pathfinder.select2-container--open .select2-selection--single{border:1px solid #568a89}.select2-container--pathfinder.select2-container--open .select2-selection--single .select2-selection__arrow{background:transparent;border:none}.select2-container--pathfinder.select2-container--open .select2-selection--single .select2-selection__arrow b{border-color:transparent transparent #888 transparent;border-width:0 4px 5px 4px}.select2-container--pathfinder.select2-container--open.select2-container--above .select2-selection--single{border-top:none;border-top-left-radius:0;border-top-right-radius:0}.select2-container--pathfinder.select2-container--open.select2-container--below .select2-selection--single{border-bottom:none;border-bottom-left-radius:0;border-bottom-right-radius:0}.select2-container--pathfinder .select2-selection--multiple{background-color:#313335;color:#313335;border:1px solid #63676a;border-radius:0px;cursor:text;outline:0}.select2-container--pathfinder .select2-selection--multiple:focus{border:1px solid #568a89}.select2-container--pathfinder .select2-selection--multiple .select2-selection__rendered{list-style:none;margin:0;padding:0 5px;width:100%}.select2-container--pathfinder .select2-selection--multiple .select2-selection__clear{display:none}.select2-container--pathfinder .select2-selection--multiple .select2-selection__choice{background-color:#adadad;border:1px solid #63676a;border-radius:4px;cursor:default;float:left;margin-right:5px;margin-top:5px;padding:0 5px}.select2-container--pathfinder .select2-selection--multiple .select2-selection__choice__remove{color:#a52521;cursor:pointer;display:inline-block;font-weight:bold;margin-right:2px}.select2-container--pathfinder .select2-selection--multiple .select2-selection__choice__remove:hover{color:#58100d}.select2-container--pathfinder .select2-selection--multiple .select2-selection__placeholder{color:#63676a}.select2-container--pathfinder[dir="rtl"] .select2-selection--multiple .select2-selection__choice{float:right}.select2-container--pathfinder[dir="rtl"] .select2-selection--multiple .select2-selection__choice{margin-left:5px;margin-right:auto}.select2-container--pathfinder[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove{margin-left:2px;margin-right:auto}.select2-container--pathfinder.select2-container--open .select2-selection--multiple{border:1px solid #568a89}.select2-container--pathfinder.select2-container--open.select2-container--above .select2-selection--multiple{border-top:none;border-top-left-radius:0;border-top-right-radius:0}.select2-container--pathfinder.select2-container--open.select2-container--below .select2-selection--multiple{border-bottom:none;border-bottom-left-radius:0;border-bottom-right-radius:0}.select2-container--pathfinder .select2-search--dropdown .select2-search__field{border:1px solid #63676a;outline:0}.select2-container--pathfinder .select2-search--inline .select2-search__field{outline:0}.select2-container--pathfinder .select2-search--inline .select2-search__field::-moz-placeholder{color:#63676a;opacity:1}.select2-container--pathfinder .select2-search--inline .select2-search__field:-ms-input-placeholder{color:#63676a}.select2-container--pathfinder .select2-search--inline .select2-search__field::-webkit-input-placeholder{color:#63676a}.select2-container--pathfinder .select2-dropdown{background-color:#313335;border:1px solid transparent;overflow:hidden;-webkit-box-shadow:0 6px 12px rgba(0,0,0,0.3);box-shadow:0 6px 12px rgba(0,0,0,0.3)}.select2-container--pathfinder .select2-dropdown--above{border-bottom:none}.select2-container--pathfinder .select2-dropdown--below{border-top:none}.select2-container--pathfinder .select2-results>.select2-results__options{max-height:200px;overflow-y:auto}.select2-container--pathfinder .select2-results__option[role=group]{padding:0}.select2-container--pathfinder .select2-results__option[aria-disabled=true],.select2-container--pathfinder .select2-results__option[aria-selected=true]{color:#63676a;background-color:#3c3f41}.select2-container--pathfinder .select2-results__option[aria-disabled=true] .pf-select-item-anchor:before,.select2-container--pathfinder .select2-results__option[aria-selected=true] .pf-select-item-anchor:before{content:"\f05e";font-family:FontAwesome;font-size:9px;position:absolute;left:0;top:0;color:#63676a}.select2-container--pathfinder .select2-results__option--highlighted[aria-selected]{background-color:#adadad;color:#313335}.select2-container--pathfinder .select2-results__group{cursor:default;display:block;padding:6px}.select2-container--pathfinder.select2-container--open .select2-dropdown{border-color:#568a89}select.select2-hidden-accessible{-moz-appearance:none;-webkit-appearance:none}.blueimp-gallery,.blueimp-gallery>.slides>.slide>.slide-content{position:absolute;top:0;right:0;bottom:0;left:0;-moz-backface-visibility:hidden}.blueimp-gallery>.slides>.slide>.slide-content{margin:auto;width:auto;height:auto;max-width:100%;max-height:100%;opacity:1}.blueimp-gallery{position:fixed;z-index:999999;overflow:hidden;background:#000;background:rgba(0,0,0,0.9);opacity:0;display:none;direction:ltr;-ms-touch-action:none;touch-action:none}.blueimp-gallery-carousel{position:relative;z-index:auto;margin:1em auto;padding-bottom:56.25%;-webkit-box-shadow:0 4px 10px rgba(0,0,0,0.4);box-shadow:0 4px 10px rgba(0,0,0,0.4);-moz-border-radius:5px;-webkit-border-radius:5px;border-radius:5px;-ms-touch-action:pan-y;touch-action:pan-y}.blueimp-gallery-display{display:block;opacity:1}.blueimp-gallery>.slides{position:relative;height:100%;overflow:hidden}.blueimp-gallery-carousel>.slides{position:absolute}.blueimp-gallery>.slides>.slide{position:relative;float:left;height:100%;text-align:center;will-change:all;-webkit-transition-timing-function:cubic-bezier(0.645, 0.045, 0.355, 1);-moz-transition-timing-function:cubic-bezier(0.645, 0.045, 0.355, 1);-ms-transition-timing-function:cubic-bezier(0.645, 0.045, 0.355, 1);-o-transition-timing-function:cubic-bezier(0.645, 0.045, 0.355, 1);transition-timing-function:cubic-bezier(0.645, 0.045, 0.355, 1)}.blueimp-gallery,.blueimp-gallery>.slides>.slide>.slide-content{-webkit-transition:opacity 0.5s linear;-moz-transition:opacity 0.5s linear;-ms-transition:opacity 0.5s linear;-o-transition:opacity 0.5s linear;transition:opacity 0.5s linear}.blueimp-gallery>.slides>.slide-loading{background-size:64px 64px}.blueimp-gallery>.slides>.slide-loading>.slide-content{opacity:0}.blueimp-gallery>.slides>.slide-error>.slide-content{display:none}.blueimp-gallery>.prev,.blueimp-gallery>.next{position:absolute;top:50%;left:15px;width:35px;height:35px;margin-top:-17px;font-size:22px;line-height:35px;color:#63676a;text-decoration:none;text-align:center;background:rgba(0,0,0,0.2);-moz-border-radius:5px;-webkit-border-radius:5px;border-radius:5px;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-transition:color 0.09s linear;transition:color 0.09s linear;will-change:color;opacity:1;cursor:pointer;display:none}.blueimp-gallery>.next{left:auto;right:15px}.blueimp-gallery>.close,.blueimp-gallery>.title{position:absolute;bottom:15px;left:15px;margin:0 40px 0 0;font-size:14px;line-height:14px;font-font:"Oxygen Bold","Helvetica Neue",Helvetica,Arial,sans-serif;color:#63676a;text-shadow:0 1px 3px #1d1d1d;opacity:1;display:none}.blueimp-gallery>.title{margin-left:20px}.blueimp-gallery>.title:before{content:'\f101';font-family:'FontAwesome';position:absolute;top:-1px;left:-20px;height:14px;width:14px}.blueimp-gallery>.close{padding:15px;right:15px;left:auto;margin:-15px;font-size:30px;text-decoration:none;cursor:pointer}.blueimp-gallery>.play-pause{position:absolute;right:15px;bottom:15px;width:35px;height:35px;font-size:22px;line-height:35px;text-align:center;background:rgba(0,0,0,0.2);-moz-border-radius:5px;-webkit-border-radius:5px;border-radius:5px;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-transition:color 0.09s linear;transition:color 0.09s linear;will-change:color;color:#e28a0d;cursor:pointer;opacity:1;display:none}.blueimp-gallery-playing>.play-pause{color:#2b2b2b}.blueimp-gallery>.prev:hover,.blueimp-gallery>.next:hover,.blueimp-gallery>.close:hover,.blueimp-gallery>.play-pause:hover{color:#e28a0d}.blueimp-gallery-controls>.prev,.blueimp-gallery-controls>.next,.blueimp-gallery-controls>.close,.blueimp-gallery-controls>.title,.blueimp-gallery-controls>.play-pause{display:block;-webkit-transform:translateZ(0);-moz-transform:translateZ(0);-ms-transform:translateZ(0);-o-transform:translateZ(0);transform:translateZ(0)}.blueimp-gallery-single>.prev,.blueimp-gallery-left>.prev,.blueimp-gallery-single>.next,.blueimp-gallery-right>.next,.blueimp-gallery-single>.play-pause{display:none}.blueimp-gallery>.slides>.slide>.slide-content,.blueimp-gallery>.prev,.blueimp-gallery>.next,.blueimp-gallery>.close,.blueimp-gallery>.play-pause{-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}body:last-child .blueimp-gallery-playing>.play-pause{background-position:-20px 0}*+html .blueimp-gallery>.slides>.slide{min-height:300px}*+html .blueimp-gallery>.slides>.slide>.slide-content{position:relative}.blueimp-gallery>.slides>.slide>.text-content{overflow:auto;margin:0 auto;overflow:hidden;text-align:left}.blueimp-gallery .modal-body{position:relative;text-align:center;padding:0 0 56.25% 0;overflow:hidden;cursor:pointer}.blueimp-gallery .modal-footer{margin:0}.blueimp-gallery .modal-body img,.blueimp-gallery .modal-body .video-content video,.blueimp-gallery .modal-body .video-content iframe,.blueimp-gallery .modal-body .video-content a{max-width:100%;max-height:100%;margin:auto;position:absolute;top:0;right:0;bottom:0;left:0}.blueimp-gallery .modal-body .video-content video{display:none}.blueimp-gallery .modal-body .video-playing video{display:block}.blueimp-gallery .modal-body .video-content iframe{width:100%;height:100%;border:none;left:100%}.blueimp-gallery .modal-body .video-playing iframe{left:0}.blueimp-gallery .modal-body .video-playing img,.blueimp-gallery .modal-body .video-playing a{display:none}.blueimp-gallery .modal-body .video-content a{cursor:pointer}.blueimp-gallery .modal-body .video-content a:after{font-family:"Glyphicons Halflings";-webkit-font-smoothing:antialiased;content:"\e029";font-size:64px;line-height:64px;width:64px;height:64px;position:absolute;top:50%;margin:-32px 0 0 -32px}.blueimp-gallery .modal-body .video-loading a{background:url(../img/loading.gif) center no-repeat;background-size:64px 64px}.blueimp-gallery .modal-body .video-loading a:after{content:none}@media screen and (min-width: 768px){.blueimp-gallery .modal-dialog{right:auto;left:auto;width:auto;max-width:1200px;padding-left:5%;padding-right:5%}}/*! ======================================================================== * Bootstrap Toggle: bootstrap2-toggle.css v2.2.0 * http://www.bootstraptoggle.com * ======================================================================== diff --git a/public/js/v1.1.7/app/map/map.js b/public/js/v1.1.7/app/map/map.js index 71d2f228..290626f2 100644 --- a/public/js/v1.1.7/app/map/map.js +++ b/public/js/v1.1.7/app/map/map.js @@ -1406,7 +1406,7 @@ define([ var moduleData = { id: config.mapContextMenuId, items: [ - {icon: 'fa-info', action: 'info', text: 'info'}, + {icon: 'fa-street-view', action: 'info', text: 'information'}, {icon: 'fa-plus', action: 'add_system', text: 'add system'}, {icon: 'fa-object-ungroup', action: 'select_all', text: 'select all'}, {icon: 'fa-filter', action: 'filter_scope', text: 'filter scope', subitems: [ diff --git a/public/js/v1.1.7/app/page.js b/public/js/v1.1.7/app/page.js index 55dbc220..da6e900b 100644 --- a/public/js/v1.1.7/app/page.js +++ b/public/js/v1.1.7/app/page.js @@ -279,9 +279,9 @@ define([ $('', { class: 'list-group-item', href: '#' - }).html('  Status').prepend( + }).html('  Information').prepend( $('',{ - class: 'fa fa-info fa-fw' + class: 'fa fa-street-view fa-fw' }) ).on('click', function(){ $(document).triggerMenuEvent('ShowMapInfo'); @@ -292,7 +292,7 @@ define([ $('', { class: 'list-group-item', href: '#' - }).html('  Map config').prepend( + }).html('  Configuration').prepend( $('',{ class: 'fa fa-gears fa-fw' }) diff --git a/public/js/v1.1.7/app/ui/dialog/map_settings.js b/public/js/v1.1.7/app/ui/dialog/map_settings.js index 1d492c64..2191fd76 100644 --- a/public/js/v1.1.7/app/ui/dialog/map_settings.js +++ b/public/js/v1.1.7/app/ui/dialog/map_settings.js @@ -20,6 +20,8 @@ define([ dialogMapSettingsContainerId: 'pf-map-dialog-settings', // id for the "settings" container dialogMapDownloadContainerId: 'pf-map-dialog-download', // id for the "download" container + deleteExpiredConnectionsId: 'pf-map-dialog-delete-connections', // id for "deleteExpiredConnections" checkbox + characterSelectId: 'pf-map-dialog-character-select', // id for "character" select corporationSelectId: 'pf-map-dialog-corporation-select', // id for "corporation" select allianceSelectId: 'pf-map-dialog-alliance-select', // id for "alliance" select @@ -103,6 +105,7 @@ define([ var accessCharacter = []; var accessCorporation = []; var accessAlliance = []; + var deleteExpiredConnections = true; if(mapData !== false){ // set current map information @@ -115,6 +118,8 @@ define([ accessCharacter = mapData.config.access.character; accessCorporation = mapData.config.access.corporation; accessAlliance = mapData.config.access.alliance; + + deleteExpiredConnections = mapData.config.deleteExpiredConnections; } // render main dialog ----------------------------------------------------- @@ -144,6 +149,9 @@ define([ hideDownloadTab: hideDownloadTab, // settings tab -------------- + deleteExpiredConnectionsId : config.deleteExpiredConnectionsId, + deleteExpiredConnections: deleteExpiredConnections, + characterSelectId: config.characterSelectId, corporationSelectId: config.corporationSelectId, allianceSelectId: config.allianceSelectId, @@ -207,10 +215,10 @@ define([ var selectField = $(this); var selectValues = selectField.val(); - if(selectValues === null){ - selectField.parents('.form-group').addClass('has-error'); - }else{ + if(selectValues.length > 0){ selectField.parents('.form-group').removeClass('has-error'); + }else{ + selectField.parents('.form-group').addClass('has-error'); } }); @@ -223,12 +231,20 @@ define([ var dialogContent = mapInfoDialog.find('.modal-content'); dialogContent.showLoadingAnimation(); - var newMapData = {formData: form.getFormValues()}; + // get form data + var formData = form.getFormValues(); + + // checkbox fix -> settings tab + if( form.find('#' + config.deleteExpiredConnectionsId).length ){ + formData.deleteExpiredConnections = formData.hasOwnProperty('deleteExpiredConnections') ? parseInt( formData.deleteExpiredConnections ) : 0; + } + + var requestData = {formData: formData}; $.ajax({ type: 'POST', url: Init.path.saveMap, - data: newMapData, + data: requestData, dataType: 'json' }).done(function(responseData){ diff --git a/public/js/v1.1.7/app/ui/form_element.js b/public/js/v1.1.7/app/ui/form_element.js index 665eb33b..36b6cfe8 100644 --- a/public/js/v1.1.7/app/ui/form_element.js +++ b/public/js/v1.1.7/app/ui/form_element.js @@ -139,7 +139,7 @@ define([ placeholder: 'System name', allowClear: true, maximumSelectionLength: options.maxSelectionLength, - escapeMarkup: function (markup) { + escapeMarkup: function(markup){ // let our custom formatter work return markup; } @@ -257,12 +257,12 @@ define([ dropdownParent: selectElement.parents('.modal-body'), theme: 'pathfinder', minimumInputLength: 3, - placeholder: '', + placeholder: options.type + ' names', allowClear: false, maximumSelectionLength: options.maxSelectionLength, templateResult: formatResultData, templateSelection: formatSelectionData, - escapeMarkup: function (markup) { + escapeMarkup: function(markup){ // let our custom formatter work return markup; } diff --git a/public/js/v1.1.7/app/util.js b/public/js/v1.1.7/app/util.js index 25d41582..3618a524 100644 --- a/public/js/v1.1.7/app/util.js +++ b/public/js/v1.1.7/app/util.js @@ -1469,7 +1469,10 @@ define([ var currentMapUserData = false; - if( mapId === parseInt(mapId, 10) ){ + if( + mapId === parseInt(mapId, 10) && + Init.currentMapUserData + ){ // search for a specific map for(var i = 0; i < Init.currentMapUserData.length; i++){ if(Init.currentMapUserData[i].config.id === mapId){ diff --git a/public/templates/dialog/map.html b/public/templates/dialog/map.html index e9614706..43c57754 100644 --- a/public/templates/dialog/map.html +++ b/public/templates/dialog/map.html @@ -40,7 +40,24 @@ {{^hideSettingsTab}}
-

Share settings

+ +

Configuration

+ +
+
+
+
+
+ + +
+
+
+
+
+
+ +

Share settings

diff --git a/public/templates/dialog/map_info.html b/public/templates/dialog/map_info.html index a4032ec0..f97e6ee0 100644 --- a/public/templates/dialog/map_info.html +++ b/public/templates/dialog/map_info.html @@ -3,7 +3,7 @@