@@ -13,96 +13,96 @@
|
||||
* | | < | <| -__|-- __|
|
||||
* |__|__|__||__|__|_____|_____|
|
||||
*
|
||||
* Copyright (c) 2016 by ikkez
|
||||
* Copyright (c) 2012-2018 by ikkez
|
||||
* Christian Knuth <ikkez0n3@gmail.com>
|
||||
* https://github.com/ikkez/F3-Sugar/
|
||||
*
|
||||
* @package DB
|
||||
* @version 2.2.1
|
||||
* @date 25.04.2017
|
||||
* @version 2.2.2
|
||||
* @date 06.03.2018
|
||||
**/
|
||||
|
||||
|
||||
namespace DB\SQL;
|
||||
|
||||
use DB\SQL;
|
||||
class Schema {
|
||||
|
||||
class Schema extends DB_Utils {
|
||||
use DB_Utils;
|
||||
|
||||
public
|
||||
$dataTypes = array(
|
||||
'BOOLEAN' => array('mysql' => 'tinyint(1)',
|
||||
'sqlite2?|pgsql' => 'BOOLEAN',
|
||||
'mssql|sybase|dblib|odbc|sqlsrv' => 'bit',
|
||||
'ibm' => 'numeric(1,0)',
|
||||
'sqlite2?|pgsql' => 'BOOLEAN',
|
||||
'mssql|sybase|dblib|odbc|sqlsrv' => 'bit',
|
||||
'ibm' => 'numeric(1,0)',
|
||||
),
|
||||
'INT1' => array('mysql' => 'tinyint(4)',
|
||||
'sqlite2?' => 'integer(4)',
|
||||
'mssql|sybase|dblib|odbc|sqlsrv' => 'tinyint',
|
||||
'pgsql|ibm' => 'smallint',
|
||||
'sqlite2?' => 'integer(4)',
|
||||
'mssql|sybase|dblib|odbc|sqlsrv' => 'tinyint',
|
||||
'pgsql|ibm' => 'smallint',
|
||||
),
|
||||
'INT2' => array('mysql' => 'smallint(6)',
|
||||
'sqlite2?' => 'integer(6)',
|
||||
'pgsql|ibm|mssql|sybase|dblib|odbc|sqlsrv' => 'smallint',
|
||||
'sqlite2?' => 'integer(6)',
|
||||
'pgsql|ibm|mssql|sybase|dblib|odbc|sqlsrv' => 'smallint',
|
||||
),
|
||||
'INT4' => array('sqlite2?' => 'integer(11)',
|
||||
'pgsql|imb' => 'integer',
|
||||
'mysql' => 'int(11)',
|
||||
'mssql|dblib|sybase|odbc|sqlsrv' => 'int',
|
||||
'pgsql|imb' => 'integer',
|
||||
'mysql' => 'int(11)',
|
||||
'mssql|dblib|sybase|odbc|sqlsrv' => 'int',
|
||||
),
|
||||
'INT8' => array('sqlite2?' => 'integer(20)',
|
||||
'pgsql|mssql|sybase|dblib|odbc|sqlsrv|imb' => 'bigint',
|
||||
'mysql' => 'bigint(20)',
|
||||
'pgsql|mssql|sybase|dblib|odbc|sqlsrv|imb' => 'bigint',
|
||||
'mysql' => 'bigint(20)',
|
||||
),
|
||||
'FLOAT' => array('mysql|sqlite2?' => 'FLOAT',
|
||||
'pgsql' => 'double precision',
|
||||
'mssql|sybase|dblib|odbc|sqlsrv' => 'float',
|
||||
'imb' => 'decfloat'
|
||||
'pgsql' => 'double precision',
|
||||
'mssql|sybase|dblib|odbc|sqlsrv' => 'float',
|
||||
'imb' => 'decfloat'
|
||||
),
|
||||
'DOUBLE' => array('mysql|ibm' => 'decimal(18,6)',
|
||||
'sqlite2?' => 'decimal(15,6)', // max 15-digit on sqlite
|
||||
'pgsql' => 'numeric(18,6)',
|
||||
'mssql|dblib|sybase|odbc|sqlsrv' => 'decimal(18,6)',
|
||||
'sqlite2?' => 'decimal(15,6)', // max 15-digit on sqlite
|
||||
'pgsql' => 'numeric(18,6)',
|
||||
'mssql|dblib|sybase|odbc|sqlsrv' => 'decimal(18,6)',
|
||||
),
|
||||
'VARCHAR128' => array('mysql|sqlite2?|ibm|mssql|sybase|dblib|odbc|sqlsrv' => 'varchar(128)',
|
||||
'pgsql' => 'character varying(128)',
|
||||
'pgsql' => 'character varying(128)',
|
||||
),
|
||||
'VARCHAR256' => array('mysql|sqlite2?|ibm|mssql|sybase|dblib|odbc|sqlsrv' => 'varchar(255)',
|
||||
'pgsql' => 'character varying(255)',
|
||||
'pgsql' => 'character varying(255)',
|
||||
),
|
||||
'VARCHAR512' => array('mysql|sqlite2?|ibm|mssql|sybase|dblib|odbc|sqlsrv' => 'varchar(512)',
|
||||
'pgsql' => 'character varying(512)',
|
||||
'pgsql' => 'character varying(512)',
|
||||
),
|
||||
'TEXT' => array('mysql|sqlite2?|pgsql|mssql' => 'text',
|
||||
'sybase|dblib|odbc|sqlsrv' => 'nvarchar(max)',
|
||||
'ibm' => 'BLOB SUB_TYPE TEXT',
|
||||
'sybase|dblib|odbc|sqlsrv' => 'nvarchar(max)',
|
||||
'ibm' => 'BLOB SUB_TYPE TEXT',
|
||||
),
|
||||
'LONGTEXT' => array('mysql' => 'LONGTEXT',
|
||||
'sqlite2?|pgsql|mssql' => 'text',
|
||||
'sybase|dblib|odbc|sqlsrv' => 'nvarchar(max)',
|
||||
'ibm' => 'CLOB(2000000000)',
|
||||
'sqlite2?|pgsql|mssql' => 'text',
|
||||
'sybase|dblib|odbc|sqlsrv' => 'nvarchar(max)',
|
||||
'ibm' => 'CLOB(2000000000)',
|
||||
),
|
||||
'DATE' => array('mysql|sqlite2?|pgsql|mssql|sybase|dblib|odbc|sqlsrv|ibm' => 'date',
|
||||
),
|
||||
'DATETIME' => array('pgsql' => 'timestamp without time zone',
|
||||
'mysql|sqlite2?|mssql|sybase|dblib|odbc|sqlsrv' => 'datetime',
|
||||
'ibm' => 'timestamp',
|
||||
'mysql|sqlite2?|mssql|sybase|dblib|odbc|sqlsrv' => 'datetime',
|
||||
'ibm' => 'timestamp',
|
||||
),
|
||||
'TIMESTAMP' => array('mysql|ibm' => 'timestamp',
|
||||
'pgsql|odbc' => 'timestamp without time zone',
|
||||
'sqlite2?|mssql|sybase|dblib|sqlsrv'=>'DATETIME',
|
||||
'pgsql|odbc' => 'timestamp without time zone',
|
||||
'sqlite2?|mssql|sybase|dblib|sqlsrv'=>'DATETIME',
|
||||
),
|
||||
'BLOB' => array('mysql|odbc|sqlite2?|ibm' => 'blob',
|
||||
'pgsql' => 'bytea',
|
||||
'mssql|sybase|dblib' => 'image',
|
||||
'sqlsrv' => 'varbinary(max)',
|
||||
'pgsql' => 'bytea',
|
||||
'mssql|sybase|dblib' => 'image',
|
||||
'sqlsrv' => 'varbinary(max)',
|
||||
),
|
||||
),
|
||||
$defaultTypes = array(
|
||||
'CUR_STAMP' => array('mysql' => 'CURRENT_TIMESTAMP',
|
||||
'mssql|sybase|dblib|odbc|sqlsrv' => 'getdate()',
|
||||
'pgsql' => 'LOCALTIMESTAMP(0)',
|
||||
'sqlite2?' => "(datetime('now','localtime'))",
|
||||
'mssql|sybase|dblib|odbc|sqlsrv' => 'getdate()',
|
||||
'pgsql' => 'LOCALTIMESTAMP(0)',
|
||||
'sqlite2?' => "(datetime('now','localtime'))",
|
||||
),
|
||||
);
|
||||
|
||||
@@ -112,9 +112,6 @@ class Schema extends DB_Utils {
|
||||
public static
|
||||
$strict = FALSE;
|
||||
|
||||
/** @var \Base */
|
||||
protected $fw;
|
||||
|
||||
const
|
||||
// DataTypes and Aliases
|
||||
DT_BOOL = 'BOOLEAN',
|
||||
@@ -147,8 +144,7 @@ class Schema extends DB_Utils {
|
||||
|
||||
public function __construct(\DB\SQL $db)
|
||||
{
|
||||
$this->fw = \Base::instance();
|
||||
parent::__construct($db);
|
||||
$this->db = $db;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -304,7 +300,9 @@ class Schema extends DB_Utils {
|
||||
}
|
||||
}
|
||||
|
||||
abstract class TableBuilder extends DB_Utils {
|
||||
abstract class TableBuilder {
|
||||
|
||||
use DB_Utils;
|
||||
|
||||
protected $columns, $pkeys, $queries, $increments, $rebuild_cmd, $suppress;
|
||||
public $name;
|
||||
@@ -318,7 +316,6 @@ abstract class TableBuilder extends DB_Utils {
|
||||
/**
|
||||
* @param string $name
|
||||
* @param Schema $schema
|
||||
* @return \DB\SQL\TableBuilder
|
||||
*/
|
||||
public function __construct($name, Schema $schema)
|
||||
{
|
||||
@@ -328,7 +325,7 @@ abstract class TableBuilder extends DB_Utils {
|
||||
$this->queries = array();
|
||||
$this->pkeys = array('id');
|
||||
$this->increments = 'id';
|
||||
parent::__construct($schema->db);
|
||||
$this->db = $schema->db;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -549,6 +546,8 @@ class TableModifier extends TableBuilder {
|
||||
/**
|
||||
* generate SQL queries for altering the table and execute it if $exec is true,
|
||||
* otherwise return the generated query string
|
||||
* @param bool $exec
|
||||
* @return array|FALSE
|
||||
*/
|
||||
public function build($exec = TRUE)
|
||||
{
|
||||
@@ -763,9 +762,9 @@ class TableModifier extends TableBuilder {
|
||||
else
|
||||
foreach ($schema as $name => &$cols) {
|
||||
$default = ($cols['default'] === '') ? null : $cols['default'];
|
||||
if (!is_null($default) && (
|
||||
(is_int(strpos($curdef=$this->findQuery($this->schema->defaultTypes['CUR_STAMP']),
|
||||
$default)) || is_int(strpos($default,$curdef)))
|
||||
if (!is_null($default) && ((is_int(strpos($curdef=strtolower(
|
||||
$this->findQuery($this->schema->defaultTypes['CUR_STAMP'])),
|
||||
strtolower($default))) || is_int(strpos(strtolower($default),$curdef)))
|
||||
|| $default == "('now'::text)::timestamp(0) without time zone"))
|
||||
{
|
||||
$default = 'CUR_STAMP';
|
||||
@@ -874,7 +873,6 @@ class TableModifier extends TableBuilder {
|
||||
* @param string $name
|
||||
* @param string|Column $datatype
|
||||
* @param bool $force
|
||||
* @return bool
|
||||
*/
|
||||
public function updateColumn($name, $datatype, $force = false)
|
||||
{
|
||||
@@ -1031,7 +1029,9 @@ class TableModifier extends TableBuilder {
|
||||
* Class Column
|
||||
* @package DB\SQL
|
||||
*/
|
||||
class Column extends DB_Utils {
|
||||
class Column {
|
||||
|
||||
use DB_Utils;
|
||||
|
||||
public $name, $type, $nullable, $default, $after, $index, $unique, $passThrough, $pkey;
|
||||
protected $table, $schema, $type_val;
|
||||
@@ -1056,7 +1056,7 @@ class Column extends DB_Utils {
|
||||
|
||||
$this->table = $table;
|
||||
$this->schema = $table->schema;
|
||||
parent::__construct($this->schema->db);
|
||||
$this->db = $this->schema->db;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1281,22 +1281,16 @@ class Column extends DB_Utils {
|
||||
constant('\PDO::PARAM_'.strtoupper($parts[0])) : \PDO::PARAM_STR;
|
||||
return ($this->default === NULL ? 'NULL' :
|
||||
$this->db->quote(htmlspecialchars($this->default, ENT_QUOTES,
|
||||
$this->f3->get('ENCODING')), $pdo_type));
|
||||
\Base::instance()->get('ENCODING')), $pdo_type));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class DB_Utils {
|
||||
trait DB_Utils {
|
||||
|
||||
/** @var \DB\SQL */
|
||||
protected $db;
|
||||
|
||||
/** @var \BASE */
|
||||
protected $f3;
|
||||
|
||||
const
|
||||
TEXT_ENGINE_NOT_SUPPORTED = 'DB Engine `%s` is not supported for this action.';
|
||||
public $db;
|
||||
|
||||
/**
|
||||
* parse command array and return backend specific query
|
||||
@@ -1308,11 +1302,6 @@ class DB_Utils {
|
||||
foreach ($cmd as $backend => $val)
|
||||
if (preg_match('/'.$backend.'/', $this->db->driver()))
|
||||
return $val;
|
||||
trigger_error(sprintf(self::TEXT_ENGINE_NOT_SUPPORTED, $this->db->driver()),E_USER_ERROR);
|
||||
}
|
||||
|
||||
public function __construct(SQL $db) {
|
||||
$this->db = $db;
|
||||
$this->f3 = \Base::instance();
|
||||
trigger_error(sprintf('DB Engine `%s` is not supported for this action.', $this->db->driver()),E_USER_ERROR);
|
||||
}
|
||||
}
|
||||
@@ -10,9 +10,9 @@ namespace Controller;
|
||||
|
||||
|
||||
use Controller\Ccp\Sso;
|
||||
use lib\Config;
|
||||
use Model\CharacterModel;
|
||||
use Model\CorporationModel;
|
||||
use lib\Config;
|
||||
use Model\MapModel;
|
||||
use Model\RoleModel;
|
||||
|
||||
@@ -421,6 +421,13 @@ class Admin extends Controller{
|
||||
}
|
||||
|
||||
$f3->set('tplMaps', $data);
|
||||
|
||||
if( !isset($data->corpMaps) ){
|
||||
$f3->set('tplNotification', $this->getNotificationObject('No maps found',
|
||||
'Only corporation maps could get loaded' ,
|
||||
'info'
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -56,24 +56,12 @@ class Connection extends Controller\AccessController {
|
||||
$connection = Model\BasicModel::getNew('ConnectionModel');
|
||||
$connection->getById( (int)$connectionData['id'] );
|
||||
|
||||
// search if systems are neighbors
|
||||
$routeController = new Route();
|
||||
$routeController->initJumpData();
|
||||
$route = $routeController->findRoute($connectionData['sourceName'], $connectionData['targetName'], 1);
|
||||
|
||||
if($route['routePossible'] == true){
|
||||
// systems are next to each other
|
||||
$connectionData['scope'] = 'stargate';
|
||||
$connectionData['type'] = ['stargate'];
|
||||
}elseif($connectionData['scope'] == 'stargate'){
|
||||
// connection scope changed -> this can not be a stargate
|
||||
$connectionData['scope'] = 'wh';
|
||||
$connectionData['type'] = ['wh_fresh'];
|
||||
}
|
||||
$connectionData['mapId'] = $map;
|
||||
|
||||
$connection->setData($connectionData);
|
||||
|
||||
// change the default type for the new connection
|
||||
$connection->setDefaultTypeData();
|
||||
|
||||
if($connection->save($activeCharacter)){
|
||||
$return->connectionData = $connection->getData();
|
||||
|
||||
|
||||
@@ -24,39 +24,17 @@ class Map extends Controller\AccessController {
|
||||
// cache keys
|
||||
const CACHE_KEY_INIT = 'CACHED_INIT';
|
||||
const CACHE_KEY_MAP_DATA = 'CACHED.MAP_DATA.%s';
|
||||
const CACHE_KEY_USER_DATA = 'CACHED.USER_DATA.%s_%s';
|
||||
const CACHE_KEY_USER_DATA = 'CACHED.USER_DATA.%s';
|
||||
const CACHE_KEY_HISTORY = 'CACHED_MAP_HISTORY_%s';
|
||||
|
||||
|
||||
/**
|
||||
* get map data cache key
|
||||
* @param Model\CharacterModel $character
|
||||
* @return string
|
||||
*/
|
||||
protected function getMapDataCacheKey(Model\CharacterModel $character): string {
|
||||
return sprintf(self::CACHE_KEY_MAP_DATA, 'CHAR_' . $character->_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* clear map data caching
|
||||
* -> cache timings are short, this will just increase update performance on map changes
|
||||
* @param Model\CharacterModel $character
|
||||
*/
|
||||
protected function clearMapDataCache(Model\CharacterModel $character){
|
||||
$cacheKey = $this->getMapDataCacheKey($character);
|
||||
if($this->getF3()->exists($cacheKey)){
|
||||
$this->getF3()->clear($cacheKey);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* get user data cache key
|
||||
* @param int $mapId
|
||||
* @param int $systemId
|
||||
* @return string
|
||||
*/
|
||||
protected function getUserDataCacheKey($mapId, $systemId = 0): string {
|
||||
return sprintf(self::CACHE_KEY_USER_DATA, 'MAP_' . $mapId, 'SYS_' . $systemId);
|
||||
protected function getUserDataCacheKey(int $mapId): string {
|
||||
return sprintf(self::CACHE_KEY_USER_DATA, 'MAP_' . $mapId);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -74,7 +52,7 @@ class Map extends Controller\AccessController {
|
||||
* @throws Exception
|
||||
* @throws Exception\PathfinderException
|
||||
*/
|
||||
public function init(\Base $f3){
|
||||
public function initData(\Base $f3){
|
||||
// expire time in seconds
|
||||
$expireTimeCache = 60 * 60;
|
||||
$expireTimeSQL = 60 * 60 * 12;
|
||||
@@ -652,11 +630,18 @@ class Map extends Controller\AccessController {
|
||||
$return = (object) [];
|
||||
|
||||
$activeCharacter = $this->getCharacter();
|
||||
$characterData = $activeCharacter->getData(true);
|
||||
$maps = $activeCharacter->getMaps();
|
||||
|
||||
// some character data is not required (in WebSocket) -> unset() and keep return small
|
||||
if(isset($characterData->corporation->rights)){
|
||||
unset($characterData->corporation->rights);
|
||||
}
|
||||
|
||||
$return->data = [
|
||||
'id' => $activeCharacter->_id,
|
||||
'token' => bin2hex(random_bytes(16)), // token for character access
|
||||
'characterData' => $characterData,
|
||||
'mapData' => []
|
||||
];
|
||||
|
||||
@@ -684,23 +669,20 @@ class Map extends Controller\AccessController {
|
||||
* @throws Exception\PathfinderException
|
||||
*/
|
||||
public function updateData(\Base $f3){
|
||||
$mapData = (array)$f3->get('POST.mapData');
|
||||
$userDataRequired = (bool)$f3->get('POST.getUserData');
|
||||
$postData = (array)$f3->get('POST');
|
||||
$mapData = (array)$postData['mapData'];
|
||||
$userDataRequired = (bool)$postData['getUserData'];
|
||||
|
||||
$return = (object) [];
|
||||
$return->error = [];
|
||||
|
||||
$activeCharacter = $this->getCharacter();
|
||||
|
||||
$cacheKey = $this->getMapDataCacheKey($activeCharacter);
|
||||
// get current map data
|
||||
$maps = $activeCharacter->getMaps();
|
||||
|
||||
// if there is any system/connection change data submitted -> save new data
|
||||
if(
|
||||
!empty($mapData) ||
|
||||
!$f3->exists($cacheKey, $return)
|
||||
){
|
||||
$return = (object) [];
|
||||
$return->error = [];
|
||||
|
||||
// get current map data ===================================================================================
|
||||
$maps = $activeCharacter->getMaps();
|
||||
if( !empty($maps) && !empty($mapData) ){
|
||||
|
||||
// loop all submitted map data that should be saved
|
||||
// -> currently there will only be ONE map data change submitted -> single loop
|
||||
@@ -807,20 +789,14 @@ class Map extends Controller\AccessController {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// format map Data for return
|
||||
$return->mapData = $this->getFormattedMapsData($maps);
|
||||
|
||||
// cache time(s) per user should be equal or less than this function is called
|
||||
// prevent request flooding
|
||||
$responseTTL = (int)Config::getPathfinderData('timer.update_server_map.delay') / 1000;
|
||||
|
||||
$f3->set($cacheKey, $return, $responseTTL);
|
||||
}
|
||||
|
||||
// format map Data for return
|
||||
$return->mapData = $this->getFormattedMapsData($maps);
|
||||
|
||||
// if userData is requested -> add it as well
|
||||
// -> Only first trigger call should request this data!
|
||||
if($userDataRequired){
|
||||
if($userDataRequired) {
|
||||
$return->userData = $activeCharacter->getUser()->getData();
|
||||
}
|
||||
|
||||
@@ -851,61 +827,51 @@ class Map extends Controller\AccessController {
|
||||
* @throws Exception\PathfinderException
|
||||
*/
|
||||
public function updateUserData(\Base $f3){
|
||||
$return = (object) [];
|
||||
|
||||
$postData = (array)$f3->get('POST');
|
||||
$mapIds = (array)$postData['mapIds'];
|
||||
$getMapUserData = (bool)$postData['getMapUserData'];
|
||||
$mapTracking = (bool)$postData['mapTracking'];
|
||||
$systemData = (array)$postData['systemData'];
|
||||
$activeCharacter = $this->getCharacter(0);
|
||||
|
||||
$postData = $f3->get('POST');
|
||||
if( !empty($mapIds = (array)$postData['mapIds']) ){
|
||||
$return = (object)[];
|
||||
|
||||
// update current location
|
||||
// -> suppress temporary timeout errors
|
||||
$activeCharacter = $activeCharacter->updateLog(['suppressHTTPErrors' => true]);
|
||||
|
||||
if( !empty($mapIds) ){
|
||||
// IMPORTANT for now -> just update a single map (save performance)
|
||||
$mapId = (int)reset($mapIds);
|
||||
// get map and check map access
|
||||
$map = $activeCharacter->getMap( (int)$mapId);
|
||||
|
||||
if( !is_null($map) ){
|
||||
$characterMapData = (array)$postData['characterMapData'];
|
||||
|
||||
// check if data for specific system is requested
|
||||
$systemData = (array)$postData['systemData'];
|
||||
// if data is requested extend the cache key in order to get new data
|
||||
$requestSystemData = (object) [];
|
||||
$requestSystemData->mapId = isset($systemData['mapId']) ? (int) $systemData['mapId'] : 0;
|
||||
$requestSystemData->systemId = isset($systemData['systemData']['id']) ? (int) $systemData['systemData']['id'] : 0;
|
||||
|
||||
// update current location
|
||||
// -> suppress temporary timeout errors
|
||||
$activeCharacter = $activeCharacter->updateLog(['suppressHTTPErrors' => true]);
|
||||
|
||||
if( !is_null($map = $activeCharacter->getMap($mapId)) ){
|
||||
// check character log (current system) and manipulate map (e.g. add new system)
|
||||
if( (bool)$characterMapData['mapTracking'] ){
|
||||
if($mapTracking){
|
||||
$map = $this->updateMapData($activeCharacter, $map);
|
||||
}
|
||||
|
||||
// get from cache
|
||||
// this should happen if a user has multiple program instances running
|
||||
// with the same main char
|
||||
$cacheKey = $this->getUserDataCacheKey($mapId, $requestSystemData->systemId);
|
||||
if( !$f3->exists($cacheKey, $return) ){
|
||||
$return = (object) [];
|
||||
$return->mapUserData[] = $map->getUserData();
|
||||
// mapUserData ----------------------------------------------------------------------------------------
|
||||
if($getMapUserData){
|
||||
$cacheKey = $this->getUserDataCacheKey($mapId);
|
||||
if( !$f3->exists($cacheKey, $mapUserData) ){
|
||||
$mapUserData = $map->getUserData();
|
||||
|
||||
// request signature data for a system if user has map access!
|
||||
if( $mapId === $requestSystemData->mapId ){
|
||||
$system = $map->getSystemById( $requestSystemData->systemId );
|
||||
|
||||
if( !is_null($system) ){
|
||||
// data for currently selected system
|
||||
$return->system = $system->getData();
|
||||
$return->system->signatures = $system->getSignaturesData();
|
||||
}
|
||||
// cache time (seconds) should be equal or less than request trigger time
|
||||
// prevent request flooding
|
||||
$responseTTL = (int)Config::getPathfinderData('timer.update_server_user_data.delay') / 1000;
|
||||
$f3->set($cacheKey, $mapUserData, $responseTTL);
|
||||
}
|
||||
$return->mapUserData[] = $mapUserData;
|
||||
}
|
||||
|
||||
// cache time (seconds) should be equal or less than request trigger time
|
||||
// prevent request flooding
|
||||
$responseTTL = (int)Config::getPathfinderData('timer.update_server_user_data.delay') / 1000;
|
||||
|
||||
// cache response
|
||||
$f3->set($cacheKey, $return, $responseTTL);
|
||||
// systemData -----------------------------------------------------------------------------------------
|
||||
if(
|
||||
$mapId === (int)$systemData['mapId'] &&
|
||||
!is_null($system = $map->getSystemById((int)$systemData['systemData']['id']))
|
||||
){
|
||||
// data for currently selected system
|
||||
$return->system = $system->getData();
|
||||
$return->system->signatures = $system->getSignaturesData();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1042,8 +1008,7 @@ class Map extends Controller\AccessController {
|
||||
// check distance between systems (in jumps)
|
||||
// -> if > 1 it is !very likely! a wormhole
|
||||
$routeController = new Route();
|
||||
$routeController->initJumpData();
|
||||
$route = $routeController->findRoute($sourceSystem->name, $targetSystem->name, 1);
|
||||
$route = $routeController->searchRoute($sourceSystem->systemId, $targetSystem->systemId, 1);
|
||||
|
||||
if( !$route['routePossible'] ){
|
||||
$addSourceSystem = true;
|
||||
@@ -1121,7 +1086,6 @@ class Map extends Controller\AccessController {
|
||||
}
|
||||
|
||||
if($mapDataChanged){
|
||||
$this->clearMapDataCache($character);
|
||||
$this->broadcastMapData($map);
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,8 @@ use Model;
|
||||
*/
|
||||
class Route extends Controller\AccessController {
|
||||
|
||||
const ROUTE_SEARCH_DEPTH_DEFAULT = 1;
|
||||
|
||||
/**
|
||||
* cache time for static jump data (e.g. K-Space stargates)
|
||||
* @var int
|
||||
@@ -44,27 +46,32 @@ class Route extends Controller\AccessController {
|
||||
private $jumpArray = [];
|
||||
|
||||
/**
|
||||
* array withh systemName => systemId matching
|
||||
* array with systemName => systemId matching
|
||||
* @var array
|
||||
*/
|
||||
private $idArray = [];
|
||||
|
||||
/**
|
||||
* set jump data for route search
|
||||
* -> this function is required for route search! (Don´t forget)
|
||||
* @param array $mapIds
|
||||
* @param array $filterData
|
||||
* @param array $keepSystems
|
||||
* template for routeData payload
|
||||
* @var array
|
||||
*/
|
||||
public function initJumpData($mapIds = [], $filterData = [], $keepSystems = []){
|
||||
// add static data (e.g. K-Space stargates,..)
|
||||
$this->setStaticJumpData();
|
||||
private $defaultRouteData = [
|
||||
'routePossible' => false,
|
||||
'routeJumps' => 0,
|
||||
'maxDepth' => self::ROUTE_SEARCH_DEPTH_DEFAULT,
|
||||
'depthSearched' => 0,
|
||||
'searchType' => '',
|
||||
'route' => [],
|
||||
'error' => ''
|
||||
];
|
||||
|
||||
// add map specific data
|
||||
$this->setDynamicJumpData($mapIds, $filterData);
|
||||
|
||||
// filter jump data (e.g. remove some systems (0.0, LS)
|
||||
$this->filterJumpData($filterData, $keepSystems);
|
||||
/**
|
||||
* reset all jump data
|
||||
*/
|
||||
protected function resetJumpData(){
|
||||
$this->nameArray = [];
|
||||
$this->jumpArray = [];
|
||||
$this->idArray = [];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -74,31 +81,11 @@ class Route extends Controller\AccessController {
|
||||
* -> this data is equal for EACH route search (does not depend on map data)
|
||||
*/
|
||||
private function setStaticJumpData(){
|
||||
$cacheKey = 'staticJumpData';
|
||||
$query = "SELECT * FROM system_neighbour";
|
||||
$rows = $this->getDB()->exec($query, null, $this->staticJumpDataCacheTime);
|
||||
|
||||
$f3 = $this->getF3();
|
||||
|
||||
$cacheKeyNamedArray = $cacheKey . '.nameArray';
|
||||
$cacheKeyJumpArray = $cacheKey . '.jumpArray';
|
||||
$cacheKeyIdArray = $cacheKey . '.idArray';
|
||||
|
||||
if(
|
||||
!$f3->exists($cacheKeyNamedArray, $this->nameArray) ||
|
||||
!$f3->exists($cacheKeyJumpArray, $this->jumpArray) ||
|
||||
!$f3->exists($cacheKeyIdArray, $this->idArray)
|
||||
){
|
||||
// nothing cached
|
||||
$query = "SELECT * FROM system_neighbour";
|
||||
$rows = $this->getDB()->exec($query, null, $this->staticJumpDataCacheTime);
|
||||
|
||||
if(count($rows) > 0){
|
||||
$this->updateJumpData($rows);
|
||||
|
||||
// static data should be cached
|
||||
$f3->set($cacheKeyNamedArray, $this->nameArray, $this->staticJumpDataCacheTime);
|
||||
$f3->set($cacheKeyJumpArray, $this->jumpArray, $this->staticJumpDataCacheTime);
|
||||
$f3->set($cacheKeyIdArray, $this->idArray, $this->staticJumpDataCacheTime);
|
||||
}
|
||||
if(count($rows) > 0){
|
||||
$this->updateJumpData($rows);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -267,12 +254,12 @@ class Route extends Controller\AccessController {
|
||||
}
|
||||
|
||||
/**
|
||||
* filter systems (remove some systems) e.g. WH,LS,0.0 for "safer search"
|
||||
* filter systems (remove some systems) e.g. WH,LS,0.0 for "secure search"
|
||||
* @param array $filterData
|
||||
* @param array $keepSystems
|
||||
*/
|
||||
private function filterJumpData($filterData = [], $keepSystems = []){
|
||||
if($filterData['safer']){
|
||||
if($filterData['flag'] == 'secure'){
|
||||
// remove all systems (TrueSec < 0.5) from search arrays
|
||||
$this->jumpArray = array_filter($this->jumpArray, function($jumpData) use($keepSystems) {
|
||||
|
||||
@@ -302,9 +289,7 @@ class Route extends Controller\AccessController {
|
||||
* @return null
|
||||
*/
|
||||
private function getSystemInfoBySystemId($systemId, $option){
|
||||
|
||||
$info = null;
|
||||
|
||||
switch($option){
|
||||
case 'systemName':
|
||||
$info = $this->nameArray[ $systemId ][0];
|
||||
@@ -395,65 +380,98 @@ class Route extends Controller\AccessController {
|
||||
}
|
||||
|
||||
/**
|
||||
* find a route between two systems (system names)
|
||||
* $searchDepth for recursive route search (5000 would be best but slow)
|
||||
* -> in reality there are no routes > 100 jumps between systems
|
||||
* @param $systemFrom
|
||||
* @param $systemTo
|
||||
* @param int $searchDepth
|
||||
* get formatted jump node data
|
||||
* @param $systemName
|
||||
* @return array
|
||||
*/
|
||||
public function findRoute($systemFrom, $systemTo, $searchDepth = 7000){
|
||||
|
||||
$routeData = [
|
||||
'routePossible' => false,
|
||||
'routeJumps' => 0,
|
||||
'maxDepth' => $searchDepth,
|
||||
'depthSearched' => 0,
|
||||
'route' => []
|
||||
protected function getJumpNodeData($systemName) : array {
|
||||
return [
|
||||
'system' => $systemName,
|
||||
'security' => $this->getSystemInfoBySystemId($this->idArray[$systemName], 'trueSec')
|
||||
];
|
||||
}
|
||||
|
||||
if(
|
||||
!empty($systemFrom) &&
|
||||
!empty($systemTo)
|
||||
){
|
||||
/**
|
||||
* search root between two systemIds
|
||||
* -> function searches over ESI API, as fallback a custom search algorithm is used (no ESI)
|
||||
* @param int $systemFromId
|
||||
* @param int $systemToId
|
||||
* @param int $searchDepth
|
||||
* @param array $mapIds
|
||||
* @param array $filterData
|
||||
* @return array
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
public function searchRoute(int $systemFromId, int $systemToId, $searchDepth = 0, array $mapIds = [], array $filterData = []) : array {
|
||||
// search root by ESI API
|
||||
$routeData = $this->searchRouteESI($systemFromId, $systemToId, $searchDepth, $mapIds, $filterData);
|
||||
|
||||
$from = strtoupper( $systemFrom );
|
||||
$to = strtoupper( $systemTo );
|
||||
if( !empty($routeData['error']) ){
|
||||
// ESI route search has errors -> fallback to custom search implementation
|
||||
$routeData = $this->searchRouteCustom($systemFromId, $systemToId, $searchDepth, $mapIds, $filterData);
|
||||
}
|
||||
|
||||
return $routeData;
|
||||
}
|
||||
|
||||
/**
|
||||
* uses a custom search algorithm to fine a route
|
||||
* @param int $systemFromId
|
||||
* @param int $systemToId
|
||||
* @param int $searchDepth
|
||||
* @param array $mapIds
|
||||
* @param array $filterData
|
||||
* @return array
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
public function searchRouteCustom(int $systemFromId, int $systemToId, $searchDepth = 0, array $mapIds = [], array $filterData = []) : array {
|
||||
// reset all previous set jump data
|
||||
$this->resetJumpData();
|
||||
|
||||
$searchDepth = $searchDepth ? $searchDepth : Config::getPathfinderData('route.search_depth');
|
||||
|
||||
$routeData = $this->defaultRouteData;
|
||||
$routeData['maxDepth'] = $searchDepth;
|
||||
$routeData['searchType'] = 'custom';
|
||||
|
||||
if($systemFromId && $systemToId){
|
||||
// prepare search data ------------------------------------------------------------------------------------
|
||||
// add static data (e.g. K-Space stargates,..)
|
||||
$this->setStaticJumpData();
|
||||
|
||||
// add map specific data
|
||||
$this->setDynamicJumpData($mapIds, $filterData);
|
||||
|
||||
// filter jump data (e.g. remove some systems (0.0, LS)
|
||||
// --> don´t filter some systems (e.g. systemFrom, systemTo) even if they are are WH,LS,0.0
|
||||
$this->filterJumpData($filterData, [$systemFromId, $systemToId]);
|
||||
|
||||
$systemFrom = $this->getSystemInfoBySystemId($systemFromId, 'systemName');
|
||||
$systemTo = $this->getSystemInfoBySystemId($systemToId, 'systemName');
|
||||
|
||||
// search route -------------------------------------------------------------------------------------------
|
||||
|
||||
// jump counter
|
||||
$jumpNum = 0;
|
||||
$depthSearched = 0;
|
||||
|
||||
if( isset($this->jumpArray[$from]) ){
|
||||
|
||||
if( isset($this->jumpArray[$systemFrom]) ){
|
||||
// check if the system we are looking for is a direct neighbour
|
||||
foreach( $this->jumpArray[$from] as $n ) {
|
||||
|
||||
if ($n == $to) {
|
||||
foreach( $this->jumpArray[$systemFrom] as $n ) {
|
||||
if ($n == $systemTo) {
|
||||
$jumpNum = 2;
|
||||
|
||||
$jumpNode = [
|
||||
'system' => $n,
|
||||
'security' => $this->getSystemInfoBySystemId($this->idArray[$n], 'trueSec')
|
||||
];
|
||||
|
||||
$routeData['route'][] = $jumpNode;
|
||||
$routeData['route'][] = $this->getJumpNodeData($n);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// system is not a direct neighbour -> search recursive its neighbours
|
||||
if ($jumpNum == 0) {
|
||||
$searchResult = $this->graph_find_path( $this->jumpArray, $from, $to, $searchDepth );
|
||||
$searchResult = $this->graph_find_path( $this->jumpArray, $systemFrom, $systemTo, $searchDepth );
|
||||
$depthSearched = $searchResult['depth'];
|
||||
foreach( $searchResult['path'] as $systemName ) {
|
||||
if ($jumpNum > 0) {
|
||||
$jumpNode = [
|
||||
'system' => $systemName,
|
||||
'security' => $this->getSystemInfoBySystemId($this->idArray[$systemName], 'trueSec')
|
||||
];
|
||||
$routeData['route'][] = $jumpNode;
|
||||
$routeData['route'][] = $this->getJumpNodeData($systemName);
|
||||
}
|
||||
$jumpNum++;
|
||||
}
|
||||
@@ -462,14 +480,8 @@ class Route extends Controller\AccessController {
|
||||
if ($jumpNum > 0) {
|
||||
// route found
|
||||
$routeData['routePossible'] = true;
|
||||
|
||||
$jumpNode = [
|
||||
'system' => $from,
|
||||
'security' => $this->getSystemInfoBySystemId($this->idArray[$from], 'trueSec')
|
||||
];
|
||||
|
||||
// insert "from" system on top
|
||||
array_unshift($routeData['route'], $jumpNode);
|
||||
array_unshift($routeData['route'], $this->getJumpNodeData($systemFrom));
|
||||
} else {
|
||||
// route not found
|
||||
$routeData['routePossible'] = false;
|
||||
@@ -484,6 +496,102 @@ class Route extends Controller\AccessController {
|
||||
return $routeData;
|
||||
}
|
||||
|
||||
/**
|
||||
* uses ESI route search endpoint to fine a route
|
||||
* @param int $systemFromId
|
||||
* @param int $systemToId
|
||||
* @param int $searchDepth
|
||||
* @param array $mapIds
|
||||
* @param array $filterData
|
||||
* @return array
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
public function searchRouteESI(int $systemFromId, int $systemToId, int $searchDepth = 0, array $mapIds = [], array $filterData = []) : array {
|
||||
// reset all previous set jump data
|
||||
$this->resetJumpData();
|
||||
|
||||
$searchDepth = $searchDepth ? $searchDepth : Config::getPathfinderData('route.search_depth');
|
||||
|
||||
$routeData = $this->defaultRouteData;
|
||||
$routeData['maxDepth'] = $searchDepth;
|
||||
$routeData['searchType'] = 'esi';
|
||||
|
||||
if($systemFromId && $systemToId){
|
||||
// prepare search data ------------------------------------------------------------------------------------
|
||||
|
||||
// add map specific data
|
||||
$this->setDynamicJumpData($mapIds, $filterData);
|
||||
|
||||
// filter jump data (e.g. remove some systems (0.0, LS)
|
||||
// --> don´t filter some systems (e.g. systemFrom, systemTo) even if they are are WH,LS,0.0
|
||||
$this->filterJumpData($filterData, [$systemFromId, $systemToId]);
|
||||
|
||||
$connections = [];
|
||||
foreach($this->jumpArray as $systemSourceName => $jumpData){
|
||||
$count = count($jumpData);
|
||||
if($count > 1){
|
||||
// ... should always > 1
|
||||
$systemSourceId = (int)$this->idArray[$systemSourceName];
|
||||
// loop all connections for current source system
|
||||
foreach($jumpData as $systemTargetName) {
|
||||
// skip last entry
|
||||
if(--$count <= 0){
|
||||
break;
|
||||
}
|
||||
$systemTargetId = (int)$this->idArray[$systemTargetName];
|
||||
|
||||
// systemIds exist and wer not removed before in filterJumpData()
|
||||
if($systemSourceId && $systemTargetId){
|
||||
$connections[] = [$systemSourceId, $systemTargetId];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// search route -------------------------------------------------------------------------------------------
|
||||
$options = [
|
||||
'flag' => $filterData['flag'],
|
||||
'connections' => $connections
|
||||
];
|
||||
|
||||
$result = $this->getF3()->ccpClient->getRouteData($systemFromId, $systemToId, $options);
|
||||
|
||||
// format result ------------------------------------------------------------------------------------------
|
||||
|
||||
// jump counter
|
||||
$jumpNum = 0;
|
||||
$depthSearched = 0;
|
||||
if( !empty($result['error']) ){
|
||||
$routeData['error'] = $result['error'];
|
||||
}elseif( !empty($result['route']) ){
|
||||
$jumpNum = count($result['route']) - 1;
|
||||
|
||||
// check max search depth
|
||||
if($jumpNum <= $routeData['maxDepth']){
|
||||
$depthSearched = $jumpNum;
|
||||
|
||||
$routeData['routePossible'] = true;
|
||||
|
||||
// Now (after search) we have to "add" static jump data information
|
||||
$this->setStaticJumpData();
|
||||
|
||||
foreach($result['route'] as $systemId){
|
||||
$systemName = $this->getSystemInfoBySystemId($systemId, 'systemName');
|
||||
$routeData['route'][] = $this->getJumpNodeData($systemName);
|
||||
}
|
||||
}else{
|
||||
$depthSearched = $routeData['maxDepth'];
|
||||
}
|
||||
}
|
||||
|
||||
// route jumps
|
||||
$routeData['routeJumps'] = $jumpNum;
|
||||
$routeData['depthSearched'] = $depthSearched;
|
||||
}
|
||||
|
||||
return $routeData;
|
||||
}
|
||||
|
||||
/**
|
||||
* get key for route cache
|
||||
* @param $mapIds
|
||||
@@ -543,7 +651,9 @@ class Route extends Controller\AccessController {
|
||||
|
||||
// check map access (filter requested mapIDs and format) ----------------------------------------------
|
||||
array_walk($mapData, function(&$item, &$key, $data){
|
||||
|
||||
/**
|
||||
* @var Model\MapModel $data[0]
|
||||
*/
|
||||
if( isset($data[1][$key]) ){
|
||||
// character has map access -> do not check again
|
||||
$item = $data[1][$key];
|
||||
@@ -577,7 +687,7 @@ class Route extends Controller\AccessController {
|
||||
'wormholesCritical' => (bool) $routeData['wormholesCritical'],
|
||||
'wormholesFrigate' => (bool) $routeData['wormholesFrigate'],
|
||||
'wormholesEOL' => (bool) $routeData['wormholesEOL'],
|
||||
'safer' => (bool) $routeData['safer']
|
||||
'flag' => $routeData['flag']
|
||||
];
|
||||
|
||||
$returnRoutData = [
|
||||
@@ -611,16 +721,8 @@ class Route extends Controller\AccessController {
|
||||
// get data from cache
|
||||
$returnRoutData = $cachedData;
|
||||
}else{
|
||||
// max search depth for search
|
||||
$searchDepth = Config::getPathfinderData('route.search_depth');
|
||||
$foundRoutData = $this->searchRoute($systemFromId, $systemToId, 0, $mapIds, $filterData);
|
||||
|
||||
// set jump data for following route search
|
||||
// --> don´t filter some systems (e.g. systemFrom, systemTo) even if they are are WH,LS,0.0
|
||||
$keepSystems = [$systemFromId, $systemToId];
|
||||
$this->initJumpData($mapIds, $filterData, $keepSystems);
|
||||
|
||||
// no cached route data found
|
||||
$foundRoutData = $this->findRoute($systemFrom, $systemTo, $searchDepth);
|
||||
$returnRoutData = array_merge($returnRoutData, $foundRoutData);
|
||||
|
||||
// cache if route was found
|
||||
|
||||
@@ -25,6 +25,7 @@ class Controller {
|
||||
const ERROR_SESSION_SUSPECT = 'id: [%45s], ip: [%45s], User-Agent: [%s]';
|
||||
const ERROR_TEMP_CHARACTER_ID = 'Invalid temp characterId: %s';
|
||||
|
||||
const NOTIFICATION_TYPES = ['danger', 'warning', 'info', 'success'];
|
||||
/**
|
||||
* @var \Base
|
||||
*/
|
||||
@@ -184,6 +185,7 @@ class Controller {
|
||||
* set/update logged in cookie by character model
|
||||
* -> store validation data in DB
|
||||
* @param Model\CharacterModel $character
|
||||
* @throws \Exception
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
protected function setLoginCookie(Model\CharacterModel $character){
|
||||
@@ -541,6 +543,20 @@ class Controller {
|
||||
return $object;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $title
|
||||
* @param string $message
|
||||
* @param string $type
|
||||
* @return \stdClass
|
||||
*/
|
||||
protected function getNotificationObject(string $title, $message = '', $type = 'danger') : \stdClass {
|
||||
$notification = (object) [];
|
||||
$notification->type = in_array($type, self::NOTIFICATION_TYPES) ? $type : 'danger';
|
||||
$notification->title = $title;
|
||||
$notification->message = $message;
|
||||
return $notification;
|
||||
}
|
||||
|
||||
/**
|
||||
* get a program URL by alias
|
||||
* -> if no $alias given -> get "default" route (index.php)
|
||||
@@ -716,11 +732,11 @@ class Controller {
|
||||
* @return array
|
||||
*/
|
||||
static function getScopesByAuthType($authType = ''){
|
||||
$scopes = (array)self::getEnvironmentData('CCP_ESI_SCOPES');
|
||||
$scopes = array_filter((array)self::getEnvironmentData('CCP_ESI_SCOPES'));
|
||||
|
||||
switch($authType){
|
||||
case 'admin':
|
||||
$scopesAdmin = (array)self::getEnvironmentData('CCP_ESI_SCOPES_ADMIN');
|
||||
$scopesAdmin = array_filter((array)self::getEnvironmentData('CCP_ESI_SCOPES_ADMIN'));
|
||||
$scopes = array_merge($scopes, $scopesAdmin);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
namespace lib;
|
||||
|
||||
|
||||
use controller\LogController;
|
||||
use Exception;
|
||||
|
||||
class Config extends \Prefab {
|
||||
@@ -378,7 +379,6 @@ class Config extends \Prefab {
|
||||
}
|
||||
|
||||
/**
|
||||
* get PATHFINDER config data
|
||||
* @param string $key
|
||||
* @return mixed
|
||||
* @throws Exception\PathfinderException
|
||||
@@ -386,8 +386,12 @@ class Config extends \Prefab {
|
||||
static function getPathfinderData($key = ''){
|
||||
$hiveKey = self::HIVE_KEY_PATHFINDER . ($key ? '.' . strtoupper($key) : '');
|
||||
|
||||
if( !\Base::instance()->exists($hiveKey, $data) ){
|
||||
throw new Exception\PathfinderException(sprintf(self::ERROR_CONF_PATHFINDER, $hiveKey));
|
||||
try{
|
||||
if( !\Base::instance()->exists($hiveKey, $data) ){
|
||||
throw new Exception\PathfinderException(sprintf(self::ERROR_CONF_PATHFINDER, $hiveKey));
|
||||
}
|
||||
}catch (Exception\PathfinderException $e){
|
||||
LogController::getLogger('ERROR')->write($e->getMessage());
|
||||
}
|
||||
|
||||
return $data;
|
||||
|
||||
@@ -222,6 +222,9 @@ class CharacterLogModel extends BasicModel {
|
||||
if($this->characterId){
|
||||
// characterId relation could be deleted by cron therefore check again first...
|
||||
$this->characterId->clearCacheDataWithPrefix(CharacterModel::DATA_CACHE_KEY_LOG);
|
||||
|
||||
// broadcast updated character data (with changed log data)
|
||||
$this->characterId->broadcastCharacterUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ use Controller\Api\User as User;
|
||||
use DB\SQL\Schema;
|
||||
use lib\Util;
|
||||
use lib\Config;
|
||||
use lib\Socket;
|
||||
use Model\Universe;
|
||||
|
||||
class CharacterModel extends BasicModel {
|
||||
@@ -904,6 +905,15 @@ class CharacterModel extends BasicModel {
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* broadcast characterData
|
||||
* @throws \ZMQSocketException
|
||||
*/
|
||||
public function broadcastCharacterUpdate(){
|
||||
$characterData = $this->getData(true);
|
||||
(new Socket( Config::getSocketUri() ))->sendData('characterUpdate', $characterData);
|
||||
}
|
||||
|
||||
/**
|
||||
* update character data from CCPs ESI API
|
||||
* @return array (some status messages)
|
||||
|
||||
@@ -179,8 +179,7 @@ class ConnectionModel extends AbstractMapTrackingModel {
|
||||
is_object($this->target)
|
||||
){
|
||||
$routeController = new Route();
|
||||
$routeController->initJumpData();
|
||||
$route = $routeController->findRoute($this->source->name, $this->target->name, 1);
|
||||
$route = $routeController->searchRoute($this->source->systemId, $this->target->systemId, 1);
|
||||
|
||||
if($route['routePossible']){
|
||||
$this->scope = 'stargate';
|
||||
|
||||
@@ -844,8 +844,9 @@ class MapModel extends AbstractMapTrackingModel {
|
||||
/**
|
||||
* get data for ALL characters with map access
|
||||
* -> The result of this function is cached!
|
||||
* @param array $options filter options
|
||||
* @return \stdClass
|
||||
* @param array $options
|
||||
* @return array|null|\stdClass
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function getCharactersData($options = []){
|
||||
// check if there is cached data
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
[PATHFINDER]
|
||||
NAME = Pathfinder
|
||||
; installed version (used for CSS/JS cache busting)
|
||||
VERSION = v1.3.3
|
||||
VERSION = v1.3.4
|
||||
; contact information [optional]
|
||||
CONTACT = https://github.com/exodus4d
|
||||
; public contact email [optional]
|
||||
@@ -123,15 +123,15 @@ SEND_RALLY_Mail_ENABLED = 0
|
||||
|
||||
; Route search ====================================================================================
|
||||
[PATHFINDER.ROUTE]
|
||||
; max recursive search depth for routes (default: 7000)
|
||||
; max recursive search depth for routes (default: 9000)
|
||||
; decrease it on performance problems
|
||||
SEARCH_DEPTH = 9000
|
||||
; default count of routes that will be checked (initial) when a system is selected (default: 2)
|
||||
SEARCH_DEFAULT_COUNT = 2
|
||||
; max count of routes that can be selected in "route settings" dialog (default: 4)
|
||||
MAX_DEFAULT_COUNT = 4
|
||||
; max count of routes that will be checked (MAX_COUNT + custom routes ) (default: 6)
|
||||
LIMIT = 6
|
||||
; default count of routes that will be checked (initial) when a system is selected (default: 4)
|
||||
SEARCH_DEFAULT_COUNT = 4
|
||||
; max count of routes that can be selected in "route settings" dialog (default: 6)
|
||||
MAX_DEFAULT_COUNT = 6
|
||||
; max count of routes that will be checked (MAX_COUNT + custom routes ) (default: 8)
|
||||
LIMIT = 8
|
||||
|
||||
; Email notifications =============================================================================
|
||||
; Requires SMTP configuration (see environment.ini)
|
||||
@@ -206,6 +206,14 @@ CACHE = 5
|
||||
; file folder for 'history' logs (e.g. map history) (default: history/)
|
||||
LOG = history/
|
||||
|
||||
; ADMIN ===========================================================================================
|
||||
; "SUPER" admins and additional "CORPORATION" admins can be added here
|
||||
;[PATHFINDER.ROLES]
|
||||
;CHARACTER.0.ID = 123456789
|
||||
;CHARACTER.0.ROLE = SUPER
|
||||
;CHARACTER.1.ID = 1122334455
|
||||
;CHARACTER.1.ROLE = CORPORATION
|
||||
|
||||
; API =============================================================================================
|
||||
[PATHFINDER.API]
|
||||
CCP_IMAGE_SERVER = https://image.eveonline.com
|
||||
|
||||
@@ -9,7 +9,7 @@ GET @login: / [sync] = Controller\AppContro
|
||||
; CCP SSO redirect
|
||||
GET @sso: /sso/@action [sync] = Controller\Ccp\Sso->@action
|
||||
; map page
|
||||
GET @map: /map [sync] = Controller\MapController->init
|
||||
GET @map: /map* [sync] = Controller\MapController->init
|
||||
; admin panel
|
||||
GET @admin: /admin* [sync] = Controller\Admin->dispatch
|
||||
|
||||
@@ -17,3 +17,4 @@ GET @admin: /admin* [sync] = Controller\Admin->di
|
||||
GET|POST /api/@controller/@action [ajax] = Controller\Api\@controller->@action, 0, 512
|
||||
GET|POST /api/@controller/@action/@arg1 [ajax] = Controller\Api\@controller->@action, 0, 512
|
||||
GET|POST /api/@controller/@action/@arg1/@arg2 [ajax] = Controller\Api\@controller->@action, 0, 512
|
||||
|
||||
|
||||
@@ -27,6 +27,6 @@
|
||||
"monolog/monolog": "1.*",
|
||||
"websoftwares/monolog-zmq-handler": "0.2.*",
|
||||
"swiftmailer/swiftmailer": "^6.0",
|
||||
"exodus4d/pathfinder_esi": "dev-master#v1.2.2"
|
||||
"exodus4d/pathfinder_esi": "dev-master#v1.2.3"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,8 +7,8 @@ require 'compass/import-once/activate'
|
||||
|
||||
http_path = "/"
|
||||
# project_path = ''
|
||||
css_dir = 'public/css'
|
||||
sass_dir = 'sass'
|
||||
# css_dir = 'public/css'
|
||||
# sass_dir = 'sass'
|
||||
images_dir = 'public/img'
|
||||
generated_images_path = 'img_cache'
|
||||
# javascripts_dir = 'javascripts'
|
||||
|
||||
234
gulpfile.js
234
gulpfile.js
@@ -5,7 +5,6 @@ let fs = require('fs');
|
||||
let ini = require('ini');
|
||||
|
||||
let gulp = require('gulp');
|
||||
let gutil = require('gulp-util');
|
||||
let requirejsOptimize = require('gulp-requirejs-optimize');
|
||||
let filter = require('gulp-filter');
|
||||
let gulpif = require('gulp-if');
|
||||
@@ -19,20 +18,23 @@ let compass = require('gulp-compass');
|
||||
let cleanCSS = require('gulp-clean-css');
|
||||
let bytediff = require('gulp-bytediff');
|
||||
let debug = require('gulp-debug');
|
||||
let notifier = require('node-notifier');
|
||||
|
||||
// -- Helper & NPM modules ----------------------------------------------------
|
||||
let flatten = require('flat');
|
||||
let padEnd = require('lodash.padend');
|
||||
let merge = require('lodash.merge');
|
||||
let minimist = require('minimist');
|
||||
let slash = require('slash');
|
||||
let fileExtension = require('file-extension');
|
||||
let log = require('fancy-log');
|
||||
let colors = require('ansi-colors');
|
||||
let stylish = require('jshint-stylish');
|
||||
let Table = require('terminal-table');
|
||||
let prettyBytes = require('pretty-bytes');
|
||||
let del = require('promised-del');
|
||||
|
||||
let minify = composer(uglifyjs, console);
|
||||
let chalk = gutil.colors;
|
||||
|
||||
// == Settings ========================================================================================================
|
||||
|
||||
@@ -55,8 +57,9 @@ let PATH = {
|
||||
}
|
||||
};
|
||||
|
||||
// Pathfinder config file
|
||||
let pathfinderConfigFile = './app/pathfinder.ini';
|
||||
// Pathfinder config files
|
||||
let pathfinderConfigFileApp = './app/pathfinder.ini';
|
||||
let pathfinderConfigFileConf = './conf/pathfinder.ini';
|
||||
|
||||
// CLI box size in characters
|
||||
let cliBoxLength = 80;
|
||||
@@ -96,36 +99,6 @@ let uglifyJsOptions = {
|
||||
// Sourcemaps options
|
||||
// https://www.npmjs.com/package/gulp-sourcemaps
|
||||
|
||||
// -- Plugin options ----------------------------------------------------------
|
||||
|
||||
let gZipOptions = {
|
||||
append: false, // disables default append ext .gz
|
||||
extension: 'gz', // use "custom" ext: .gz
|
||||
threshold: '1kb', // min size required to compress a file
|
||||
deleteMode: PATH.JS.DIST_BUILD, // replace *.gz files if size < 'threhold'
|
||||
gzipOptions: {
|
||||
level: 9 // zlib.Gzip compression level [0-9]
|
||||
},
|
||||
skipGrowingFiles: true // use orig. files in case of *.gz size > orig. size
|
||||
};
|
||||
|
||||
let brotliOptions = {
|
||||
extension: 'br', // use "custom" ext: .br
|
||||
mode: 1, // compression mode for UTF-8 formatted text
|
||||
quality: 11, // quality [1 worst - 11 best]
|
||||
skipLarger: true // use orig. files in case of *.br size > orig. size
|
||||
};
|
||||
|
||||
let compassOptions = {
|
||||
config_file: './config.rb',
|
||||
css: 'public/css',
|
||||
sass: 'sass',
|
||||
time: true, // show execution time
|
||||
sourcemap: true
|
||||
};
|
||||
|
||||
let compressionExt = [gZipOptions.extension, brotliOptions.extension];
|
||||
|
||||
// -- Error output ------------------------------------------------------------
|
||||
|
||||
/**
|
||||
@@ -136,14 +109,14 @@ let compressionExt = [gZipOptions.extension, brotliOptions.extension];
|
||||
let printError = (title, example) => {
|
||||
let cliLineLength = (cliBoxLength - 8);
|
||||
|
||||
gutil.log('').log(chalk.red( '= ERROR ' + '=' . repeat(cliLineLength)));
|
||||
gutil.log(chalk.red(title));
|
||||
log('').log(colors.red( '= ERROR ' + '=' . repeat(cliLineLength)));
|
||||
log(colors.red(title));
|
||||
if(example){
|
||||
gutil.log(`
|
||||
${chalk.gray(example)}
|
||||
log(`
|
||||
${colors.gray(example)}
|
||||
`);
|
||||
}
|
||||
gutil.log(chalk.red('='.repeat(cliBoxLength))).log('');
|
||||
log(colors.red('='.repeat(cliBoxLength))).log('');
|
||||
};
|
||||
|
||||
// == Settings ========================================================================================================
|
||||
@@ -151,19 +124,23 @@ let printError = (title, example) => {
|
||||
// parse pathfinder.ini config file for relevant data
|
||||
let tagVersion;
|
||||
try{
|
||||
let pathfinderIni = ini.parse(fs.readFileSync(pathfinderConfigFile, 'utf-8'));
|
||||
let pathfinderAppIni = ini.parse(fs.readFileSync(pathfinderConfigFileApp, 'utf-8'));
|
||||
let pathfinderConfIni = fs.existsSync(pathfinderConfigFileConf) ?
|
||||
ini.parse(fs.readFileSync(pathfinderConfigFileConf, 'utf-8')) : {};
|
||||
let pathfinderIni = merge(pathfinderAppIni, pathfinderConfIni);
|
||||
|
||||
try{
|
||||
tagVersion = pathfinderIni.PATHFINDER.VERSION;
|
||||
}catch(err){
|
||||
printError(
|
||||
err.message,
|
||||
'Missing "PATHFINDER.VERSION" in "' + pathfinderConfigFile + '"');
|
||||
'Missing "PATHFINDER.VERSION" in "' + pathfinderConfigFileApp + '"');
|
||||
process.exit(1);
|
||||
}
|
||||
}catch(err){
|
||||
printError(
|
||||
err.message,
|
||||
'Check read permissions for "' + pathfinderConfigFile + '"');
|
||||
'Check read permissions for "' + pathfinderConfigFileApp + '"');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
@@ -188,6 +165,36 @@ let CONF = {
|
||||
DEBUG: false
|
||||
};
|
||||
|
||||
// -- Plugin options ----------------------------------------------------------
|
||||
|
||||
let gZipOptions = {
|
||||
append: false, // disables default append ext .gz
|
||||
extension: 'gz', // use "custom" ext: .gz
|
||||
threshold: '1kb', // min size required to compress a file
|
||||
deleteMode: PATH.JS.DIST_BUILD, // replace *.gz files if size < 'threshold'
|
||||
gzipOptions: {
|
||||
level: 9 // zlib.Gzip compression level [0-9]
|
||||
},
|
||||
skipGrowingFiles: true // use orig. files in case of *.gz size > orig. size
|
||||
};
|
||||
|
||||
let brotliOptions = {
|
||||
extension: 'br', // use "custom" ext: .br
|
||||
mode: 1, // compression mode for UTF-8 formatted text
|
||||
quality: 11, // quality [1 worst - 11 best]
|
||||
skipLarger: true // use orig. files in case of *.br size > orig. size
|
||||
};
|
||||
|
||||
let compassOptions = {
|
||||
config_file: './config.rb',
|
||||
css: 'public/css/' + CONF.TAG, // #VERSION# will be replaced with version tag
|
||||
sass: 'sass',
|
||||
time: true, // show execution time
|
||||
sourcemap: true
|
||||
};
|
||||
|
||||
let compressionExt = [gZipOptions.extension, brotliOptions.extension];
|
||||
|
||||
// == Helper methods ==================================================================================================
|
||||
|
||||
/**
|
||||
@@ -263,33 +270,33 @@ let mergeConf = (confUser, confDefault) => {
|
||||
*/
|
||||
let printHelp = () => {
|
||||
let cliLineLength = (cliBoxLength - 7);
|
||||
gutil.log('')
|
||||
.log(chalk.cyan( '= HELP ' + '='.repeat(cliLineLength)))
|
||||
log('')
|
||||
.log(colors.cyan( '= HELP ' + '='.repeat(cliLineLength)))
|
||||
.log(`
|
||||
${chalk.cyan('documentation:')} ${chalk.gray('https://github.com/exodus4d/pathfinder/wiki/GulpJs')}
|
||||
${colors.cyan('documentation:')} ${colors.gray('https://github.com/exodus4d/pathfinder/wiki/GulpJs')}
|
||||
|
||||
${chalk.cyan('usage:')} ${chalk.gray('$ npm run gulp [task] -- [--options] ...')}
|
||||
${colors.cyan('usage:')} ${colors.gray('$ npm run gulp [task] -- [--options] ...')}
|
||||
|
||||
${chalk.cyan('tasks:')}
|
||||
${chalk.gray('help')} This view
|
||||
${chalk.gray('default')} Development environment. Working with row src files and file watcher, default:
|
||||
${chalk.gray('')} ${chalk.gray('--jsUglify=false --jsSourcemaps=false --cssSourcemaps=false --jsGzip=false --cssGzip=false --jsBrotli=false --cssBrotli=false')}
|
||||
${chalk.gray('production')} Production build. Concat and uglify static resources, default:
|
||||
${chalk.gray('')} ${chalk.gray('--jsUglify=true --jsSourcemaps=true --cssSourcemaps=true --jsGzip=true --cssGzip=true --jsBrotli=true --cssBrotli=true')}
|
||||
${colors.cyan('tasks:')}
|
||||
${colors.gray('help')} This view
|
||||
${colors.gray('default')} Development environment. Working with row src files and file watcher, default:
|
||||
${colors.gray('')} ${colors.gray('--jsUglify=false --jsSourcemaps=false --cssSourcemaps=false --jsGzip=false --cssGzip=false --jsBrotli=false --cssBrotli=false')}
|
||||
${colors.gray('production')} Production build. Concat and uglify static resources, default:
|
||||
${colors.gray('')} ${colors.gray('--jsUglify=true --jsSourcemaps=true --cssSourcemaps=true --jsGzip=true --cssGzip=true --jsBrotli=true --cssBrotli=true')}
|
||||
|
||||
${chalk.cyan('options:')}
|
||||
${chalk.gray('--tag')} Set build version. ${chalk.gray('default: --tag="v1.2.4" -> dest path: public/js/v1.2.4')}
|
||||
${chalk.gray('--jsUglify')} Set js uglification. ${chalk.gray('(true || false)')}
|
||||
${chalk.gray('--jsSourcemaps')} Set js sourcemaps generation. ${chalk.gray('(true || false)')}
|
||||
${chalk.gray('--jsGzip')} Set js "gzip" compression mode. ${chalk.gray('(true || false)')}
|
||||
${chalk.gray('--jsBrotli')} Set js "brotli" compression mode. ${chalk.gray('(true || false)')}
|
||||
${colors.cyan('options:')}
|
||||
${colors.gray('--tag')} Set build version. ${colors.gray('default: --tag="v1.2.4" -> dest path: public/js/v1.2.4')}
|
||||
${colors.gray('--jsUglify')} Set js uglification. ${colors.gray('(true || false)')}
|
||||
${colors.gray('--jsSourcemaps')} Set js sourcemaps generation. ${colors.gray('(true || false)')}
|
||||
${colors.gray('--jsGzip')} Set js "gzip" compression mode. ${colors.gray('(true || false)')}
|
||||
${colors.gray('--jsBrotli')} Set js "brotli" compression mode. ${colors.gray('(true || false)')}
|
||||
|
||||
${chalk.gray('--cssSourcemaps')} Set CSS sourcemaps generation. ${chalk.gray('(true || false)')}
|
||||
${chalk.gray('--cssGzip')} Set CSS "gzip" compression mode. ${chalk.gray('(true || false)')}
|
||||
${chalk.gray('--cssBrotli')} Set CSS "brotli" compression mode. ${chalk.gray('(true || false)')}
|
||||
${chalk.gray('--debug')} Set debug mode (more output). ${chalk.gray('(true || false)')}
|
||||
${colors.gray('--cssSourcemaps')} Set CSS sourcemaps generation. ${colors.gray('(true || false)')}
|
||||
${colors.gray('--cssGzip')} Set CSS "gzip" compression mode. ${colors.gray('(true || false)')}
|
||||
${colors.gray('--cssBrotli')} Set CSS "brotli" compression mode. ${colors.gray('(true || false)')}
|
||||
${colors.gray('--debug')} Set debug mode (more output). ${colors.gray('(true || false)')}
|
||||
`)
|
||||
.log(chalk.cyan('='.repeat(cliBoxLength)))
|
||||
.log(colors.cyan('='.repeat(cliBoxLength)))
|
||||
.log('');
|
||||
};
|
||||
|
||||
@@ -484,7 +491,7 @@ gulp.task('task:cleanJsBuild', () => del([PATH.JS.DIST_BUILD]));
|
||||
/**
|
||||
* clean CSS build dir
|
||||
*/
|
||||
gulp.task('task:cleanCssBuild', () => del([PATH.ASSETS.DIST + '/css']));
|
||||
gulp.task('task:cleanCssBuild', () => del([PATH.ASSETS.DIST + '/css/' + CONF.TAG]));
|
||||
|
||||
/**
|
||||
* clean JS destination (final) dir
|
||||
@@ -535,11 +542,11 @@ gulp.task('task:concatJS', () => {
|
||||
};
|
||||
}))
|
||||
.pipe(bytediff.start())
|
||||
.pipe(gulpif(CONF.JS.UGLIFY, minify(uglifyJsOptions).on('warnings', gutil.log)))
|
||||
.pipe(gulpif(CONF.JS.UGLIFY, minify(uglifyJsOptions).on('warnings', log)))
|
||||
.pipe(gulpif(CONF.JS.SOURCEMAPS, sourcemaps.write('.', {includeContent: false, sourceRoot: '/js'}))) // prod (minify)
|
||||
.pipe(bytediff.stop(data => {
|
||||
trackFile(data, {src: 'startSize', src_percent: 'percent', uglify: 'endSize'});
|
||||
return chalk.green('Build concat file "' + data.fileName + '"');
|
||||
return colors.green('Build concat file "' + data.fileName + '"');
|
||||
}))
|
||||
.pipe(gulp.dest(PATH.JS.DIST_BUILD));
|
||||
});
|
||||
@@ -559,7 +566,7 @@ gulp.task('task:diffJS', () => {
|
||||
.pipe(gulpif(CONF.JS.SOURCEMAPS, sourcemaps.write('.', {includeContent: false, sourceRoot: '/js'})))
|
||||
.pipe(bytediff.stop(data => {
|
||||
trackFile(data, {src: 'startSize', src_percent: 'percent', uglify: 'endSize'});
|
||||
return chalk.green('Build file "' + data.fileName + '"');
|
||||
return colors.green('Build file "' + data.fileName + '"');
|
||||
}))
|
||||
.pipe(gulp.dest(PATH.JS.DIST_BUILD, {overwrite: false}));
|
||||
});
|
||||
@@ -595,9 +602,9 @@ let gzipAssets = (config, taskName) => {
|
||||
.pipe(bytediff.stop(data => {
|
||||
trackFile(data, {gzipFile: 'fileName', gzip: 'endSize'});
|
||||
if(fileExtension(data.fileName) === gZipOptions.extension){
|
||||
return chalk.green('Gzip generate "' + data.fileName + '"');
|
||||
return colors.green('Gzip generate "' + data.fileName + '"');
|
||||
}else{
|
||||
return chalk.gray('Gzip skip "' + data.fileName + '". Size < ' + gZipOptions.threshold + ' (threehold)');
|
||||
return colors.gray('Gzip skip "' + data.fileName + '". Size < ' + gZipOptions.threshold + ' (threehold)');
|
||||
}
|
||||
}))
|
||||
.pipe(gulp.dest(PATH.ASSETS.DIST));
|
||||
@@ -618,9 +625,9 @@ let brotliAssets = (config, taskName) => {
|
||||
.pipe(bytediff.stop(data => {
|
||||
trackFile(data, {brotliFile: 'fileName', brotli: 'endSize'});
|
||||
if(fileExtension(data.fileName) === brotliOptions.extension){
|
||||
return chalk.green('Brotli generate "' + data.fileName + '"');
|
||||
return colors.green('Brotli generate "' + data.fileName + '"');
|
||||
}else{
|
||||
return chalk.gray('Brotli skip "' + data.fileName + '"');
|
||||
return colors.gray('Brotli skip "' + data.fileName + '"');
|
||||
}
|
||||
}))
|
||||
.pipe(gulp.dest(PATH.ASSETS.DIST));
|
||||
@@ -664,9 +671,9 @@ gulp.task('task:sass', () => {
|
||||
.pipe(bytediff.start())
|
||||
.pipe(bytediff.stop(data => {
|
||||
trackFile(data, {src: 'startSize', src_percent: 'percent', uglify: 'endSize'});
|
||||
return chalk.green('Build CSS file "' + data.fileName + '"');
|
||||
return colors.green('Build CSS file "' + data.fileName + '"');
|
||||
}))
|
||||
.pipe(gulp.dest(PATH.ASSETS.DIST + '/css'));
|
||||
.pipe(gulp.dest(PATH.ASSETS.DIST + '/css/' + CONF.TAG));
|
||||
});
|
||||
|
||||
/**
|
||||
@@ -678,7 +685,7 @@ gulp.task('task:cleanCss', () => {
|
||||
compatibility: '*',
|
||||
level: 2
|
||||
}))
|
||||
.pipe(gulp.dest(PATH.ASSETS.DIST +'/css'));
|
||||
.pipe(gulp.dest(PATH.ASSETS.DIST +'/css/' + CONF.TAG));
|
||||
});
|
||||
|
||||
// == Helper tasks ====================================================================================================
|
||||
@@ -703,13 +710,13 @@ gulp.task('task:printJsSummary', done => {
|
||||
* print task configuration (e.g. CLI parameters)
|
||||
*/
|
||||
gulp.task('task:printConfig', done => {
|
||||
let error = chalk.red;
|
||||
let success = chalk.green;
|
||||
let error = colors.red;
|
||||
let success = colors.green;
|
||||
|
||||
let columnLength = Math.round(cliBoxLength / 2);
|
||||
let cliLineLength = cliBoxLength - 9;
|
||||
|
||||
gutil.log(chalk.gray( '= CONFIG ' + '='.repeat(cliLineLength)));
|
||||
log(colors.gray( '= CONFIG ' + '='.repeat(cliLineLength)));
|
||||
|
||||
let configFlat = flatten(CONF);
|
||||
for (let key in configFlat) {
|
||||
@@ -717,13 +724,13 @@ gulp.task('task:printConfig', done => {
|
||||
let value = configFlat[key];
|
||||
// format value
|
||||
value = padEnd((typeof value === 'undefined') ? 'undefined': value, columnLength);
|
||||
gutil.log(
|
||||
chalk.gray.yellow(padEnd(key, columnLength)),
|
||||
log(
|
||||
colors.yellow(padEnd(key, columnLength)),
|
||||
configFlat[key] ? success(value) : error(value)
|
||||
);
|
||||
}
|
||||
}
|
||||
gutil.log(chalk.reset.gray('='.repeat(cliBoxLength)));
|
||||
log(colors.gray('='.repeat(cliBoxLength)));
|
||||
done();
|
||||
});
|
||||
|
||||
@@ -733,7 +740,7 @@ gulp.task('task:printConfig', done => {
|
||||
gulp.task('task:checkConfig', done => {
|
||||
if(!CONF.TAG){
|
||||
printError(
|
||||
'Missing TAG version. Add param ' + chalk.cyan('--tag'),
|
||||
'Missing TAG version. Add param ' + colors.cyan('--tag'),
|
||||
'$ npm run gulp default -- --tag="v1.2.4"');
|
||||
process.exit(0);
|
||||
}
|
||||
@@ -802,7 +809,7 @@ gulp.task('task:updateJsDest', gulp.series(
|
||||
'task:gzipJsAssets',
|
||||
'task:brotliJsAssets',
|
||||
'task:renameJsDest',
|
||||
'task:printJsSummary',
|
||||
// 'task:printJsSummary',
|
||||
'task:cleanJsBuild'
|
||||
)
|
||||
);
|
||||
@@ -826,6 +833,36 @@ gulp.task('task:buildCss', gulp.series(
|
||||
)
|
||||
);
|
||||
|
||||
// == Notification tasks ==============================================================================================
|
||||
|
||||
/**
|
||||
* JS Build done notification
|
||||
*/
|
||||
gulp.task('task:notifyJsDone', done => {
|
||||
notifier.notify({
|
||||
title: 'Done JS build',
|
||||
message: 'JS build task finished',
|
||||
icon: PATH.ASSETS.DIST + '/img/logo.png',
|
||||
wait: false
|
||||
});
|
||||
done();
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* CSS Build done notification
|
||||
*/
|
||||
gulp.task('task:notifyCssDone', done => {
|
||||
notifier.notify({
|
||||
title: 'Done CSS build',
|
||||
message: 'CSS build task finished',
|
||||
icon: PATH.ASSETS.DIST + '/img/logo.png',
|
||||
wait: false
|
||||
});
|
||||
done();
|
||||
}
|
||||
);
|
||||
|
||||
// == Watcher tasks ===================================================================================================
|
||||
|
||||
/**
|
||||
@@ -836,7 +873,8 @@ gulp.task(
|
||||
gulp.series(
|
||||
'task:hintJS',
|
||||
'task:diffJS',
|
||||
'task:updateJsDest'
|
||||
'task:updateJsDest',
|
||||
'task:notifyJsDone'
|
||||
)
|
||||
);
|
||||
|
||||
@@ -850,18 +888,30 @@ gulp.task(
|
||||
// 'task:cleanCss',
|
||||
'task:gzipCssAssets',
|
||||
'task:brotliCssAssets',
|
||||
'task:printJsSummary'
|
||||
// 'task:printJsSummary',
|
||||
'task:notifyCssDone'
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* watch files for changes
|
||||
*/
|
||||
gulp.task('task:setWatcher', () => {
|
||||
gulp.watch(PATH.JS.SRC, gulp.series('task:watchJsSrc'));
|
||||
gulp.watch(PATH.CSS.SRC, gulp.series('task:watchCss'));
|
||||
|
||||
gulp.task('task:setWatcherJs', function() {
|
||||
return gulp.watch(PATH.JS.SRC, gulp.series('task:watchJsSrc', 'task:printJsSummary'));
|
||||
});
|
||||
|
||||
gulp.task('task:setWatcherCss', function() {
|
||||
return gulp.watch(PATH.CSS.SRC, gulp.series('task:watchCss', 'task:printJsSummary'));
|
||||
});
|
||||
|
||||
gulp.task('task:setWatcher',
|
||||
gulp.parallel(
|
||||
'task:setWatcherJs',
|
||||
'task:setWatcherCss'
|
||||
)
|
||||
);
|
||||
|
||||
// == Default/Main tasks ==============================================================================================
|
||||
|
||||
gulp.task(
|
||||
@@ -883,9 +933,10 @@ gulp.task(
|
||||
gulp.series(
|
||||
'task:cleanCssBuild',
|
||||
'task:watchCss'
|
||||
),
|
||||
'task:setWatcher'
|
||||
)
|
||||
)
|
||||
),
|
||||
'task:printJsSummary',
|
||||
'task:setWatcher'
|
||||
)
|
||||
);
|
||||
|
||||
@@ -902,7 +953,8 @@ gulp.task(
|
||||
'task:cleanCssBuild',
|
||||
'task:watchCss'
|
||||
)
|
||||
)
|
||||
),
|
||||
'task:printJsSummary'
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
@@ -8,51 +8,51 @@ define(['jquery'], ($) => {
|
||||
|
||||
let Config = {
|
||||
path: {
|
||||
img: 'public/img/', // path for images
|
||||
img: '/public/img/', // path for images
|
||||
// user API
|
||||
getCaptcha: 'api/user/getCaptcha', // ajax URL - get captcha image
|
||||
getServerStatus: 'api/user/getEveServerStatus', // ajax URL - get EVE-Online server status
|
||||
getCookieCharacterData: 'api/user/getCookieCharacter', // ajax URL - get character data from cookie
|
||||
logIn: 'api/user/logIn', // ajax URL - login
|
||||
logout: 'api/user/logout', // ajax URL - logout
|
||||
deleteLog: 'api/user/deleteLog', // ajax URL - delete character log
|
||||
openIngameWindow: 'api/user/openIngameWindow', // ajax URL - open inGame Window
|
||||
saveUserConfig: 'api/user/saveAccount', // ajax URL - saves/update user account
|
||||
deleteAccount: 'api/user/deleteAccount', // ajax URL - delete Account data
|
||||
getCaptcha: '/api/user/getCaptcha', // ajax URL - get captcha image
|
||||
getServerStatus: '/api/user/getEveServerStatus', // ajax URL - get EVE-Online server status
|
||||
getCookieCharacterData: '/api/user/getCookieCharacter', // ajax URL - get character data from cookie
|
||||
logIn: '/api/user/logIn', // ajax URL - login
|
||||
logout: '/api/user/logout', // ajax URL - logout
|
||||
deleteLog: '/api/user/deleteLog', // ajax URL - delete character log
|
||||
openIngameWindow: '/api/user/openIngameWindow', // ajax URL - open inGame Window
|
||||
saveUserConfig: '/api/user/saveAccount', // ajax URL - saves/update user account
|
||||
deleteAccount: '/api/user/deleteAccount', // ajax URL - delete Account data
|
||||
// access API
|
||||
searchAccess: 'api/access/search', // ajax URL - search user/corporation/ally by name
|
||||
searchAccess: '/api/access/search', // ajax URL - search user/corporation/ally by name
|
||||
// main config/map ping API
|
||||
initMap: 'api/map/init', // ajax URL - get static data
|
||||
getAccessData: 'api/map/getAccessData', // ajax URL - get map access tokens (WebSocket)
|
||||
updateMapData: 'api/map/updateData', // ajax URL - main map update trigger
|
||||
updateUserData: 'api/map/updateUserData', // ajax URL - main map user data trigger
|
||||
initData: '/api/map/initData', // ajax URL - get static configuration data
|
||||
getAccessData: '/api/map/getAccessData', // ajax URL - get map access tokens (WebSocket)
|
||||
updateMapData: '/api/map/updateData', // ajax URL - main map update trigger
|
||||
updateUserData: '/api/map/updateUserData', // ajax URL - main map user data trigger
|
||||
// map API
|
||||
saveMap: 'api/map/save', // ajax URL - save/update map
|
||||
deleteMap: 'api/map/delete', // ajax URL - delete map
|
||||
importMap: 'api/map/import', // ajax URL - import map
|
||||
getMapConnectionData: 'api/map/getConnectionData', // ajax URL - get connection data
|
||||
getMapLogData: 'api/map/getLogData', // ajax URL - get logs data
|
||||
saveMap: '/api/map/save', // ajax URL - save/update map
|
||||
deleteMap: '/api/map/delete', // ajax URL - delete map
|
||||
importMap: '/api/map/import', // ajax URL - import map
|
||||
getMapConnectionData: '/api/map/getConnectionData', // ajax URL - get connection data
|
||||
getMapLogData: '/api/map/getLogData', // ajax URL - get logs data
|
||||
// system API
|
||||
searchSystem: 'api/system/search', // ajax URL - search system by name
|
||||
saveSystem: 'api/system/save', // ajax URL - saves system to map
|
||||
deleteSystem: 'api/system/delete', // ajax URL - delete system from map
|
||||
getSystemGraphData: 'api/system/graphData', // ajax URL - get all system graph data
|
||||
getConstellationData: 'api/system/constellationData', // ajax URL - get system constellation data
|
||||
setDestination: 'api/system/setDestination', // ajax URL - set destination
|
||||
pokeRally: 'api/system/pokeRally', // ajax URL - send rally point pokes
|
||||
searchSystem: '/api/system/search', // ajax URL - search system by name
|
||||
saveSystem: '/api/system/save', // ajax URL - saves system to map
|
||||
deleteSystem: '/api/system/delete', // ajax URL - delete system from map
|
||||
getSystemGraphData: '/api/system/graphData', // ajax URL - get all system graph data
|
||||
getConstellationData: '/api/system/constellationData', // ajax URL - get system constellation data
|
||||
setDestination: '/api/system/setDestination', // ajax URL - set destination
|
||||
pokeRally: '/api/system/pokeRally', // ajax URL - send rally point pokes
|
||||
// connection API
|
||||
saveConnection: 'api/connection/save', // ajax URL - save new connection to map
|
||||
deleteConnection: 'api/connection/delete', // ajax URL - delete connection from map
|
||||
saveConnection: '/api/connection/save', // ajax URL - save new connection to map
|
||||
deleteConnection: '/api/connection/delete', // ajax URL - delete connection from map
|
||||
// signature API
|
||||
getSignatures: 'api/signature/getAll', // ajax URL - get all signature data for system
|
||||
saveSignatureData: 'api/signature/save', // ajax URL - save signature data for system
|
||||
deleteSignatureData: 'api/signature/delete', // ajax URL - delete signature data for system
|
||||
getSignatures: '/api/signature/getAll', // ajax URL - get all signature data for system
|
||||
saveSignatureData: '/api/signature/save', // ajax URL - save signature data for system
|
||||
deleteSignatureData: '/api/signature/delete', // ajax URL - delete signature data for system
|
||||
// route API
|
||||
searchRoute: 'api/route/search', // ajax URL - search system routes
|
||||
searchRoute: '/api/route/search', // ajax URL - search system routes
|
||||
// stats API
|
||||
getStatisticsData: 'api/statistic/getData', // ajax URL - get statistics data (activity log)
|
||||
getStatisticsData: '/api/statistic/getData', // ajax URL - get statistics data (activity log)
|
||||
// GitHub API
|
||||
gitHubReleases: 'api/github/releases' // ajax URL - get release info from GitHub
|
||||
gitHubReleases: '/api/github/releases' // ajax URL - get release info from GitHub
|
||||
},
|
||||
breakpoints: [
|
||||
{ name: 'desktop', width: Infinity },
|
||||
|
||||
@@ -119,21 +119,21 @@ define([
|
||||
columnDefs: [
|
||||
{
|
||||
targets: 0,
|
||||
title: '<i class="fas fa-lg fa-tag"></i>',
|
||||
title: '<i class="fas fa-tag"></i>',
|
||||
width: '18px',
|
||||
searchable: false,
|
||||
class: ['text-center'].join(' '),
|
||||
data: 'status'
|
||||
},{
|
||||
targets: 1,
|
||||
title: '<i class="far fa-lg fa-fw fa-clock"></i> ',
|
||||
title: '<i class="far fa-fw fa-clock"></i> ',
|
||||
width: '50px',
|
||||
searchable: true,
|
||||
class: 'text-right',
|
||||
data: 'time'
|
||||
},{
|
||||
targets: 2,
|
||||
title: '<i class="fas fa-lg fa-fw fa-history"></i> ',
|
||||
title: '<i class="fas fa-fw fa-history"></i> ',
|
||||
width: '35px',
|
||||
searchable: false,
|
||||
class: 'text-right',
|
||||
|
||||
@@ -18,7 +18,7 @@ define([
|
||||
'dialog/manual',
|
||||
'dialog/changelog',
|
||||
'dialog/credit'
|
||||
], function($, Init, Util, Render, Gallery, bootbox) {
|
||||
], ($, Init, Util, Render, Gallery, bootbox) => {
|
||||
|
||||
'use strict';
|
||||
|
||||
@@ -79,7 +79,7 @@ define([
|
||||
/**
|
||||
* set link observer for "version info" dialog
|
||||
*/
|
||||
let setVersionLinkObserver = function(){
|
||||
let setVersionLinkObserver = () => {
|
||||
$('.' + config.navigationVersionLinkClass).off('click').on('click', function(e){
|
||||
$.fn.changelogsDialog();
|
||||
});
|
||||
@@ -94,13 +94,24 @@ define([
|
||||
adminPanel.css({bottom: ((direction === 'up') ? '+' : '-') + '=35px'});
|
||||
};
|
||||
|
||||
let setAcceptCookie = () => {
|
||||
Util.setCookie('cookie', 1, config.defaultAcceptCookieExpire, 'd');
|
||||
};
|
||||
|
||||
/**
|
||||
* set page observer
|
||||
*/
|
||||
let setPageObserver = function(){
|
||||
let setPageObserver = () => {
|
||||
let ssoButtonElement = $('.' + config.ssoButtonClass);
|
||||
let cookieHintElement = $('#' + config.cookieHintId);
|
||||
|
||||
// cookie hint --------------------------------------------------------
|
||||
cookieHintElement.find('.btn-success').on('click', function(){
|
||||
setAcceptCookie();
|
||||
// confirmation no longer needed on SSO login button
|
||||
ssoButtonElement.confirmation('destroy');
|
||||
});
|
||||
|
||||
cookieHintElement.on('show.bs.collapse', function () {
|
||||
// move admin panel upwards (prevents overlapping with cookie notice)
|
||||
moveAdminPanel('up');
|
||||
@@ -127,7 +138,7 @@ define([
|
||||
btnCancelIcon: 'fas fa-fw fa-check',
|
||||
onCancel: function(e, target){
|
||||
// "Accept cookies"
|
||||
Util.setCookie('cookie', 1, config.defaultAcceptCookieExpire, 'd');
|
||||
setAcceptCookie();
|
||||
|
||||
// set "default" href
|
||||
let href = $(target).data('bs.confirmation').getHref();
|
||||
@@ -141,13 +152,9 @@ define([
|
||||
}
|
||||
};
|
||||
|
||||
$('.' + config.ssoButtonClass).confirmation(confirmationSettings);
|
||||
ssoButtonElement.confirmation(confirmationSettings);
|
||||
}
|
||||
|
||||
cookieHintElement.find('.btn-success').on('click', function(){
|
||||
Util.setCookie('cookie', 1, config.defaultAcceptCookieExpire, 'd');
|
||||
});
|
||||
|
||||
// manual -------------------------------------------------------------
|
||||
$('.' + config.navigationLinkManualClass).on('click', function(e){
|
||||
e.preventDefault();
|
||||
@@ -179,7 +186,7 @@ define([
|
||||
/**
|
||||
* init image carousel
|
||||
*/
|
||||
let initCarousel = function(){
|
||||
let initCarousel = () => {
|
||||
|
||||
// check if carousel exists
|
||||
if($('#' + config.galleryCarouselId).length === 0){
|
||||
@@ -313,7 +320,7 @@ define([
|
||||
* get all thumbnail elements
|
||||
* @returns {*|jQuery|HTMLElement}
|
||||
*/
|
||||
let getThumbnailElements = function(){
|
||||
let getThumbnailElements = () => {
|
||||
return $('a[data-gallery="#' + config.galleryId + '"]').not('.disabled');
|
||||
};
|
||||
|
||||
@@ -321,14 +328,14 @@ define([
|
||||
* init gallery for thumbnail elements
|
||||
* @param newElements
|
||||
*/
|
||||
let initGallery = function(newElements){
|
||||
let initGallery = (newElements) => {
|
||||
if( newElements.length > 0){
|
||||
// We have to add ALL thumbnail elements to the gallery!
|
||||
// -> even those wthat are invisible (not lazyLoaded) now!
|
||||
// -> This is required for "swipe" through all images
|
||||
let allThumbLinks = getThumbnailElements();
|
||||
|
||||
requirejs(['blueImpGalleryBootstrap'], function() {
|
||||
requirejs(['blueImpGalleryBootstrap'], () => {
|
||||
$(newElements).each(function() {
|
||||
let borderless = false;
|
||||
|
||||
@@ -360,7 +367,7 @@ define([
|
||||
/**
|
||||
* init "YouTube" video preview
|
||||
*/
|
||||
let initYoutube = function(){
|
||||
let initYoutube = () => {
|
||||
|
||||
$('.youtube').each(function() {
|
||||
// Based on the YouTube ID, we can easily find the thumbnail image
|
||||
@@ -395,11 +402,11 @@ define([
|
||||
/**
|
||||
* init scrollSpy for navigation bar
|
||||
*/
|
||||
let initScrollSpy = function(){
|
||||
let initScrollSpy = () => {
|
||||
// init scrollspy
|
||||
|
||||
// show elements that are currently in the viewport
|
||||
let showVisibleElements = function(){
|
||||
let showVisibleElements = () => {
|
||||
// find all elements that should be animated
|
||||
let visibleElements = $('.' + config.animateElementClass).isInViewport();
|
||||
|
||||
@@ -421,7 +428,7 @@ define([
|
||||
});
|
||||
};
|
||||
|
||||
$( window ).scroll(function() {
|
||||
$( window ).scroll(() => {
|
||||
// check for new visible elements
|
||||
showVisibleElements();
|
||||
});
|
||||
@@ -446,7 +453,7 @@ define([
|
||||
* get current EVE-Online server status
|
||||
* -> show "server panel"
|
||||
*/
|
||||
let initServerStatus = function(){
|
||||
let initServerStatus = () => {
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: Init.path.getServerStatus,
|
||||
@@ -485,16 +492,16 @@ define([
|
||||
* show "notification panel" to user
|
||||
* -> checks if panel not already shown
|
||||
*/
|
||||
let initNotificationPanel = function(){
|
||||
let initNotificationPanel = () => {
|
||||
let storageKey = 'notification_panel';
|
||||
let currentVersion = Util.getVersion();
|
||||
|
||||
let showNotificationPanel = function(){
|
||||
let showNotificationPanel = () => {
|
||||
let data = {
|
||||
version: Util.getVersion()
|
||||
};
|
||||
|
||||
requirejs(['text!templates/ui/notice.html', 'mustache'], function(template, Mustache) {
|
||||
requirejs(['text!templates/ui/notice.html', 'mustache'], (template, Mustache) => {
|
||||
let content = Mustache.render(template, data);
|
||||
|
||||
let notificationPanel = $('#' + config.notificationPanelId);
|
||||
@@ -704,7 +711,7 @@ define([
|
||||
* @param status
|
||||
* @param error
|
||||
*/
|
||||
let handleAjaxErrorResponse = function(jqXHR, status, error){
|
||||
let handleAjaxErrorResponse = (jqXHR, status, error) => {
|
||||
|
||||
let type = status;
|
||||
let title = 'Status ' + jqXHR.status + ': ' + error;
|
||||
@@ -734,7 +741,7 @@ define([
|
||||
/**
|
||||
* main init "landing" page
|
||||
*/
|
||||
$(function(){
|
||||
$(() => {
|
||||
// clear sessionStorage
|
||||
Util.clearSessionStorage();
|
||||
|
||||
@@ -816,9 +823,9 @@ define([
|
||||
initYoutube();
|
||||
|
||||
// draw header logo
|
||||
$('#' + config.logoContainerId).drawLogo(function(){
|
||||
$('#' + config.logoContainerId).drawLogo(() => {
|
||||
// init header animation
|
||||
$('#' + config.headerContainerId).initHeader(function(){
|
||||
$('#' + config.headerContainerId).initHeader(() => {
|
||||
|
||||
});
|
||||
}, false);
|
||||
|
||||
@@ -64,9 +64,6 @@ define([
|
||||
systemSec: 'pf-system-sec'
|
||||
};
|
||||
|
||||
// active jsPlumb instances currently running
|
||||
let activeInstances = {};
|
||||
|
||||
// active connections per map (cache object)
|
||||
let connectionCache = {};
|
||||
|
||||
@@ -947,35 +944,70 @@ define([
|
||||
*/
|
||||
let setMapWrapperObserver = (mapWrapper, mapConfig) => {
|
||||
|
||||
/**
|
||||
* save current map dimension to local storage
|
||||
* @param entry
|
||||
*/
|
||||
let saveMapSize = (entry) => {
|
||||
let width = '';
|
||||
let height = '';
|
||||
if(entry.constructor.name === 'HTMLDivElement'){
|
||||
width = entry.style.width;
|
||||
height = entry.style.height;
|
||||
}else if (entry.constructor.name === 'ResizeObserverEntry'){
|
||||
width = entry.target.style.width;
|
||||
height = entry.target.style.height;
|
||||
}
|
||||
|
||||
width = parseInt(width.substring(0, width.length - 2)) || 0;
|
||||
height = parseInt(height.substring(0, height.length - 2)) || 0;
|
||||
|
||||
let promiseStore = MapUtil.getLocaleData('map', mapConfig.config.id );
|
||||
promiseStore.then((data) => {
|
||||
let storeData = true;
|
||||
|
||||
if (
|
||||
data && data.style &&
|
||||
data.style.width === width &&
|
||||
data.style.height === height
|
||||
) {
|
||||
// no style changes
|
||||
storeData = false;
|
||||
}
|
||||
|
||||
if (storeData) {
|
||||
MapUtil.storeLocalData('map', mapConfig.config.id, 'style', {
|
||||
width: width,
|
||||
height: height
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// map resize observer ----------------------------------------------------------------------------------------
|
||||
if(window.ResizeObserver) {
|
||||
// ResizeObserver() supported
|
||||
let resizeTimer;
|
||||
let wrapperResize = new ResizeObserver(entries => { // jshint ignore:line
|
||||
/**
|
||||
* save current map dimension to local storage
|
||||
* @param entry
|
||||
*/
|
||||
let saveMapSize = (entry) => {
|
||||
return setTimeout(() => {
|
||||
let width = entry.target.style.width;
|
||||
let height = entry.target.style.height;
|
||||
width = parseInt( width.substring(0, width.length - 2) ) || 0;
|
||||
height = parseInt( height.substring(0, height.length - 2) ) || 0;
|
||||
|
||||
MapUtil.storeLocalData('map', mapConfig.config.id, 'style', {
|
||||
width: width,
|
||||
height: height
|
||||
});
|
||||
}, 100);
|
||||
let checkMapSize = (entry) => {
|
||||
return setTimeout(saveMapSize, 100, entry);
|
||||
};
|
||||
for (let entry of entries){
|
||||
// use timeout to "throttle" save actions
|
||||
clearTimeout(resizeTimer);
|
||||
resizeTimer = saveMapSize(entry);
|
||||
resizeTimer = checkMapSize(entry);
|
||||
}
|
||||
});
|
||||
|
||||
wrapperResize.observe(mapWrapper[0]);
|
||||
}else if(requestAnimationFrame){
|
||||
// ResizeObserver() not supported
|
||||
let checkMapSize = (entry) => {
|
||||
saveMapSize(entry);
|
||||
return setTimeout(checkMapSize, 500, entry);
|
||||
};
|
||||
|
||||
checkMapSize(mapWrapper[0]);
|
||||
}
|
||||
|
||||
};
|
||||
@@ -2602,7 +2634,7 @@ define([
|
||||
*/
|
||||
let getMapInstance = function(mapId){
|
||||
|
||||
if(typeof activeInstances[mapId] !== 'object'){
|
||||
if( !MapUtil.existsMapInstance(mapId) ){
|
||||
// create new instance
|
||||
jsPlumb.Defaults.LogEnabled = true;
|
||||
|
||||
@@ -2712,10 +2744,10 @@ define([
|
||||
return (targetEndpoint.connections.length === 0);
|
||||
});
|
||||
|
||||
activeInstances[mapId] = newJsPlumbInstance;
|
||||
MapUtil.setMapInstance(mapId, newJsPlumbInstance);
|
||||
}
|
||||
|
||||
return activeInstances[mapId];
|
||||
return MapUtil.getMapInstance(mapId);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -3112,7 +3144,9 @@ define([
|
||||
// data for header update
|
||||
let headerUpdateData = {
|
||||
mapId: userData.config.id,
|
||||
userCount: 0 // active user on a map
|
||||
userCountInside: 0, // active user on a map
|
||||
userCountOutside: 0, // active user NOT on map
|
||||
userCountInactive: 0 // inactive users (no location)
|
||||
};
|
||||
|
||||
if(
|
||||
@@ -3152,7 +3186,7 @@ define([
|
||||
tempUserData = systemData;
|
||||
|
||||
// add "user count" to "total map user count"
|
||||
headerUpdateData.userCount += tempUserData.user.length;
|
||||
headerUpdateData.userCountInside += tempUserData.user.length;
|
||||
|
||||
// remove system from "search" array -> speed up loop
|
||||
userData.data.systems.splice(j, 1);
|
||||
@@ -3177,6 +3211,16 @@ define([
|
||||
system.updateSystemUserData(map, tempUserData, currentUserIsHere);
|
||||
}
|
||||
|
||||
// users who are not in any map system --------------------------------------------------------------------
|
||||
for(let i = 0; i < userData.data.systems.length; i++){
|
||||
// users without location are grouped in systemid: 0
|
||||
if(userData.data.systems[i].id){
|
||||
headerUpdateData.userCountOutside += userData.data.systems[i].user.length;
|
||||
}else{
|
||||
headerUpdateData.userCountInactive += userData.data.systems[i].user.length;
|
||||
}
|
||||
}
|
||||
|
||||
// trigger document event -> update header
|
||||
$(document).trigger('pf:updateHeaderMapData', headerUpdateData);
|
||||
}
|
||||
@@ -3339,16 +3383,6 @@ define([
|
||||
return systemData;
|
||||
};
|
||||
|
||||
/**
|
||||
* removes a map instance from local cache
|
||||
* @param mapId
|
||||
*/
|
||||
let clearMapInstance = (mapId) => {
|
||||
if(typeof activeInstances[mapId] === 'object'){
|
||||
delete activeInstances[mapId];
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* init map options
|
||||
* @param mapConfig
|
||||
@@ -3513,7 +3547,6 @@ define([
|
||||
|
||||
return {
|
||||
getMapInstance: getMapInstance,
|
||||
clearMapInstance: clearMapInstance,
|
||||
loadMap: loadMap,
|
||||
showNewSystemDialog: showNewSystemDialog
|
||||
};
|
||||
|
||||
@@ -55,6 +55,48 @@ define([
|
||||
}
|
||||
};
|
||||
|
||||
// active jsPlumb instances currently running =====================================================================
|
||||
let activeInstances = {};
|
||||
|
||||
/**
|
||||
* set mapInstance
|
||||
* @param mapId
|
||||
* @param map
|
||||
*/
|
||||
let setMapInstance = (mapId, map) => {
|
||||
activeInstances[mapId] = map;
|
||||
};
|
||||
|
||||
/**
|
||||
* get mapInstance
|
||||
* @param mapId
|
||||
* @returns {*}
|
||||
*/
|
||||
let getMapInstance = (mapId) => {
|
||||
return activeInstances[mapId];
|
||||
};
|
||||
|
||||
/**
|
||||
* check for mapInstance is set
|
||||
* @param mapId
|
||||
* @returns {boolean}
|
||||
*/
|
||||
let existsMapInstance = (mapId) => {
|
||||
return typeof activeInstances[mapId] === 'object';
|
||||
};
|
||||
|
||||
/**
|
||||
* removes a map instance
|
||||
* @param mapId
|
||||
*/
|
||||
let clearMapInstance = (mapId) => {
|
||||
if(existsMapInstance(mapId)){
|
||||
delete activeInstances[mapId];
|
||||
}
|
||||
};
|
||||
|
||||
// ================================================================================================================
|
||||
|
||||
/**
|
||||
* get all available map Types
|
||||
* optional they can be filtered by current access level of a user
|
||||
@@ -162,6 +204,28 @@ define([
|
||||
return systemInfo;
|
||||
};
|
||||
|
||||
/**
|
||||
* get system data by mapId and systemid
|
||||
* @param mapId
|
||||
* @param systemId
|
||||
* @returns {boolean}
|
||||
*/
|
||||
let getSystemData = (mapId, systemId) => {
|
||||
let systemData = false;
|
||||
let mapData = Util.getCurrentMapData(mapId);
|
||||
|
||||
if(mapData){
|
||||
for(let j = 0; j < mapData.data.systems.length; j++){
|
||||
let systemDataTemp = mapData.data.systems[j];
|
||||
if(systemDataTemp.id === systemId){
|
||||
systemData = systemDataTemp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return systemData;
|
||||
};
|
||||
|
||||
/**
|
||||
* get system type information
|
||||
* @param {number} systemTypeId
|
||||
@@ -582,6 +646,19 @@ define([
|
||||
return connectionInfo;
|
||||
};
|
||||
|
||||
/**
|
||||
* get CSS classes for connection types
|
||||
* @param types
|
||||
* @returns {string[]}
|
||||
*/
|
||||
let getConnectionFakeClassesByTypes = (types) => {
|
||||
let connectionClasses = ['pf-fake-connection'];
|
||||
for(let i = 0; i < types.length; i++){
|
||||
connectionClasses.push(getConnectionInfo( types[i], 'cssClass'));
|
||||
}
|
||||
return connectionClasses;
|
||||
};
|
||||
|
||||
/**
|
||||
* get all direct connections between two given systems
|
||||
* @param map
|
||||
@@ -1039,15 +1116,32 @@ define([
|
||||
return hasAccess;
|
||||
};
|
||||
|
||||
/**
|
||||
* get a unique map url for deeplinking
|
||||
* @param mapId
|
||||
* @returns {string}
|
||||
*/
|
||||
let getMapDeeplinkUrl = (mapId) => {
|
||||
let url = location.protocol + '//' + location.host + '/map';
|
||||
url += mapId ? '/' + encodeURIComponent(window.btoa(mapId)) : '';
|
||||
|
||||
return url;
|
||||
};
|
||||
|
||||
return {
|
||||
config: config,
|
||||
mapOptions: mapOptions,
|
||||
setMapInstance: setMapInstance,
|
||||
getMapInstance: getMapInstance,
|
||||
existsMapInstance: existsMapInstance,
|
||||
clearMapInstance: clearMapInstance,
|
||||
getMapTypes: getMapTypes,
|
||||
getMapScopes: getMapScopes,
|
||||
getScopeInfoForMap: getScopeInfoForMap,
|
||||
getMapIcons: getMapIcons,
|
||||
getInfoForMap: getInfoForMap,
|
||||
getInfoForSystem: getInfoForSystem,
|
||||
getSystemData: getSystemData,
|
||||
getSystemTypeInfo: getSystemTypeInfo,
|
||||
getEffectInfoForSystem: getEffectInfoForSystem,
|
||||
toggleSelectSystem: toggleSelectSystem,
|
||||
@@ -1059,6 +1153,7 @@ define([
|
||||
searchConnectionsBySystems: searchConnectionsBySystems,
|
||||
searchConnectionsByScopeAndType: searchConnectionsByScopeAndType,
|
||||
getConnectionInfo: getConnectionInfo,
|
||||
getConnectionFakeClassesByTypes: getConnectionFakeClassesByTypes,
|
||||
checkForConnection: checkForConnection,
|
||||
getDefaultConnectionTypeByScope: getDefaultConnectionTypeByScope,
|
||||
setConnectionWHStatus: setConnectionWHStatus,
|
||||
@@ -1073,6 +1168,7 @@ define([
|
||||
storeLocalData: storeLocalData,
|
||||
deleteLocalData: deleteLocalData,
|
||||
getSystemId: getSystemId,
|
||||
checkRight: checkRight
|
||||
checkRight: checkRight,
|
||||
getMapDeeplinkUrl: getMapDeeplinkUrl
|
||||
};
|
||||
});
|
||||
@@ -44,164 +44,292 @@ define([
|
||||
|
||||
let mapModule = $('#' + Util.config.mapModuleId);
|
||||
|
||||
// map init load static data =======================================================
|
||||
$.getJSON( Init.path.initMap, (initData) => {
|
||||
// main update intervals/trigger (heartbeat)
|
||||
let updateTimeouts = {
|
||||
mapUpdate: 0,
|
||||
userUpdate: 0
|
||||
};
|
||||
|
||||
|
||||
if( initData.error.length > 0 ){
|
||||
for(let i = 0; i < initData.error.length; i++){
|
||||
Util.showNotify({
|
||||
title: initData.error[i].title,
|
||||
text: initData.error[i].message,
|
||||
type: initData.error[i].type
|
||||
});
|
||||
/**
|
||||
* clear both main update timeouts
|
||||
* -> stop program from working -> shutdown
|
||||
*/
|
||||
let clearUpdateTimeouts = () => {
|
||||
for(let intervalKey in updateTimeouts) {
|
||||
if(updateTimeouts.hasOwnProperty(intervalKey)){
|
||||
clearTimeout(updateTimeouts[intervalKey]);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Init.timer = initData.timer;
|
||||
Init.mapTypes = initData.mapTypes;
|
||||
Init.mapScopes = initData.mapScopes;
|
||||
Init.connectionScopes = initData.connectionScopes;
|
||||
Init.systemStatus = initData.systemStatus;
|
||||
Init.systemType = initData.systemType;
|
||||
Init.wormholes = initData.wormholes;
|
||||
Init.characterStatus = initData.characterStatus;
|
||||
Init.routes = initData.routes;
|
||||
Init.url = initData.url;
|
||||
Init.slack = initData.slack;
|
||||
Init.discord = initData.discord;
|
||||
Init.routeSearch = initData.routeSearch;
|
||||
Init.programMode = initData.programMode;
|
||||
/**
|
||||
* Ajax error response handler function for main-ping functions
|
||||
* @param jqXHR
|
||||
* @param status
|
||||
* @param error
|
||||
*/
|
||||
let handleAjaxErrorResponse = (jqXHR, status, error) => {
|
||||
// clear both main update request trigger timer
|
||||
clearUpdateTimeouts();
|
||||
|
||||
// init tab change observer, Once the timers are available
|
||||
Page.initTabChangeObserver();
|
||||
let reason = status + ' ' + jqXHR.status + ': ' + error;
|
||||
let errorData = [];
|
||||
|
||||
// init map module
|
||||
mapModule.initMapModule();
|
||||
|
||||
// load info (maintenance) info panel (if scheduled)
|
||||
if(Init.programMode.maintenance){
|
||||
$('body').showGlobalInfoPanel();
|
||||
if(jqXHR.responseJSON){
|
||||
// handle JSON
|
||||
let errorObj = jqXHR.responseJSON;
|
||||
if(
|
||||
errorObj.error &&
|
||||
errorObj.error.length > 0
|
||||
){
|
||||
errorData = errorObj.error;
|
||||
}
|
||||
}else{
|
||||
// handle HTML
|
||||
errorData.push({
|
||||
type: 'error',
|
||||
message: 'Please restart and reload this page'
|
||||
});
|
||||
}
|
||||
|
||||
}).fail(( jqXHR, status, error) => {
|
||||
let reason = status + ' ' + jqXHR.status + ': ' + error;
|
||||
console.error(' ↪ %s Error response: %o', jqXHR.url, errorData);
|
||||
$(document).trigger('pf:shutdown', {status: jqXHR.status, reason: reason, error: errorData});
|
||||
};
|
||||
|
||||
$(document).trigger('pf:shutdown', {status: jqXHR.status, reason: reason});
|
||||
});
|
||||
// map init functions =========================================================================================
|
||||
|
||||
/**
|
||||
* get static init data and store response
|
||||
* @returns {Promise<any>}
|
||||
*/
|
||||
let initData = () => {
|
||||
|
||||
let initDataExecutor = (resolve, reject) => {
|
||||
$.getJSON(Init.path.initData).done(response => {
|
||||
if( response.error.length > 0 ){
|
||||
for(let i = 0; i < response.error.length; i++){
|
||||
Util.showNotify({
|
||||
title: response.error[i].title,
|
||||
text: response.error[i].message,
|
||||
type: response.error[i].type
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Init.timer = response.timer;
|
||||
Init.mapTypes = response.mapTypes;
|
||||
Init.mapScopes = response.mapScopes;
|
||||
Init.connectionScopes = response.connectionScopes;
|
||||
Init.systemStatus = response.systemStatus;
|
||||
Init.systemType = response.systemType;
|
||||
Init.wormholes = response.wormholes;
|
||||
Init.characterStatus = response.characterStatus;
|
||||
Init.routes = response.routes;
|
||||
Init.url = response.url;
|
||||
Init.slack = response.slack;
|
||||
Init.discord = response.discord;
|
||||
Init.routeSearch = response.routeSearch;
|
||||
Init.programMode = response.programMode;
|
||||
|
||||
resolve({
|
||||
action: 'initData',
|
||||
data: false
|
||||
});
|
||||
}).fail((jqXHR, status, error) => {
|
||||
reject({
|
||||
action: 'shutdown',
|
||||
data: {
|
||||
jqXHR: jqXHR,
|
||||
status: status,
|
||||
error: error
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
return new Promise(initDataExecutor);
|
||||
};
|
||||
|
||||
/**
|
||||
* get mapAccess Data for WebSocket subscription
|
||||
* @returns {Promise<any>}
|
||||
*/
|
||||
let getMapAccessData = () => {
|
||||
|
||||
let getMapAccessDataExecutor = (resolve, reject) => {
|
||||
$.getJSON(Init.path.getAccessData).done(response => {
|
||||
resolve({
|
||||
action: 'mapAccessData',
|
||||
data: response
|
||||
});
|
||||
}).fail((jqXHR, status, error) => {
|
||||
reject({
|
||||
action: 'shutdown',
|
||||
data: {
|
||||
jqXHR: jqXHR,
|
||||
status: status,
|
||||
error: error
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
return new Promise(getMapAccessDataExecutor);
|
||||
};
|
||||
|
||||
/**
|
||||
* init main mapModule
|
||||
* -> initData() needs to be resolved first!
|
||||
* @param payload
|
||||
* @returns {Promise<any>}
|
||||
*/
|
||||
let initMapModule = (payload) => {
|
||||
|
||||
let initMapModuleExecutor = (resolve, reject) => {
|
||||
// init tab change observer, Once the timers are available
|
||||
Page.initTabChangeObserver();
|
||||
|
||||
// init map module
|
||||
mapModule.initMapModule() ;
|
||||
|
||||
// load info (maintenance) info panel (if scheduled)
|
||||
if(Init.programMode.maintenance){
|
||||
$('body').showGlobalInfoPanel();
|
||||
}
|
||||
|
||||
resolve({
|
||||
action: 'initMapModule',
|
||||
data: false
|
||||
});
|
||||
};
|
||||
|
||||
return new Promise(initMapModuleExecutor);
|
||||
};
|
||||
|
||||
/**
|
||||
* request all map access data (tokens) -> required wor WebSocket subscription
|
||||
* -> initData() needs to be resolved first!
|
||||
* @param payloadMapAccessData
|
||||
* @returns {Promise<any>}
|
||||
*/
|
||||
let getMapAccessData = () => {
|
||||
$.getJSON( Init.path.getAccessData, ( response ) => {
|
||||
if(response.status === 'OK'){
|
||||
// init SharedWorker for maps
|
||||
MapWorker.init({
|
||||
characterId: response.data.id,
|
||||
callbacks: {
|
||||
onInit: (MsgWorkerMessage) => {
|
||||
Util.setSyncStatus(MsgWorkerMessage.command);
|
||||
},
|
||||
onOpen: (MsgWorkerMessage) => {
|
||||
Util.setSyncStatus(MsgWorkerMessage.command, MsgWorkerMessage.meta());
|
||||
let initMapWorker = (payloadMapAccessData) => {
|
||||
|
||||
MapWorker.send( 'subscribe', response.data);
|
||||
},
|
||||
onGet: (MsgWorkerMessage) => {
|
||||
switch(MsgWorkerMessage.task()){
|
||||
case 'mapUpdate':
|
||||
Util.updateCurrentMapData( MsgWorkerMessage.data() );
|
||||
ModuleMap.updateMapModule(mapModule);
|
||||
break;
|
||||
case 'mapAccess':
|
||||
case 'mapDeleted':
|
||||
Util.deleteCurrentMapData( MsgWorkerMessage.data() );
|
||||
ModuleMap.updateMapModule(mapModule);
|
||||
break;
|
||||
}
|
||||
|
||||
Util.setSyncStatus('ws:get');
|
||||
},
|
||||
onClosed: (MsgWorkerMessage) => {
|
||||
Util.setSyncStatus(MsgWorkerMessage.command, MsgWorkerMessage.meta());
|
||||
},
|
||||
onError: (MsgWorkerMessage) => {
|
||||
Util.setSyncStatus(MsgWorkerMessage.command, MsgWorkerMessage.meta());
|
||||
}
|
||||
let initMapWorkerExecutor = (resolve, reject) => {
|
||||
let getPayload = (command) => {
|
||||
return {
|
||||
action: 'initMapWorker',
|
||||
data: {
|
||||
syncStatus: Init.syncStatus.type,
|
||||
command: command
|
||||
}
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
let validMapAccessData = false;
|
||||
|
||||
if(payloadMapAccessData && payloadMapAccessData.action === 'mapAccessData'){
|
||||
let response = payloadMapAccessData.data;
|
||||
if(response.status === 'OK'){
|
||||
validMapAccessData = true;
|
||||
|
||||
// init SharedWorker for maps
|
||||
MapWorker.init({
|
||||
characterId: response.data.id,
|
||||
callbacks: {
|
||||
onInit: (MsgWorkerMessage) => {
|
||||
Util.setSyncStatus(MsgWorkerMessage.command);
|
||||
|
||||
},
|
||||
onOpen: (MsgWorkerMessage) => {
|
||||
Util.setSyncStatus(MsgWorkerMessage.command, MsgWorkerMessage.meta());
|
||||
MapWorker.send( 'subscribe', response.data);
|
||||
|
||||
resolve(getPayload(MsgWorkerMessage.command));
|
||||
},
|
||||
onGet: (MsgWorkerMessage) => {
|
||||
switch(MsgWorkerMessage.task()){
|
||||
case 'mapUpdate':
|
||||
Util.updateCurrentMapData( MsgWorkerMessage.data() );
|
||||
ModuleMap.updateMapModule(mapModule);
|
||||
break;
|
||||
case 'mapAccess':
|
||||
case 'mapDeleted':
|
||||
Util.deleteCurrentMapData( MsgWorkerMessage.data() );
|
||||
ModuleMap.updateMapModule(mapModule);
|
||||
break;
|
||||
case 'mapSubscriptions':
|
||||
Util.updateCurrentMapUserData(MsgWorkerMessage.data());
|
||||
ModuleMap.updateActiveMapUserData(mapModule);
|
||||
break;
|
||||
}
|
||||
|
||||
Util.setSyncStatus('ws:get');
|
||||
},
|
||||
onClosed: (MsgWorkerMessage) => {
|
||||
Util.setSyncStatus(MsgWorkerMessage.command, MsgWorkerMessage.meta());
|
||||
reject(getPayload(MsgWorkerMessage.command));
|
||||
|
||||
},
|
||||
onError: (MsgWorkerMessage) => {
|
||||
Util.setSyncStatus(MsgWorkerMessage.command, MsgWorkerMessage.meta());
|
||||
reject(getPayload(MsgWorkerMessage.command));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if( !validMapAccessData ){
|
||||
reject(getPayload('Invalid mapAccessData'));
|
||||
}
|
||||
};
|
||||
|
||||
return new Promise(initMapWorkerExecutor);
|
||||
};
|
||||
|
||||
getMapAccessData();
|
||||
// run all init functions for mainModule and WebSocket configuration async
|
||||
Promise.all([initData(), getMapAccessData()])
|
||||
.then(payload => Promise.all([initMapModule(payload[0]), initMapWorker(payload[1])]))
|
||||
.then(payload => {
|
||||
// mapModule initialized and WebSocket configuration working
|
||||
console.info('%s() complete! command: "%s"; syncStatus: "%s"',
|
||||
payload[1].action,
|
||||
payload[1].data.command,
|
||||
payload[1].data.syncStatus
|
||||
);
|
||||
})
|
||||
.catch(payload => {
|
||||
switch(payload.action){
|
||||
case 'shutdown':
|
||||
// ajax error
|
||||
handleAjaxErrorResponse(payload.data.jqXHR, payload.data.status, payload.data.error);
|
||||
break;
|
||||
case 'initMapWorker':
|
||||
// WebSocket not working -> no error here -> fallback to Ajax
|
||||
console.warn('%s() rejects Promise. command: "%s"; syncStatus: "%s", payload: %o',
|
||||
payload.action,
|
||||
payload.data.command,
|
||||
payload.data.syncStatus,
|
||||
payload.data
|
||||
);
|
||||
break;
|
||||
default:
|
||||
console.error('Unhandled error thrown while initialization: %o ', payload);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* main function for init all map relevant trigger calls
|
||||
*/
|
||||
$.fn.initMapModule = function(){
|
||||
|
||||
let mapModule = $(this);
|
||||
|
||||
// log keys ------------------------------------------------------------------------
|
||||
// log keys -----------------------------------------------------------------------------------------------
|
||||
let logKeyServerMapData = Init.performanceLogging.keyServerMapData;
|
||||
let logKeyServerUserData = Init.performanceLogging.keyServerUserData;
|
||||
|
||||
// main update intervals/trigger (heartbeat)
|
||||
let updateTimeouts = {
|
||||
mapUpdate: 0,
|
||||
userUpdate: 0
|
||||
};
|
||||
|
||||
let locationToggle = $('#' + Util.config.headMapTrackingId);
|
||||
|
||||
/**
|
||||
* Ajax error response handler function for main-ping functions
|
||||
* @param jqXHR
|
||||
* @param status
|
||||
* @param error
|
||||
*/
|
||||
let handleAjaxErrorResponse = (jqXHR, status, error) => {
|
||||
// clear both main update request trigger timer
|
||||
clearUpdateTimeouts();
|
||||
|
||||
let reason = status + ' ' + jqXHR.status + ': ' + error;
|
||||
let errorData = [];
|
||||
|
||||
if(jqXHR.responseJSON){
|
||||
// handle JSON
|
||||
let errorObj = jqXHR.responseJSON;
|
||||
if(
|
||||
errorObj.error &&
|
||||
errorObj.error.length > 0
|
||||
){
|
||||
errorData = errorObj.error;
|
||||
}
|
||||
}else{
|
||||
// handle HTML
|
||||
errorData.push({
|
||||
type: 'error',
|
||||
message: 'Please restart and reload this page'
|
||||
});
|
||||
}
|
||||
|
||||
$(document).trigger('pf:shutdown', {status: jqXHR.status, reason: reason, error: errorData});
|
||||
};
|
||||
|
||||
/**
|
||||
* init (schedule) next MapUpdate Ping
|
||||
*/
|
||||
let initMapUpdatePing = (forceUpdateMapData) => {
|
||||
// get the current update delay (this can change if a user is inactive)
|
||||
let delay = Util.getCurrentTriggerDelay( logKeyServerMapData, 0 );
|
||||
|
||||
updateTimeouts.mapUpdate = setTimeout((forceUpdateMapData) => {
|
||||
triggerMapUpdatePing(forceUpdateMapData);
|
||||
}, delay, forceUpdateMapData);
|
||||
};
|
||||
|
||||
// ping for main map update ========================================================
|
||||
// ping for main map update ===============================================================================
|
||||
/**
|
||||
* @param forceUpdateMapData // force request to be send
|
||||
*/
|
||||
@@ -218,7 +346,7 @@ define([
|
||||
// get updated map data
|
||||
let updatedMapData = {
|
||||
mapData: mapModule.getMapModuleDataForUpdate(),
|
||||
getUserData: ( Util.getCurrentUserData() ) ? 0 : 1
|
||||
getUserData: Util.getCurrentUserData() ? 0 : 1
|
||||
};
|
||||
|
||||
// check if mapUpdate trigger should be send
|
||||
@@ -267,7 +395,7 @@ define([
|
||||
|
||||
// load/update main map module
|
||||
ModuleMap.updateMapModule(mapModule).then(() => {
|
||||
// map update done, init new trigger
|
||||
// map update done, init new trigger
|
||||
|
||||
// get the current update delay (this can change if a user is inactive)
|
||||
let mapUpdateDelay = Util.getCurrentTriggerDelay( logKeyServerMapData, 0 );
|
||||
@@ -293,7 +421,7 @@ define([
|
||||
}
|
||||
};
|
||||
|
||||
// ping for user data update =======================================================
|
||||
// ping for user data update ==============================================================================
|
||||
let triggerUserUpdatePing = () => {
|
||||
|
||||
// IMPORTANT: Get user data for ONE map that is currently visible
|
||||
@@ -307,10 +435,9 @@ define([
|
||||
|
||||
let updatedUserData = {
|
||||
mapIds: mapIds,
|
||||
systemData: Util.getCurrentSystemData(),
|
||||
characterMapData: {
|
||||
mapTracking: (locationToggle.is(':checked') ? 1 : 0) // location tracking
|
||||
}
|
||||
getMapUserData: Util.getSyncType() === 'webSocket' ? 0 : 1,
|
||||
mapTracking: locationToggle.is(':checked') ? 1 : 0, // location tracking
|
||||
systemData: Util.getCurrentSystemData()
|
||||
};
|
||||
|
||||
Util.timeStart(logKeyServerUserData);
|
||||
@@ -321,62 +448,66 @@ define([
|
||||
data: updatedUserData,
|
||||
dataType: 'json'
|
||||
}).done((data) => {
|
||||
|
||||
// log request time
|
||||
let duration = Util.timeStop(logKeyServerUserData);
|
||||
Util.log(logKeyServerUserData, {duration: duration, type: 'server', description:'request user data'});
|
||||
|
||||
if(data.error.length > 0){
|
||||
if(
|
||||
data.error &&
|
||||
data.error.length > 0
|
||||
){
|
||||
// any error in the main trigger functions result in a user log-off
|
||||
$(document).trigger('pf:menuLogout');
|
||||
}else{
|
||||
|
||||
$(document).setProgramStatus('online');
|
||||
|
||||
if(data.userData !== undefined){
|
||||
// store current user data global (cache)
|
||||
let userData = Util.setCurrentUserData(data.userData);
|
||||
|
||||
// store current map user data (cache)
|
||||
if(data.mapUserData !== undefined){
|
||||
Util.setCurrentMapUserData(data.mapUserData);
|
||||
}
|
||||
|
||||
// active character data found
|
||||
mapModule.updateMapModuleData();
|
||||
|
||||
// update system info panels
|
||||
if(data.system){
|
||||
mapModule.updateSystemModuleData(data.system);
|
||||
}
|
||||
|
||||
// get the current update delay (this can change if a user is inactive)
|
||||
let mapUserUpdateDelay = Util.getCurrentTriggerDelay( logKeyServerUserData, 0 );
|
||||
|
||||
// init new trigger
|
||||
updateTimeouts.userUpdate = setTimeout(() => {
|
||||
triggerUserUpdatePing();
|
||||
}, mapUserUpdateDelay);
|
||||
// store current map user data (cache)
|
||||
if(data.mapUserData !== undefined){
|
||||
Util.setCurrentMapUserData(data.mapUserData);
|
||||
}
|
||||
|
||||
// update map module character data
|
||||
ModuleMap.updateActiveMapUserData(mapModule).then(() => {
|
||||
// map module update done, init new trigger
|
||||
initMapUserUpdatePing();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}).fail(handleAjaxErrorResponse);
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* init (schedule) next MapUpdate Ping
|
||||
*/
|
||||
let initMapUpdatePing = (forceUpdateMapData) => {
|
||||
// get the current update delay (this can change if a user is inactive)
|
||||
let delay = Util.getCurrentTriggerDelay(logKeyServerMapData, 0);
|
||||
|
||||
updateTimeouts.mapUpdate = setTimeout((forceUpdateMapData) => {
|
||||
triggerMapUpdatePing(forceUpdateMapData);
|
||||
}, delay, forceUpdateMapData);
|
||||
};
|
||||
|
||||
/**
|
||||
* clear both main update timeouts
|
||||
* -> stop program from working -> shutdown
|
||||
* init (schedule) next MapUserUpdate Ping
|
||||
*/
|
||||
let clearUpdateTimeouts = () => {
|
||||
for(let intervalKey in updateTimeouts) {
|
||||
let initMapUserUpdatePing = () => {
|
||||
// get the current update delay (this can change if a user is inactive)
|
||||
let delay = Util.getCurrentTriggerDelay(logKeyServerUserData, 0);
|
||||
|
||||
if(updateTimeouts.hasOwnProperty(intervalKey)){
|
||||
clearTimeout( updateTimeouts[intervalKey] );
|
||||
}
|
||||
}
|
||||
updateTimeouts.userUpdate = setTimeout(() => {
|
||||
triggerUserUpdatePing();
|
||||
}, delay);
|
||||
};
|
||||
|
||||
// initial start of the map update function
|
||||
|
||||
@@ -298,39 +298,55 @@ define([
|
||||
};
|
||||
|
||||
/**
|
||||
* updates only visible/active map module
|
||||
* @returns {boolean}
|
||||
* updates current visible/active mapElement in mapModuleElement with user data
|
||||
* @param mapModuleElement
|
||||
* @returns {Promise<any>}
|
||||
*/
|
||||
$.fn.updateMapModuleData = function(){
|
||||
let mapModule = $(this);
|
||||
let updateActiveMapUserData = (mapModuleElement) => {
|
||||
|
||||
let updateActiveMapModuleExecutor = (resolve, reject) => {
|
||||
// get all active map elements for module
|
||||
let mapElement = mapModuleElement.getActiveMap();
|
||||
|
||||
updateMapUserData(mapElement).then(payload => resolve());
|
||||
};
|
||||
|
||||
return new Promise(updateActiveMapModuleExecutor);
|
||||
};
|
||||
|
||||
/**
|
||||
* updates mapElement with user data
|
||||
* update
|
||||
* @param mapElement
|
||||
* @returns {Promise<any>}
|
||||
*/
|
||||
let updateMapUserData = (mapElement) => {
|
||||
// performance logging (time measurement)
|
||||
let logKeyClientUserData = Init.performanceLogging.keyClientUserData;
|
||||
Util.timeStart(logKeyClientUserData);
|
||||
|
||||
// get all active map elements for module
|
||||
let mapElement = mapModule.getActiveMap();
|
||||
let updateMapUserDataExecutor = (resolve, reject) => {
|
||||
if(mapElement !== false){
|
||||
let mapId = mapElement.data('id');
|
||||
let currentMapUserData = Util.getCurrentMapUserData(mapId);
|
||||
|
||||
if(mapElement !== false){
|
||||
let mapId = mapElement.data('id');
|
||||
if(currentMapUserData){
|
||||
// trigger "update local" for this map => async
|
||||
mapElement.trigger('pf:updateLocal', currentMapUserData);
|
||||
|
||||
let currentMapUserData = Util.getCurrentMapUserData(mapId);
|
||||
|
||||
|
||||
if(currentMapUserData){
|
||||
// trigger "update local" for this map => async
|
||||
mapElement.trigger('pf:updateLocal', currentMapUserData);
|
||||
|
||||
// update map with current user data
|
||||
mapElement.updateUserData(currentMapUserData);
|
||||
// update map with current user data
|
||||
mapElement.updateUserData(currentMapUserData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// log client user data update time
|
||||
let duration = Util.timeStop(logKeyClientUserData);
|
||||
Util.log(logKeyClientUserData, {duration: duration, type: 'client', description:'update users'});
|
||||
resolve();
|
||||
};
|
||||
|
||||
return true;
|
||||
return new Promise(updateMapUserDataExecutor).then(payload => {
|
||||
// log client map update time
|
||||
let duration = Util.timeStop(logKeyClientUserData);
|
||||
Util.log(logKeyClientUserData, {duration: duration, type: 'client', description: 'update users'});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -628,6 +644,15 @@ define([
|
||||
let mapElement = $(mapConfig.map.getContainer());
|
||||
let mapWrapperElement = mapElement.closest('.mCustomScrollbar');
|
||||
mapWrapperElement.mCustomScrollbar('update');
|
||||
|
||||
// change url to unique map URL
|
||||
if (history.pushState) {
|
||||
let mapUrl = MapUtil.getMapDeeplinkUrl(mapConfig.config.id);
|
||||
history.pushState({}, '', mapUrl);
|
||||
}
|
||||
|
||||
// update map user data (do not wait until next update is triggered)
|
||||
updateMapUserData(mapElement);
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -899,7 +924,7 @@ define([
|
||||
contentElement.remove();
|
||||
|
||||
// remove map instance from local cache
|
||||
Map.clearMapInstance(mapId);
|
||||
MapUtil.clearMapInstance(mapId);
|
||||
}
|
||||
|
||||
resolve({
|
||||
@@ -937,6 +962,15 @@ define([
|
||||
return Promise.all(promiseDeleteTab);
|
||||
};
|
||||
|
||||
/**
|
||||
* get last URL segment e.g. https://pathfinder/map/test -> test
|
||||
* @returns {string | undefined}
|
||||
*/
|
||||
let getLastUrlSegment = () => {
|
||||
let parts = window.location.pathname.split('/');
|
||||
return parts.pop() || parts.pop();
|
||||
};
|
||||
|
||||
/**
|
||||
* set "default" map tab
|
||||
* -> default mapId might be available in local storage
|
||||
@@ -946,6 +980,10 @@ define([
|
||||
*/
|
||||
let showDefaultTab = (tabMapElement, currentUserData) => {
|
||||
|
||||
let getActiveTabLinkElement = (mapId) => {
|
||||
return tabMapElement.find('.' + config.mapTabClass + '[data-mapid="' + mapId + '"] > a');
|
||||
};
|
||||
|
||||
/**
|
||||
* show default tab promise
|
||||
* @param resolve
|
||||
@@ -956,13 +994,31 @@ define([
|
||||
promiseStore.then((data) => {
|
||||
let activeTabLinkElement = false;
|
||||
|
||||
if(data && data.defaultMapId){
|
||||
// make specific map tab active
|
||||
activeTabLinkElement = tabMapElement.find('.' + config.mapTabClass + '[data-mapid="' + data.defaultMapId + '"] > a');
|
||||
// check for existing mapId URL identifier ------------------------------------------------------------
|
||||
let lastURLSegment = getLastUrlSegment();
|
||||
|
||||
let defaultMapId = 0;
|
||||
try{
|
||||
defaultMapId = parseInt(atob(decodeURIComponent(lastURLSegment)));
|
||||
}catch(e){
|
||||
// defaultMapID could not be extracted from URL -> ignore
|
||||
}
|
||||
|
||||
if(defaultMapId){
|
||||
activeTabLinkElement = getActiveTabLinkElement(defaultMapId);
|
||||
}
|
||||
|
||||
// ... else check for existing cached default mapId ---------------------------------------------------
|
||||
if(
|
||||
(!activeTabLinkElement || !activeTabLinkElement.length) &&
|
||||
data && data.defaultMapId
|
||||
){
|
||||
// make specific map tab active
|
||||
activeTabLinkElement = getActiveTabLinkElement(data.defaultMapId);
|
||||
}
|
||||
|
||||
// ... else make first map tab active (default) -------------------------------------------------------
|
||||
if(!activeTabLinkElement || !activeTabLinkElement.length){
|
||||
// make first map tab active (default)
|
||||
activeTabLinkElement = tabMapElement.find('.' + config.mapTabClass + ':not(.pull-right):first > a');
|
||||
}
|
||||
|
||||
@@ -1152,6 +1208,7 @@ define([
|
||||
|
||||
return {
|
||||
updateTabData: updateTabData,
|
||||
updateMapModule: updateMapModule
|
||||
updateMapModule: updateMapModule,
|
||||
updateActiveMapUserData: updateActiveMapUserData
|
||||
};
|
||||
});
|
||||
@@ -63,6 +63,7 @@ define([
|
||||
|
||||
// menu
|
||||
menuHeadMenuLogoClass: 'pf-head-menu-logo', // class for main menu logo
|
||||
menuClockClass: 'pf-menu-clock', // class for EVE-Time clock
|
||||
|
||||
// helper element
|
||||
dynamicElementWrapperId: 'pf-dialog-wrapper',
|
||||
@@ -290,6 +291,10 @@ define([
|
||||
).on('click', function(){
|
||||
$(document).triggerMenuEvent('Logout', {clearCookies: 1});
|
||||
})
|
||||
).append(
|
||||
$('<div>', {
|
||||
class: config.menuClockClass
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
@@ -477,7 +482,7 @@ define([
|
||||
});
|
||||
|
||||
// active pilots
|
||||
$('.' + config.headActiveUserClass).find('a').on('click', function(){
|
||||
$('.' + config.headActiveUserClass).on('click', function(){
|
||||
$(document).triggerMenuEvent('ShowMapInfo', {tab: 'activity'});
|
||||
});
|
||||
|
||||
@@ -713,7 +718,9 @@ define([
|
||||
documentElement.on('pf:updateHeaderMapData', function(e, data){
|
||||
let activeMap = Util.getMapModule().getActiveMap();
|
||||
|
||||
let userCount = 0;
|
||||
let userCountInside = 0;
|
||||
let userCountOutside = 0;
|
||||
let userCountInactive = 0;
|
||||
let currentLocationData = {};
|
||||
|
||||
// show active user just for the current active map
|
||||
@@ -721,10 +728,12 @@ define([
|
||||
activeMap &&
|
||||
activeMap.data('id') === data.mapId
|
||||
){
|
||||
userCount = data.userCount;
|
||||
userCountInside = data.userCountInside;
|
||||
userCountOutside = data.userCountOutside;
|
||||
userCountInactive = data.userCountInactive;
|
||||
currentLocationData = data;
|
||||
}
|
||||
updateHeaderActiveUserCount(userCount);
|
||||
updateHeaderActiveUserCount(userCountInside, userCountOutside, userCountInactive);
|
||||
updateHeaderCurrentLocation(currentLocationData);
|
||||
});
|
||||
|
||||
@@ -787,6 +796,29 @@ define([
|
||||
return false;
|
||||
});
|
||||
|
||||
initEveClock();
|
||||
};
|
||||
|
||||
/**
|
||||
* init clock element with current EVE time
|
||||
*/
|
||||
let initEveClock = () => {
|
||||
let clockElement = $('.' + config.menuClockClass);
|
||||
|
||||
let checkTime = (i) => {
|
||||
return (i < 10) ? '0' + i : i;
|
||||
};
|
||||
|
||||
let startTime = () => {
|
||||
let date = Util.getServerTime();
|
||||
let h = date.getHours();
|
||||
let m = checkTime(date.getMinutes());
|
||||
clockElement.text(h + ':' + m);
|
||||
|
||||
let t = setTimeout(startTime, 500);
|
||||
};
|
||||
|
||||
startTime();
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -953,23 +985,35 @@ define([
|
||||
|
||||
/**
|
||||
* update the "active user" badge in header
|
||||
* @param userCount
|
||||
* @param userCountInside
|
||||
* @param userCountOutside
|
||||
* @param userCountInactive
|
||||
*/
|
||||
let updateHeaderActiveUserCount = function(userCount){
|
||||
let updateHeaderActiveUserCount = (userCountInside, userCountOutside, userCountInactive) => {
|
||||
let activeUserElement = $('.' + config.headActiveUserClass);
|
||||
let badge = activeUserElement.find('.badge');
|
||||
|
||||
if(badge.data('userCount') !== userCount){
|
||||
badge.data('userCount', userCount);
|
||||
let updateCount = (badge, count) => {
|
||||
let changed = false;
|
||||
if(badge.data('userCount') !== count){
|
||||
changed = true;
|
||||
badge.data('userCount', count);
|
||||
badge.text(count);
|
||||
|
||||
badge.text(userCount);
|
||||
|
||||
badge.toggleClass('txt-color-greenLight', (userCount > 0) );
|
||||
badge.toggleClass('txt-color-red', (userCount === 0) );
|
||||
|
||||
if(! activeUserElement.is(':visible')){
|
||||
activeUserElement.velocity('fadeIn', {duration: Init.animationSpeed.headerLink});
|
||||
badge.toggleClass(badge.attr('data-on'), (count > 0) );
|
||||
badge.toggleClass(badge.attr('data-off'), (count === 0) );
|
||||
}
|
||||
return changed;
|
||||
};
|
||||
|
||||
let changedInside = updateCount(activeUserElement.find('.badge[data-type="inside"]'), userCountInside);
|
||||
let changedOutside = updateCount(activeUserElement.find('.badge[data-type="outside"]'), userCountOutside);
|
||||
let changedInactive = updateCount(activeUserElement.find('.badge[data-type="inactive"]'), userCountInactive);
|
||||
|
||||
if(
|
||||
(changedInactive || changedOutside || changedInactive) &&
|
||||
!activeUserElement.is(':visible')
|
||||
){
|
||||
activeUserElement.velocity('fadeIn', {duration: Init.animationSpeed.headerLink});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -124,15 +124,6 @@ define([
|
||||
// connection scope -----------------------------------------------------------------------
|
||||
let scopeLabel = MapUtil.getScopeInfoForConnection(connectionData.scope, 'label');
|
||||
|
||||
// connection type (dummy) classes --------------------------------------------------------
|
||||
let getConnectionClasses = (types) => {
|
||||
let connectionClasses = ['pf-fake-connection'];
|
||||
for(let i = 0; i < types.length; i++){
|
||||
connectionClasses.push( MapUtil.getConnectionInfo( types[i], 'cssClass') );
|
||||
}
|
||||
return connectionClasses;
|
||||
};
|
||||
|
||||
let element = $('<div>', {
|
||||
class: 'pf-dynamic-area'
|
||||
}).append(
|
||||
@@ -199,7 +190,7 @@ define([
|
||||
class: ['text-right', config.connectionInfoTableCellConnectionClass].join(' ')
|
||||
}).append(
|
||||
$('<div>', {
|
||||
class: getConnectionClasses(connectionData.type).join(' ')
|
||||
class: MapUtil.getConnectionFakeClassesByTypes(connectionData.type).join(' ')
|
||||
})
|
||||
)
|
||||
),
|
||||
@@ -382,7 +373,7 @@ define([
|
||||
}
|
||||
|
||||
// get connection type (show fake connection div) ---------------------------------
|
||||
connectionCell.find('div').removeClass().addClass(getConnectionClasses(connectionData.type).join(' '));
|
||||
connectionCell.find('div').removeClass().addClass(MapUtil.getConnectionFakeClassesByTypes(connectionData.type).join(' '));
|
||||
|
||||
// get wormhole status ------------------------------------------------------------
|
||||
if(connectionData.type.indexOf('wh_critical') !== -1){
|
||||
|
||||
@@ -67,6 +67,7 @@ define([
|
||||
lengthMenu: 'Show _MENU_ wormholes',
|
||||
info: 'Showing _START_ to _END_ of _TOTAL_ wormholes'
|
||||
},
|
||||
columnDefs: []
|
||||
});
|
||||
|
||||
$(this).find('.' + config.wormholeInfoJumpTableClass).DataTable({
|
||||
@@ -83,6 +84,7 @@ define([
|
||||
lengthMenu: 'Show _MENU_ wormholes',
|
||||
info: 'Showing _START_ to _END_ of _TOTAL_ wormholes'
|
||||
},
|
||||
columnDefs: []
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -41,6 +41,10 @@ define([
|
||||
tableCellCounterClass: 'pf-table-counter-cell', // class for table "counter" cells
|
||||
tableCellEllipsisClass: 'pf-table-cell-ellipses-auto', // class for table "ellipsis" cells
|
||||
tableCellActionIconClass: 'pf-table-action-icon-cell', // class for table "action" icon (icon is part of cell content)
|
||||
tableCellUnknownDataClass: 'pf-table-unknown-cell', // class for table "unknown" cells
|
||||
|
||||
textActionIconClass: 'pf-module-icon-button', // class for text action
|
||||
textActionIconCopyClass: 'pf-module-icon-button-copy', // class for text action "copy"
|
||||
|
||||
loadingOptions: { // config for loading overlay
|
||||
icon: {
|
||||
@@ -79,6 +83,107 @@ define([
|
||||
return icon.length ? '<i class="fas fa-fw ' + icon + ' ' + config.tableCellActionIconClass + '" title="' + type + '" data-toggle="tooltip"></i>' : '';
|
||||
};
|
||||
|
||||
/**
|
||||
* get label for "unknown" label
|
||||
* @returns {string}
|
||||
*/
|
||||
let getLabelForUnknownData = () => {
|
||||
return '<span class="' + config.tableCellUnknownDataClass + '">unknown</span>';
|
||||
};
|
||||
|
||||
/**
|
||||
* write clipboard text
|
||||
* @param text
|
||||
* @returns {Promise<any>}
|
||||
*/
|
||||
let copyToClipboard = (text) => {
|
||||
|
||||
let copyToClipboardExecutor = (resolve, reject) => {
|
||||
let payload = {
|
||||
action: 'copyToClipboard',
|
||||
data: false
|
||||
};
|
||||
|
||||
if (navigator.clipboard) {
|
||||
// get current permission status
|
||||
navigator.permissions.query({
|
||||
name: 'clipboard-write'
|
||||
}).then(permissionStatus => {
|
||||
// will be 'granted', 'denied' or 'prompt'
|
||||
if(
|
||||
permissionStatus.state === 'granted' ||
|
||||
permissionStatus.state === 'prompt'
|
||||
){
|
||||
navigator.clipboard.writeText(text)
|
||||
.then(() => {
|
||||
payload.data = true;
|
||||
resolve(payload); })
|
||||
.catch(err => {
|
||||
let errorMsg = 'Failed to write clipboard content';
|
||||
console.error(errorMsg, err);
|
||||
Util.showNotify({title: 'Clipboard API', text: errorMsg, type: 'error'});
|
||||
resolve(payload);
|
||||
});
|
||||
}else{
|
||||
Util.showNotify({title: 'Clipboard API', text: 'You denied write access', type: 'warning'});
|
||||
resolve(payload);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
console.warn('Clipboard API not supported by your browser');
|
||||
resolve(payload);
|
||||
}
|
||||
};
|
||||
|
||||
return new Promise(copyToClipboardExecutor);
|
||||
};
|
||||
|
||||
/**
|
||||
* read clipboard text
|
||||
* @returns {Promise<any>}
|
||||
*/
|
||||
let readFromClipboard = () => {
|
||||
|
||||
let readFromClipboardExecutor = (resolve, reject) => {
|
||||
let payload = {
|
||||
action: 'readFromClipboard',
|
||||
data: false
|
||||
};
|
||||
|
||||
if (navigator.clipboard) {
|
||||
// get current permission status
|
||||
navigator.permissions.query({
|
||||
name: 'clipboard-read'
|
||||
}).then(permissionStatus => {
|
||||
// will be 'granted', 'denied' or 'prompt'
|
||||
if(
|
||||
permissionStatus.state === 'granted' ||
|
||||
permissionStatus.state === 'prompt'
|
||||
){
|
||||
navigator.clipboard.readText()
|
||||
.then(text => {
|
||||
payload.data = text;
|
||||
resolve(payload); })
|
||||
.catch(err => {
|
||||
let errorMsg = 'Failed to read clipboard content';
|
||||
console.error(errorMsg, err);
|
||||
Util.showNotify({title: 'Clipboard API', text: errorMsg, type: 'error'});
|
||||
resolve(payload);
|
||||
});
|
||||
}else{
|
||||
Util.showNotify({title: 'Clipboard API', text: 'You denied read access', type: 'warning'});
|
||||
resolve(payload);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
console.warn('Clipboard API not supported by your browser');
|
||||
resolve(payload);
|
||||
}
|
||||
};
|
||||
|
||||
return new Promise(readFromClipboardExecutor);
|
||||
};
|
||||
|
||||
/**
|
||||
* loads the map info data into an element
|
||||
* @param mapData
|
||||
@@ -115,58 +220,82 @@ define([
|
||||
class: 'dl-horizontal',
|
||||
css: {'float': 'left'}
|
||||
}).append(
|
||||
$('<dt>').text( 'Icon' )
|
||||
$('<dt>').text('Icon')
|
||||
).append(
|
||||
$('<dd>').append(
|
||||
$('<i>', {
|
||||
class: ['fas', 'fa-fw', mapData.config.icon].join(' ')
|
||||
})
|
||||
)
|
||||
).append(
|
||||
$('<dt>').text('Name')
|
||||
).append(
|
||||
$('<dd>').text(mapData.config.name)
|
||||
).append(
|
||||
$('<dt>').text('Type')
|
||||
).append(
|
||||
$('<dd>', {
|
||||
class: mapType.class
|
||||
}).text(mapType.name)
|
||||
).append(
|
||||
$('<dt>').text('Link')
|
||||
).append(
|
||||
$('<dd>', {
|
||||
class: [config.textActionIconClass, config.textActionIconCopyClass].join(' ')
|
||||
}).append(
|
||||
$('<span>', {
|
||||
title: 'copy to clipboard',
|
||||
}).text(MapUtil.getMapDeeplinkUrl(mapData.config.id) + ' ')
|
||||
).append(
|
||||
$('<dd>').append(
|
||||
$('<i>', {
|
||||
class: ['fas', 'fa-fw', mapData.config.icon].join(' ')
|
||||
})
|
||||
)
|
||||
).append(
|
||||
$('<dt>').text( 'Name' )
|
||||
).append(
|
||||
$('<dd>').text( mapData.config.name )
|
||||
).append(
|
||||
$('<dt>').text( 'Type' )
|
||||
).append(
|
||||
$('<dd>', {
|
||||
class: mapType.class
|
||||
}).text( mapType.name )
|
||||
);
|
||||
$('<i>', {
|
||||
class: ['fas', 'fa-fw', 'fa-copy'].join(' ')
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
mapElement.append(dlElementLeft);
|
||||
|
||||
let dlElementRight = $('<dl>', {
|
||||
class: 'dl-horizontal',
|
||||
css: {'float': 'right'}
|
||||
}).append(
|
||||
$('<dt>').text( 'Systems' )
|
||||
).append(
|
||||
$('<dd>', {
|
||||
class: ['txt-color', maxSystemsClass].join(' ')
|
||||
}).text( countSystems + ' / ' + mapType.defaultConfig.max_systems )
|
||||
).append(
|
||||
$('<dt>').text( 'Connections' )
|
||||
).append(
|
||||
$('<dd>').text( countConnections )
|
||||
).append(
|
||||
$('<dt>').text( 'Lifetime' )
|
||||
).append(
|
||||
$('<dd>', {
|
||||
class: config.mapInfoLifetimeCounterClass,
|
||||
text: mapData.config.created
|
||||
})
|
||||
).append(
|
||||
$('<dt>').text( 'Created' )
|
||||
).append(
|
||||
$('<dd>').text(Util.getObjVal(mapDataOrigin, 'config.created.character.name'))
|
||||
);
|
||||
}).append(
|
||||
$('<dt>').text('Systems')
|
||||
).append(
|
||||
$('<dd>', {
|
||||
class: ['txt-color', maxSystemsClass].join(' ')
|
||||
}).text(countSystems + ' / ' + mapType.defaultConfig.max_systems)
|
||||
).append(
|
||||
$('<dt>').text('Connections')
|
||||
).append(
|
||||
$('<dd>').text(countConnections)
|
||||
).append(
|
||||
$('<dt>').text('Lifetime')
|
||||
).append(
|
||||
$('<dd>', {
|
||||
class: config.mapInfoLifetimeCounterClass,
|
||||
text: mapData.config.created
|
||||
})
|
||||
).append(
|
||||
$('<dt>').text('Created')
|
||||
).append(
|
||||
$('<dd>').text(Util.getObjVal(mapDataOrigin, 'config.created.character.name'))
|
||||
);
|
||||
|
||||
mapElement.append(dlElementRight);
|
||||
|
||||
// init map lifetime counter
|
||||
$('.' + config.mapInfoLifetimeCounterClass).initTimestampCounter();
|
||||
|
||||
mapElement.find('.' + config.textActionIconCopyClass).on('click', function(){
|
||||
let mapUrl = $(this).find('span').text().trim();
|
||||
copyToClipboard(mapUrl).then(payload => {
|
||||
if(payload.data){
|
||||
Util.showNotify({title: 'Copied to clipbaord', text: mapUrl, type: 'success'});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
mapElement.initTooltips();
|
||||
mapElement.hideLoadingAnimation();
|
||||
};
|
||||
|
||||
@@ -387,7 +516,7 @@ define([
|
||||
title: 'region',
|
||||
data: 'region'
|
||||
},{
|
||||
title: '<i class="far fa-square fa-lg" title="system status" data-toggle="tooltip"></i>',
|
||||
title: '<i class="far fa-square" title="system status" data-toggle="tooltip"></i>',
|
||||
width: '12px',
|
||||
searchable: false,
|
||||
data: 'status',
|
||||
@@ -396,7 +525,7 @@ define([
|
||||
sort: 'status_sort'
|
||||
}
|
||||
},{
|
||||
title: '<i class="fas fa-square fa-lg" title="system effect" data-toggle="tooltip"></i>',
|
||||
title: '<i class="fas fa-square" title="system effect" data-toggle="tooltip"></i>',
|
||||
width: '12px',
|
||||
className: 'text-center',
|
||||
searchable: false,
|
||||
@@ -410,7 +539,7 @@ define([
|
||||
width: '30px',
|
||||
data: 'static'
|
||||
},{
|
||||
title: '<i class="fas fa-map-marker-alt fa-lg" title="your position" data-toggle="tooltip"></i>',
|
||||
title: '<i class="fas fa-map-marker-alt" title="your position" data-toggle="tooltip"></i>',
|
||||
width: '8px',
|
||||
searchable: false,
|
||||
data: 'position',
|
||||
@@ -419,13 +548,13 @@ define([
|
||||
sort: 'position_sort'
|
||||
}
|
||||
},{
|
||||
title: '<i class="fas fa-plane fa-lg" title="active pilots" data-toggle="tooltip"></i>',
|
||||
title: '<i class="fas fa-plane" title="active pilots" data-toggle="tooltip"></i>',
|
||||
width: '12px',
|
||||
className: 'text-center',
|
||||
searchable: false,
|
||||
data: 'userCount'
|
||||
},{
|
||||
title: '<i class="fas fa-lock fa-lg" title="system locked" data-toggle="tooltip"></i>',
|
||||
title: '<i class="fas fa-lock" title="system locked" data-toggle="tooltip"></i>',
|
||||
width: '10px',
|
||||
searchable: false,
|
||||
data: 'locked',
|
||||
@@ -538,13 +667,8 @@ define([
|
||||
};
|
||||
|
||||
// connection
|
||||
let connectionClasses = [];
|
||||
for(let k = 0; k < tempConnectionData.type.length; k++){
|
||||
connectionClasses.push( MapUtil.getConnectionInfo( tempConnectionData.type[k], 'cssClass') );
|
||||
}
|
||||
|
||||
let connectionClasses = MapUtil.getConnectionFakeClassesByTypes(tempConnectionData.type);
|
||||
connectionClasses = connectionClasses.join(' ');
|
||||
|
||||
tempConData.connection = '<div class="pf-fake-connection ' + connectionClasses + '"></div>';
|
||||
|
||||
tempConData.target = {
|
||||
@@ -734,10 +858,11 @@ define([
|
||||
searchable: false,
|
||||
className: ['pf-help-default', 'text-center', config.tableCellImageClass].join(' '),
|
||||
data: 'log.ship',
|
||||
defaultContent: '',
|
||||
render: {
|
||||
_: function(data, type, row, meta){
|
||||
let value = data;
|
||||
if(type === 'display'){
|
||||
if(data && type === 'display'){
|
||||
value = '<img src="' + Init.url.ccpImageServer + '/Render/' + value.typeId + '_32.png" title="' + value.typeName + '" data-toggle="tooltip" />';
|
||||
}
|
||||
return value;
|
||||
@@ -750,12 +875,17 @@ define([
|
||||
orderable: true,
|
||||
searchable: true,
|
||||
data: 'log.ship',
|
||||
defaultContent: getLabelForUnknownData(),
|
||||
render: {
|
||||
_: function(data, type, row){
|
||||
let value = data.name;
|
||||
if(type === 'display'){
|
||||
value = '<div class="' + MapUtil.config.tableCellEllipsisClass + ' ' + MapUtil.config.tableCellEllipsis100Class + '">' + data.name + '</div>';
|
||||
let value = data;
|
||||
if(data){
|
||||
value = data.name;
|
||||
if(type === 'display'){
|
||||
value = '<div class="' + MapUtil.config.tableCellEllipsisClass + ' ' + MapUtil.config.tableCellEllipsis100Class + '">' + data.name + '</div>';
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
}
|
||||
@@ -845,9 +975,15 @@ define([
|
||||
orderable: true,
|
||||
searchable: true,
|
||||
data: 'log.system',
|
||||
defaultContent: getLabelForUnknownData(),
|
||||
render: {
|
||||
_: 'name',
|
||||
sort: 'name'
|
||||
_: function(data, type, row, meta){
|
||||
let value = data;
|
||||
if(data && type === 'display'){
|
||||
value = data.name;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
},{
|
||||
targets: 7,
|
||||
@@ -856,13 +992,18 @@ define([
|
||||
searchable: true,
|
||||
className: [config.tableCellActionClass].join(' '),
|
||||
data: 'log',
|
||||
defaultContent: getLabelForUnknownData(),
|
||||
render: {
|
||||
_: function (data, type, row, meta) {
|
||||
let value = '';
|
||||
if(data.station && data.station.id > 0){
|
||||
value = data.station.name + ' ' + getIconForDockedStatus('station');
|
||||
}else if(data.structure && data.structure.id > 0){
|
||||
value = data.structure.name + ' ' + getIconForDockedStatus('structure');
|
||||
let value = data;
|
||||
if(data){
|
||||
if(data.station && data.station.id > 0){
|
||||
value = data.station.name + ' ' + getIconForDockedStatus('station');
|
||||
}else if(data.structure && data.structure.id > 0){
|
||||
value = data.structure.name + ' ' + getIconForDockedStatus('structure');
|
||||
}else{
|
||||
value = '';
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
@@ -997,7 +1138,7 @@ define([
|
||||
},{
|
||||
targets: 1,
|
||||
name: 'timestamp',
|
||||
title: '<i class="far fa-lg fa-fw fa-clock"></i>',
|
||||
title: '<i class="far fa-fw fa-clock"></i>',
|
||||
width: 100,
|
||||
className: ['text-right'].join(' '),
|
||||
data: 'datetime.date',
|
||||
@@ -1090,7 +1231,7 @@ define([
|
||||
data: 'context.data.formatted'
|
||||
},{
|
||||
targets: 8,
|
||||
title: '<i class="fas fa-lg fa-code text-right"></i>',
|
||||
title: '<i class="fas fa-code text-right"></i>',
|
||||
width: 12,
|
||||
className: [config.tableCellActionClass].join(' '),
|
||||
data: 'context.data',
|
||||
|
||||
@@ -62,7 +62,11 @@ define([
|
||||
|
||||
// render function for numeric columns
|
||||
let renderNumericColumn = function(data, type, row, meta){
|
||||
return data.toLocaleString();
|
||||
let value = data;
|
||||
if(type === 'display'){
|
||||
value = data.toLocaleString();
|
||||
}
|
||||
return value;
|
||||
};
|
||||
|
||||
// get table element
|
||||
@@ -348,7 +352,7 @@ define([
|
||||
});
|
||||
|
||||
$(sumColumnIndexes).each(function(index, value){
|
||||
$( api.column( value ).footer() ).text( renderNumericColumn(pageTotalColumns[index]) );
|
||||
$( api.column( value ).footer() ).text( renderNumericColumn(pageTotalColumns[index], 'display') );
|
||||
});
|
||||
},
|
||||
data: [] // will be added dynamic
|
||||
|
||||
@@ -18,7 +18,7 @@ define([
|
||||
moduleHeadClass: 'pf-module-head', // class for module header
|
||||
moduleHandlerClass: 'pf-module-handler-drag', // class for "drag" handler
|
||||
|
||||
routeCacheTTL: 10, // route cache timer (client) in seconds
|
||||
routeCacheTTL: 5, // route cache timer (client) in seconds
|
||||
|
||||
// system route module
|
||||
moduleTypeClass: 'pf-system-route-module', // class for this module
|
||||
@@ -38,12 +38,64 @@ define([
|
||||
systemInfoRoutesTableClass: 'pf-system-route-table', // class for route tables
|
||||
mapSelectId: 'pf-route-dialog-map-select', // id for "map" select
|
||||
|
||||
dataTableActionCellClass: 'pf-table-action-cell' // class for "action" cells
|
||||
dataTableActionCellClass: 'pf-table-action-cell', // class for "action" cells
|
||||
dataTableRouteCellClass: 'pf-table-route-cell', // class for "route" cells
|
||||
dataTableJumpCellClass: 'pf-table-jump-cell' // class for "route jump" cells
|
||||
};
|
||||
|
||||
// cache for system routes
|
||||
let cache = {
|
||||
systemRoutes: {} // jump information between solar systems
|
||||
systemRoutes: {}, // jump information between solar systems
|
||||
mapConnections: {} // connection data read from UI
|
||||
};
|
||||
|
||||
/**
|
||||
* set cache data
|
||||
* @param cacheType
|
||||
* @param cacheKey
|
||||
* @param data
|
||||
*/
|
||||
let setCacheData = (cacheType, cacheKey, data) => {
|
||||
cache[cacheType][cacheKey] = {
|
||||
data: data,
|
||||
updated: Util.getServerTime().getTime() / 1000
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* get cache data
|
||||
* @param cacheType
|
||||
* @param cacheKey
|
||||
* @returns {*}
|
||||
*/
|
||||
let getCacheData = (cacheType, cacheKey) => {
|
||||
let cachedData = null;
|
||||
let currentTimestamp = Util.getServerTime().getTime();
|
||||
|
||||
if(
|
||||
cache[cacheType].hasOwnProperty(cacheKey) &&
|
||||
Math.round(
|
||||
( currentTimestamp - (new Date( cache[cacheType][cacheKey].updated * 1000).getTime())) / 1000
|
||||
) <= config.routeCacheTTL
|
||||
){
|
||||
cachedData = cache[cacheType][cacheKey].data;
|
||||
}
|
||||
|
||||
return cachedData;
|
||||
};
|
||||
|
||||
let getRouteDataCacheKey = (mapIds, sourceName, targetName) => {
|
||||
return [mapIds.join('_'), sourceName.toLowerCase(), targetName.toLowerCase()].join('###');
|
||||
};
|
||||
|
||||
/**
|
||||
* get a unique cache key name for "source"/"target"-name
|
||||
* @param sourceName
|
||||
* @param targetName
|
||||
* @returns {string}
|
||||
*/
|
||||
let getConnectionDataCacheKey = (sourceName, targetName) => {
|
||||
return [sourceName.toLowerCase(), targetName.toLowerCase()].sort().join('###');
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -59,22 +111,12 @@ define([
|
||||
|
||||
// format routeData
|
||||
let rowData = formatRouteData(routeData);
|
||||
|
||||
if(rowData.route){
|
||||
let cacheKey = routeData.systemFromData.name.toLowerCase() +
|
||||
'_' + routeData.systemToData.name.toLowerCase();
|
||||
|
||||
// update route cache
|
||||
cache.systemRoutes[cacheKey] = {
|
||||
data: rowData,
|
||||
updated: Util.getServerTime().getTime() / 1000
|
||||
};
|
||||
let cacheKey = getRouteDataCacheKey(rowData.mapIds, routeData.systemFromData.name, routeData.systemToData.name);
|
||||
setCacheData('systemRoutes', cacheKey, rowData);
|
||||
|
||||
let rowElement = addRow(context, rowData);
|
||||
|
||||
rowElement.initTooltips({
|
||||
container: 'body'
|
||||
});
|
||||
addRow(context, rowData);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -116,10 +158,13 @@ define([
|
||||
|
||||
if(row.length > 0){
|
||||
rowElement = row.nodes().to$();
|
||||
|
||||
if(animationStatus !== null){
|
||||
rowElement.data('animationStatus', animationStatus);
|
||||
}
|
||||
|
||||
rowElement.initTooltips({
|
||||
container: 'body'
|
||||
});
|
||||
}
|
||||
|
||||
return rowElement;
|
||||
@@ -186,7 +231,8 @@ define([
|
||||
wormholesCritical: (rowData.hasOwnProperty('wormholesCritical')) ? rowData.wormholesCritical | 0 : 1,
|
||||
wormholesFrigate: (rowData.hasOwnProperty('wormholesFrigate')) ? rowData.wormholesFrigate | 0 : 1,
|
||||
wormholesEOL: (rowData.hasOwnProperty('wormholesEOL')) ? rowData.wormholesEOL | 0 : 1,
|
||||
safer: (rowData.hasOwnProperty('safer')) ? rowData.safer.value | 0 : 0
|
||||
connections: (rowData.hasOwnProperty('connections')) ? rowData.connections.value | 0 : 0,
|
||||
flag: (rowData.hasOwnProperty('flag')) ? rowData.flag.value : 'shortest'
|
||||
};
|
||||
};
|
||||
|
||||
@@ -320,34 +366,30 @@ define([
|
||||
* @param routesTable
|
||||
* @param systemsTo
|
||||
*/
|
||||
let drawRouteTable = function(mapId, moduleElement, systemFromData, routesTable, systemsTo){
|
||||
let drawRouteTable = (mapId, moduleElement, systemFromData, routesTable, systemsTo) => {
|
||||
let requestRouteData = [];
|
||||
let currentTimestamp = Util.getServerTime().getTime();
|
||||
|
||||
// Skip some routes from search
|
||||
// -> this should help to throttle requests (heavy CPU load for route calculation)
|
||||
let defaultRoutesCount = Init.routeSearch.defaultCount;
|
||||
let rowElements = [];
|
||||
|
||||
for(let i = 0; i < systemsTo.length; i++){
|
||||
let systemToData = systemsTo[i];
|
||||
|
||||
if(systemFromData.name !== systemToData.name){
|
||||
let cacheKey = 'route_' + mapId + '_' + systemFromData.name.toUpperCase() + '_' + systemToData.name.toUpperCase();
|
||||
|
||||
if(
|
||||
cache.systemRoutes.hasOwnProperty(cacheKey) &&
|
||||
Math.round(
|
||||
( currentTimestamp - (new Date( cache.systemRoutes[cacheKey].updated * 1000).getTime())) / 1000
|
||||
) <= config.routeCacheTTL
|
||||
){
|
||||
// check for cached rowData
|
||||
let cacheKey = getRouteDataCacheKey([mapId], systemFromData.name, systemToData.name);
|
||||
let rowData = getCacheData('systemRoutes', cacheKey);
|
||||
if(rowData){
|
||||
// route data is cached (client side)
|
||||
let context = {
|
||||
dataTable: routesTable
|
||||
};
|
||||
|
||||
addRow(context, cache.systemRoutes[cacheKey].data);
|
||||
rowElements.push( addRow(context, rowData) );
|
||||
}else{
|
||||
// get route data
|
||||
// get route data -> ajax
|
||||
let searchData = {
|
||||
mapIds: [mapId],
|
||||
systemFromData: systemFromData,
|
||||
@@ -360,6 +402,11 @@ define([
|
||||
}
|
||||
}
|
||||
|
||||
// rows added from cache -> redraw() table
|
||||
if(rowElements.length){
|
||||
routesTable.draw();
|
||||
}
|
||||
|
||||
// check if routes data is not cached and is requested
|
||||
if(requestRouteData.length > 0){
|
||||
let contextData = {
|
||||
@@ -382,7 +429,7 @@ define([
|
||||
* @param systemFromData
|
||||
* @param routesTable
|
||||
*/
|
||||
let showSettingsDialog = function(dialogData, moduleElement, systemFromData, routesTable){
|
||||
let showSettingsDialog = (dialogData, moduleElement, systemFromData, routesTable) => {
|
||||
|
||||
let promiseStore = MapUtil.getLocaleData('map', dialogData.mapId);
|
||||
promiseStore.then(function(dataStore) {
|
||||
@@ -405,7 +452,7 @@ define([
|
||||
maxSelectionLength: maxSelectionLength
|
||||
};
|
||||
|
||||
requirejs(['text!templates/dialog/route_settings.html', 'mustache'], function(template, Mustache) {
|
||||
requirejs(['text!templates/dialog/route_settings.html', 'mustache'], (template, Mustache) => {
|
||||
let content = Mustache.render(template, data);
|
||||
|
||||
let settingsDialog = bootbox.dialog({
|
||||
@@ -461,7 +508,7 @@ define([
|
||||
* @param {Array} data
|
||||
* @returns {Array}
|
||||
*/
|
||||
let formSystemSelectData = function(data){
|
||||
let formSystemSelectData = (data) => {
|
||||
let formattedData = [];
|
||||
for(let i = 0; i < data.length; i++){
|
||||
let tmpData = data[i];
|
||||
@@ -479,7 +526,7 @@ define([
|
||||
* set event observer for route finder dialog
|
||||
* @param routeDialog
|
||||
*/
|
||||
let setDialogObserver = function(routeDialog){
|
||||
let setDialogObserver = (routeDialog) => {
|
||||
let wormholeCheckbox = routeDialog.find('input[type="checkbox"][name="wormholes"]');
|
||||
let wormholeReducedCheckbox = routeDialog.find('input[type="checkbox"][name="wormholesReduced"]');
|
||||
let wormholeCriticalCheckbox = routeDialog.find('input[type="checkbox"][name="wormholesCritical"]');
|
||||
@@ -528,19 +575,137 @@ define([
|
||||
onWormholeCheckboxChange();
|
||||
};
|
||||
|
||||
/**
|
||||
* get a connectionsData object that holds all connections for given mapIds (used as cache for route search)
|
||||
* @param mapIds
|
||||
* @returns {{}}
|
||||
*/
|
||||
let getConnectionsDataFromMaps = (mapIds) => {
|
||||
let connectionsData = {};
|
||||
for(let mapId of mapIds) {
|
||||
let map = MapUtil.getMapInstance(mapId);
|
||||
if(map){
|
||||
let cacheKey = 'map_' + mapId;
|
||||
let mapConnectionsData = getCacheData('mapConnections', cacheKey);
|
||||
|
||||
if(!mapConnectionsData){
|
||||
mapConnectionsData = {};
|
||||
let connections = map.getAllConnections();
|
||||
if(connections.length){
|
||||
let connectionsData = MapUtil.getDataByConnections(connections);
|
||||
for(let connectionData of connectionsData){
|
||||
let connectionDataCacheKey = getConnectionDataCacheKey(connectionData.sourceName, connectionData.targetName);
|
||||
|
||||
// skip double connections between same systems
|
||||
if( !mapConnectionsData.hasOwnProperty(connectionDataCacheKey) ){
|
||||
mapConnectionsData[connectionDataCacheKey] = {
|
||||
map: {
|
||||
id: mapId
|
||||
},
|
||||
connection: {
|
||||
id: connectionData.id,
|
||||
type: connectionData.type,
|
||||
scope: connectionData.scope
|
||||
},
|
||||
source: {
|
||||
id: connectionData.source,
|
||||
name: connectionData.sourceName,
|
||||
alias: connectionData.sourceAlias
|
||||
},
|
||||
target: {
|
||||
id: connectionData.target,
|
||||
name: connectionData.targetName,
|
||||
alias: connectionData.targetAlias
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// update cache
|
||||
setCacheData('mapConnections', cacheKey, mapConnectionsData);
|
||||
}
|
||||
|
||||
if(connectionsData !== null){
|
||||
connectionsData = Object.assign({}, mapConnectionsData, connectionsData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return connectionsData;
|
||||
};
|
||||
|
||||
/**
|
||||
* search for a specific connection by "source"/"target"-name inside connectionsData cache
|
||||
* @param connectionsData
|
||||
* @param sourceName
|
||||
* @param targetName
|
||||
* @returns {{}}
|
||||
*/
|
||||
let findConnectionsData = (connectionsData, sourceName, targetName) => {
|
||||
let connectionDataCacheKey = getConnectionDataCacheKey(sourceName, targetName);
|
||||
return connectionsData.hasOwnProperty(connectionDataCacheKey) ?
|
||||
connectionsData[connectionDataCacheKey] : {};
|
||||
};
|
||||
|
||||
/**
|
||||
* get stargate connection data (default connection type in case connection was not found on a map)
|
||||
* @param sourceRouteNodeData
|
||||
* @param targetRouteNodeData
|
||||
* @returns {{connection: {id: number, type: string[], scope: string}, source: {id: number, name, alias}, target: {id: number, name, alias}}}
|
||||
*/
|
||||
let getStargateConnectionData = (sourceRouteNodeData, targetRouteNodeData) => {
|
||||
return {
|
||||
connection: {
|
||||
id: 0,
|
||||
type: ['stargate'],
|
||||
scope: 'stargate'
|
||||
},
|
||||
source: {
|
||||
id: 0,
|
||||
name: sourceRouteNodeData.system,
|
||||
alias: sourceRouteNodeData.system
|
||||
},
|
||||
target: {
|
||||
id: 0,
|
||||
name: targetRouteNodeData.system,
|
||||
alias: targetRouteNodeData.system
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* get fake connection Element
|
||||
* @param connectionData
|
||||
* @returns {string}
|
||||
*/
|
||||
let getFakeConnectionElement = (connectionData) => {
|
||||
let mapId = Util.getObjVal(connectionData, 'map.id') | 0;
|
||||
let connectionId = Util.getObjVal(connectionData, 'connection.id') | 0;
|
||||
let scope = Util.getObjVal(connectionData, 'connection.scope');
|
||||
let classes = MapUtil.getConnectionFakeClassesByTypes(connectionData.connection.type);
|
||||
let disabled = !mapId || !connectionId;
|
||||
|
||||
let connectionElement = '<div data-mapId="' + mapId + '" data-connectionId="' + connectionId + '" ';
|
||||
connectionElement += (disabled ? 'data-disabled' : '');
|
||||
connectionElement += ' class="' + classes.join(' ') + '" ';
|
||||
connectionElement += ' title="' + scope + '" data-placement="bottom"></div>';
|
||||
return connectionElement;
|
||||
};
|
||||
|
||||
/**
|
||||
* format route data from API request into dataTable row format
|
||||
* @param routeData
|
||||
* @returns {{}}
|
||||
*/
|
||||
let formatRouteData = function(routeData){
|
||||
let formatRouteData = (routeData) => {
|
||||
|
||||
/**
|
||||
* get status icon for route
|
||||
* @param status
|
||||
* @returns {string}
|
||||
*/
|
||||
let getStatusIcon= function(status){
|
||||
let getStatusIcon= (status) => {
|
||||
let color = 'txt-color-danger';
|
||||
let title = 'route not found';
|
||||
switch(status){
|
||||
@@ -563,10 +728,11 @@ define([
|
||||
// 2: not searched
|
||||
let routeStatus = routeData.skipSearch ? 2 : 0;
|
||||
|
||||
// button class for "safer" routes
|
||||
let saferButtonClass = routeData.safer ? 'txt-color-success' : '';
|
||||
// button class for flag (e.g. "secure" routes)
|
||||
let flagButtonClass = routeData.flag === 'secure' ? 'txt-color-success' : '';
|
||||
|
||||
let saferButton = '<i class="fas ' + ['fa-shield-alt', 'txt-color', saferButtonClass].join(' ') + '"></i>';
|
||||
let connectionButton = '<i class="fas ' + ['fa-link', 'txt-color'].join(' ') + '"></i>';
|
||||
let flagButton = '<i class="fas ' + ['fa-shield-alt', 'txt-color', flagButtonClass].join(' ') + '"></i>';
|
||||
let reloadButton = '<i class="fas ' + ['fa-sync'].join(' ') + '"></i>';
|
||||
let searchButton = '<i class="fas ' + ['fa-search-plus '].join(' ') + '"></i>';
|
||||
let deleteButton = '<i class="fas ' + ['fa-times', 'txt-color', 'txt-color-redDarker'].join(' ') + '"></i>';
|
||||
@@ -583,7 +749,10 @@ define([
|
||||
value: '',
|
||||
formatted: ''
|
||||
},
|
||||
route: routeStatus === 2 ? 'search now' : 'not found',
|
||||
route: {
|
||||
value: routeStatus === 2 ? 'search now' : 'not found',
|
||||
data: routeData.route
|
||||
},
|
||||
stargates: routeData.stargates,
|
||||
jumpbridges: routeData.jumpbridges,
|
||||
wormholes: routeData.wormholes,
|
||||
@@ -591,9 +760,13 @@ define([
|
||||
wormholesCritical: routeData.wormholesCritical,
|
||||
wormholesFrigate: routeData.wormholesFrigate,
|
||||
wormholesEOL: routeData.wormholesEOL,
|
||||
safer: {
|
||||
value: routeData.safer,
|
||||
button: saferButton
|
||||
connections: {
|
||||
value: 0,
|
||||
button: connectionButton
|
||||
},
|
||||
flag: {
|
||||
value: routeData.flag,
|
||||
button: flagButton
|
||||
},
|
||||
reload: {
|
||||
button: routeData.skipSearch ? searchButton : reloadButton
|
||||
@@ -613,15 +786,28 @@ define([
|
||||
routeStatus = 1;
|
||||
|
||||
// add route Data
|
||||
let jumpData = [];
|
||||
let routeJumpElements = [];
|
||||
let avgSecTemp = 0;
|
||||
|
||||
let connectionsData = getConnectionsDataFromMaps(routeData.mapIds);
|
||||
let prevRouteNodeData = null;
|
||||
// loop all systems on this route
|
||||
for(let i = 0; i < routeData.route.length; i++){
|
||||
let routeNodeData = routeData.route[i];
|
||||
// format system name
|
||||
let systemName = routeNodeData.system;
|
||||
|
||||
// fake connection elements between systems -----------------------------------------------------------
|
||||
if(prevRouteNodeData){
|
||||
let connectionData = findConnectionsData(connectionsData, prevRouteNodeData.system, systemName);
|
||||
if(!connectionData.hasOwnProperty('connection')){
|
||||
connectionData = getStargateConnectionData(prevRouteNodeData, routeNodeData);
|
||||
}
|
||||
let connectionElement = getFakeConnectionElement(connectionData);
|
||||
|
||||
routeJumpElements.push( connectionElement );
|
||||
}
|
||||
|
||||
// system elements ------------------------------------------------------------------------------------
|
||||
let systemSec = Number(routeNodeData.security).toFixed(1).toString();
|
||||
let tempSystemSec = systemSec;
|
||||
|
||||
@@ -640,12 +826,14 @@ define([
|
||||
let system = '<i class="' + icon + ' ' + systemSecClass + '" ';
|
||||
system += 'data-toggle="tooltip" data-placement="bottom" data-container="body" ';
|
||||
system += 'title="' + systemName + ' [' + systemSec + '] "></i>';
|
||||
jumpData.push( system );
|
||||
routeJumpElements.push( system );
|
||||
|
||||
// "source" system is not relevant for average security
|
||||
if(i > 0){
|
||||
avgSecTemp += Number(routeNodeData.security);
|
||||
}
|
||||
|
||||
prevRouteNodeData = routeNodeData;
|
||||
}
|
||||
|
||||
let avgSec = ( avgSecTemp / (routeData.route.length - 1)).toFixed(2);
|
||||
@@ -666,7 +854,8 @@ define([
|
||||
value: avgSec,
|
||||
formatted: '<span class="' + avgSecClass + '">' + avgSec + '</span>'
|
||||
};
|
||||
tableRowData.route = jumpData.join(' ');
|
||||
|
||||
tableRowData.route.value = routeJumpElements.join(' ');
|
||||
}
|
||||
|
||||
// route status data ----------------------------------------------------------------------
|
||||
@@ -682,7 +871,7 @@ define([
|
||||
* get module element
|
||||
* @returns {*}
|
||||
*/
|
||||
let getModule = function(){
|
||||
let getModule = () => {
|
||||
// create new module container
|
||||
let moduleElement = $('<div>').append(
|
||||
$('<div>', {
|
||||
@@ -694,14 +883,14 @@ define([
|
||||
$('<h5>', {
|
||||
class: 'pull-right'
|
||||
}).append(
|
||||
$('<i>', {
|
||||
class: ['fas', 'fa-fw', 'fa-search', config.moduleHeadlineIconClass, config.moduleHeadlineIconSearchClass].join(' '),
|
||||
title: 'find route'
|
||||
}).attr('data-html', 'true').attr('data-toggle', 'tooltip'),
|
||||
$('<i>', {
|
||||
class: ['fas', 'fa-fw', 'fa-sliders-h', config.moduleHeadlineIconClass, config.moduleHeadlineIconSettingsClass].join(' '),
|
||||
title: 'settings'
|
||||
}).attr('data-html', 'true').attr('data-toggle', 'tooltip'),
|
||||
$('<i>', {
|
||||
class: ['fas', 'fa-fw', 'fa-search', config.moduleHeadlineIconClass, config.moduleHeadlineIconSearchClass].join(' '),
|
||||
title: 'find route'
|
||||
}).attr('data-html', 'true').attr('data-toggle', 'tooltip'),
|
||||
$('<i>', {
|
||||
class: ['fas', 'fa-fw', 'fa-sync', config.moduleHeadlineIconClass, config.moduleHeadlineIconRefreshClass].join(' '),
|
||||
title: 'refresh all'
|
||||
@@ -737,7 +926,7 @@ define([
|
||||
targets: 0,
|
||||
orderable: true,
|
||||
title: '',
|
||||
width: '10px',
|
||||
width: 2,
|
||||
class: ['text-center'].join(' '),
|
||||
data: 'status',
|
||||
render: {
|
||||
@@ -764,7 +953,7 @@ define([
|
||||
targets: 2,
|
||||
orderable: true,
|
||||
title: '<span title="jumps" data-toggle="tooltip"><i class="fas fa-arrows-alt-h"></i> </span>',
|
||||
width: '18px',
|
||||
width: 18,
|
||||
class: 'text-right',
|
||||
data: 'jumps',
|
||||
render: {
|
||||
@@ -775,7 +964,7 @@ define([
|
||||
targets: 3,
|
||||
orderable: true,
|
||||
title: '<span title="average security" data-toggle="tooltip">Ø </span>',
|
||||
width: '15px',
|
||||
width: 15,
|
||||
class: 'text-right',
|
||||
data: 'avgTrueSec',
|
||||
render: {
|
||||
@@ -786,19 +975,49 @@ define([
|
||||
targets: 4,
|
||||
orderable: false,
|
||||
title: 'route',
|
||||
data: 'route'
|
||||
class: [config.dataTableRouteCellClass].join(' '),
|
||||
data: 'route',
|
||||
render: {
|
||||
_: 'value'
|
||||
}
|
||||
},{
|
||||
targets: 5,
|
||||
title: '<i title="search safer route (HS)" data-toggle="tooltip" class="fas fa-shield-alt text-right"></i>',
|
||||
title: '<i title="toggle connections" data-toggle="tooltip" class="fas fa-link text-right"></i>',
|
||||
orderable: false,
|
||||
searchable: false,
|
||||
width: '10px',
|
||||
width: 10,
|
||||
class: ['text-center', config.dataTableActionCellClass].join(' '),
|
||||
data: 'safer',
|
||||
data: 'connections',
|
||||
render: {
|
||||
_: 'button'
|
||||
},
|
||||
createdCell: function(cell, cellData, rowData, rowIndex, colIndex){
|
||||
createdCell: function(cell, cellData, rowData, rowIndex, colIndex) {
|
||||
let tempTableApi = this.api();
|
||||
|
||||
$(cell).on('click', function(e) {
|
||||
let routeCellElement = tempTableApi.cell( rowIndex, 4 ).nodes().to$();
|
||||
|
||||
if(routeCellElement.hasClass(config.dataTableJumpCellClass)){
|
||||
routeCellElement.toggleClass(config.dataTableJumpCellClass, false);
|
||||
$(this).find('i').toggleClass('txt-color-orange', false);
|
||||
}else{
|
||||
routeCellElement.toggleClass(config.dataTableJumpCellClass, true);
|
||||
$(this).find('i').toggleClass('txt-color-orange', true);
|
||||
}
|
||||
});
|
||||
}
|
||||
},{
|
||||
targets: 6,
|
||||
title: '<i title="search safer route (HS)" data-toggle="tooltip" class="fas fa-shield-alt text-right"></i>',
|
||||
orderable: false,
|
||||
searchable: false,
|
||||
width: 10,
|
||||
class: ['text-center', config.dataTableActionCellClass].join(' '),
|
||||
data: 'flag',
|
||||
render: {
|
||||
_: 'button'
|
||||
},
|
||||
createdCell: function(cell, cellData, rowData, rowIndex, colIndex) {
|
||||
let tempTableApi = this.api();
|
||||
|
||||
$(cell).on('click', function(e) {
|
||||
@@ -809,7 +1028,7 @@ define([
|
||||
|
||||
// overwrite some params
|
||||
routeData.skipSearch = 0;
|
||||
routeData.safer = 1 - routeData.safer; // toggle
|
||||
routeData.flag = routeData.flag === 'shortest' ? 'secure' : 'shortest'; // toggle
|
||||
|
||||
let context = {
|
||||
moduleElement: moduleElement,
|
||||
@@ -824,11 +1043,11 @@ define([
|
||||
});
|
||||
}
|
||||
},{
|
||||
targets: 6,
|
||||
targets: 7,
|
||||
title: '',
|
||||
orderable: false,
|
||||
searchable: false,
|
||||
width: '10px',
|
||||
width: 10,
|
||||
class: ['text-center', config.dataTableActionCellClass].join(' '),
|
||||
data: 'reload',
|
||||
render: {
|
||||
@@ -859,11 +1078,11 @@ define([
|
||||
});
|
||||
}
|
||||
},{
|
||||
targets: 7,
|
||||
targets: 8,
|
||||
title: '',
|
||||
orderable: false,
|
||||
searchable: false,
|
||||
width: '10px',
|
||||
width: 10,
|
||||
class: ['text-center', config.dataTableActionCellClass].join(' '),
|
||||
data: 'clear',
|
||||
render: {
|
||||
@@ -908,6 +1127,20 @@ define([
|
||||
}
|
||||
|
||||
},
|
||||
initComplete: function(settings, json){
|
||||
// click on "fake connection" -------------------------------------------------------------------------
|
||||
$(this).on('click', '.pf-fake-connection', function(){
|
||||
let fakeConnectionElement = $(this);
|
||||
let mapId = fakeConnectionElement.attr('data-mapId');
|
||||
let connectionId = fakeConnectionElement.attr('data-connectionId');
|
||||
let connection = $().getConnectionById(mapId, connectionId);
|
||||
|
||||
if(connection){
|
||||
let map = connection._jsPlumb.instance;
|
||||
MapUtil.showConnectionInfo(map, [connection]);
|
||||
}
|
||||
});
|
||||
},
|
||||
data: [] // will be added dynamic
|
||||
});
|
||||
|
||||
@@ -990,7 +1223,7 @@ define([
|
||||
* @param mapId
|
||||
* @param systemData
|
||||
*/
|
||||
let initModule = function(moduleElement, mapId, systemData){
|
||||
let initModule = (moduleElement, mapId, systemData) => {
|
||||
|
||||
let systemFromData = {
|
||||
name: systemData.name,
|
||||
|
||||
@@ -225,37 +225,39 @@ define([
|
||||
let getTableData = function(tableApi){
|
||||
let tableData = [];
|
||||
|
||||
tableApi.rows().eq(0).each(function(idx){
|
||||
let row = tableApi.row(idx);
|
||||
// default row data
|
||||
let defaultRowData = row.data();
|
||||
let rowElement = row.nodes().to$();
|
||||
if(tableApi){
|
||||
tableApi.rows().eq(0).each(function(idx){
|
||||
let row = tableApi.row(idx);
|
||||
// default row data
|
||||
let defaultRowData = row.data();
|
||||
let rowElement = row.nodes().to$();
|
||||
|
||||
if(defaultRowData.id > 0){
|
||||
// get all editable fields per row
|
||||
let editableFields = rowElement.find('.editable');
|
||||
if(defaultRowData.id > 0){
|
||||
// get all editable fields per row
|
||||
let editableFields = rowElement.find('.editable');
|
||||
|
||||
if(editableFields.length > 0){
|
||||
let values = $(editableFields).editable('getValue');
|
||||
if(editableFields.length > 0){
|
||||
let values = $(editableFields).editable('getValue');
|
||||
|
||||
if(values.name){
|
||||
// convert to lower for better compare options
|
||||
values.name = values.name.toLowerCase();
|
||||
if(values.name){
|
||||
// convert to lower for better compare options
|
||||
values.name = values.name.toLowerCase();
|
||||
|
||||
// add pk for this row
|
||||
values.id = defaultRowData.id;
|
||||
// add pk for this row
|
||||
values.id = defaultRowData.id;
|
||||
|
||||
// add updated for this row
|
||||
values.updated = defaultRowData.updated;
|
||||
// add updated for this row
|
||||
values.updated = defaultRowData.updated;
|
||||
|
||||
// add row index
|
||||
values.index = idx;
|
||||
// add row index
|
||||
values.index = idx;
|
||||
|
||||
tableData.push( values );
|
||||
tableData.push( values );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
return tableData;
|
||||
};
|
||||
@@ -1500,6 +1502,7 @@ define([
|
||||
let map = Map.getMapInstance( mapId );
|
||||
let systemId = MapUtil.getSystemId(mapId, systemData.id);
|
||||
let systemConnections = MapUtil.searchConnectionsBySystems(map, [systemId], 'wh');
|
||||
let newSelectOptions = [];
|
||||
let connectionOptions = [];
|
||||
|
||||
for(let i = 0; i < systemConnections.length; i++){
|
||||
@@ -1510,25 +1513,35 @@ define([
|
||||
// check whether "source" or "target" system is relevant for this connection
|
||||
// -> hint "source" === 'target' --> loop
|
||||
if(systemData.id !== connectionData.target){
|
||||
// take target...
|
||||
connectionOptions.push({
|
||||
value: connectionData.id,
|
||||
text: connectionData.targetAlias
|
||||
});
|
||||
let targetSystemData = MapUtil.getSystemData(mapId, connectionData.target);
|
||||
if(targetSystemData){
|
||||
// take target...
|
||||
connectionOptions.push({
|
||||
value: connectionData.id,
|
||||
text: connectionData.targetAlias + ' - ' + targetSystemData.security
|
||||
});
|
||||
}
|
||||
}else if(systemData.id !== connectionData.source){
|
||||
// take source...
|
||||
connectionOptions.push({
|
||||
value: connectionData.id,
|
||||
text: connectionData.sourceAlias
|
||||
});
|
||||
let sourceSystemData = MapUtil.getSystemData(mapId, connectionData.source);
|
||||
if(sourceSystemData){
|
||||
// take source...
|
||||
connectionOptions.push({
|
||||
value: connectionData.id,
|
||||
text: connectionData.sourceAlias + ' - ' + sourceSystemData.security
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// add empty entry
|
||||
connectionOptions.unshift({ value: null, text: ''});
|
||||
if(connectionOptions.length > 0){
|
||||
newSelectOptions.push({ text: 'System', children: connectionOptions});
|
||||
}
|
||||
|
||||
return connectionOptions;
|
||||
// add empty entry
|
||||
newSelectOptions.unshift({ value: null, text: ''});
|
||||
|
||||
return newSelectOptions;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -1621,7 +1634,7 @@ define([
|
||||
if(newSelectOptionsCount > 0){
|
||||
if(groupId === 5){
|
||||
// "wormhole" selected => multiple <optgroup> available
|
||||
newSelectOptions.push({ text: 'Wandering WHs', children: fixSelectOptions});
|
||||
newSelectOptions.push({ text: 'Wandering WH', children: fixSelectOptions});
|
||||
}else{
|
||||
newSelectOptions = fixSelectOptions;
|
||||
}
|
||||
@@ -1645,7 +1658,7 @@ define([
|
||||
}
|
||||
|
||||
if(frigateWHData.length > 0){
|
||||
newSelectOptions.push({ text: 'Frigate WHs', children: frigateWHData});
|
||||
newSelectOptions.push({ text: 'Frigate WH', children: frigateWHData});
|
||||
}
|
||||
|
||||
// add possible incoming holes
|
||||
@@ -1661,7 +1674,7 @@ define([
|
||||
}
|
||||
|
||||
if(incomingWHData.length > 0){
|
||||
newSelectOptions.push({ text: 'Incoming WHs', children: incomingWHData});
|
||||
newSelectOptions.push({ text: 'Incoming WH', children: incomingWHData});
|
||||
}
|
||||
}else{
|
||||
// groups without "children" (optgroup) should be sorted by "value"
|
||||
@@ -1686,7 +1699,7 @@ define([
|
||||
}
|
||||
|
||||
if(staticWHData.length > 0){
|
||||
newSelectOptions.unshift({ text: 'Static WHs', children: staticWHData});
|
||||
newSelectOptions.unshift({ text: 'Static WH', children: staticWHData});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
204
js/app/util.js
204
js/app/util.js
@@ -72,9 +72,9 @@ define([
|
||||
let localStorage; // cache for "localForage" singleton
|
||||
|
||||
/*
|
||||
* ===========================================================================================================
|
||||
* ===============================================================================================================
|
||||
* Global jQuery plugins for some common and frequently used functions
|
||||
* ==========================================================================================================
|
||||
* ==============================================================================================================
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -820,9 +820,9 @@ define([
|
||||
};
|
||||
|
||||
/*
|
||||
* ===========================================================================================================
|
||||
* ===============================================================================================================
|
||||
* Util functions that are global available for all modules
|
||||
* ==========================================================================================================
|
||||
* ==============================================================================================================
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -1149,11 +1149,29 @@ define([
|
||||
return logInfo;
|
||||
};
|
||||
|
||||
/**
|
||||
* set currentUserData as "global" variable
|
||||
* this function should be called continuously after data change
|
||||
* to keep the data always up2data
|
||||
* @param userData
|
||||
*/
|
||||
let setCurrentUserData = (userData) => {
|
||||
Init.currentUserData = userData;
|
||||
|
||||
// check if function is available
|
||||
// this is not the case in "login" page
|
||||
if( $.fn.updateHeaderUserData ){
|
||||
$.fn.updateHeaderUserData();
|
||||
}
|
||||
|
||||
return getCurrentUserData();
|
||||
};
|
||||
|
||||
/**
|
||||
* get currentUserData from "global" variable
|
||||
* @returns {*}
|
||||
*/
|
||||
let getCurrentUserData = function(){
|
||||
let getCurrentUserData = () => {
|
||||
return Init.currentUserData;
|
||||
};
|
||||
|
||||
@@ -1196,15 +1214,18 @@ define([
|
||||
/**
|
||||
* set default jQuery AJAX configuration
|
||||
*/
|
||||
let ajaxSetup = function(){
|
||||
let ajaxSetup = () => {
|
||||
$.ajaxSetup({
|
||||
beforeSend: function(xhr, settings) {
|
||||
beforeSend: function(jqXHR, settings) {
|
||||
// store request URL for later use (e.g. in error messages)
|
||||
jqXHR.url = location.protocol + '//' + location.host + settings.url;
|
||||
|
||||
// Add custom application headers on "same origin" requests only!
|
||||
// -> Otherwise a "preflight" request is made, which will "probably" fail
|
||||
if(settings.crossDomain === false){
|
||||
// add current character data to ANY XHR request (HTTP HEADER)
|
||||
// -> This helps to identify multiple characters on multiple browser tabs
|
||||
xhr.setRequestHeader('Pf-Character', getCurrentCharacterId());
|
||||
jqXHR.setRequestHeader('Pf-Character', getCurrentCharacterId());
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -1702,13 +1723,34 @@ define([
|
||||
return signatureTypeId;
|
||||
};
|
||||
|
||||
/**
|
||||
* get array key that points to map data catching mapId
|
||||
* @param data
|
||||
* @param mapId
|
||||
* @returns {boolean}
|
||||
*/
|
||||
let getDataIndexByMapId = (data, mapId) => {
|
||||
let index = false;
|
||||
if( Array.isArray(data) && mapId === parseInt(mapId, 10) ){
|
||||
for(let i = 0; i < data.length; i++){
|
||||
if(data[i].config.id === mapId){
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return index;
|
||||
};
|
||||
|
||||
// CurrentMapUserData =============================================================================================
|
||||
|
||||
/**
|
||||
* set currentMapUserData as "global" variable (count of active pilots)
|
||||
* this function should be called continuously after data change
|
||||
* to keep the data always up2data
|
||||
* @param mapUserData
|
||||
*/
|
||||
let setCurrentMapUserData = function(mapUserData){
|
||||
let setCurrentMapUserData = (mapUserData) => {
|
||||
Init.currentMapUserData = mapUserData;
|
||||
|
||||
return getCurrentMapUserData();
|
||||
@@ -1719,23 +1761,26 @@ define([
|
||||
* @param mapId
|
||||
* @returns {boolean}
|
||||
*/
|
||||
let getCurrentMapUserData = function(mapId){
|
||||
let getCurrentMapUserData = (mapId) => {
|
||||
let currentMapUserData = false;
|
||||
|
||||
if(
|
||||
mapId === parseInt(mapId, 10) &&
|
||||
Init.currentMapUserData
|
||||
){
|
||||
// search for a specific map
|
||||
for(let i = 0; i < Init.currentMapUserData.length; i++){
|
||||
if(Init.currentMapUserData[i].config.id === mapId){
|
||||
currentMapUserData = Init.currentMapUserData[i];
|
||||
break;
|
||||
if(Init.currentMapUserData){
|
||||
if(mapId === parseInt(mapId, 10)){
|
||||
|
||||
// search for a specific map
|
||||
for(let i = 0; i < Init.currentMapUserData.length; i++){
|
||||
if(
|
||||
Init.currentMapUserData[i].config &&
|
||||
Init.currentMapUserData[i].config.id === mapId
|
||||
){
|
||||
currentMapUserData = Init.currentMapUserData[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
// get data for all maps
|
||||
currentMapUserData = Init.currentMapUserData;
|
||||
}
|
||||
}else{
|
||||
// get data for all maps
|
||||
currentMapUserData = Init.currentMapUserData;
|
||||
}
|
||||
|
||||
if(currentMapUserData !== false){
|
||||
@@ -1746,60 +1791,54 @@ define([
|
||||
return currentMapUserData;
|
||||
};
|
||||
|
||||
/**
|
||||
* get mapDataUser array index by mapId
|
||||
* @param mapId
|
||||
* @returns {boolean|int}
|
||||
*/
|
||||
let getCurrentMapUserDataIndex = (mapId) => {
|
||||
return getDataIndexByMapId(Init.currentMapUserData, mapId);
|
||||
};
|
||||
|
||||
/**
|
||||
* update cached mapUserData for a single map
|
||||
* @param mapUserData
|
||||
*/
|
||||
let updateCurrentMapUserData = (mapUserData) => {
|
||||
let mapUserDataIndex = getCurrentMapUserDataIndex( mapUserData.config.id );
|
||||
|
||||
if( !Array.isArray(Init.currentMapUserData) ){
|
||||
Init.currentMapUserData = [];
|
||||
}
|
||||
|
||||
if(mapUserDataIndex !== false){
|
||||
Init.currentMapUserData[mapUserDataIndex] = mapUserData;
|
||||
}else{
|
||||
// new map data
|
||||
Init.currentMapUserData.push(mapUserData);
|
||||
}
|
||||
};
|
||||
|
||||
// CurrentMapData =================================================================================================
|
||||
|
||||
/**
|
||||
* set currentMapData as "global" variable
|
||||
* this function should be called continuously after data change
|
||||
* to keep the data always up2data
|
||||
* @param mapData
|
||||
*/
|
||||
let setCurrentMapData = function(mapData){
|
||||
let setCurrentMapData = (mapData) => {
|
||||
Init.currentMapData = mapData;
|
||||
|
||||
return getCurrentMapData();
|
||||
};
|
||||
|
||||
/**
|
||||
* get mapData array index by mapId
|
||||
* @param mapId
|
||||
* @returns {boolean|int}
|
||||
*/
|
||||
let getCurrentMapDataIndex = function(mapId){
|
||||
let mapDataIndex = false;
|
||||
|
||||
if( mapId === parseInt(mapId, 10) ){
|
||||
for(let i = 0; i < Init.currentMapData.length; i++){
|
||||
if(Init.currentMapData[i].config.id === mapId){
|
||||
mapDataIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return mapDataIndex;
|
||||
};
|
||||
|
||||
/**
|
||||
* update cached mapData for a single map
|
||||
* @param mapData
|
||||
*/
|
||||
let updateCurrentMapData = function(mapData){
|
||||
let mapDataIndex = getCurrentMapDataIndex( mapData.config.id );
|
||||
|
||||
if(mapDataIndex !== false){
|
||||
Init.currentMapData[mapDataIndex].config = mapData.config;
|
||||
Init.currentMapData[mapDataIndex].data = mapData.data;
|
||||
}else{
|
||||
// new map data
|
||||
Init.currentMapData.push(mapData);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* get currentMapData from "global" variable for a specific map or all maps
|
||||
* @param mapId
|
||||
* @returns {boolean}
|
||||
*/
|
||||
let getCurrentMapData = function(mapId){
|
||||
let getCurrentMapData = (mapId) => {
|
||||
let currentMapData = false;
|
||||
|
||||
if( mapId === parseInt(mapId, 10) ){
|
||||
@@ -1818,6 +1857,31 @@ define([
|
||||
return currentMapData;
|
||||
};
|
||||
|
||||
/**
|
||||
* get mapData array index by mapId
|
||||
* @param mapId
|
||||
* @returns {boolean|int}
|
||||
*/
|
||||
let getCurrentMapDataIndex = (mapId) => {
|
||||
return getDataIndexByMapId(Init.currentMapData, mapId);
|
||||
};
|
||||
|
||||
/**
|
||||
* update cached mapData for a single map
|
||||
* @param mapData
|
||||
*/
|
||||
let updateCurrentMapData = (mapData) => {
|
||||
let mapDataIndex = getCurrentMapDataIndex( mapData.config.id );
|
||||
|
||||
if(mapDataIndex !== false){
|
||||
Init.currentMapData[mapDataIndex].config = mapData.config;
|
||||
Init.currentMapData[mapDataIndex].data = mapData.data;
|
||||
}else{
|
||||
// new map data
|
||||
Init.currentMapData.push(mapData);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @param path
|
||||
* @param value
|
||||
@@ -1843,24 +1907,6 @@ define([
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* set currentUserData as "global" variable
|
||||
* this function should be called continuously after data change
|
||||
* to keep the data always up2data
|
||||
* @param userData
|
||||
*/
|
||||
let setCurrentUserData = function(userData){
|
||||
Init.currentUserData = userData;
|
||||
|
||||
// check if function is available
|
||||
// this is not the case in "login" page
|
||||
if( $.fn.updateHeaderUserData ){
|
||||
$.fn.updateHeaderUserData();
|
||||
}
|
||||
|
||||
return getCurrentUserData();
|
||||
};
|
||||
|
||||
/**
|
||||
* get the current log data for the current user character
|
||||
* @returns {boolean}
|
||||
@@ -2397,10 +2443,10 @@ define([
|
||||
getAreaIdBySecurity: getAreaIdBySecurity,
|
||||
setCurrentMapUserData: setCurrentMapUserData,
|
||||
getCurrentMapUserData: getCurrentMapUserData,
|
||||
updateCurrentMapUserData: updateCurrentMapUserData,
|
||||
setCurrentMapData: setCurrentMapData,
|
||||
getCurrentMapData: getCurrentMapData,
|
||||
filterCurrentMapData: filterCurrentMapData,
|
||||
getCurrentMapDataIndex: getCurrentMapDataIndex,
|
||||
updateCurrentMapData: updateCurrentMapData,
|
||||
deleteCurrentMapData: deleteCurrentMapData,
|
||||
setCurrentUserData: setCurrentUserData,
|
||||
|
||||
223
js/lib/bootstrap-confirmation.js
vendored
223
js/lib/bootstrap-confirmation.js
vendored
@@ -1,5 +1,5 @@
|
||||
/*!
|
||||
* Bootstrap Confirmation v1.0.5
|
||||
* Bootstrap Confirmation v1.0.7
|
||||
* https://github.com/tavicu/bs-confirmation
|
||||
*/
|
||||
+function ($) {
|
||||
@@ -15,62 +15,47 @@
|
||||
|
||||
this.init('confirmation', element, options);
|
||||
|
||||
$(element).on('show.bs.confirmation', function(e) {
|
||||
that.options.onShow(e, this);
|
||||
|
||||
$(this).addClass('open');
|
||||
|
||||
var options = that.options;
|
||||
var all = options.all_selector;
|
||||
|
||||
if(options.singleton)
|
||||
{
|
||||
$(all).not(that.$element).each(function()
|
||||
{
|
||||
if( $(this).hasClass('open') )
|
||||
{
|
||||
$(this).confirmation('hide');
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
$(element).on('hide.bs.confirmation', function(e) {
|
||||
that.options.onHide(e, this);
|
||||
|
||||
$(this).removeClass('open');
|
||||
});
|
||||
|
||||
$(element).on('shown.bs.confirmation', function(e) {
|
||||
var options = that.options;
|
||||
var all = options.all_selector;
|
||||
|
||||
if(that.isPopout()) {
|
||||
if(!event_body) {
|
||||
event_body = $('body').on('click', function (e) {
|
||||
if(that.$element.is(e.target)) return;
|
||||
if(that.$element.has(e.target).length) return;
|
||||
if($('.popover').has(e.target).length) return;
|
||||
|
||||
that.hide();
|
||||
that.inState.click = false;
|
||||
|
||||
$('body').unbind(e);
|
||||
|
||||
event_body = false;
|
||||
|
||||
return;
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if(options.selector) {
|
||||
if (options.selector) {
|
||||
$(element).on('click.bs.confirmation', options.selector, function(e) {
|
||||
e.preventDefault();
|
||||
});
|
||||
} else {
|
||||
$(element).on('click.bs.confirmation', function(e) {
|
||||
$(element).on('show.bs.confirmation', function(event) {
|
||||
that.runCallback(that.options.onShow, event, that.$element);
|
||||
|
||||
that.$element.addClass('open');
|
||||
|
||||
if (that.options.singleton) {
|
||||
$(that.options.all_selector).not(that.$element).each(function() {
|
||||
if ($(this).hasClass('open')) {
|
||||
$(this).confirmation('hide');
|
||||
}
|
||||
});
|
||||
}
|
||||
}).on('hide.bs.confirmation', function(event) {
|
||||
that.runCallback(that.options.onHide, event, that.$element);
|
||||
|
||||
that.$element.removeClass('open');
|
||||
}).on('shown.bs.confirmation', function(e) {
|
||||
if (!that.isPopout() && !event_body) {
|
||||
return;
|
||||
}
|
||||
|
||||
event_body = $('body').on('click', function (e) {
|
||||
if (that.$element.is(e.target)) return;
|
||||
if (that.$element.has(e.target).length) return;
|
||||
if ($('.popover').has(e.target).length) return;
|
||||
|
||||
that.hide();
|
||||
that.inState.click = false;
|
||||
|
||||
$('body').unbind(e);
|
||||
|
||||
event_body = false;
|
||||
|
||||
return;
|
||||
});
|
||||
}).on('click.bs.confirmation', function(e) {
|
||||
e.preventDefault();
|
||||
});
|
||||
}
|
||||
@@ -78,30 +63,30 @@
|
||||
|
||||
if (!$.fn.popover || !$.fn.tooltip) throw new Error('Confirmation requires popover.js and tooltip.js');
|
||||
|
||||
Confirmation.VERSION = '1.0.5'
|
||||
Confirmation.VERSION = '1.0.7'
|
||||
|
||||
Confirmation.DEFAULTS = $.extend({}, $.fn.popover.Constructor.DEFAULTS, {
|
||||
placement : 'right',
|
||||
title : 'Are you sure?',
|
||||
btnOkClass : 'btn btn-sm btn-danger',
|
||||
btnOkLabel : 'Delete',
|
||||
btnOkIcon : 'glyphicon glyphicon-ok',
|
||||
btnCancelClass : 'btn btn-sm btn-default',
|
||||
btnCancelLabel : 'Cancel',
|
||||
btnCancelIcon : 'glyphicon glyphicon-remove',
|
||||
href : '#',
|
||||
target : '_self',
|
||||
singleton : true,
|
||||
popout : true,
|
||||
onShow : function(event, element){},
|
||||
onHide : function(event, element){},
|
||||
onConfirm : function(event, element){},
|
||||
onCancel : function(event, element){},
|
||||
template : '<div class="popover"><div class="arrow"></div>'
|
||||
placement : 'right',
|
||||
title : 'Are you sure?',
|
||||
btnOkClass : 'btn btn-sm btn-danger',
|
||||
btnOkLabel : 'Delete',
|
||||
btnOkIcon : 'glyphicon glyphicon-ok',
|
||||
btnCancelClass : 'btn btn-sm btn-default',
|
||||
btnCancelLabel : 'Cancel',
|
||||
btnCancelIcon : 'glyphicon glyphicon-remove',
|
||||
href : '#',
|
||||
target : '_self',
|
||||
singleton : true,
|
||||
popout : true,
|
||||
onShow : function(event, element) {},
|
||||
onHide : function(event, element) {},
|
||||
onConfirm : function(event, element) {},
|
||||
onCancel : function(event, element) {},
|
||||
template : '<div class="popover"><div class="arrow"></div>'
|
||||
+ '<h3 class="popover-title"></h3>'
|
||||
+ '<div class="popover-content">'
|
||||
+ '<a data-apply="confirmation">Yes</a>'
|
||||
+ '<a data-dismiss="confirmation">No</a>'
|
||||
+ ' <a data-apply="confirmation">Yes</a>'
|
||||
+ ' <a data-dismiss="confirmation">No</a>'
|
||||
+ '</div>'
|
||||
+ '</div>'
|
||||
});
|
||||
@@ -131,24 +116,34 @@
|
||||
.attr('href', this.getHref())
|
||||
.attr('target', this.getTarget())
|
||||
.off('click').on('click', function(event) {
|
||||
options.onConfirm(event, that.$element);
|
||||
that.runCallback(that.options.onConfirm, event, that.$element);
|
||||
|
||||
// If the button is a submit one
|
||||
if (that.$element.attr('type') == 'submit')
|
||||
that.$element.closest('form:first').submit();
|
||||
if (that.$element.attr('type') == 'submit') {
|
||||
var form = that.$element.closest('form');
|
||||
var novalidate = form.attr('novalidate') !== undefined;
|
||||
|
||||
if (novalidate || form[0].checkValidity()) {
|
||||
form.submit();
|
||||
}
|
||||
}
|
||||
|
||||
that.hide();
|
||||
that.inState.click = false;
|
||||
|
||||
that.$element.trigger($.Event('confirm.bs.confirmation'));
|
||||
});
|
||||
|
||||
$btnCancel.addClass(this.getBtnCancelClass())
|
||||
.html(this.getBtnCancelLabel())
|
||||
.prepend($('<i></i>').addClass(this.getBtnCancelIcon()), " ")
|
||||
.off('click').on('click', function(event){
|
||||
options.onCancel(event, that.$element);
|
||||
.off('click').on('click', function(event) {
|
||||
that.runCallback(that.options.onCancel, event, that.$element);
|
||||
|
||||
that.hide();
|
||||
that.inState.click = false;
|
||||
|
||||
that.$element.trigger($.Event('cancel.bs.confirmation'));
|
||||
});
|
||||
|
||||
$tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title);
|
||||
@@ -161,73 +156,71 @@
|
||||
}
|
||||
|
||||
Confirmation.prototype.getBtnOkClass = function () {
|
||||
var $e = this.$element;
|
||||
var o = this.options;
|
||||
|
||||
return $e.attr('data-btnOkClass') || (typeof o.btnOkClass == 'function' ? o.btnOkClass.call(this, $e[0]) : o.btnOkClass);
|
||||
return this.$element.data('btnOkClass') ||
|
||||
(typeof this.options.btnOkClass == 'function' ? this.options.btnOkClass.call(this, this.$element) : this.options.btnOkClass);
|
||||
}
|
||||
|
||||
Confirmation.prototype.getBtnOkLabel = function () {
|
||||
var $e = this.$element;
|
||||
var o = this.options;
|
||||
|
||||
return $e.attr('data-btnOkLabel') || (typeof o.btnOkLabel == 'function' ? o.btnOkLabel.call(this, $e[0]) : o.btnOkLabel);
|
||||
return this.$element.data('btnOkLabel') ||
|
||||
(typeof this.options.btnOkLabel == 'function' ? this.options.btnOkLabel.call(this, this.$element) : this.options.btnOkLabel);
|
||||
}
|
||||
|
||||
Confirmation.prototype.getBtnOkIcon = function () {
|
||||
var $e = this.$element;
|
||||
var o = this.options;
|
||||
|
||||
return $e.attr('data-btnOkIcon') || (typeof o.btnOkIcon == 'function' ? o.btnOkIcon.call(this, $e[0]) : o.btnOkIcon);
|
||||
return this.$element.data('btnOkIcon') ||
|
||||
(typeof this.options.btnOkIcon == 'function' ? this.options.btnOkIcon.call(this, this.$element) : this.options.btnOkIcon);
|
||||
}
|
||||
|
||||
Confirmation.prototype.getBtnCancelClass = function () {
|
||||
var $e = this.$element;
|
||||
var o = this.options;
|
||||
|
||||
return $e.attr('data-btnCancelClass') || (typeof o.btnCancelClass == 'function' ? o.btnCancelClass.call(this, $e[0]) : o.btnCancelClass);
|
||||
return this.$element.data('btnCancelClass') ||
|
||||
(typeof this.options.btnCancelClass == 'function' ? this.options.btnCancelClass.call(this, this.$element) : this.options.btnCancelClass);
|
||||
}
|
||||
|
||||
Confirmation.prototype.getBtnCancelLabel = function () {
|
||||
var $e = this.$element;
|
||||
var o = this.options;
|
||||
|
||||
return $e.attr('data-btnCancelLabel') || (typeof o.btnCancelLabel == 'function' ? o.btnCancelLabel.call(this, $e[0]) : o.btnCancelLabel);
|
||||
return this.$element.data('btnCancelLabel') ||
|
||||
(typeof this.options.btnCancelLabel == 'function' ? this.options.btnCancelLabel.call(this, this.$element) : this.options.btnCancelLabel);
|
||||
}
|
||||
|
||||
Confirmation.prototype.getBtnCancelIcon = function () {
|
||||
var $e = this.$element;
|
||||
var o = this.options;
|
||||
return this.$element.data('btnCancelIcon') ||
|
||||
(typeof this.options.btnCancelIcon == 'function' ? this.options.btnCancelIcon.call(this, this.$element) : this.options.btnCancelIcon);
|
||||
}
|
||||
|
||||
return $e.attr('data-btnCancelIcon') || (typeof o.btnCancelIcon == 'function' ? o.btnCancelIcon.call(this, $e[0]) : o.btnCancelIcon);
|
||||
Confirmation.prototype.getTitle = function () {
|
||||
return this.$element.data('confirmation-title') ||
|
||||
this.$element.data('title') ||
|
||||
this.$element.attr('title') ||
|
||||
(typeof this.options.title == 'function' ? this.options.title.call(this, this.$element) : this.options.title);
|
||||
}
|
||||
|
||||
Confirmation.prototype.getHref = function () {
|
||||
var $e = this.$element;
|
||||
var o = this.options;
|
||||
|
||||
return $e.attr('data-href') || (typeof o.href == 'function' ? o.href.call(this, $e[0]) : o.href);
|
||||
return this.$element.data('href') ||
|
||||
this.$element.attr('href') ||
|
||||
(typeof this.options.href == 'function' ? this.options.href.call(this, this.$element) : this.options.href);
|
||||
}
|
||||
|
||||
Confirmation.prototype.getTarget = function () {
|
||||
var $e = this.$element;
|
||||
var o = this.options;
|
||||
|
||||
return $e.attr('data-target') || (typeof o.target == 'function' ? o.target.call(this, $e[0]) : o.target);
|
||||
return this.$element.data('target') ||
|
||||
this.$element.attr('target') ||
|
||||
(typeof this.options.target == 'function' ? this.options.target.call(this, this.$element) : this.options.target);
|
||||
}
|
||||
|
||||
Confirmation.prototype.isPopout = function () {
|
||||
var popout;
|
||||
var $e = this.$element;
|
||||
var o = this.options;
|
||||
var popout = this.$element.data('popout') ||
|
||||
(typeof this.options.popout == 'function' ? this.options.popout.call(this, this.$element) : this.options.popout);
|
||||
|
||||
popout = $e.attr('data-popout') || (typeof o.popout == 'function' ? o.popout.call(this, $e[0]) : o.popout);
|
||||
|
||||
if(popout == 'false') popout = false;
|
||||
if (popout == 'false') popout = false;
|
||||
|
||||
return popout
|
||||
}
|
||||
|
||||
Confirmation.prototype.runCallback = function (callback, event, element) {
|
||||
if (typeof callback == 'function') {
|
||||
callback.call(this, event, element);
|
||||
} else if (typeof callback == 'string') {
|
||||
eval(callback);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// CONFIRMATION PLUGIN DEFINITION
|
||||
// =========================
|
||||
|
||||
16
package.json
16
package.json
@@ -9,12 +9,11 @@
|
||||
"dependencies": {
|
||||
},
|
||||
"devDependencies": {
|
||||
"gulp": "gulpjs/gulp#4.0",
|
||||
"gulp-util": "3.0.x",
|
||||
"gulp-requirejs-optimize": "1.2.x",
|
||||
"gulp-filter": "5.0.x",
|
||||
"gulp": "next",
|
||||
"gulp-requirejs-optimize": "1.3.x",
|
||||
"gulp-filter": "5.1.x",
|
||||
"gulp-if": "2.0.x",
|
||||
"gulp-jshint": "2.0.x",
|
||||
"gulp-jshint": "2.1.x",
|
||||
"gulp-sourcemaps": "2.6.x",
|
||||
"gulp-gzip": "1.x.x",
|
||||
"gulp-brotli": "1.2.x",
|
||||
@@ -24,6 +23,7 @@
|
||||
"gulp-clean-css": "3.x.x",
|
||||
"gulp-bytediff": "1.0.x",
|
||||
"gulp-debug": "^3.1.x",
|
||||
"node-notifier": "5.2.x",
|
||||
"uglify-es": "^3.0.x",
|
||||
"jshint": "^2.9.x",
|
||||
"jshint-stylish": "^2.x.x",
|
||||
@@ -32,8 +32,10 @@
|
||||
"promised-del": "1.0.x",
|
||||
"flat": "2.0.x",
|
||||
"lodash.padend": "4.6.x",
|
||||
"slash": "1.0.x",
|
||||
"file-extension": "3.1.x"
|
||||
"slash": "2.x.x",
|
||||
"file-extension": "3.1.x",
|
||||
"fancy-log": "1.3.x",
|
||||
"ansi-colors": "1.x.x"
|
||||
},
|
||||
"scripts": {
|
||||
"gulp": "gulp"
|
||||
|
||||
File diff suppressed because one or more lines are too long
Binary file not shown.
51
public/css/v1.3.4/pathfinder.css
Normal file
51
public/css/v1.3.4/pathfinder.css
Normal file
File diff suppressed because one or more lines are too long
BIN
public/css/v1.3.4/pathfinder.css.br
Normal file
BIN
public/css/v1.3.4/pathfinder.css.br
Normal file
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
BIN
public/js/v1.3.4/app.js.br
Normal file
BIN
public/js/v1.3.4/app.js.br
Normal file
Binary file not shown.
2
public/js/v1.3.4/app/admin.js
Normal file
2
public/js/v1.3.4/app/admin.js
Normal file
File diff suppressed because one or more lines are too long
BIN
public/js/v1.3.4/app/admin.js.br
Normal file
BIN
public/js/v1.3.4/app/admin.js.br
Normal file
Binary file not shown.
1
public/js/v1.3.4/app/admin.js.map
Normal file
1
public/js/v1.3.4/app/admin.js.map
Normal file
File diff suppressed because one or more lines are too long
2
public/js/v1.3.4/app/datatables.loader.js
Normal file
2
public/js/v1.3.4/app/datatables.loader.js
Normal file
File diff suppressed because one or more lines are too long
BIN
public/js/v1.3.4/app/datatables.loader.js.br
Normal file
BIN
public/js/v1.3.4/app/datatables.loader.js.br
Normal file
Binary file not shown.
1
public/js/v1.3.4/app/datatables.loader.js.map
Normal file
1
public/js/v1.3.4/app/datatables.loader.js.map
Normal file
File diff suppressed because one or more lines are too long
2
public/js/v1.3.4/app/login.js
Normal file
2
public/js/v1.3.4/app/login.js
Normal file
File diff suppressed because one or more lines are too long
BIN
public/js/v1.3.4/app/login.js.br
Normal file
BIN
public/js/v1.3.4/app/login.js.br
Normal file
Binary file not shown.
1
public/js/v1.3.4/app/login.js.map
Normal file
1
public/js/v1.3.4/app/login.js.map
Normal file
File diff suppressed because one or more lines are too long
2
public/js/v1.3.4/app/mappage.js
Normal file
2
public/js/v1.3.4/app/mappage.js
Normal file
File diff suppressed because one or more lines are too long
BIN
public/js/v1.3.4/app/mappage.js.br
Normal file
BIN
public/js/v1.3.4/app/mappage.js.br
Normal file
Binary file not shown.
1
public/js/v1.3.4/app/mappage.js.map
Normal file
1
public/js/v1.3.4/app/mappage.js.map
Normal file
File diff suppressed because one or more lines are too long
2
public/js/v1.3.4/app/notification.js
Normal file
2
public/js/v1.3.4/app/notification.js
Normal file
File diff suppressed because one or more lines are too long
BIN
public/js/v1.3.4/app/notification.js.br
Normal file
BIN
public/js/v1.3.4/app/notification.js.br
Normal file
Binary file not shown.
1
public/js/v1.3.4/app/notification.js.map
Normal file
1
public/js/v1.3.4/app/notification.js.map
Normal file
File diff suppressed because one or more lines are too long
2
public/js/v1.3.4/app/setup.js
Normal file
2
public/js/v1.3.4/app/setup.js
Normal file
File diff suppressed because one or more lines are too long
BIN
public/js/v1.3.4/app/setup.js.br
Normal file
BIN
public/js/v1.3.4/app/setup.js.br
Normal file
Binary file not shown.
1
public/js/v1.3.4/app/setup.js.map
Normal file
1
public/js/v1.3.4/app/setup.js.map
Normal file
File diff suppressed because one or more lines are too long
BIN
public/js/v1.3.4/app/worker/map.js.br
Normal file
BIN
public/js/v1.3.4/app/worker/map.js.br
Normal file
Binary file not shown.
1
public/js/v1.3.4/app/worker/message.js.br
Normal file
1
public/js/v1.3.4/app/worker/message.js.br
Normal file
@@ -0,0 +1 @@
|
||||
9<01>Ĵ9<C4B4>F<EFBFBD>0~y<><18>|uK<75>v0<76>Iw<49><77>.<2E>x<14><><EFBFBD><EFBFBD>(O<><4F><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><12><>zʘL0<4C><05><><EFBFBD><EFBFBD>ů<EFBFBD>r<16>_D<5F>? <1<><31>P(<28>LFj<46><1C><><EFBFBD>H<EFBFBD><48><EFBFBD><EFBFBD><EFBFBD>26hL<68>3<EFBFBD><33>-<0C>0+<2B> ;<3B><0F>#<23>dMFj=<3D><><EFBFBD><EFBFBD><EFBFBD>`+s$<24>P=.a<>veS<65>r<EFBFBD>z<EFBFBD><7A><EFBFBD>>
|
||||
BIN
public/js/v1.3.4/lib/bootstrap-image-gallery.js.br
Normal file
BIN
public/js/v1.3.4/lib/bootstrap-image-gallery.js.br
Normal file
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user