@@ -62,11 +62,18 @@ class GitHub extends Controller\Controller {
|
||||
$md = \Markdown::instance();
|
||||
foreach($releasesData as &$releaseData){
|
||||
if(isset($releaseData->body)){
|
||||
$body = $releaseData->body;
|
||||
|
||||
// remove "update information" from release text
|
||||
// -> keep everything until first "***" -> horizontal line
|
||||
if( ($pos = strpos($body, '***')) !== false){
|
||||
$body = substr($body, 0, $pos);
|
||||
}
|
||||
|
||||
// convert list style
|
||||
$body = str_replace(' - ', '* ', $releaseData->body );
|
||||
$body = str_replace(' - ', '* ', $body );
|
||||
|
||||
$releaseData->body = $md->convert( $body );
|
||||
$releaseData->body = $md->convert( trim($body) );
|
||||
}
|
||||
}
|
||||
$f3->set($cacheKey, $releasesData, $ttl);
|
||||
|
||||
@@ -779,7 +779,8 @@ class Map extends Controller\AccessController {
|
||||
$systemPosX = 0;
|
||||
$systemPosY = 30;
|
||||
|
||||
$sourceSystemId = (int)$this->getF3()->get(User::SESSION_KEY_CHARACTER_PREV_SYSTEM_ID);
|
||||
$sessionCharacter = $this->getSessionCharacterData();
|
||||
$sourceSystemId = (int)$sessionCharacter['PREV_SYSTEM_ID'];
|
||||
$targetSystemId = (int)$log->systemId;
|
||||
|
||||
if($sourceSystemId){
|
||||
|
||||
@@ -119,6 +119,7 @@ class Route extends \Controller\AccessController {
|
||||
$whereQuery = "";
|
||||
$includeScopes = [];
|
||||
$includeTypes = [];
|
||||
$includeEOL = true;
|
||||
|
||||
if( $filterData['stargates'] === true){
|
||||
// include "stargates" for search
|
||||
@@ -146,6 +147,10 @@ class Route extends \Controller\AccessController {
|
||||
if( $filterData['wormholesCritical'] === true ){
|
||||
$includeTypes[] = 'wh_critical';
|
||||
}
|
||||
|
||||
if( $filterData['wormholesEOL'] === false ){
|
||||
$includeEOL = false;
|
||||
}
|
||||
}
|
||||
|
||||
// search connections -------------------------------------------------------
|
||||
@@ -157,6 +162,9 @@ class Route extends \Controller\AccessController {
|
||||
$whereQuery .= " `connection`.`type` REGEXP '" . implode("|", $includeTypes) . "' AND ";
|
||||
}
|
||||
|
||||
if(!$includeEOL){
|
||||
$whereQuery .= " `connection`.`eolUpdated` IS NULL AND ";
|
||||
}
|
||||
|
||||
$query = "SELECT
|
||||
`system_src`.`regionId` regionId,
|
||||
@@ -521,7 +529,8 @@ class Route extends \Controller\AccessController {
|
||||
'jumpbridges' => (bool) $routeData['jumpbridges'],
|
||||
'wormholes' => (bool) $routeData['wormholes'],
|
||||
'wormholesReduced' => (bool) $routeData['wormholesReduced'],
|
||||
'wormholesCritical' => (bool) $routeData['wormholesCritical']
|
||||
'wormholesCritical' => (bool) $routeData['wormholesCritical'],
|
||||
'wormholesEOL' => (bool) $routeData['wormholesEOL']
|
||||
];
|
||||
|
||||
$returnRoutData = [
|
||||
|
||||
@@ -49,9 +49,9 @@ class System extends \Controller\AccessController {
|
||||
FROM
|
||||
mapSolarSystems map_sys INNER JOIN
|
||||
mapConstellations map_con ON
|
||||
map_con.constellationID = map_sys.constellationID INNER JOIN
|
||||
map_sys.constellationID = map_con.constellationID INNER JOIN
|
||||
mapRegions map_reg ON
|
||||
map_reg.regionID = map_sys.regionID";
|
||||
map_con.regionID = map_reg.regionID";
|
||||
|
||||
private $whereQuery = "";
|
||||
|
||||
|
||||
@@ -25,18 +25,14 @@ class User extends Controller\Controller{
|
||||
const SESSION_KEY_USER_NAME = 'SESSION.USER.NAME';
|
||||
|
||||
// character specific session keys
|
||||
const SESSION_KEY_CHARACTER = 'SESSION.CHARACTER';
|
||||
const SESSION_KEY_CHARACTER_ID = 'SESSION.CHARACTER.ID';
|
||||
const SESSION_KEY_CHARACTER_NAME = 'SESSION.CHARACTER.NAME';
|
||||
const SESSION_KEY_CHARACTER_TIME = 'SESSION.CHARACTER.TIME';
|
||||
const SESSION_KEY_CHARACTER_PREV_SYSTEM_ID = 'SESSION.CHARACTER.PREV_SYSTEM_ID';
|
||||
const SESSION_KEY_CHARACTERS = 'SESSION.CHARACTERS';
|
||||
|
||||
const SESSION_KEY_CHARACTER_ACCESS_TOKEN = 'SESSION.CHARACTER.ACCESS_TOKEN';
|
||||
const SESSION_KEY_CHARACTER_REFRESH_TOKEN = 'SESSION.CHARACTER.REFRESH_TOKEN';
|
||||
// temp login character ID (during HTTP redirects on login)
|
||||
const SESSION_KEY_TEMP_CHARACTER_ID = 'SESSION.TEMP_CHARACTER_ID';
|
||||
|
||||
// log text
|
||||
const LOG_LOGGED_IN = 'userId: [%10s], userName: [%30s], charId: [%20s], charName: %s';
|
||||
const LOG_DELETE_ACCOUNT = 'userId: [%10s], userName: [%30s], ip: [%45s]';
|
||||
const LOG_DELETE_ACCOUNT = 'userId: [%10s], userName: [%30s]';
|
||||
|
||||
|
||||
/**
|
||||
@@ -54,24 +50,40 @@ class User extends Controller\Controller{
|
||||
$login = false;
|
||||
|
||||
if($user = $characterModel->getUser()){
|
||||
// set user/character data to session -------------------
|
||||
$this->f3->set(self::SESSION_KEY_USER, [
|
||||
'ID' => $user->_id,
|
||||
'NAME' => $user->name
|
||||
]);
|
||||
// check if character belongs to current user
|
||||
// -> If there is already a logged in user! (e.g. multi character use)
|
||||
$currentUser = $this->getUser();
|
||||
|
||||
$dateTime = new \DateTime();
|
||||
$this->f3->set(self::SESSION_KEY_CHARACTER, [
|
||||
'ID' => $characterModel->_id,
|
||||
'NAME' => $characterModel->name,
|
||||
'TIME' => $dateTime->getTimestamp()
|
||||
]);
|
||||
$sessionCharacters = [
|
||||
[
|
||||
'ID' => $characterModel->_id,
|
||||
'NAME' => $characterModel->name,
|
||||
'TIME' => (new \DateTime())->getTimestamp()
|
||||
]
|
||||
];
|
||||
|
||||
// save user login information ---------------------------
|
||||
if(
|
||||
is_null($currentUser) ||
|
||||
$currentUser->_id !== $user->_id
|
||||
){
|
||||
// user has changed OR new user ---------------------------------------------------
|
||||
//-> set user/character data to session
|
||||
$this->f3->set(self::SESSION_KEY_USER, [
|
||||
'ID' => $user->_id,
|
||||
'NAME' => $user->name
|
||||
]);
|
||||
}else{
|
||||
// user has NOT changed -----------------------------------------------------------
|
||||
$sessionCharacters = $characterModel::mergeSessionCharacterData($sessionCharacters);
|
||||
}
|
||||
|
||||
$this->f3->set(self::SESSION_KEY_CHARACTERS, $sessionCharacters);
|
||||
|
||||
// save user login information --------------------------------------------------------
|
||||
$characterModel->touch('lastLogin');
|
||||
$characterModel->save();
|
||||
|
||||
// write login log --------------------------------------
|
||||
// write login log --------------------------------------------------------------------
|
||||
self::getLogger('LOGIN')->write(
|
||||
sprintf(self::LOG_LOGGED_IN,
|
||||
$user->_id,
|
||||
@@ -210,7 +222,7 @@ class User extends Controller\Controller{
|
||||
if($activeCharacter = $this->getCharacter(0)){
|
||||
$user = $activeCharacter->getUser();
|
||||
|
||||
// captcha is send -> check captcha ---------------------------------
|
||||
// captcha is send -> check captcha -------------------------------------------
|
||||
if(
|
||||
isset($formData['captcha']) &&
|
||||
!empty($formData['captcha'])
|
||||
@@ -250,7 +262,7 @@ class User extends Controller\Controller{
|
||||
}
|
||||
}
|
||||
|
||||
// sharing config ---------------------------------------------------
|
||||
// sharing config -------------------------------------------------------------
|
||||
if(isset($formData['share'])){
|
||||
$privateSharing = 0;
|
||||
$corporationSharing = 0;
|
||||
@@ -343,7 +355,7 @@ class User extends Controller\Controller{
|
||||
if($status){
|
||||
// save log
|
||||
self::getLogger('DELETE_ACCOUNT')->write(
|
||||
sprintf(self::LOG_DELETE_ACCOUNT, $user->id, $user->name, $f3->get('IP'))
|
||||
sprintf(self::LOG_DELETE_ACCOUNT, $user->id, $user->name)
|
||||
);
|
||||
|
||||
// remove user
|
||||
|
||||
@@ -36,9 +36,6 @@ class Sso extends Api\User{
|
||||
const SESSION_KEY_SSO_STATE = 'SESSION.SSO.STATE';
|
||||
const SESSION_KEY_SSO_FROM_MAP = 'SESSION.SSO.FROM_MAP';
|
||||
|
||||
// cache keys
|
||||
const CACHE_KEY_LOCATION_DATA = 'CACHED.LOCATION.%s';
|
||||
|
||||
// error messages
|
||||
const ERROR_CCP_SSO_URL = 'Invalid "ENVIRONMENT.[ENVIRONMENT].SSO_CCP_URL" url. %s';
|
||||
const ERROR_CCP_CREST_URL = 'Invalid "ENVIRONMENT.[ENVIRONMENT].CCP_CREST_URL" url. %s';
|
||||
@@ -115,6 +112,10 @@ class Sso extends Api\User{
|
||||
if($loginCheck){
|
||||
// set "login" cookie
|
||||
$this->setLoginCookie($character);
|
||||
|
||||
// -> pass current character data to target page
|
||||
$f3->set(Api\User::SESSION_KEY_TEMP_CHARACTER_ID, $character->_id);
|
||||
|
||||
// route to "map"
|
||||
$f3->reroute('@map');
|
||||
}
|
||||
@@ -218,15 +219,18 @@ class Sso extends Api\User{
|
||||
// -> update character log (current location,...)
|
||||
$characterModel = $characterModel->updateLog();
|
||||
|
||||
// check if there is already an active user logged in
|
||||
if($activeCharacter = $this->getCharacter()){
|
||||
// connect character with current user
|
||||
$user = $activeCharacter->getUser();
|
||||
}elseif( is_null( $user = $characterModel->getUser()) ){
|
||||
// no user found (new character) -> create new user and connect to character
|
||||
$user = Model\BasicModel::getNew('UserModel');
|
||||
$user->name = $characterModel->name;
|
||||
$user->save();
|
||||
// connect character with current user
|
||||
if( is_null($user = $this->getUser()) ){
|
||||
// connect character with existing user (no changes)
|
||||
if( is_null( $user = $characterModel->getUser()) ){
|
||||
// no user found (new character) -> create new user and connect to character
|
||||
/**
|
||||
* @var $user Model\UserModel
|
||||
*/
|
||||
$user = Model\BasicModel::getNew('UserModel');
|
||||
$user->name = $characterModel->name;
|
||||
$user->save();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -251,6 +255,9 @@ class Sso extends Api\User{
|
||||
// set "login" cookie
|
||||
$this->setLoginCookie($characterModel);
|
||||
|
||||
// -> pass current character data to target page
|
||||
$f3->set(Api\User::SESSION_KEY_TEMP_CHARACTER_ID, $characterModel->_id);
|
||||
|
||||
// route to "map"
|
||||
$f3->reroute('@map');
|
||||
}else{
|
||||
@@ -308,6 +315,10 @@ class Sso extends Api\User{
|
||||
// login by character
|
||||
$loginCheck = $this->loginByCharacter($character);
|
||||
if($loginCheck){
|
||||
// set character id
|
||||
// -> pass current character data to target page
|
||||
$f3->set(Api\User::SESSION_KEY_TEMP_CHARACTER_ID, $character->_id);
|
||||
|
||||
// route to "map"
|
||||
$f3->reroute('@map');
|
||||
}
|
||||
@@ -617,49 +628,36 @@ class Sso extends Api\User{
|
||||
* get current character location data (result is cached!)
|
||||
* -> solarSystem data where character is currently active
|
||||
* @param $accessToken
|
||||
* @param int $ttl
|
||||
* @param array $additionalOptions
|
||||
* @return array|mixed
|
||||
* @return array
|
||||
*/
|
||||
public function getCharacterLocationData($accessToken, $ttl = 5, $additionalOptions = []){
|
||||
public function getCharacterLocationData($accessToken, $additionalOptions = []){
|
||||
// null == CREST call failed (e.g. timeout)
|
||||
$locationData = [
|
||||
'timeout' => false
|
||||
];
|
||||
|
||||
// in addition to the cURL caching (based on cache-control headers,
|
||||
// the final location data is cached additionally -> speed up
|
||||
$cacheKey = sprintf(self::CACHE_KEY_LOCATION_DATA, 'TOKEN_' . hash('md5', $accessToken));
|
||||
$endpoints = $this->getEndpoints($accessToken, $additionalOptions);
|
||||
|
||||
if( !$this->getF3()->exists($cacheKey) ){
|
||||
$endpoints = $this->getEndpoints($accessToken, $additionalOptions);
|
||||
$additionalOptions['accept'] = 'application/vnd.ccp.eve.CharacterLocation-v1+json';
|
||||
$endpoint = $this->walkEndpoint($endpoints, $accessToken, [
|
||||
'decode',
|
||||
'character',
|
||||
'location'
|
||||
], $additionalOptions);
|
||||
|
||||
$additionalOptions['accept'] = 'application/vnd.ccp.eve.CharacterLocation-v1+json';
|
||||
$endpoint = $this->walkEndpoint($endpoints, $accessToken, [
|
||||
'decode',
|
||||
'character',
|
||||
'location'
|
||||
], $additionalOptions);
|
||||
|
||||
if( !is_null($endpoint) ){
|
||||
// request succeeded (e.g. no timeout)
|
||||
|
||||
if(isset($endpoint['solarSystem'])){
|
||||
$locationData['system'] = (new Mapper\CrestSystem($endpoint['solarSystem']))->getData();
|
||||
}
|
||||
|
||||
if(isset($endpoint['station'])){
|
||||
$locationData['station'] = (new Mapper\CrestStation($endpoint['station']))->getData();
|
||||
}
|
||||
|
||||
$this->getF3()->set($cacheKey, $locationData, $ttl);
|
||||
}else{
|
||||
// timeout
|
||||
$locationData['timeout'] = true;
|
||||
if( !is_null($endpoint) ){
|
||||
// request succeeded (e.g. no timeout)
|
||||
if(isset($endpoint['solarSystem'])){
|
||||
$locationData['system'] = (new Mapper\CrestSystem($endpoint['solarSystem']))->getData();
|
||||
}
|
||||
|
||||
if(isset($endpoint['station'])){
|
||||
$locationData['station'] = (new Mapper\CrestStation($endpoint['station']))->getData();
|
||||
}
|
||||
}else{
|
||||
$locationData = $this->getF3()->get($cacheKey);
|
||||
// timeout
|
||||
$locationData['timeout'] = true;
|
||||
}
|
||||
|
||||
return $locationData;
|
||||
|
||||
@@ -19,8 +19,10 @@ class Controller {
|
||||
const COOKIE_NAME_STATE = 'cookie';
|
||||
const COOKIE_PREFIX_CHARACTER = 'char';
|
||||
|
||||
const LOG_UNAUTHORIZED = 'ip: [%45s], User-Agent: [%s]';
|
||||
const ERROR_SESSION_SUSPECT = 'Suspect id: [%45s], ip: [%45s], new ip: [%45s], User-Agent: %s ';
|
||||
// log text
|
||||
const LOG_UNAUTHORIZED = 'User-Agent: [%s]';
|
||||
const ERROR_SESSION_SUSPECT = 'Suspect id: [%45s], ip: [%45s], new ip: [%45s], User-Agent: [%s]';
|
||||
|
||||
/**
|
||||
* @var \Base
|
||||
*/
|
||||
@@ -282,7 +284,7 @@ class Controller {
|
||||
// make sure character data is up2date!
|
||||
// -> this is not the case if e.g. userCharacters was removed "ownerHash" changed...
|
||||
$character = $characterAuth->rel('characterId');
|
||||
$character->getById($characterAuth->characterId->_id);
|
||||
$character->getById( $characterAuth->get('characterId', true) );
|
||||
|
||||
// check if character still has user (is not the case of "ownerHash" changed
|
||||
// check if character is still authorized to log in (e.g. corp/ally or config has changed
|
||||
@@ -318,17 +320,57 @@ class Controller {
|
||||
}
|
||||
|
||||
/**
|
||||
* checks whether a user is currently logged in
|
||||
* get current character data from session
|
||||
* ->
|
||||
* @return array
|
||||
*/
|
||||
public function getSessionCharacterData(){
|
||||
$data = [];
|
||||
|
||||
if($user = $this->getUser()){
|
||||
$requestedCharacterId = 0;
|
||||
|
||||
// get all characterData from currently active characters
|
||||
if($this->getF3()->get('AJAX')){
|
||||
// Ajax request -> get characterId from Header (if already available!)
|
||||
$header = $this->getRequestHeaders();
|
||||
$requestedCharacterId = (int)$header['Pf-Character'];
|
||||
|
||||
if(
|
||||
$requestedCharacterId > 0 &&
|
||||
(int)$this->getF3()->get(Api\User::SESSION_KEY_TEMP_CHARACTER_ID) === $requestedCharacterId
|
||||
){
|
||||
// requested characterId is "now" available on the client (Javascript)
|
||||
// -> clear temp characterId for next character login/switch
|
||||
$this->getF3()->clear(Api\User::SESSION_KEY_TEMP_CHARACTER_ID);
|
||||
}
|
||||
}
|
||||
|
||||
if($requestedCharacterId <= 0){
|
||||
// Ajax BUT characterID not yet set as HTTP header
|
||||
// OR non Ajax -> get characterId from temp session (e.g. from HTTP redirect)
|
||||
$requestedCharacterId = (int)$this->getF3()->get(Api\User::SESSION_KEY_TEMP_CHARACTER_ID);
|
||||
}
|
||||
|
||||
$data = $user->getSessionCharacterData($requestedCharacterId);
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* checks whether a user/character is currently logged in
|
||||
* @param \Base $f3
|
||||
* @return bool
|
||||
*/
|
||||
protected function checkLogTimer($f3){
|
||||
$loginCheck = false;
|
||||
$characterData = $this->getSessionCharacterData();
|
||||
|
||||
if($f3->get(Api\User::SESSION_KEY_CHARACTER_TIME) > 0){
|
||||
if( !empty($characterData) ){
|
||||
// check logIn time
|
||||
$logInTime = new \DateTime();
|
||||
$logInTime->setTimestamp( $f3->get(Api\User::SESSION_KEY_CHARACTER_TIME) );
|
||||
$logInTime->setTimestamp( (int)$characterData['TIME'] );
|
||||
$now = new \DateTime();
|
||||
|
||||
$timeDiff = $now->diff($logInTime);
|
||||
@@ -346,35 +388,66 @@ class Controller {
|
||||
}
|
||||
|
||||
/**
|
||||
* get current character model
|
||||
* get current character
|
||||
* @param int $ttl
|
||||
* @return Model\CharacterModel|null
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function getCharacter($ttl = 0){
|
||||
$character = null;
|
||||
$characterData = $this->getSessionCharacterData();
|
||||
|
||||
if( $this->getF3()->exists(Api\User::SESSION_KEY_CHARACTER_ID) ){
|
||||
$characterId = (int)$this->getF3()->get(Api\User::SESSION_KEY_CHARACTER_ID);
|
||||
if($characterId){
|
||||
/**
|
||||
* @var $characterModel Model\CharacterModel
|
||||
*/
|
||||
$characterModel = Model\BasicModel::getNew('CharacterModel');
|
||||
$characterModel->getById($characterId, $ttl);
|
||||
if( !empty($characterData) ){
|
||||
/**
|
||||
* @var $characterModel Model\CharacterModel
|
||||
*/
|
||||
$characterModel = Model\BasicModel::getNew('CharacterModel');
|
||||
$characterModel->getById( (int)$characterData['ID'], $ttl);
|
||||
|
||||
if(
|
||||
!$characterModel->dry() &&
|
||||
$characterModel->hasUserCharacter()
|
||||
){
|
||||
$character = &$characterModel;
|
||||
}
|
||||
if(
|
||||
!$characterModel->dry() &&
|
||||
$characterModel->hasUserCharacter()
|
||||
){
|
||||
$character = &$characterModel;
|
||||
}
|
||||
}
|
||||
|
||||
return $character;
|
||||
}
|
||||
|
||||
/**
|
||||
* get current user
|
||||
* @param int $ttl
|
||||
* @return Model\UserModel|null
|
||||
*/
|
||||
public function getUser($ttl = 0){
|
||||
$user = null;
|
||||
|
||||
if( $this->getF3()->exists(Api\User::SESSION_KEY_USER_ID) ){
|
||||
$userId = (int)$this->getF3()->get(Api\User::SESSION_KEY_USER_ID);
|
||||
if($userId){
|
||||
/**
|
||||
* @var $userModel Model\UserModel
|
||||
*/
|
||||
$userModel = Model\BasicModel::getNew('UserModel');
|
||||
$userModel->getById($userId, $ttl);
|
||||
|
||||
if(
|
||||
!$userModel->dry() &&
|
||||
$userModel->hasUserCharacters()
|
||||
){
|
||||
$user = &$userModel;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $user;
|
||||
}
|
||||
|
||||
public function getCharacterSessionData(){
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* log out current character
|
||||
* @param \Base $f3
|
||||
@@ -384,7 +457,7 @@ class Controller {
|
||||
|
||||
// ----------------------------------------------------------
|
||||
// delete server side cookie validation data
|
||||
// for the current character as well
|
||||
// for the active character
|
||||
if(
|
||||
$params['clearCookies'] === '1' &&
|
||||
( $activeCharacter = $this->getCharacter())
|
||||
@@ -549,7 +622,6 @@ class Controller {
|
||||
case 403: // Unauthorized
|
||||
self::getLogger('UNAUTHORIZED')->write(sprintf(
|
||||
self::LOG_UNAUTHORIZED,
|
||||
$f3->get('IP'),
|
||||
$f3->get('AGENT')
|
||||
));
|
||||
$halt = true;
|
||||
|
||||
@@ -8,8 +8,8 @@
|
||||
|
||||
namespace Model;
|
||||
|
||||
use Controller\Api\User;
|
||||
use Controller\Controller;
|
||||
use Controller\Api\User as User;
|
||||
use Controller\Controller as Controller;
|
||||
use DB\SQL\Schema;
|
||||
|
||||
class CharacterLogModel extends BasicModel {
|
||||
@@ -192,6 +192,10 @@ class CharacterLogModel extends BasicModel {
|
||||
return $logData;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $systemId
|
||||
* @return int
|
||||
*/
|
||||
public function set_systemId($systemId){
|
||||
if($systemId > 0){
|
||||
$this->updateCharacterSessionLocation($systemId);
|
||||
@@ -205,20 +209,21 @@ class CharacterLogModel extends BasicModel {
|
||||
*/
|
||||
protected function updateCharacterSessionLocation($systemId){
|
||||
$controller = new Controller();
|
||||
$f3 = $this->getF3();
|
||||
$systemId = (int)$systemId;
|
||||
|
||||
if(
|
||||
( $activeCharacter = $controller->getCharacter() ) &&
|
||||
( $activeCharacter->_id === $this->characterId->_id )
|
||||
!empty($sessionCharacter = $controller->getSessionCharacterData()) &&
|
||||
$sessionCharacter['ID'] === $this->get('characterId', true)
|
||||
){
|
||||
$prevSystemId = (int)$f3->get( User::SESSION_KEY_CHARACTER_PREV_SYSTEM_ID);
|
||||
$prevSystemId = (int)$sessionCharacter['PREV_SYSTEM_ID'];
|
||||
|
||||
if($prevSystemId === 0){
|
||||
$f3->set( User::SESSION_KEY_CHARACTER_PREV_SYSTEM_ID, $systemId);
|
||||
$sessionCharacter['PREV_SYSTEM_ID'] = (int)$systemId;
|
||||
}else{
|
||||
$f3->set( User::SESSION_KEY_CHARACTER_PREV_SYSTEM_ID, (int)$this->systemId);
|
||||
$sessionCharacter['PREV_SYSTEM_ID'] = $this->systemId;
|
||||
}
|
||||
|
||||
$sessionCharacters = CharacterModel::mergeSessionCharacterData([$sessionCharacter]);
|
||||
$this->getF3()->set(User::SESSION_KEY_CHARACTERS, $sessionCharacters);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,10 +8,9 @@
|
||||
|
||||
namespace Model;
|
||||
|
||||
use Controller;
|
||||
use Controller\Ccp\Sso as Sso;
|
||||
use Controller\Api\User as User;
|
||||
use DB\SQL\Schema;
|
||||
use Data\Mapper as Mapper;
|
||||
|
||||
class CharacterModel extends BasicModel {
|
||||
|
||||
@@ -316,7 +315,7 @@ class CharacterModel extends BasicModel {
|
||||
if(
|
||||
!empty($whitelistCorporations) &&
|
||||
$this->hasCorporation() &&
|
||||
in_array($this->getCorporation()->_id, $whitelistCorporations)
|
||||
in_array($this->get('corporationId', true), $whitelistCorporations)
|
||||
){
|
||||
$isAuthorized = true;
|
||||
}
|
||||
@@ -326,7 +325,7 @@ class CharacterModel extends BasicModel {
|
||||
!$isAuthorized &&
|
||||
!empty($whitelistAlliance) &&
|
||||
$this->hasAlliance() &&
|
||||
in_array($this->getAlliance()->_id, $whitelistAlliance)
|
||||
in_array($this->get('allianceId', true), $whitelistAlliance)
|
||||
){
|
||||
$isAuthorized = true;
|
||||
}
|
||||
@@ -344,7 +343,7 @@ class CharacterModel extends BasicModel {
|
||||
public function updateLog($additionalOptions = []){
|
||||
// Try to pull data from CREST
|
||||
$ssoController = new Sso();
|
||||
$logData = $ssoController->getCharacterLocationData($this->getAccessToken(), 5, $additionalOptions);
|
||||
$logData = $ssoController->getCharacterLocationData($this->getAccessToken(), $additionalOptions);
|
||||
|
||||
if($logData['timeout'] === false){
|
||||
if( empty($logData['system']) ){
|
||||
@@ -496,7 +495,7 @@ class CharacterModel extends BasicModel {
|
||||
$maps = array_merge($maps, $corporation->getMaps());
|
||||
}
|
||||
|
||||
if($this->characterMaps){
|
||||
if( is_object($this->characterMaps) ){
|
||||
$mapCountPrivate = 0;
|
||||
foreach($this->characterMaps as $characterMap){
|
||||
if(
|
||||
@@ -517,7 +516,7 @@ class CharacterModel extends BasicModel {
|
||||
* -> clear authentication data
|
||||
*/
|
||||
public function logout(){
|
||||
if($this->characterAuthentications){
|
||||
if( is_object($this->characterAuthentications) ){
|
||||
foreach($this->characterAuthentications as $characterAuthentication){
|
||||
/**
|
||||
* @var $characterAuthentication CharacterAuthenticationModel
|
||||
@@ -527,4 +526,29 @@ class CharacterModel extends BasicModel {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* merges two multidimensional characterSession arrays by checking characterID
|
||||
* @param array $characterDataBase
|
||||
* @return array
|
||||
*/
|
||||
static function mergeSessionCharacterData(array $characterDataBase = []){
|
||||
$addData = [];
|
||||
// get current session characters to be merged with
|
||||
$characterData = (array)self::getF3()->get(User::SESSION_KEY_CHARACTERS);
|
||||
|
||||
foreach($characterDataBase as $i => $baseData){
|
||||
foreach($characterData as $data){
|
||||
if((int)$baseData['ID'] === (int)$data['ID']){
|
||||
// overwrite static data -> should NEVER change on merge!
|
||||
$characterDataBase[$i]['NAME'] = $data['NAME'];
|
||||
$characterDataBase[$i]['TIME'] = $data['TIME'];
|
||||
}else{
|
||||
$addData[] = $data;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return array_merge($characterDataBase, $addData);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -180,8 +180,8 @@ class ConnectionModel extends BasicModel{
|
||||
if(
|
||||
is_object($this->source) &&
|
||||
is_object($this->target) &&
|
||||
$this->source->_id === $this->target->_id ||
|
||||
$this->source->mapId->_id !== $this->target->mapId->_id
|
||||
$this->get('source', true) === $this->get('target', true) ||
|
||||
$this->source->get('mapId', true) !== $this->target->get('mapId', true)
|
||||
){
|
||||
$isValid = false;
|
||||
}
|
||||
|
||||
@@ -288,7 +288,7 @@ class MapModel extends BasicModel {
|
||||
|
||||
/**
|
||||
* get either all system models in this map
|
||||
* @return array|mixed
|
||||
* @return SystemModel[]
|
||||
*/
|
||||
public function getSystems(){
|
||||
$systems = [];
|
||||
@@ -310,10 +310,9 @@ class MapModel extends BasicModel {
|
||||
* @return \stdClass[]
|
||||
*/
|
||||
public function getSystemData(){
|
||||
|
||||
$systemData = [];
|
||||
$systems = $this->getSystems();
|
||||
|
||||
$systemData = [];
|
||||
foreach($systems as $system){
|
||||
/**
|
||||
* @var $system SystemModel
|
||||
@@ -326,15 +325,16 @@ class MapModel extends BasicModel {
|
||||
|
||||
/**
|
||||
* get all connections in this map
|
||||
* @return array
|
||||
* @return ConnectionModel[]
|
||||
*/
|
||||
public function getConnections(){
|
||||
$connections = [];
|
||||
|
||||
$this->filter('connections', [
|
||||
'active = :active AND source > 0 AND target > 0',
|
||||
':active' => 1
|
||||
]);
|
||||
|
||||
$connections = [];
|
||||
if($this->connections){
|
||||
$connections = $this->connections;
|
||||
}
|
||||
@@ -347,9 +347,9 @@ class MapModel extends BasicModel {
|
||||
* @return \stdClass[]
|
||||
*/
|
||||
public function getConnectionData(){
|
||||
$connectionData = [];
|
||||
$connections = $this->getConnections();
|
||||
|
||||
$connectionData = [];
|
||||
foreach($connections as $connection){
|
||||
/**
|
||||
* @var $connection ConnectionModel
|
||||
@@ -427,7 +427,6 @@ class MapModel extends BasicModel {
|
||||
* @param array $clearKeys
|
||||
*/
|
||||
public function clearAccess($clearKeys = ['character', 'corporation', 'alliance']){
|
||||
|
||||
foreach($clearKeys as $key){
|
||||
switch($key){
|
||||
case 'character':
|
||||
@@ -692,8 +691,8 @@ class MapModel extends BasicModel {
|
||||
public function searchConnection(SystemModel $sourceSystem, SystemModel $targetSystem){
|
||||
// check if both systems belong to this map
|
||||
if(
|
||||
$sourceSystem->mapId->id === $this->id &&
|
||||
$targetSystem->mapId->id === $this->id
|
||||
$sourceSystem->get('mapId', true) === $this->id &&
|
||||
$targetSystem->get('mapId', true) === $this->id
|
||||
){
|
||||
$this->filter('connections', [
|
||||
'active = :active AND
|
||||
|
||||
@@ -221,7 +221,7 @@ class SystemModel extends BasicModel {
|
||||
|
||||
$systemData = (object) [];
|
||||
$systemData->id = $this->id;
|
||||
$systemData->mapId = is_object($this->mapId) ? $this->mapId->id : 0;
|
||||
$systemData->mapId = is_object($this->mapId) ? $this->get('mapId', true) : 0;
|
||||
$systemData->systemId = $this->systemId;
|
||||
$systemData->name = $this->name;
|
||||
$systemData->alias = $this->alias;
|
||||
@@ -284,7 +284,6 @@ class SystemModel extends BasicModel {
|
||||
* @return float
|
||||
*/
|
||||
public function set_trueSec($trueSec){
|
||||
|
||||
if(
|
||||
$trueSec > 0 &&
|
||||
$trueSec < 0.1
|
||||
@@ -452,9 +451,9 @@ class SystemModel extends BasicModel {
|
||||
* @return SystemSignatureModel[]
|
||||
*/
|
||||
public function getSignatures(){
|
||||
$signatures = [];
|
||||
$this->filter('signatures', ['active = ?', 1], ['order' => 'name']);
|
||||
|
||||
$signatures = [];
|
||||
if($this->signatures){
|
||||
$signatures = $this->signatures;
|
||||
}
|
||||
@@ -467,9 +466,9 @@ class SystemModel extends BasicModel {
|
||||
* @return \stdClass[]
|
||||
*/
|
||||
public function getSignaturesData(){
|
||||
$signaturesData = [];
|
||||
$signatures = $this->getSignatures();
|
||||
|
||||
$signaturesData = [];
|
||||
foreach($signatures as $signature){
|
||||
$signaturesData[] = $signature->getData();
|
||||
}
|
||||
|
||||
@@ -91,9 +91,7 @@ class SystemSignatureModel extends BasicModel {
|
||||
* @param $signatureData
|
||||
*/
|
||||
public function setData($signatureData){
|
||||
|
||||
foreach((array)$signatureData as $key => $value){
|
||||
|
||||
if(!is_array($value)){
|
||||
if($this->exists($key)){
|
||||
$this->$key = $value;
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace Model;
|
||||
|
||||
use DB\SQL\Schema;
|
||||
use Controller;
|
||||
use Controller\Api;
|
||||
use Controller\Api\User as User;
|
||||
use Exception;
|
||||
|
||||
class UserModel extends BasicModel {
|
||||
@@ -133,6 +133,15 @@ class UserModel extends BasicModel {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* check whether this character has already a user assigned to it
|
||||
* @return bool
|
||||
*/
|
||||
public function hasUserCharacters(){
|
||||
$this->filter('userCharacters', ['active = ?', 1]);
|
||||
return is_object($this->userCharacters);
|
||||
}
|
||||
|
||||
/**
|
||||
* search for user by unique username
|
||||
* @param $name
|
||||
@@ -142,6 +151,61 @@ class UserModel extends BasicModel {
|
||||
return $this->getByForeignKey('name', $name, [], 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* get current character data from session
|
||||
* -> if §characterID == 0 -> get first character data (random)
|
||||
* @param int $characterId
|
||||
* @param bool $objectCheck
|
||||
* @return array
|
||||
*/
|
||||
public function getSessionCharacterData($characterId = 0, $objectCheck = true){
|
||||
$data = [];
|
||||
$characterId = (int)$characterId;
|
||||
$currentSessionUser = (array)$this->getF3()->get(User::SESSION_KEY_USER);
|
||||
|
||||
if($this->_id === $currentSessionUser['ID']){
|
||||
// user matches session data
|
||||
$sessionCharacters = (array)$this->getF3()->get(User::SESSION_KEY_CHARACTERS);
|
||||
|
||||
if($characterId > 0){
|
||||
// search for specific characterData
|
||||
foreach($sessionCharacters as $characterData){
|
||||
if($characterId === (int)$characterData['ID']){
|
||||
$data = $characterData;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}elseif( !empty($sessionCharacters) ){
|
||||
// no character was requested ($requestedCharacterId = 0) AND session characters were found
|
||||
// -> get first matched character (e.g. user open browser tab)
|
||||
$data = $sessionCharacters[0];
|
||||
}
|
||||
}
|
||||
|
||||
if(
|
||||
$objectCheck === true &&
|
||||
!empty($data)
|
||||
){
|
||||
// check if character still exists on DB (e.g. was manually removed in the meantime)
|
||||
// -> This should NEVER happen just for security and "local development"
|
||||
/**
|
||||
* @var $character CharacterModel
|
||||
*/
|
||||
$character = BasicModel::getNew('CharacterModel');
|
||||
$character->getById( (int)$data['ID']);
|
||||
|
||||
if(
|
||||
$character->dry() ||
|
||||
!$character->hasUserCharacter()
|
||||
){
|
||||
// character data is invalid!
|
||||
$data = [];
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* get all userCharacters models for a user
|
||||
* characters will be checked/updated on login by CCP API call
|
||||
@@ -189,8 +253,9 @@ class UserModel extends BasicModel {
|
||||
* @return CharacterModel[]
|
||||
*/
|
||||
public function getCharacters(){
|
||||
$userCharacters = $this->getUserCharacters();
|
||||
$characters = [];
|
||||
$userCharacters = $this->getUserCharacters();
|
||||
|
||||
foreach($userCharacters as $userCharacter){
|
||||
/**
|
||||
* @var $userCharacter UserCharacterModel
|
||||
@@ -211,9 +276,9 @@ class UserModel extends BasicModel {
|
||||
* @return CharacterModel[]
|
||||
*/
|
||||
public function getActiveCharacters(){
|
||||
$activeCharacters = [];
|
||||
$userCharacters = $this->getUserCharacters();
|
||||
|
||||
$activeCharacters = [];
|
||||
foreach($userCharacters as $userCharacter){
|
||||
/**
|
||||
* @var $userCharacter UserCharacterModel
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
[PATHFINDER]
|
||||
NAME = Pathfinder
|
||||
; installed version (used for CSS/JS cache busting)
|
||||
VERSION = v1.1.4
|
||||
VERSION = v1.1.5
|
||||
; contact information [optional]
|
||||
CONTACT = https://github.com/exodus4d
|
||||
; public contact email [optional]
|
||||
|
||||
@@ -138,7 +138,13 @@ define(['jquery'], function($) {
|
||||
5: 'Ordinary Perimeter Reservoir' //*
|
||||
},
|
||||
5: { // Wormhole
|
||||
1: 'F135 - Thera'
|
||||
1: 'Z647 - C1',
|
||||
2: 'D382 - C2',
|
||||
3: 'O477 - C3',
|
||||
4: 'Y683 - C4',
|
||||
5: 'N062 - C5',
|
||||
6: 'R474 - C6',
|
||||
7: 'F135 - Thera'
|
||||
},
|
||||
6: { // ORE
|
||||
1: 'Ordinary Perimeter Deposit', //*
|
||||
|
||||
@@ -78,7 +78,7 @@ define([
|
||||
}else{
|
||||
clearInterval( element.data('interval') );
|
||||
}
|
||||
}, 100);
|
||||
}, 500);
|
||||
|
||||
element.data('interval', refreshIntervalId);
|
||||
}
|
||||
|
||||
@@ -165,7 +165,7 @@ define([
|
||||
systemBody.empty();
|
||||
|
||||
// loop "again" and build DOM object with user information
|
||||
for(var j = 0; j < data.user.length; j++){
|
||||
for(let j = 0; j < data.user.length; j++){
|
||||
var userData = data.user[j];
|
||||
|
||||
var statusClass = Util.getStatusInfoForCharacter(userData, 'class');
|
||||
@@ -2102,6 +2102,7 @@ define([
|
||||
|
||||
// init drag-frame selection
|
||||
$(mapContainer).dragToSelect({
|
||||
selectOnMove: true,
|
||||
selectables: '.' + config.systemClass,
|
||||
onHide: function (selectBox, deselectedSystems) {
|
||||
var selectedSystems = $(mapContainer).getSelectedSystems();
|
||||
@@ -2120,7 +2121,6 @@ define([
|
||||
for(var j = 0; j < deselectedSystems.length; j++){
|
||||
map.removeFromDragSelection( deselectedSystems[j] );
|
||||
}
|
||||
|
||||
},
|
||||
onShow: function(){
|
||||
$(document).trigger('pf:closeMenu', [{}]);
|
||||
|
||||
@@ -508,7 +508,7 @@ define([
|
||||
var getLocaleData = function(type, objectId){
|
||||
if(objectId > 0){
|
||||
var storageKey = getLocalStoragePrefixByType(type) + objectId;
|
||||
return Util.localforage.getItem(storageKey);
|
||||
return Util.getLocalStorage().getItem(storageKey);
|
||||
}else{
|
||||
console.warn('Local storage requires object id > 0');
|
||||
}
|
||||
@@ -525,13 +525,13 @@ define([
|
||||
if(objectId > 0){
|
||||
// get current map config
|
||||
var storageKey = getLocalStoragePrefixByType(type) + objectId;
|
||||
Util.localforage.getItem(storageKey).then(function(data) {
|
||||
Util.getLocalStorage().getItem(storageKey).then(function(data) {
|
||||
// This code runs once the value has been loaded
|
||||
// from the offline store.
|
||||
data = (data === null) ? {} : data;
|
||||
// set/update value
|
||||
data[this.key] = this.value;
|
||||
Util.localforage.setItem(this.storageKey, data);
|
||||
Util.getLocalStorage().setItem(this.storageKey, data);
|
||||
}.bind({
|
||||
key: key,
|
||||
value: value,
|
||||
@@ -555,13 +555,13 @@ define([
|
||||
if(objectId > 0){
|
||||
// get current map config
|
||||
var storageKey = getLocalStoragePrefixByType(type) + objectId;
|
||||
Util.localforage.getItem(storageKey).then(function(data) {
|
||||
Util.getLocalStorage().getItem(storageKey).then(function(data) {
|
||||
if(
|
||||
data &&
|
||||
data.hasOwnProperty(key)
|
||||
){
|
||||
delete data[key];
|
||||
Util.localforage.setItem(this.storageKey, data);
|
||||
Util.getLocalStorage().setItem(this.storageKey, data);
|
||||
}
|
||||
}.bind({
|
||||
storageKey: storageKey
|
||||
|
||||
@@ -19,7 +19,10 @@ define([
|
||||
* main init "map" page
|
||||
*/
|
||||
$(function(){
|
||||
// set Dialog default config
|
||||
// set default AJAX config
|
||||
Util.ajaxSetup();
|
||||
|
||||
// set default dialog config
|
||||
Util.initDefaultBootboxConfig();
|
||||
|
||||
// load page
|
||||
@@ -28,11 +31,6 @@ define([
|
||||
// show app information in browser console
|
||||
Util.showVersionInfo();
|
||||
|
||||
// init local storage
|
||||
Util.localforage.config({
|
||||
name: 'Pathfinder local storage'
|
||||
});
|
||||
|
||||
// init logging
|
||||
Logging.init();
|
||||
|
||||
@@ -72,7 +70,7 @@ define([
|
||||
}).fail(function( jqXHR, status, error) {
|
||||
var reason = status + ' ' + jqXHR.status + ': ' + error;
|
||||
|
||||
$(document).trigger('pf:shutdown', {reason: reason});
|
||||
$(document).trigger('pf:shutdown', {status: jqXHR.status, reason: reason});
|
||||
});
|
||||
|
||||
/**
|
||||
@@ -284,7 +282,8 @@ define([
|
||||
var reason = status + ' ' + jqXHR.status + ': ' + error;
|
||||
var errorData = [];
|
||||
|
||||
if(jqXHR.responseText){
|
||||
if(jqXHR.responseJSON){
|
||||
// handle JSON
|
||||
var errorObj = $.parseJSON(jqXHR.responseText);
|
||||
|
||||
if(
|
||||
@@ -293,9 +292,15 @@ define([
|
||||
){
|
||||
errorData = errorObj.error;
|
||||
}
|
||||
}else{
|
||||
// handle HTML
|
||||
errorData.push({
|
||||
type: 'error',
|
||||
message: 'Please restart and reload this page'
|
||||
});
|
||||
}
|
||||
|
||||
$(document).trigger('pf:shutdown', {reason: reason, error: errorData});
|
||||
$(document).trigger('pf:shutdown', {status: jqXHR.status, reason: reason, error: errorData});
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -223,8 +223,9 @@ define([
|
||||
|
||||
if(currentSystemData){
|
||||
if(systemData.id === currentSystemData.systemData.id){
|
||||
// trigger system update event
|
||||
$(document).trigger('pf:updateSystemModules', [systemData]);
|
||||
// trigger system update events
|
||||
$(document).triggerHandler('pf:updateSystemInfoModule', [systemData]);
|
||||
$(document).triggerHandler('pf:updateSystemSignatureModule', [systemData]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -138,7 +138,7 @@ define([
|
||||
href: '#'
|
||||
}).html(' Settings').prepend(
|
||||
$('<i>',{
|
||||
class: 'fa fa-gears fa-fw'
|
||||
class: 'fa fa-sliders fa-fw'
|
||||
})
|
||||
).on('click', function(){
|
||||
$(document).triggerMenuEvent('ShowSettingsDialog');
|
||||
@@ -253,7 +253,7 @@ define([
|
||||
href: '#'
|
||||
}).html(' Settings').prepend(
|
||||
$('<i>',{
|
||||
class: 'fa fa-gears fa-fw'
|
||||
class: 'fa fa-sliders fa-fw'
|
||||
})
|
||||
).on('click', function(){
|
||||
$(document).triggerMenuEvent('ShowMapSettings', {tab: 'settings'});
|
||||
@@ -573,10 +573,11 @@ define([
|
||||
$(document).on('pf:menuLogout', function(e, data){
|
||||
|
||||
var clearCookies = false;
|
||||
if( typeof data === 'object' ){
|
||||
if( data.hasOwnProperty('clearCookies') ){
|
||||
clearCookies = data.clearCookies;
|
||||
}
|
||||
if(
|
||||
typeof data === 'object' &&
|
||||
data.hasOwnProperty('clearCookies')
|
||||
){
|
||||
clearCookies = data.clearCookies;
|
||||
}
|
||||
|
||||
// logout
|
||||
@@ -618,9 +619,15 @@ define([
|
||||
logout: {
|
||||
label: '<i class="fa fa-fw fa-refresh"></i> restart',
|
||||
className: ['btn-primary'].join(' '),
|
||||
callback: function() {
|
||||
|
||||
$(document).trigger('pf:menuLogout');
|
||||
callback: function(){
|
||||
// check if error was 5xx -> reload page
|
||||
// -> else try to logout -> ajax request
|
||||
if(data.status >= 500 && data.status < 600){
|
||||
// redirect to login
|
||||
window.location = '../';
|
||||
}else{
|
||||
$(document).trigger('pf:menuLogout');
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -641,7 +648,7 @@ define([
|
||||
data.error &&
|
||||
data.error.length
|
||||
){
|
||||
for(var i = 0; i < data.error.length; i++){
|
||||
for(let i = 0; i < data.error.length; i++){
|
||||
options.content.textSmaller.push(data.error[i].message);
|
||||
}
|
||||
}
|
||||
@@ -674,6 +681,7 @@ define([
|
||||
|
||||
var userInfoElement = $('.' + config.headUserCharacterClass);
|
||||
var currentCharacterId = userInfoElement.data('characterId');
|
||||
var currentCharactersOptionIds = userInfoElement.data('characterOptionIds') ? userInfoElement.data('characterOptionIds') : [];
|
||||
var newCharacterId = 0;
|
||||
var newCharacterName = '';
|
||||
|
||||
@@ -691,7 +699,6 @@ define([
|
||||
visibility : 'hidden',
|
||||
duration: 500,
|
||||
complete: function(){
|
||||
|
||||
// callback
|
||||
callback();
|
||||
|
||||
@@ -727,25 +734,31 @@ define([
|
||||
}
|
||||
}
|
||||
|
||||
// update user character data ---------------------------------------------------
|
||||
if(currentCharacterId !== newCharacterId){
|
||||
var newCharactersOptionIds = userData.characters.map(function(data){
|
||||
return data.id;
|
||||
});
|
||||
|
||||
var showCharacterElement = true;
|
||||
if(newCharacterId === 0){
|
||||
showCharacterElement = false;
|
||||
// update user character data ---------------------------------------------------
|
||||
if(currentCharactersOptionIds.toString() !== newCharactersOptionIds.toString()){
|
||||
|
||||
var currentCharacterChanged = false;
|
||||
if(currentCharacterId !== newCharacterId){
|
||||
currentCharacterChanged = true;
|
||||
}
|
||||
|
||||
// toggle element
|
||||
animateHeaderElement(userInfoElement, function(){
|
||||
userInfoElement.find('span').text( newCharacterName );
|
||||
userInfoElement.find('img').attr('src', Init.url.ccpImageServer + 'Character/' + newCharacterId + '_32.jpg' );
|
||||
|
||||
if(currentCharacterChanged){
|
||||
userInfoElement.find('span').text( newCharacterName );
|
||||
userInfoElement.find('img').attr('src', Init.url.ccpImageServer + 'Character/' + newCharacterId + '_32.jpg' );
|
||||
}
|
||||
// init "character switch" popover
|
||||
userInfoElement.initCharacterSwitchPopover(userData);
|
||||
}, showCharacterElement);
|
||||
}, true);
|
||||
|
||||
// set new id for next check
|
||||
// store new id(s) for next check
|
||||
userInfoElement.data('characterId', newCharacterId);
|
||||
userInfoElement.data('characterOptionIds', newCharactersOptionIds);
|
||||
}
|
||||
|
||||
// update user ship data --------------------------------------------------------
|
||||
|
||||
@@ -26,8 +26,6 @@ define([
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* init a select element as an ajax based "select2" object for system search
|
||||
* @param options
|
||||
@@ -35,6 +33,11 @@ define([
|
||||
$.fn.initSystemSelect = function(options){
|
||||
var selectElement = $(this);
|
||||
|
||||
var config = {
|
||||
maxSelectionLength: 1
|
||||
};
|
||||
options = $.extend({}, config, options);
|
||||
|
||||
// format result data
|
||||
function formatResultData (data) {
|
||||
|
||||
@@ -135,6 +138,7 @@ define([
|
||||
templateResult: formatResultData,
|
||||
placeholder: 'System name',
|
||||
allowClear: true,
|
||||
maximumSelectionLength: options.maxSelectionLength,
|
||||
escapeMarkup: function (markup) {
|
||||
// let our custom formatter work
|
||||
return markup;
|
||||
|
||||
@@ -50,7 +50,7 @@ define([
|
||||
* set module observer and look for relevant system data to update
|
||||
*/
|
||||
var setModuleObserver = function(moduleElement){
|
||||
$(document).on('pf:updateSystemModules', function(e, data){
|
||||
$(document).off('pf:updateSystemInfoModule').on('pf:updateSystemInfoModule', function(e, data){
|
||||
if(data){
|
||||
moduleElement.updateSystemInfoModule(data);
|
||||
}
|
||||
|
||||
@@ -6,8 +6,9 @@ define([
|
||||
'jquery',
|
||||
'app/init',
|
||||
'app/util',
|
||||
'bootbox'
|
||||
], function($, Init, Util, bootbox) {
|
||||
'bootbox',
|
||||
'app/map/util'
|
||||
], function($, Init, Util, bootbox, MapUtil) {
|
||||
'use strict';
|
||||
|
||||
var config = {
|
||||
@@ -22,12 +23,14 @@ define([
|
||||
// headline toolbar
|
||||
systemModuleHeadlineIcon: 'pf-module-icon-button', // class for toolbar icons in the head
|
||||
systemModuleHeadlineIconSearch: 'pf-module-icon-button-search', // class for "search" icon
|
||||
systemModuleHeadlineIconSettings: 'pf-module-icon-button-settings', // class for "settings" icon
|
||||
systemModuleHeadlineIconRefresh: 'pf-module-icon-button-refresh', // class for "refresh" icon
|
||||
|
||||
systemSecurityClassPrefix: 'pf-system-security-', // prefix class for system security level (color)
|
||||
|
||||
// dialog
|
||||
routeDialogId: 'pf-route-dialog', // id for route dialog
|
||||
routeSettingsDialogId: 'pf-route-settings-dialog', // id for route "settings" dialog
|
||||
routeDialogId: 'pf-route-dialog', // id for route "search" dialog
|
||||
systemDialogSelectClass: 'pf-system-dialog-select', // class for system select Element
|
||||
systemInfoRoutesTableClass: 'pf-system-route-table', // class for route tables
|
||||
mapSelectId: 'pf-route-dialog-map-select', // id for "map" select
|
||||
@@ -148,11 +151,12 @@ define([
|
||||
mapIds: (rowData.hasOwnProperty('mapIds')) ? rowData.mapIds : [],
|
||||
systemFromData: (rowData.hasOwnProperty('systemFromData')) ? rowData.systemFromData : {},
|
||||
systemToData: (rowData.hasOwnProperty('systemToData')) ? rowData.systemToData : {},
|
||||
stargates: (rowData.hasOwnProperty('stargates')) ? rowData.stargates : 1,
|
||||
jumpbridges: (rowData.hasOwnProperty('jumpbridges')) ? rowData.jumpbridges : 1,
|
||||
wormholes: (rowData.hasOwnProperty('wormholes')) ? rowData.wormholes : 1,
|
||||
wormholesReduced: (rowData.hasOwnProperty('wormholesReduced')) ? rowData.wormholesReduced : 1,
|
||||
wormholesCritical: (rowData.hasOwnProperty('wormholesCritical')) ? rowData.wormholesCritical : 1
|
||||
stargates: (rowData.hasOwnProperty('stargates')) ? rowData.stargates | 0 : 1,
|
||||
jumpbridges: (rowData.hasOwnProperty('jumpbridges')) ? rowData.jumpbridges | 0 : 1,
|
||||
wormholes: (rowData.hasOwnProperty('wormholes')) ? rowData.wormholes | 0 : 1,
|
||||
wormholesReduced: (rowData.hasOwnProperty('wormholesReduced')) ? rowData.wormholesReduced | 0 : 1,
|
||||
wormholesCritical: (rowData.hasOwnProperty('wormholesCritical')) ? rowData.wormholesCritical | 0 : 1,
|
||||
wormholesEOL: (rowData.hasOwnProperty('wormholesEOL')) ? rowData.wormholesEOL | 0 : 1
|
||||
};
|
||||
};
|
||||
|
||||
@@ -192,10 +196,7 @@ define([
|
||||
buttons: {
|
||||
close: {
|
||||
label: 'cancel',
|
||||
className: 'btn-default',
|
||||
callback: function(){
|
||||
$(findRouteDialog).modal('hide');
|
||||
}
|
||||
className: 'btn-default'
|
||||
},
|
||||
success: {
|
||||
label: '<i class="fa fa-fw fa-search"></i> search route',
|
||||
@@ -243,7 +244,8 @@ define([
|
||||
jumpbridges: routeDialogData.hasOwnProperty('jumpbridges') ? parseInt( routeDialogData.jumpbridges ) : 0,
|
||||
wormholes: routeDialogData.hasOwnProperty('wormholes') ? parseInt( routeDialogData.wormholes ) : 0,
|
||||
wormholesReduced: routeDialogData.hasOwnProperty('wormholesReduced') ? parseInt( routeDialogData.wormholesReduced ) : 0,
|
||||
wormholesCritical: routeDialogData.hasOwnProperty('wormholesCritical') ? parseInt( routeDialogData.wormholesCritical ) : 0
|
||||
wormholesCritical: routeDialogData.hasOwnProperty('wormholesCritical') ? parseInt( routeDialogData.wormholesCritical ) : 0,
|
||||
wormholesEOL: routeDialogData.hasOwnProperty('wormholesEOL') ? parseInt( routeDialogData.wormholesEOL ) : 0
|
||||
}]
|
||||
};
|
||||
|
||||
@@ -279,6 +281,105 @@ define([
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* show route settings dialog
|
||||
* @param dialogData
|
||||
* @param moduleElement
|
||||
* @param systemFromData
|
||||
* @param routesTable
|
||||
*/
|
||||
var showSettingsDialog = function(dialogData, moduleElement, systemFromData, routesTable){
|
||||
|
||||
var promiseStore = MapUtil.getLocaleData('map', dialogData.mapId);
|
||||
promiseStore.then(function(dataStore) {
|
||||
// selected systems (if already stored)
|
||||
var systemSelectOptions = [];
|
||||
if(
|
||||
dataStore &&
|
||||
dataStore.routes
|
||||
){
|
||||
systemSelectOptions = dataStore.routes;
|
||||
}
|
||||
|
||||
var maxSelectionLength = 4;
|
||||
|
||||
var data = {
|
||||
id: config.routeSettingsDialogId,
|
||||
selectClass: config.systemDialogSelectClass,
|
||||
systemSelectOptions: systemSelectOptions,
|
||||
maxSelectionLength: maxSelectionLength
|
||||
};
|
||||
|
||||
requirejs(['text!templates/dialog/route_settings.html', 'mustache'], function(template, Mustache) {
|
||||
var content = Mustache.render(template, data);
|
||||
|
||||
var settingsDialog = bootbox.dialog({
|
||||
title: 'Route settings',
|
||||
message: content,
|
||||
show: false,
|
||||
buttons: {
|
||||
close: {
|
||||
label: 'cancel',
|
||||
className: 'btn-default'
|
||||
},
|
||||
success: {
|
||||
label: '<i class="fa fa-fw fa-check"></i> save',
|
||||
className: 'btn-success',
|
||||
callback: function () {
|
||||
var form = this.find('form');
|
||||
// get all system data from select2
|
||||
var systemSelectData = form.find('.' + config.systemDialogSelectClass).select2('data');
|
||||
var systemsTo = [];
|
||||
|
||||
if( systemSelectData.length > 0 ){
|
||||
systemsTo = formSystemSelectData(systemSelectData);
|
||||
MapUtil.storeLocalData('map', dialogData.mapId, 'routes', systemsTo);
|
||||
}else{
|
||||
MapUtil.deleteLocalData('map', dialogData.mapId, 'routes');
|
||||
}
|
||||
|
||||
Util.showNotify({title: 'Route settings stored', type: 'success'});
|
||||
|
||||
// (re) draw table
|
||||
drawRouteTable(dialogData.mapId, moduleElement, systemFromData, routesTable, systemsTo);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
settingsDialog.on('shown.bs.modal', function(e) {
|
||||
|
||||
// init default system select -----------------------------------------------------
|
||||
// -> add some delay until modal transition has finished
|
||||
var systemTargetSelect = $(this).find('.' + config.systemDialogSelectClass);
|
||||
systemTargetSelect.delay(240).initSystemSelect({key: 'name', maxSelectionLength: maxSelectionLength});
|
||||
});
|
||||
|
||||
// show dialog
|
||||
settingsDialog.modal('show');
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* format select2 system data
|
||||
* @param {Array} data
|
||||
* @returns {Array}
|
||||
*/
|
||||
var formSystemSelectData = function(data){
|
||||
var formattedData = [];
|
||||
for(let i = 0; i < data.length; i++){
|
||||
var tmpData = data[i];
|
||||
|
||||
formattedData.push({
|
||||
name: tmpData.id,
|
||||
systemId: parseInt( tmpData.hasOwnProperty('systemId') ? tmpData.systemId : tmpData.element.getAttribute('data-systemid') )
|
||||
});
|
||||
}
|
||||
|
||||
return formattedData;
|
||||
};
|
||||
|
||||
/**
|
||||
* set event observer for route finder dialog
|
||||
* @param routeDialog
|
||||
@@ -287,11 +388,13 @@ define([
|
||||
var wormholeCheckbox = routeDialog.find('input[type="checkbox"][name="wormholes"]');
|
||||
var wormholeReducedCheckbox = routeDialog.find('input[type="checkbox"][name="wormholesReduced"]');
|
||||
var wormholeCriticalCheckbox = routeDialog.find('input[type="checkbox"][name="wormholesCritical"]');
|
||||
var wormholeEolCheckbox = routeDialog.find('input[type="checkbox"][name="wormholesEOL"]');
|
||||
|
||||
// store current "checked" state for each box ---------------------------------------------
|
||||
var storeCheckboxStatus = function(){
|
||||
wormholeReducedCheckbox.data('selectState', wormholeReducedCheckbox.prop('checked'));
|
||||
wormholeCriticalCheckbox.data('selectState', wormholeCriticalCheckbox.prop('checked'));
|
||||
wormholeEolCheckbox.data('selectState', wormholeEolCheckbox.prop('checked'));
|
||||
};
|
||||
|
||||
// on wormhole checkbox change ------------------------------------------------------------
|
||||
@@ -300,9 +403,11 @@ define([
|
||||
if( $(this).is(':checked') ){
|
||||
wormholeReducedCheckbox.prop('disabled', false);
|
||||
wormholeCriticalCheckbox.prop('disabled', false);
|
||||
wormholeEolCheckbox.prop('disabled', false);
|
||||
|
||||
wormholeReducedCheckbox.prop('checked', wormholeReducedCheckbox.data('selectState'));
|
||||
wormholeCriticalCheckbox.prop('checked', wormholeCriticalCheckbox.data('selectState'));
|
||||
wormholeEolCheckbox.prop('checked', wormholeEolCheckbox.data('selectState'));
|
||||
}else{
|
||||
storeCheckboxStatus();
|
||||
|
||||
@@ -310,6 +415,8 @@ define([
|
||||
wormholeReducedCheckbox.prop('disabled', true);
|
||||
wormholeCriticalCheckbox.prop('checked', false);
|
||||
wormholeCriticalCheckbox.prop('disabled', true);
|
||||
wormholeEolCheckbox.prop('checked', false);
|
||||
wormholeEolCheckbox.prop('disabled', true);
|
||||
}
|
||||
}.bind(wormholeCheckbox);
|
||||
|
||||
@@ -374,6 +481,7 @@ define([
|
||||
wormholes: routeData.wormholes,
|
||||
wormholesReduced: routeData.wormholesReduced,
|
||||
wormholesCritical: routeData.wormholesCritical,
|
||||
wormholesEOL: routeData.wormholesEOL,
|
||||
reload: {
|
||||
button: reloadButton
|
||||
},
|
||||
@@ -463,6 +571,10 @@ define([
|
||||
class: ['fa', 'fa-fw', 'fa-search', config.systemModuleHeadlineIcon, config.systemModuleHeadlineIconSearch].join(' '),
|
||||
title: 'find route'
|
||||
}).attr('data-html', 'true').attr('data-toggle', 'tooltip'),
|
||||
$('<i>', {
|
||||
class: ['fa', 'fa-fw', 'fa-sliders', config.systemModuleHeadlineIcon, config.systemModuleHeadlineIconSettings].join(' '),
|
||||
title: 'settings'
|
||||
}).attr('data-html', 'true').attr('data-toggle', 'tooltip'),
|
||||
$('<i>', {
|
||||
class: ['fa', 'fa-fw', 'fa-refresh', config.systemModuleHeadlineIcon, config.systemModuleHeadlineIconRefresh].join(' '),
|
||||
title: 'refresh all'
|
||||
@@ -576,7 +688,8 @@ define([
|
||||
jumpbridges: rowData.jumpbridges ? 1 : 0,
|
||||
wormholes: rowData.wormholes ? 1 : 0,
|
||||
wormholesReduced: rowData.wormholesReduced ? 1 : 0,
|
||||
wormholesCritical: rowData.wormholesCritical ? 1 : 0
|
||||
wormholesCritical: rowData.wormholesCritical ? 1 : 0,
|
||||
wormholesEOL: rowData.wormholesEOL ? 1 : 0
|
||||
}]
|
||||
};
|
||||
|
||||
@@ -722,22 +835,6 @@ define([
|
||||
systemId: systemData.systemId
|
||||
};
|
||||
|
||||
var systemsTo = [
|
||||
{
|
||||
name: 'Jita',
|
||||
systemId: 30000142
|
||||
},{
|
||||
name: 'Amarr',
|
||||
systemId: 30002187
|
||||
},{
|
||||
name: 'Rens',
|
||||
systemId: 30002510
|
||||
},{
|
||||
name: 'Dodixie',
|
||||
systemId: 30002659
|
||||
}
|
||||
];
|
||||
|
||||
var routesTableElement = moduleElement.find('.' + config.systemInfoRoutesTableClass);
|
||||
|
||||
var routesTable = routesTableElement.DataTable();
|
||||
@@ -759,7 +856,38 @@ define([
|
||||
showFindRouteDialog(dialogData);
|
||||
});
|
||||
|
||||
// init settings dialog -------------------------------------------------------------------
|
||||
moduleElement.find('.' + config.systemModuleHeadlineIconSettings).on('click', function(e){
|
||||
var dialogData = {
|
||||
mapId: mapId
|
||||
};
|
||||
|
||||
showSettingsDialog(dialogData, moduleElement, systemFromData, routesTable);
|
||||
});
|
||||
|
||||
// fill routesTable with data -------------------------------------------------------------
|
||||
var promiseStore = MapUtil.getLocaleData('map', mapId);
|
||||
promiseStore.then(function(dataStore) {
|
||||
// selected systems (if already stored)
|
||||
var systemsTo = [{
|
||||
name: 'Jita',
|
||||
systemId: 30000142
|
||||
}];
|
||||
|
||||
if(
|
||||
dataStore &&
|
||||
dataStore.routes
|
||||
){
|
||||
systemsTo = dataStore.routes;
|
||||
}
|
||||
|
||||
drawRouteTable(mapId, moduleElement, systemFromData, routesTable, systemsTo);
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
|
||||
var drawRouteTable = function(mapId, moduleElement, systemFromData, routesTable, systemsTo){
|
||||
var requestRouteData = [];
|
||||
var currentTimestamp = Util.getServerTime().getTime();
|
||||
|
||||
@@ -809,7 +937,6 @@ define([
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* updates an dom element with the system route module
|
||||
* @param mapId
|
||||
|
||||
@@ -1775,7 +1775,7 @@ define([
|
||||
var dataTablePrimary = signatureTable.DataTable();
|
||||
var signatureTableApi = signatureTable.api();
|
||||
|
||||
$(document).off('pf:updateSystemModules').on('pf:updateSystemModules', function(e, data){
|
||||
$(document).off('pf:updateSystemSignatureModule').on('pf:updateSystemSignatureModule', function(e, data){
|
||||
if(data.signatures){
|
||||
moduleElement.updateSignatureTable(data.signatures, true);
|
||||
}
|
||||
|
||||
118
js/app/util.js
118
js/app/util.js
@@ -33,6 +33,7 @@ define([
|
||||
|
||||
// head
|
||||
headMapTrackingId: 'pf-head-map-tracking', // id for "map tracking" toggle (checkbox)
|
||||
headCharacterSwitchId: 'pf-head-character-switch', // id for "character switch" popover
|
||||
|
||||
// menu
|
||||
menuButtonFullScreenId: 'pf-menu-button-fullscreen', // id for menu button "fullscreen"
|
||||
@@ -64,6 +65,8 @@ define([
|
||||
|
||||
var animationTimerCache = {}; // cache for table row animation timeout
|
||||
|
||||
var localStorage; // cache for "localForage" singleton
|
||||
|
||||
/*
|
||||
* ===========================================================================================================
|
||||
* Global jQuery plugins for some common and frequently used functions
|
||||
@@ -576,6 +579,7 @@ define([
|
||||
requirejs(['text!templates/tooltip/character_switch.html', 'mustache'], function (template, Mustache) {
|
||||
|
||||
var data = {
|
||||
id: config.headCharacterSwitchId,
|
||||
routes: Init.routes,
|
||||
userData: userData,
|
||||
otherCharacters: $.grep( userData.characters, function( character ) {
|
||||
@@ -589,40 +593,50 @@ define([
|
||||
return elements.each(function() {
|
||||
var element = $(this);
|
||||
|
||||
// destroy "popover" and remove "click" event for animation
|
||||
element.popover('destroy').off();
|
||||
|
||||
// init popover and add specific class to it (for styling)
|
||||
element.popover({
|
||||
html: true,
|
||||
title: 'select character',
|
||||
trigger: 'click',
|
||||
placement: 'bottom',
|
||||
container: 'body',
|
||||
content: content,
|
||||
animation: false
|
||||
}).data('bs.popover').tip().addClass('pf-popover');
|
||||
// check if tooltip already exists -> remove it
|
||||
if(element.data('bs.popover') !== undefined){
|
||||
element.off('click').popover('destroy');
|
||||
}
|
||||
|
||||
element.on('click', function(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
var easeEffect = $(this).attr('data-easein');
|
||||
var popover = $(this).data('bs.popover').tip();
|
||||
var popoverData = $(this).data('bs.popover');
|
||||
var popoverElement = null;
|
||||
|
||||
var velocityOptions = {
|
||||
duration: Init.animationSpeed.dialogEvents
|
||||
};
|
||||
|
||||
switch(easeEffect){
|
||||
case 'shake':
|
||||
case 'pulse':
|
||||
case 'tada':
|
||||
case 'flash':
|
||||
case 'bounce':
|
||||
case 'swing':
|
||||
popover.velocity('callout.' + easeEffect, velocityOptions);
|
||||
break;
|
||||
default:
|
||||
popover.velocity('transition.' + easeEffect, velocityOptions);
|
||||
break;
|
||||
if(popoverData === undefined){
|
||||
|
||||
// init popover and add specific class to it (for styling)
|
||||
$(this).popover({
|
||||
html: true,
|
||||
title: 'select character',
|
||||
trigger: 'manual',
|
||||
placement: 'bottom',
|
||||
container: 'body',
|
||||
content: content,
|
||||
animation: false
|
||||
}).data('bs.popover').tip().addClass('pf-popover');
|
||||
|
||||
$(this).popover('show');
|
||||
|
||||
popoverElement = $(this).data('bs.popover').tip();
|
||||
popoverElement.velocity('transition.' + easeEffect, velocityOptions);
|
||||
popoverElement.initTooltips();
|
||||
}else{
|
||||
popoverElement = $(this).data('bs.popover').tip();
|
||||
if(popoverElement.is(':visible')){
|
||||
popoverElement.velocity('reverse');
|
||||
}else{
|
||||
$(this).popover('show');
|
||||
popoverElement.initTooltips();
|
||||
popoverElement.velocity('transition.' + easeEffect, velocityOptions);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -650,7 +664,14 @@ define([
|
||||
popoverElement.has(e.target).length === 0 &&
|
||||
$('.popover').has(e.target).length === 0
|
||||
){
|
||||
popoverElement.popover('hide');
|
||||
var popover = popoverElement.data('bs.popover');
|
||||
|
||||
if(
|
||||
popover !== undefined &&
|
||||
popover.tip().is(':visible')
|
||||
){
|
||||
popoverElement.popover('hide');
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -1014,6 +1035,32 @@ define([
|
||||
return logInfo;
|
||||
};
|
||||
|
||||
/**
|
||||
* set default jQuery AJAX configuration
|
||||
*/
|
||||
var ajaxSetup = function(){
|
||||
$.ajaxSetup({
|
||||
beforeSend: function(xhr, settings) {
|
||||
// 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
|
||||
var userData = getCurrentUserData();
|
||||
var currentCharacterId = 0;
|
||||
if(
|
||||
userData &&
|
||||
userData.character
|
||||
){
|
||||
currentCharacterId = parseInt( userData.character.id );
|
||||
}
|
||||
|
||||
xhr.setRequestHeader('Pf-Character', currentCharacterId);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns true if the user hit Esc or navigated away from the
|
||||
* current page before an AJAX call was done. (The response
|
||||
@@ -1665,6 +1712,20 @@ define([
|
||||
return price + ' ISK';
|
||||
};
|
||||
|
||||
/**
|
||||
* get localForage instance (singleton) for offline client site storage
|
||||
* @returns {localforage}
|
||||
*/
|
||||
var getLocalStorage = function(){
|
||||
if(localStorage === undefined){
|
||||
localStorage = localforage.createInstance({
|
||||
driver: localforage.INDEXEDDB,
|
||||
name: 'Pathfinder local storage'
|
||||
});
|
||||
}
|
||||
return localStorage;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create Date as UTC
|
||||
* @param date
|
||||
@@ -1756,7 +1817,6 @@ define([
|
||||
|
||||
return {
|
||||
config: config,
|
||||
localforage: localforage,
|
||||
showVersionInfo: showVersionInfo,
|
||||
initDefaultBootboxConfig: initDefaultBootboxConfig,
|
||||
getCurrentTriggerDelay: getCurrentTriggerDelay,
|
||||
@@ -1769,6 +1829,7 @@ define([
|
||||
showNotify: showNotify,
|
||||
stopTabBlink: stopTabBlink,
|
||||
getLogInfo: getLogInfo,
|
||||
ajaxSetup: ajaxSetup,
|
||||
isXHRAborted: isXHRAborted,
|
||||
getMapModule: getMapModule,
|
||||
getSystemEffectData: getSystemEffectData,
|
||||
@@ -1797,6 +1858,7 @@ define([
|
||||
convertDateToString: convertDateToString,
|
||||
getOpenDialogs: getOpenDialogs,
|
||||
formatPrice: formatPrice,
|
||||
getLocalStorage: getLocalStorage,
|
||||
getDocumentPath: getDocumentPath,
|
||||
redirect: redirect,
|
||||
logout: logout
|
||||
|
||||
@@ -69,8 +69,12 @@ jQuery.fn.dragToSelect = function (conf) {
|
||||
var realParent = jQuery(this);
|
||||
var parent = realParent;
|
||||
|
||||
var animationFrameId;
|
||||
var mouseIsDown = false;
|
||||
var lastMousePosition = { x: 0, y: 0 };
|
||||
|
||||
// deselected items
|
||||
var deselectedItems = [];
|
||||
var deselectedItems = $();
|
||||
|
||||
do {
|
||||
if (/auto|scroll|hidden/.test(parent.css('overflow'))) {
|
||||
@@ -130,9 +134,11 @@ jQuery.fn.dragToSelect = function (conf) {
|
||||
};
|
||||
|
||||
// Refreshes the select box dimensions and possibly position
|
||||
var refreshSelectBox = function (e) {
|
||||
var refreshSelectBox = function () {
|
||||
var refreshed = false;
|
||||
|
||||
if (!selectBox.is('.' + config.activeClass) || parent.is('.' + config.disabledClass)) {
|
||||
return;
|
||||
return refreshed;
|
||||
}
|
||||
|
||||
// get scroll position
|
||||
@@ -147,13 +153,12 @@ jQuery.fn.dragToSelect = function (conf) {
|
||||
rightScroll = realParent.data('scrollRight');
|
||||
}
|
||||
|
||||
var left = e.pageX - parentDim.left + parent[0].scrollLeft;
|
||||
var top = e.pageY - parentDim.top + parent[0].scrollTop;
|
||||
var left = lastMousePosition.x - parentDim.left + parent[0].scrollLeft;
|
||||
var top = lastMousePosition.y - parentDim.top + parent[0].scrollTop;
|
||||
var newLeft = left;
|
||||
var newTop = top;
|
||||
var tempWidth = selectBoxOrigin.left - newLeft ;
|
||||
var newHeight = selectBoxOrigin.top - newTop;
|
||||
|
||||
newLeft = selectBoxOrigin.left - leftScroll;
|
||||
var newWidth = left - selectBoxOrigin.left;
|
||||
|
||||
@@ -169,19 +174,28 @@ jQuery.fn.dragToSelect = function (conf) {
|
||||
newHeight = top - selectBoxOrigin.top;
|
||||
}
|
||||
|
||||
var css = {
|
||||
left: newLeft + 'px',
|
||||
top: newTop + 'px',
|
||||
width: newWidth + 'px',
|
||||
height: newHeight + 'px'
|
||||
};
|
||||
selectBox.css(css);
|
||||
// check if dimension has changed -> save performance
|
||||
var dimensionHash = [newWidth, newHeight].join('_');
|
||||
|
||||
config.onRefresh();
|
||||
if(selectBox.data('dimension-hash') !== dimensionHash){
|
||||
selectBox.data('dimension-hash', dimensionHash);
|
||||
var css = {
|
||||
left: newLeft + 'px',
|
||||
top: newTop + 'px',
|
||||
width: newWidth + 'px',
|
||||
height: newHeight + 'px'
|
||||
};
|
||||
|
||||
selectBox.css(css);
|
||||
config.onRefresh();
|
||||
refreshed = true;
|
||||
}
|
||||
|
||||
return refreshed;
|
||||
};
|
||||
|
||||
// Hides the select box
|
||||
var hideSelectBox = function (e) {
|
||||
var hideSelectBox = function () {
|
||||
if (!selectBox.is('.' + config.activeClass) || parent.is('.' + config.disabledClass)) {
|
||||
return;
|
||||
}
|
||||
@@ -229,9 +243,6 @@ jQuery.fn.dragToSelect = function (conf) {
|
||||
height: selectBox.height()
|
||||
};
|
||||
|
||||
// reset deselected item array
|
||||
deselectedItems = [];
|
||||
|
||||
selectables.each(function (i) {
|
||||
var el = $(this);
|
||||
var elOffset = el.offset();
|
||||
@@ -244,13 +255,14 @@ jQuery.fn.dragToSelect = function (conf) {
|
||||
|
||||
if (percentCovered(selectBoxDim, elDim) > config.percentCovered) {
|
||||
el.addClass(config.selectedClass);
|
||||
// remove element from "deselected" elements (e.g on add -> remove -> add scenario)
|
||||
deselectedItems = deselectedItems.not(el);
|
||||
}else {
|
||||
|
||||
if(el.hasClass(config.selectedClass)){
|
||||
el.removeClass(config.selectedClass);
|
||||
deselectedItems.push(el);
|
||||
deselectedItems = deselectedItems.add(el);
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
@@ -301,80 +313,64 @@ jQuery.fn.dragToSelect = function (conf) {
|
||||
return 0;
|
||||
};
|
||||
|
||||
// Do the right stuff then return this
|
||||
selectBox
|
||||
.mousemove(function (e) {
|
||||
// Event functions ----------------------------------------------------------------------------
|
||||
var mousemoveCallback = function(){
|
||||
if(mouseIsDown){
|
||||
var refreshed = refreshSelectBox();
|
||||
|
||||
refreshSelectBox(e);
|
||||
|
||||
if (config.selectables && config.selectOnMove) {
|
||||
selectElementsInRange();
|
||||
}
|
||||
|
||||
if (config.autoScroll) {
|
||||
scrollPerhaps(e);
|
||||
}
|
||||
|
||||
e.preventDefault();
|
||||
})
|
||||
.mouseup(function(e) {
|
||||
|
||||
if (config.selectables) {
|
||||
selectElementsInRange();
|
||||
}
|
||||
|
||||
hideSelectBox(e);
|
||||
|
||||
e.preventDefault();
|
||||
});
|
||||
|
||||
parent.mousedown(function (e) {
|
||||
|
||||
if(
|
||||
e.which === 1 && // left mouse down
|
||||
e.target === realParent[0] // prevent while dragging a system :)
|
||||
){
|
||||
|
||||
// Make sure user isn't clicking scrollbar (or disallow clicks far to the right actually)
|
||||
if ((e.pageX + 20) > jQuery(document.body).width()) {
|
||||
return;
|
||||
}
|
||||
|
||||
showSelectBox(e);
|
||||
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
|
||||
var dragSelectMousemove = function (e) {
|
||||
|
||||
refreshSelectBox(e);
|
||||
|
||||
if (config.selectables && config.selectOnMove) {
|
||||
|
||||
selectElementsInRange();
|
||||
}
|
||||
|
||||
if (config.autoScroll) {
|
||||
scrollPerhaps(e);
|
||||
}
|
||||
|
||||
e.preventDefault();
|
||||
};
|
||||
parent.mousemove( dragSelectMousemove );
|
||||
|
||||
|
||||
parent.mouseup(function (e) {
|
||||
if (config.selectables) {
|
||||
if(refreshed && config.selectables && config.selectOnMove){
|
||||
selectElementsInRange();
|
||||
}
|
||||
|
||||
hideSelectBox(e);
|
||||
// recursive re-call on next render
|
||||
animationFrameId = requestAnimationFrame(mousemoveCallback);
|
||||
}
|
||||
}
|
||||
|
||||
var mouseupCallback = function(){
|
||||
if (config.selectables){
|
||||
selectElementsInRange();
|
||||
}
|
||||
hideSelectBox();
|
||||
|
||||
// stop animation frame and "reset" to default
|
||||
cancelAnimationFrame(animationFrameId);
|
||||
mouseIsDown = false;
|
||||
// reset deselected item array
|
||||
deselectedItems = $();
|
||||
}
|
||||
|
||||
// Do the right stuff then return this --------------------------------------------------------
|
||||
|
||||
selectBox.mousemove(function(e){
|
||||
lastMousePosition.x = e.pageX;
|
||||
lastMousePosition.y = e.pageY;
|
||||
e.preventDefault();
|
||||
}).mouseup(mouseupCallback);
|
||||
|
||||
parent.mousedown(function(e){
|
||||
if (
|
||||
e.which === 1 && // left mouse down
|
||||
e.target === realParent[0] // prevent while dragging a system :)
|
||||
) {
|
||||
|
||||
// Make sure user isn't clicking scrollbar (or disallow clicks far to the right actually)
|
||||
if ((e.pageX + 20) > jQuery(document.body).width()) {
|
||||
return;
|
||||
}
|
||||
|
||||
showSelectBox(e);
|
||||
mouseIsDown = true;
|
||||
animationFrameId = requestAnimationFrame(mousemoveCallback);
|
||||
}
|
||||
|
||||
e.preventDefault();
|
||||
}).mousemove(function(e){
|
||||
lastMousePosition.x = e.pageX;
|
||||
lastMousePosition.y = e.pageY;
|
||||
e.preventDefault();
|
||||
}).mouseup(mouseupCallback);
|
||||
|
||||
e.preventDefault();
|
||||
});
|
||||
|
||||
// Be nice
|
||||
return this;
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
1
public/js/v1.1.5/app/login.js.map
Normal file
1
public/js/v1.1.5/app/login.js.map
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
1
public/js/v1.1.5/app/setup.js.map
Normal file
1
public/js/v1.1.5/app/setup.js.map
Normal file
File diff suppressed because one or more lines are too long
@@ -40,7 +40,6 @@
|
||||
<div class="col-sm-12 col-xs-6 checkbox checkbox-primary" title="include stargate connections">
|
||||
<input id="form_stargates" name="stargates" value="1" type="checkbox" checked>
|
||||
<label for="form_stargates">Stargates</label>
|
||||
<div class="help-block with-errors"></div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-12 col-xs-6 checkbox checkbox-primary" title="include jump bridge connections">
|
||||
@@ -55,12 +54,13 @@
|
||||
<div class="form-group">
|
||||
<label class="col-sm-2 control-label" for="{{mapSelectId}}">Maps</label>
|
||||
<div class="col-sm-10">
|
||||
<div class="input-group" title="add/remove maps for search">
|
||||
<div class="input-group">
|
||||
<select id="{{mapSelectId}}" name="mapIds[]" multiple="multiple">
|
||||
{{#mapSelectOptions}}
|
||||
<option value="{{id}}" {{#selected}}selected{{/selected}}>{{name}}</option>
|
||||
{{/mapSelectOptions}}
|
||||
</select>
|
||||
<span class="help-block with-errors">Set maps from search</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -69,6 +69,8 @@
|
||||
|
||||
<hr>
|
||||
|
||||
{{! wormhole ----------------------------------------------------------------- }}
|
||||
|
||||
<div class="row">
|
||||
<div class="col-sm-4">
|
||||
<div class="form-group">
|
||||
@@ -76,7 +78,6 @@
|
||||
<div class="col-sm-12 col-xs-6 checkbox checkbox-primary" title="include wormhole connections">
|
||||
<input id="form_wormholes" name="wormholes" value="1" type="checkbox" checked>
|
||||
<label for="form_wormholes">Wormholes</label>
|
||||
<div class="help-block with-errors"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -88,7 +89,6 @@
|
||||
<div class="col-sm-12 col-xs-6 checkbox checkbox-warning checkbox-circle" title="include reduced connections">
|
||||
<input id="form_wormholes_reduced" name="wormholesReduced" value="1" type="checkbox" checked>
|
||||
<label for="form_wormholes_reduced">Stage 1 (reduced)</label>
|
||||
<div class="help-block with-errors"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -100,13 +100,22 @@
|
||||
<div class="col-sm-12 col-xs-6 checkbox checkbox-danger checkbox-circle" title="include critical connections">
|
||||
<input id="form_wormholes_critical" name="wormholesCritical" value="1" type="checkbox" checked>
|
||||
<label for="form_wormholes_critical">Stage 2 (critical)</label>
|
||||
<div class="help-block with-errors"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-4 col-sm-offset-8">
|
||||
<div class="form-group">
|
||||
<div class="col-sm-offset-1 col-sm-11">
|
||||
<div class="col-sm-12 col-xs-6 checkbox checkbox-danger checkbox-circle" title="include EOL connections">
|
||||
<input id="form_wormholes_eol" name="wormholesEOL" value="1" type="checkbox" checked>
|
||||
<label for="form_wormholes_eol">End of life (EOL)</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</form>
|
||||
</div>
|
||||
24
public/templates/dialog/route_settings.html
Normal file
24
public/templates/dialog/route_settings.html
Normal file
@@ -0,0 +1,24 @@
|
||||
<div id="{{id}}">
|
||||
<form role="form" class="form-horizontal">
|
||||
|
||||
<div class="row">
|
||||
<div class="col-xs-8">
|
||||
<div class="form-group">
|
||||
<label class="col-sm-2 control-label" for="form_system">Systems</label>
|
||||
<div class="col-sm-10">
|
||||
<div class="input-group">
|
||||
<label for="form_system"></label>
|
||||
<select id="form_system" name="routeSystems[]" class="{{selectClass}}" multiple="multiple">
|
||||
{{#systemSelectOptions}}
|
||||
<option value="{{name}}" data-systemid="{{systemId}}" selected="selected">{{name}}</option>
|
||||
{{/systemSelectOptions}}
|
||||
</select>
|
||||
<span class="help-block with-errors">Set default systems (max {{maxSelectionLength}}) for route search</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
</div>
|
||||
@@ -1,11 +1,28 @@
|
||||
<div class="list-group">
|
||||
{{#otherCharacters}}
|
||||
<a class="list-group-item" href="{{routes.ssoLogin}}?characterId={{id}}">
|
||||
<img src="https://image.eveonline.com/Character/{{id}}_32.jpg" alt="{{name}}">
|
||||
{{name}}
|
||||
</a>
|
||||
{{/otherCharacters}}
|
||||
<a class="list-group-item" target="_self" href="{{routes.ssoLogin}}?characterId=-1">
|
||||
<i class="fa fa-user-plus fa-fw"></i>add new
|
||||
</a>
|
||||
</div>
|
||||
<table id="{{id}}" class="table table-condensed">
|
||||
<tbody>
|
||||
{{#otherCharacters}}
|
||||
<tr>
|
||||
<td><img src="https://image.eveonline.com/Character/{{id}}_32.jpg" alt="{{name}}"></td>
|
||||
<td>{{name}}</td>
|
||||
<td class="text-right text-nowrap">
|
||||
<a class="btn btn-sm btn-default" href="{{routes.ssoLogin}}?characterId={{id}}" target="_blank" title="new tab">
|
||||
<i class="fa fa-fw fa-external-link"></i>
|
||||
</a>
|
||||
<a class="btn btn-sm btn-primary" href="{{routes.ssoLogin}}?characterId={{id}}" target="_self" title="switch character">
|
||||
<i class="fa fa-fw fa-exchange"></i>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
{{/otherCharacters}}
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>add more</td>
|
||||
<td class="text-right text-nowrap">
|
||||
<a class="btn btn-sm btn-success" href="{{routes.ssoLogin}}?characterId=-1" target="_self">
|
||||
<i class="fa fa-fw fa-user-plus"></i>
|
||||
new character
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
@@ -3,15 +3,16 @@
|
||||
<div class="col-xs-12 col-md-8 col-md-offset-2 pf-landing-pricing-panel">
|
||||
<div class="panel panel-primary pricing-big">
|
||||
<div class="panel-heading" >
|
||||
<h3 class="panel-title">Release v1.1.4</h3>
|
||||
<h3 class="panel-title">Release v1.1.5</h3>
|
||||
</div>
|
||||
<div class="panel-body no-padding text-align-center">
|
||||
<div class="price-features" style="min-height: inherit;">
|
||||
<ul class="list-unstyled text-left">
|
||||
<li><i class="fa fa-fw fa-angle-right"></i>New persistent system data (e.g. "description",...).</li>
|
||||
<li><i class="fa fa-fw fa-angle-right"></i>New persistent map settings ("grid snap", "magnetizing").</li>
|
||||
<li><i class="fa fa-fw fa-angle-right"></i>New "Thera" wormhole connection types.</li>
|
||||
<li><i class="fa fa-fw fa-angle-right"></i>complete <a href="javascript:void(0)" class="pf-navbar-version-info">changelog</a>.</li>
|
||||
<li><i class="fa fa-fw fa-angle-right"></i>New: Support for multiple active characters</li>
|
||||
<li><i class="fa fa-fw fa-angle-right"></i>New: Customizable default routes</li>
|
||||
<li><i class="fa fa-fw fa-angle-right"></i>New: Filter option for "<em>EOL</em>" connections added to route finder</li>
|
||||
|
||||
<li><i class="fa fa-fw fa-angle-double-right"></i>Complete <a href="javascript:void(0)" class="pf-navbar-version-info">changelog</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<div class="timeline-heading">
|
||||
<h4 class="timeline-title">
|
||||
<a href="{{releaseData.html_url}}" target="_blank">
|
||||
<i class="fa fa-tag" aria-hidden="true"></i> {{ releaseData.name }}
|
||||
<i class="fa fa-fw fa-tag"></i>{{ releaseData.name }}
|
||||
</a>
|
||||
|
||||
<span class="text-muted pull-right">
|
||||
|
||||
@@ -62,6 +62,20 @@
|
||||
<section id="pf-landing-login">
|
||||
<div class="container">
|
||||
|
||||
{* check for setup mode *}
|
||||
<check if="{{ array_key_exists('/setup', @ROUTES) && @PATHFINDER.SHOW_SETUP_WARNING }}">
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col-sm-8 col-sm-offset-2">
|
||||
<div class="alert alert-warning" >
|
||||
<span class="txt-color txt-color-warning">Setup mode active</span>
|
||||
<small>Disable setup route in routes.ini on production environment! <a href="{{ 'setup' | alias }}">Setup</a></small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</check>
|
||||
|
||||
{* cookie characters *}
|
||||
<check if="{{ @cookieCharacters }}">
|
||||
<true>
|
||||
@@ -80,20 +94,6 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{* check for setup mode *}
|
||||
<check if="{{ array_key_exists('/setup', @ROUTES) && @PATHFINDER.SHOW_SETUP_WARNING }}">
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col-sm-8 col-sm-offset-2">
|
||||
<div class="alert alert-warning" >
|
||||
<span class="txt-color txt-color-warning">Setup mode active</span>
|
||||
<small>Disable setup route in routes.ini in production environment! <a href="{{ 'setup' | alias }}">Setup</a></small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</check>
|
||||
|
||||
<div class="row text-center pf-character-selection">
|
||||
<repeat group="{{ @cookieCharacters }}" key="{{ @cookieName }}" value="{{ @characterData }}">
|
||||
<div class="col-sm-{{ @getCharacterGrid( @cookieCharacters ) }}">
|
||||
|
||||
@@ -827,6 +827,7 @@ table{
|
||||
|
||||
td{
|
||||
padding: 0 5px;
|
||||
vertical-align: middle !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1014,6 +1015,18 @@ td.pf-popover-trigger{
|
||||
@include box-shadow(0 6px 12px rgba(0,0,0,.4));
|
||||
}
|
||||
|
||||
// character switch popover
|
||||
#pf-head-character-switch{
|
||||
td{
|
||||
border: none;
|
||||
|
||||
&:first-child + td{
|
||||
// 2nd column
|
||||
padding: 0 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// footer (map) ===================================================================================
|
||||
#pf-footer{
|
||||
position: absolute;
|
||||
|
||||
@@ -8,13 +8,12 @@ div.pf-map-drag-to-select {
|
||||
opacity: 0; // triggered by js
|
||||
z-index: 9000;
|
||||
border: 1px dashed $gray-lighter;
|
||||
will-change: opacity, visibility;
|
||||
will-change: left, top, width, height, opacity;
|
||||
@include border-radius(5px);
|
||||
@include transition(opacity 0.15s linear, visibility 0.15s linear);
|
||||
@include transition(opacity 0.15s linear);
|
||||
|
||||
&.active {
|
||||
visibility: visible;
|
||||
opacity: 0.3;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user