- New "station" data added, closed #858
- Improved system deeplinks. EveEye.com added, closed #859 - Improved cronjob performance for "SovereigntyData" import, closed #853 - Updated static DB dump for `eve_universe.sql`
@@ -14,7 +14,7 @@
|
||||
"node": true,
|
||||
|
||||
// Allow ES6.
|
||||
"esversion": 6,
|
||||
"esversion": 7,
|
||||
|
||||
/*
|
||||
* ENFORCING OPTIONS
|
||||
|
||||
12
app/cron.ini
@@ -59,9 +59,13 @@ deleteStatisticsData = Cron\StatisticsUpdate->deleteStatisticsD
|
||||
; truncate map history log files
|
||||
truncateMapHistoryLogFiles = Cron\MapHistory->truncateFiles, @halfHour
|
||||
|
||||
; updates small amount of static system data from CCP API
|
||||
;updateUniverseSystems = Cron\Universe->updateUniverseSystems, @instant
|
||||
;updateSovereigntyData = Cron\Universe->updateSovereigntyData, @instant
|
||||
; sync "sovereignty" and "faction warfare" data from CCP´s ESI API
|
||||
updateSovereigntyData = Cron\Universe->updateSovereigntyData, @halfPastHour
|
||||
|
||||
; setup universe DB with static data from ESI
|
||||
; sync static system data from CCP´s ESI API
|
||||
; -> Job is WIP!
|
||||
;updateUniverseSystems = Cron\Universe->updateUniverseSystems, @instant
|
||||
|
||||
; bootstrap job for "eve_universe" DB from CCP´s ESI API
|
||||
; -> Only for development! This job is used to build the initial export/sql/eve_universe.sql
|
||||
;setup = Cron\Universe->setup, @instant
|
||||
@@ -176,7 +176,10 @@ class Map extends Controller\AccessController {
|
||||
// get third party APIs -----------------------------------------------------------------------------------
|
||||
$return->url = [
|
||||
'ccpImageServer' => Config::getPathfinderData('api.ccp_image_server'),
|
||||
'zKillboard' => Config::getPathfinderData('api.z_killboard')
|
||||
'zKillboard' => Config::getPathfinderData('api.z_killboard'),
|
||||
'eveeye' => Config::getPathfinderData('api.eveeye'),
|
||||
'dotlan' => Config::getPathfinderData('api.dotlan'),
|
||||
'anoik' => Config::getPathfinderData('api.anoik')
|
||||
];
|
||||
|
||||
// Character default config -------------------------------------------------------------------------------
|
||||
|
||||
@@ -38,6 +38,7 @@ class System extends AbstractRestController {
|
||||
$systemData->signatures = $system->getSignaturesData();
|
||||
$systemData->sigHistory = $system->getSignaturesHistory();
|
||||
$systemData->structures = $system->getStructuresData();
|
||||
$systemData->stations = $system->getStationsData();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -111,7 +111,7 @@ class System extends Controller\AccessController {
|
||||
}
|
||||
|
||||
/**
|
||||
* set destination for specific systemIds
|
||||
* set destination for system, station or structure
|
||||
* @param \Base $f3
|
||||
* @throws \Exception
|
||||
*/
|
||||
@@ -120,25 +120,25 @@ class System extends Controller\AccessController {
|
||||
|
||||
$return = (object) [];
|
||||
$return->error = [];
|
||||
$return->systemData = [];
|
||||
$return->destData = [];
|
||||
|
||||
if( !empty($postData['systemData'] )){
|
||||
if(!empty($destData = (array)$postData['destData'])){
|
||||
$activeCharacter = $this->getCharacter();
|
||||
|
||||
$return->clearOtherWaypoints = (bool)$postData['clearOtherWaypoints'];
|
||||
$return->first = (bool)$postData['first'];
|
||||
|
||||
if( $accessToken = $activeCharacter->getAccessToken() ){
|
||||
if($accessToken = $activeCharacter->getAccessToken()){
|
||||
$options = [
|
||||
'clearOtherWaypoints' => $return->clearOtherWaypoints,
|
||||
'addToBeginning' => $return->first,
|
||||
];
|
||||
|
||||
foreach($postData['systemData'] as $systemData){
|
||||
$response = $f3->ccpClient()->setWaypoint($systemData['systemId'], $accessToken, $options);
|
||||
foreach($destData as $data){
|
||||
$response = $f3->ccpClient()->setWaypoint((int)$data['id'], $accessToken, $options);
|
||||
|
||||
if(empty($response)){
|
||||
$return->systemData[] = $systemData;
|
||||
$return->destData[] = $data;
|
||||
}else{
|
||||
$error = (object) [];
|
||||
$error->type = 'error';
|
||||
|
||||
@@ -161,7 +161,7 @@ class Universe extends Controller {
|
||||
$system = Model\Universe\AbstractUniverseModel::getNew('SystemModel');
|
||||
$indexData = [];
|
||||
foreach($systemIds as $systemId){
|
||||
$system->getById($systemId);
|
||||
$system->getById($systemId, 0);
|
||||
if($hashKeyId = $system->getHashKey()){
|
||||
$indexData[$hashKeyId] = $system->getData();
|
||||
}
|
||||
|
||||
@@ -112,6 +112,8 @@ class Setup extends Controller {
|
||||
'Model\Universe\FactionModel',
|
||||
'Model\Universe\AllianceModel',
|
||||
'Model\Universe\CorporationModel',
|
||||
'Model\Universe\RaceModel',
|
||||
'Model\Universe\StationModel',
|
||||
'Model\Universe\StructureModel',
|
||||
'Model\Universe\StargateModel',
|
||||
'Model\Universe\StarModel',
|
||||
|
||||
@@ -10,13 +10,21 @@ namespace cron;
|
||||
|
||||
abstract class AbstractCron {
|
||||
|
||||
// default max_execution_time for cronJobs
|
||||
/**
|
||||
* default max_execution_time for cronJobs
|
||||
// -> should be less then execution period
|
||||
*/
|
||||
const DEFAULT_MAX_EXECUTION_TIME = 50;
|
||||
|
||||
/**
|
||||
* set max execution time for cronjobs
|
||||
* -> Default CLI execution time is "0" -> infinite!
|
||||
* default threshold time in seconds before a running script (e.g. a large loop) should stop
|
||||
* -> so there is some time or e.g. logging,... left
|
||||
*/
|
||||
const DEFAULT_EXECUTION_TIME_THRESHOLD = 3;
|
||||
|
||||
/**
|
||||
* set max execution time for cronJbs
|
||||
* -> Default CLI execution time is 0 == infinite!
|
||||
* php.ini settings are ignored! http://php.net/manual/en/info.configuration.php#ini.max-execution-time
|
||||
* @param int $time
|
||||
*/
|
||||
@@ -24,4 +32,33 @@ abstract class AbstractCron {
|
||||
ini_set('max_execution_time', $time);
|
||||
}
|
||||
|
||||
/**
|
||||
* get max execution time
|
||||
* -> 0 means == infinite!
|
||||
* @return int
|
||||
*/
|
||||
protected function getMaxExecutionTime() : int {
|
||||
return (int)ini_get('max_execution_time');
|
||||
}
|
||||
|
||||
/**
|
||||
* checks execution time of a "long" running script
|
||||
* -> returns false if execution time is close to maxExecutionTime
|
||||
* @param float $timeTotalStart
|
||||
* @param float|null $timeCheck
|
||||
* @param int $timeThreshold
|
||||
* @return bool
|
||||
*/
|
||||
protected function isExecutionTimeLeft(float $timeTotalStart, float $timeCheck = null, int $timeThreshold = self::DEFAULT_EXECUTION_TIME_THRESHOLD) : bool {
|
||||
$timeLeft = true;
|
||||
if($timeTotalMax = $this->getMaxExecutionTime()){
|
||||
$timeTotalMaxThreshold = $timeTotalStart + $timeTotalMax - $timeThreshold;
|
||||
$timeCheck = $timeCheck ? : microtime(true);
|
||||
if($timeCheck >= $timeTotalMaxThreshold){
|
||||
$timeLeft = false;
|
||||
}
|
||||
}
|
||||
return $timeLeft;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -13,6 +13,7 @@ use Model;
|
||||
class Universe extends AbstractCron {
|
||||
|
||||
const LOG_TEXT = '%s type: %s %s/%s peak: %s total: %s msg: %s';
|
||||
const LOG_TEXT_SOV_FW = '%s %4s/%-4s checked, %s peak, %s total, %4s updated [%4s sovChanges, %4s fwChanges], msg: %s';
|
||||
|
||||
|
||||
/**
|
||||
@@ -133,10 +134,11 @@ class Universe extends AbstractCron {
|
||||
* @param float $timeTotalStart
|
||||
*/
|
||||
private function echoLoaded(int $importCount, int $id, float $timeLoopStart, float $timeTotalStart){
|
||||
$time = microtime(true);
|
||||
echo '[' . date('H:i:s') . '] loaded ' . str_pad('', strlen($importCount), ' ') . ' id: ' . $this->formatIdValue($id) .
|
||||
' memory: ' . $this->formatMemoryValue(memory_get_usage()) .
|
||||
' time: ' . $this->formatSeconds(microtime(true) - $timeLoopStart) .
|
||||
' total: ' . $this->formatSeconds(microtime(true) - $timeTotalStart) . PHP_EOL;
|
||||
' time: ' . $this->formatSeconds($time - $timeLoopStart) .
|
||||
' total: ' . $this->formatSeconds($time - $timeTotalStart) . PHP_EOL;
|
||||
$this->echoFlush();
|
||||
}
|
||||
|
||||
@@ -169,8 +171,8 @@ class Universe extends AbstractCron {
|
||||
$msg = '';
|
||||
|
||||
$ids = [];
|
||||
$importCount = 0;
|
||||
$count = 0;
|
||||
$importCount = [];
|
||||
$modelClass = '';
|
||||
$setupModel = function(Model\Universe\AbstractUniverseModel &$model, int $id){};
|
||||
|
||||
@@ -193,6 +195,18 @@ class Universe extends AbstractCron {
|
||||
$model->loadStargatesData();
|
||||
};
|
||||
break;
|
||||
case 'station':
|
||||
$ids = $f3->ccpClient()->getUniverseSystems();
|
||||
$modelClass = 'SystemModel';
|
||||
$setupModel = function(Model\Universe\SystemModel &$model, int $id){
|
||||
if($model->getById($id)){
|
||||
$model->loadStationsData();
|
||||
}else{
|
||||
echo 'NOT VALID ' . $id . PHP_EOL;
|
||||
die();
|
||||
}
|
||||
};
|
||||
break;
|
||||
case 'sovereignty':
|
||||
// load sovereignty map data. Systems must be present first!
|
||||
$sovData = $f3->ccpClient()->getSovereigntyMap();
|
||||
@@ -243,6 +257,7 @@ class Universe extends AbstractCron {
|
||||
sort($ids, SORT_NUMERIC);
|
||||
$ids = array_slice($ids, $offset, $length);
|
||||
$importCount = count($ids);
|
||||
$count = 0;
|
||||
|
||||
$this->echoInfo($total, $offset, $importCount, $ids);
|
||||
$this->echoStart();
|
||||
@@ -264,9 +279,9 @@ class Universe extends AbstractCron {
|
||||
|
||||
// Log --------------------------------------------------------------------------------------------------------
|
||||
$log = new \Log('cron_' . __FUNCTION__ . '.log');
|
||||
$log->write( sprintf(self::LOG_TEXT, __FUNCTION__, $type,
|
||||
$log->write(sprintf(self::LOG_TEXT, __FUNCTION__, $type,
|
||||
$this->formatCounterValue($count), $importCount, $this->formatMemoryValue(memory_get_peak_usage ()),
|
||||
$this->formatSeconds(microtime(true) - $timeTotalStart), $msg) );
|
||||
$this->formatSeconds(microtime(true) - $timeTotalStart), $msg));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -278,23 +293,69 @@ class Universe extends AbstractCron {
|
||||
*/
|
||||
function updateSovereigntyData(\Base $f3){
|
||||
$this->setMaxExecutionTime();
|
||||
$timeTotalStart = microtime(true);
|
||||
$msg = '';
|
||||
|
||||
/**
|
||||
* @var $system Model\Universe\SystemModel
|
||||
*/
|
||||
$system = Model\Universe\AbstractUniverseModel::getNew('SystemModel');
|
||||
|
||||
$sovData = $f3->ccpClient()->getSovereigntyMap();
|
||||
$fwSystems = $f3->ccpClient()->getFactionWarSystems();
|
||||
$fwSystems = $fwSystems['systems'];
|
||||
$ids = !empty($sovData = $sovData['map']) ? array_keys($sovData): [];
|
||||
sort($ids, SORT_NUMERIC);
|
||||
$importCount = count($ids);
|
||||
$count = 0;
|
||||
|
||||
$changes = [];
|
||||
foreach($ids as $id){
|
||||
if($system->getById($id)){
|
||||
$system->updateSovereigntyData($sovData[$id]);
|
||||
$count++;
|
||||
|
||||
if(is_array($fwSystems[$id])){
|
||||
$system->updateFactionWarData($fwSystems[$id]);
|
||||
// skip wormhole systems -> can not have sov data
|
||||
// -> even though they are returned from sovereignty/map endpoint?!
|
||||
if(
|
||||
$system->getById($id, 0) &&
|
||||
strpos($system->security, 'C') === false
|
||||
){
|
||||
if($changedSovData = $system->updateSovereigntyData($sovData[$id])){
|
||||
$changes['sovereignty'][] = $id;
|
||||
}
|
||||
$system->reset();
|
||||
|
||||
$changedFwData = false;
|
||||
if(is_array($fwSystems[$id])){
|
||||
if($changedFwData = $system->updateFactionWarData($fwSystems[$id])){
|
||||
$changes['factionWarfare'][] = $id;
|
||||
}
|
||||
}
|
||||
|
||||
if($changedSovData || $changedFwData){
|
||||
$system->buildIndex();
|
||||
}
|
||||
}
|
||||
$system->reset();
|
||||
|
||||
// stop loop if runtime gets close to "max_execution_time"
|
||||
// -> we need some time for writing *.log file
|
||||
if(!$this->isExecutionTimeLeft($timeTotalStart)){
|
||||
$msg = 'Script execution stopped due to "max_execution_time" limit reached';
|
||||
// TODO store current loop index and use it as new "offset" for next call
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$changedIds = array_reduce($changes, function(array $reducedIds, array $changedIds) : array {
|
||||
return array_unique(array_merge($reducedIds, $changedIds));
|
||||
}, []);
|
||||
|
||||
// Log ------------------------
|
||||
$log = new \Log('cron_' . __FUNCTION__ . '.log');
|
||||
$log->write(sprintf(self::LOG_TEXT_SOV_FW, __FUNCTION__,
|
||||
$count, $importCount, $this->formatMemoryValue(memory_get_peak_usage ()),
|
||||
$this->formatSeconds(microtime(true) - $timeTotalStart),
|
||||
count($changedIds), count($changes['sovereignty'] ? : []), count($changes['factionWarfare'] ? : []),
|
||||
$msg));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
124
app/main/lib/PriorityCacheStore.php
Normal file
@@ -0,0 +1,124 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace lib;
|
||||
|
||||
|
||||
class PriorityCacheStore {
|
||||
|
||||
/**
|
||||
* default max entry limit before store gets truncated
|
||||
*/
|
||||
const DEFAULT_ENTRY_LIMIT = 100;
|
||||
|
||||
/**
|
||||
* default cleanup interval
|
||||
* -> truncate store after 10 inserts. Max store entries:
|
||||
* DEFAULT_ENTRY_LIMIT + DEFAULT_CLEANUP_INTERVAL - 1
|
||||
*/
|
||||
const DEFAULT_CLEANUP_INTERVAL = 10;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected $entryLimit;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected $cleanupInterval;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $store;
|
||||
|
||||
/**
|
||||
* @var \SplPriorityQueue
|
||||
*/
|
||||
protected $priorityQueue;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected $priority = 0;
|
||||
|
||||
/**
|
||||
* PriorityCacheStore constructor.
|
||||
* @param int $entryLimit
|
||||
* @param int $cleanupInterval
|
||||
*/
|
||||
function __construct(int $entryLimit = self::DEFAULT_ENTRY_LIMIT, int $cleanupInterval = self::DEFAULT_CLEANUP_INTERVAL){
|
||||
$this->cleanupInterval = $cleanupInterval;
|
||||
$this->entryLimit = $entryLimit;
|
||||
$this->store = [];
|
||||
$this->priorityQueue = new \SplPriorityQueue ();
|
||||
$this->priorityQueue->setExtractFlags(\SplPriorityQueue::EXTR_BOTH);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $key
|
||||
* @param $data
|
||||
*/
|
||||
public function set($key, $data){
|
||||
if(!$this->exists($key)){
|
||||
$this->priorityQueue->insert($key, $this->priority--);
|
||||
}
|
||||
|
||||
$this->store[$key] = $data;
|
||||
|
||||
// check cleanup interval and cleanup Store
|
||||
$this->cleanupInterval();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $key
|
||||
* @return mixed|null
|
||||
*/
|
||||
public function get($key){
|
||||
return $this->exists($key) ? $this->store[$key] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $key
|
||||
* @return bool
|
||||
*/
|
||||
public function exists($key){
|
||||
return isset($this->store[$key]);
|
||||
}
|
||||
|
||||
public function cleanupInterval() : void {
|
||||
if(
|
||||
!$this->priorityQueue->isEmpty() && $this->cleanupInterval &&
|
||||
($this->priorityQueue->count() % $this->cleanupInterval === 0)
|
||||
){
|
||||
$this->cleanup();
|
||||
}
|
||||
}
|
||||
|
||||
public function cleanup(){
|
||||
while(
|
||||
$this->entryLimit < $this->priorityQueue->count() &&
|
||||
$this->priorityQueue->valid()
|
||||
){
|
||||
if($this->exists($key = $this->priorityQueue->extract()['data'])){
|
||||
unset($this->store[$key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function clear(){
|
||||
$limit = $this->entryLimit;
|
||||
$this->entryLimit = 0;
|
||||
$this->cleanup();
|
||||
// restore entryLimit for next data
|
||||
$this->entryLimit = $limit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function __toString(){
|
||||
return 'Store count: ' . count($this->store) . ' priorityQueue count: ' . $this->priorityQueue->count();
|
||||
}
|
||||
}
|
||||
@@ -74,7 +74,7 @@ class Util {
|
||||
* @param mixed $array
|
||||
* @return bool
|
||||
*/
|
||||
static function is_assoc($array): bool {
|
||||
static function is_assoc($array) : bool {
|
||||
$isAssoc = false;
|
||||
if(
|
||||
is_array($array) &&
|
||||
@@ -127,7 +127,7 @@ class Util {
|
||||
* @param int $maxHideChars
|
||||
* @return string
|
||||
*/
|
||||
static function obscureString(string $string, int $maxHideChars = 10): string {
|
||||
static function obscureString(string $string, int $maxHideChars = 10) : string {
|
||||
$formatted = '';
|
||||
$length = mb_strlen((string)$string);
|
||||
if($length > 0){
|
||||
@@ -143,7 +143,7 @@ class Util {
|
||||
* @param array $scopes
|
||||
* @return string
|
||||
*/
|
||||
static function getHashFromScopes($scopes){
|
||||
static function getHashFromScopes($scopes) : string {
|
||||
$scopes = (array)$scopes;
|
||||
sort($scopes);
|
||||
return md5(serialize($scopes));
|
||||
|
||||
@@ -521,7 +521,7 @@ abstract class AbstractModel extends Cortex {
|
||||
* @return bool
|
||||
*/
|
||||
public function getById(int $id, int $ttl = self::DEFAULT_SQL_TTL, bool $isActive = true) : bool {
|
||||
return $this->getByForeignKey('id', $id, ['limit' => 1], $ttl, $isActive);
|
||||
return $this->getByForeignKey($this->primary, $id, ['limit' => 1], $ttl, $isActive);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -534,10 +534,7 @@ abstract class AbstractModel extends Cortex {
|
||||
* @return bool
|
||||
*/
|
||||
public function getByForeignKey(string $key, $value, array $options = [], int $ttl = 0, bool $isActive = true) : bool {
|
||||
$filters = [];
|
||||
if($this->exists($key)){
|
||||
$filters[] = [$key . ' = :' . $key, ':' . $key => $value];
|
||||
}
|
||||
$filters = [self::getFilter($key, $value)];
|
||||
|
||||
if($isActive && $this->exists('active')){
|
||||
$filters[] = self::getFilter('active', true);
|
||||
@@ -975,6 +972,15 @@ abstract class AbstractModel extends Cortex {
|
||||
return \Base::instance();
|
||||
}
|
||||
|
||||
/**
|
||||
* get model data as array
|
||||
* @param $data
|
||||
* @return array
|
||||
*/
|
||||
public static function toArray($data) : array {
|
||||
return json_decode(json_encode($data), true);
|
||||
}
|
||||
|
||||
/**
|
||||
* get new filter array representation
|
||||
* -> $suffix can be used fore unique placeholder,
|
||||
|
||||
@@ -12,8 +12,14 @@ use DB\SQL\Schema;
|
||||
|
||||
class AllianceMapModel extends AbstractPathfinderModel {
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $table = 'alliance_map';
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $fieldConf = [
|
||||
'active' => [
|
||||
'type' => Schema::DT_BOOL,
|
||||
|
||||
@@ -96,6 +96,15 @@ class CharacterLogModel extends AbstractPathfinderModel {
|
||||
'default' => '',
|
||||
'activity-log' => true
|
||||
],
|
||||
'structureTypeId' => [
|
||||
'type' => Schema::DT_INT,
|
||||
'index' => true
|
||||
],
|
||||
'structureTypeName' => [
|
||||
'type' => Schema::DT_VARCHAR128,
|
||||
'nullable' => false,
|
||||
'default' => ''
|
||||
],
|
||||
'structureId' => [
|
||||
'type' => Schema::DT_BIGINT,
|
||||
'index' => true,
|
||||
@@ -146,9 +155,13 @@ class CharacterLogModel extends AbstractPathfinderModel {
|
||||
}
|
||||
|
||||
if( isset($logData['structure']) ){
|
||||
$this->structureTypeId = (int)$logData['structure']['type']['id'];
|
||||
$this->structureTypeName = $logData['structure']['type']['name'];
|
||||
$this->structureId = (int)$logData['structure']['id'];
|
||||
$this->structureName = $logData['structure']['name'];
|
||||
}else{
|
||||
$this->structureTypeId = null;
|
||||
$this->structureTypeName = '';
|
||||
$this->structureId = null;
|
||||
$this->structureName = '';
|
||||
}
|
||||
@@ -178,20 +191,15 @@ class CharacterLogModel extends AbstractPathfinderModel {
|
||||
$logData->station->name = $this->stationName;
|
||||
|
||||
$logData->structure = (object) [];
|
||||
$logData->structure->type = (object) [];
|
||||
$logData->structure->type->id = $this->structureTypeId;
|
||||
$logData->structure->type->name = $this->structureTypeName;
|
||||
$logData->structure->id = (int)$this->structureId;
|
||||
$logData->structure->name = $this->structureName;
|
||||
|
||||
return $logData;
|
||||
}
|
||||
|
||||
/**
|
||||
* get 'character log' data as array
|
||||
* @return array
|
||||
*/
|
||||
public function getDataAsArray() : array {
|
||||
return json_decode(json_encode($this->getData()), true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Event "Hook" function
|
||||
* return false will stop any further action
|
||||
|
||||
@@ -857,23 +857,22 @@ class CharacterModel extends AbstractPathfinderModel {
|
||||
if($this->isOnline($accessToken)){
|
||||
$locationData = self::getF3()->ccpClient()->getCharacterLocationData($this->_id, $accessToken);
|
||||
|
||||
if( !empty($locationData['system']['id']) ){
|
||||
if(!empty($locationData['system']['id'])){
|
||||
// character is currently in-game
|
||||
|
||||
// get current $characterLog or get new ---------------------------------------------------
|
||||
if( !($characterLog = $this->getLog()) ){
|
||||
// get current $characterLog or get new -------------------------------------------------------
|
||||
if(!$characterLog = $this->getLog()){
|
||||
// create new log
|
||||
$characterLog = $this->rel('characterLog');
|
||||
}
|
||||
|
||||
// get current log data and modify on change
|
||||
$logData = $characterLog->getDataAsArray();
|
||||
$logData = $characterLog::toArray($characterLog->getData());
|
||||
|
||||
// check system and station data for changes ----------------------------------------------
|
||||
// check system and station data for changes --------------------------------------------------
|
||||
|
||||
// IDs for "systemId", "stationId" that require more data
|
||||
$lookupUniverseIds = [];
|
||||
|
||||
if(
|
||||
empty($logData['system']['name']) ||
|
||||
$logData['system']['id'] !== $locationData['system']['id']
|
||||
@@ -882,33 +881,18 @@ class CharacterModel extends AbstractPathfinderModel {
|
||||
$lookupUniverseIds[] = $locationData['system']['id'];
|
||||
}
|
||||
|
||||
if( !empty($locationData['station']['id']) ){
|
||||
if(
|
||||
empty($logData['station']['name']) ||
|
||||
$logData['station']['id'] !== $locationData['station']['id']
|
||||
){
|
||||
// station changed -> request "station name" for current station
|
||||
$lookupUniverseIds[] = $locationData['station']['id'];
|
||||
}
|
||||
}else{
|
||||
unset($logData['station']);
|
||||
}
|
||||
|
||||
$logData = array_replace_recursive($logData, $locationData);
|
||||
|
||||
// get "more" data for systemId and/or stationId -----------------------------------------
|
||||
if( !empty($lookupUniverseIds) ){
|
||||
// get "more" data for systemId ---------------------------------------------------------------
|
||||
if(!empty($lookupUniverseIds)){
|
||||
// get "more" information for some Ids (e.g. name)
|
||||
$universeData = self::getF3()->ccpClient()->getUniverseNamesData($lookupUniverseIds);
|
||||
|
||||
if( !empty($universeData) && !isset($universeData['error']) ){
|
||||
if(!empty($universeData) && !isset($universeData['error'])){
|
||||
// We expect max ONE system AND/OR station data, not an array of e.g. systems
|
||||
if(!empty($universeData['system'])){
|
||||
$universeData['system'] = reset($universeData['system']);
|
||||
}
|
||||
if(!empty($universeData['station'])){
|
||||
$universeData['station'] = reset($universeData['station']);
|
||||
}
|
||||
|
||||
$logData = array_replace_recursive($logData, $universeData);
|
||||
}else{
|
||||
@@ -917,32 +901,63 @@ class CharacterModel extends AbstractPathfinderModel {
|
||||
}
|
||||
}
|
||||
|
||||
// check structure data for changes -------------------------------------------------------
|
||||
// check station data for changes -------------------------------------------------------------
|
||||
if(!$deleteLog){
|
||||
// IDs for "stationId" that require more data
|
||||
$lookupStationId = 0;
|
||||
if(!empty($locationData['station']['id'])){
|
||||
if(
|
||||
empty($logData['station']['name']) ||
|
||||
$logData['station']['id'] !== $locationData['station']['id']
|
||||
){
|
||||
// station changed -> request station data
|
||||
$lookupStationId = $locationData['station']['id'];
|
||||
}
|
||||
}else{
|
||||
unset($logData['station']);
|
||||
}
|
||||
|
||||
// get "more" data for stationId
|
||||
if($lookupStationId > 0){
|
||||
/**
|
||||
* @var $stationModel Universe\StationModel
|
||||
*/
|
||||
$stationModel = Universe\AbstractUniverseModel::getNew('StationModel');
|
||||
$stationModel->loadById($lookupStationId, $accessToken, $additionalOptions);
|
||||
if($stationModel->valid()){
|
||||
$stationData['station'] = $stationModel::toArray($stationModel->getData());
|
||||
$logData = array_replace_recursive($logData, $stationData);
|
||||
}else{
|
||||
unset($logData['station']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check structure data for changes -----------------------------------------------------------
|
||||
if(!$deleteLog){
|
||||
// IDs for "structureId" that require more data
|
||||
$lookupStructureId = 0;
|
||||
if( !empty($locationData['structure']['id']) ){
|
||||
if(!empty($locationData['structure']['id'])){
|
||||
if(
|
||||
empty($logData['structure']['name']) ||
|
||||
$logData['structure']['id'] !== $locationData['structure']['id']
|
||||
){
|
||||
// structure changed -> request "structure name" for current station
|
||||
// structure changed -> request structure data
|
||||
$lookupStructureId = $locationData['structure']['id'];
|
||||
}
|
||||
}else{
|
||||
unset($logData['structure']);
|
||||
}
|
||||
|
||||
// get "more" data for structureId ---------------------------------------------------
|
||||
// get "more" data for structureId
|
||||
if($lookupStructureId > 0){
|
||||
/**
|
||||
* @var $structureModel Universe\StructureModel
|
||||
*/
|
||||
$structureModel = Universe\AbstractUniverseModel::getNew('StructureModel');
|
||||
$structureModel->loadById($lookupStructureId, $accessToken, $additionalOptions);
|
||||
if(!$structureModel->dry()){
|
||||
$structureData['structure'] = (array)$structureModel->getData();
|
||||
if($structureModel->valid()){
|
||||
$structureData['structure'] = $structureModel::toArray($structureModel->getData());
|
||||
$logData = array_replace_recursive($logData, $structureData);
|
||||
}else{
|
||||
unset($logData['structure']);
|
||||
@@ -950,13 +965,13 @@ class CharacterModel extends AbstractPathfinderModel {
|
||||
}
|
||||
}
|
||||
|
||||
// check ship data for changes ------------------------------------------------------------
|
||||
if( !$deleteLog ){
|
||||
// check ship data for changes ----------------------------------------------------------------
|
||||
if(!$deleteLog){
|
||||
$shipData = self::getF3()->ccpClient()->getCharacterShipData($this->_id, $accessToken);
|
||||
|
||||
// IDs for "shipTypeId" that require more data
|
||||
$lookupShipTypeId = 0;
|
||||
if( !empty($shipData['ship']['typeId']) ){
|
||||
if(!empty($shipData['ship']['typeId'])){
|
||||
if(
|
||||
empty($logData['ship']['typeName']) ||
|
||||
$logData['ship']['typeId'] !== $shipData['ship']['typeId']
|
||||
@@ -973,7 +988,7 @@ class CharacterModel extends AbstractPathfinderModel {
|
||||
$invalidResponse = true;
|
||||
}
|
||||
|
||||
// get "more" data for shipTypeId ----------------------------------------------------
|
||||
// get "more" data for shipTypeId
|
||||
if($lookupShipTypeId > 0){
|
||||
/**
|
||||
* @var $typeModel Universe\TypeModel
|
||||
@@ -990,7 +1005,7 @@ class CharacterModel extends AbstractPathfinderModel {
|
||||
}
|
||||
}
|
||||
|
||||
if( !$deleteLog ){
|
||||
if(!$deleteLog){
|
||||
// mark log as "updated" even if no changes were made
|
||||
if($additionalOptions['markUpdated'] === true){
|
||||
$characterLog->touch('updated');
|
||||
@@ -1079,7 +1094,7 @@ class CharacterModel extends AbstractPathfinderModel {
|
||||
){
|
||||
$task = 'add';
|
||||
$mapIds = [];
|
||||
$historyLog = $characterLog->getDataAsArray();
|
||||
$historyLog = $characterLog::toArray($characterLog->getData());
|
||||
|
||||
if($logHistoryData = $this->getLogsHistory()){
|
||||
// skip logging if no relevant fields changed
|
||||
|
||||
@@ -12,8 +12,14 @@ use DB\SQL\Schema;
|
||||
|
||||
class CorporationMapModel extends AbstractPathfinderModel {
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $table = 'corporation_map';
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $fieldConf = [
|
||||
'active' => [
|
||||
'type' => Schema::DT_BOOL,
|
||||
|
||||
@@ -125,15 +125,15 @@ class StructureModel extends AbstractPathfinderModel {
|
||||
/**
|
||||
* set corporationId (owner) for this structure
|
||||
* -> if corporation does not exists in DB -> load from API
|
||||
* @param int $corporationId
|
||||
* @param int|null $corporationId
|
||||
* @return int|null
|
||||
*/
|
||||
public function set_corporationId(int $corporationId) : ?int {
|
||||
public function set_corporationId(?int $corporationId) : ?int {
|
||||
$oldCorporationId = $this->get('corporationId', true) ? : 0;
|
||||
|
||||
if($corporationId){
|
||||
if($corporationId !== $oldCorporationId){
|
||||
// make sure there is already corporation data stored for new corporationId
|
||||
// make sure there is already corporation data available for new corporationId
|
||||
/**
|
||||
* @var CorporationModel $corporation
|
||||
*/
|
||||
@@ -151,26 +151,20 @@ class StructureModel extends AbstractPathfinderModel {
|
||||
}
|
||||
/**
|
||||
* validates systemId
|
||||
* -> a structure always belongs to the same system
|
||||
* @param string $key
|
||||
* @param string $val
|
||||
* @return bool
|
||||
*/
|
||||
protected function validate_systemId(string $key, string $val): bool {
|
||||
$valid = true;
|
||||
|
||||
if( !$this->dry() && $this->systemId !== (int)$val ){
|
||||
// structure always belongs to the same system
|
||||
$valid = false;
|
||||
}
|
||||
|
||||
return $valid;
|
||||
protected function validate_systemId(string $key, string $val) : bool {
|
||||
return !($this->valid() && $this->systemId !== (int)$val);
|
||||
}
|
||||
|
||||
/**
|
||||
* check whether this model is valid or not
|
||||
* @return bool
|
||||
*/
|
||||
public function isValid(): bool {
|
||||
public function isValid() : bool {
|
||||
if($valid = parent::isValid()){
|
||||
// structure always belongs to a systemId
|
||||
if(!(int)$this->systemId){
|
||||
@@ -239,7 +233,7 @@ class StructureModel extends AbstractPathfinderModel {
|
||||
* @param string $name
|
||||
* @param int $systemId
|
||||
*/
|
||||
public function getByName(CorporationModel $corporation, string $name, int $systemId) {
|
||||
public function getByName(CorporationModel $corporation, string $name, int $systemId){
|
||||
if( !$corporation->dry() && $name){
|
||||
$this->has('structureCorporations', ['corporationId = :corporationId', ':corporationId' => $corporation->_id]);
|
||||
$this->load(['name = :name AND systemId = :systemId AND active = :active',
|
||||
|
||||
@@ -13,8 +13,14 @@ use DB\SQL\Schema;
|
||||
|
||||
class StructureStatusModel extends AbstractPathfinderModel {
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $table = 'structure_status';
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $fieldConf = [
|
||||
'active' => [
|
||||
'type' => Schema::DT_BOOL,
|
||||
@@ -42,6 +48,9 @@ class StructureStatusModel extends AbstractPathfinderModel {
|
||||
]
|
||||
];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected static $tableData = [
|
||||
[
|
||||
'id' => 1,
|
||||
|
||||
@@ -10,6 +10,7 @@ namespace Model\Pathfinder;
|
||||
|
||||
use DB\SQL\Schema;
|
||||
use lib\logging;
|
||||
use lib\PriorityCacheStore;
|
||||
use Controller\Ccp\Universe;
|
||||
|
||||
class SystemModel extends AbstractMapTrackingModel {
|
||||
@@ -39,16 +40,16 @@ class SystemModel extends AbstractMapTrackingModel {
|
||||
*/
|
||||
const DATA_CACHE_KEY_SIGNATURES_HISTORY = 'HISTORY_SIGNATURES';
|
||||
|
||||
/**
|
||||
* @var PriorityCacheStore
|
||||
*/
|
||||
protected static $priorityCacheStore;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $table = 'system';
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $staticSystemDataCache = [];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
@@ -242,14 +243,19 @@ class SystemModel extends AbstractMapTrackingModel {
|
||||
*/
|
||||
private function getStaticSystemData(){
|
||||
$staticData = null;
|
||||
if( !empty($this->staticSystemDataCache[$this->systemId]) ){
|
||||
$staticData = $this->staticSystemDataCache[$this->systemId];
|
||||
if(!is_object(self::$priorityCacheStore)){
|
||||
self::$priorityCacheStore = new PriorityCacheStore();
|
||||
}
|
||||
|
||||
if(self::$priorityCacheStore->exists($this->systemId)){
|
||||
$staticData = self::$priorityCacheStore->get($this->systemId);
|
||||
}else{
|
||||
$staticData = (new Universe())->getSystemData($this->systemId);
|
||||
if($staticData){
|
||||
$this->staticSystemDataCache = [$this->systemId => $staticData];
|
||||
self::$priorityCacheStore->set($this->systemId, $staticData);
|
||||
}
|
||||
}
|
||||
|
||||
return $staticData;
|
||||
}
|
||||
|
||||
@@ -457,6 +463,10 @@ class SystemModel extends AbstractMapTrackingModel {
|
||||
return $this->getStaticSystemValue('planets');
|
||||
}
|
||||
|
||||
public function get_stations(){
|
||||
return $this->getStaticSystemValue('stations');
|
||||
}
|
||||
|
||||
public function get_sovereignty(){
|
||||
return $this->getStaticSystemValue('sovereignty');
|
||||
}
|
||||
@@ -657,6 +667,14 @@ class SystemModel extends AbstractMapTrackingModel {
|
||||
return $this->getMap()->getStructuresData($this->systemId);
|
||||
}
|
||||
|
||||
/**
|
||||
* get data for all stations in this system
|
||||
* @return array
|
||||
*/
|
||||
public function getStationsData() : array {
|
||||
return $this->stations ? : [];
|
||||
}
|
||||
|
||||
/**
|
||||
* check whether this system is in w-space
|
||||
* @return bool
|
||||
|
||||
@@ -36,6 +36,21 @@ abstract class AbstractUniverseModel extends AbstractModel {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* setter for positions array (x/y/z)
|
||||
* @param $position
|
||||
* @return null
|
||||
*/
|
||||
public function set_position($position){
|
||||
$position = (array)$position;
|
||||
if(count($position) === 3){
|
||||
$this->x = $position['x'];
|
||||
$this->y = $position['y'];
|
||||
$this->z = $position['z'];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Event "Hook" function
|
||||
* return false will stop any further action
|
||||
|
||||
@@ -74,21 +74,6 @@ class ConstellationModel extends AbstractUniverseModel {
|
||||
return $constellationData;
|
||||
}
|
||||
|
||||
/**
|
||||
* setter for positions array (x/y/z)
|
||||
* @param $position
|
||||
* @return null
|
||||
*/
|
||||
public function set_position($position){
|
||||
$position = (array)$position;
|
||||
if(count($position) === 3){
|
||||
$this->x = $position['x'];
|
||||
$this->y = $position['y'];
|
||||
$this->z = $position['z'];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $id
|
||||
* @param string $accessToken
|
||||
|
||||
@@ -64,6 +64,9 @@ class CorporationModel extends AbstractUniverseModel {
|
||||
],
|
||||
'sovereigntySystems' => [
|
||||
'has-many' => ['Model\Universe\SovereigntyMapModel', 'corporationId']
|
||||
],
|
||||
'stations' => [
|
||||
'has-many' => ['Model\Universe\StationModel', 'corporationId']
|
||||
]
|
||||
];
|
||||
|
||||
@@ -102,7 +105,7 @@ class CorporationModel extends AbstractUniverseModel {
|
||||
|
||||
if($data['allianceId']){
|
||||
/**
|
||||
* @var $faction AllianceModel
|
||||
* @var $alliance AllianceModel
|
||||
*/
|
||||
$alliance = $this->rel('allianceId');
|
||||
$alliance->loadById($data['allianceId'], $accessToken, $additionalOptions);
|
||||
|
||||
@@ -89,7 +89,7 @@ class DogmaAttributeModel extends AbstractUniverseModel {
|
||||
*/
|
||||
protected function loadData(int $id, string $accessToken = '', array $additionalOptions = []){
|
||||
$data = self::getF3()->ccpClient()->getDogmaAttributeData($id);
|
||||
if(!empty($data)){
|
||||
if(!empty($data) && !isset($data['error'])){
|
||||
$this->copyfrom($data, ['id', 'name', 'displayName', 'description', 'published', 'stackable', 'highIsGood', 'defaultValue', 'iconId', 'unitId']);
|
||||
$this->save();
|
||||
}
|
||||
|
||||
@@ -46,6 +46,9 @@ class FactionModel extends AbstractUniverseModel {
|
||||
'nullable' => false,
|
||||
'default' => 0
|
||||
],
|
||||
'race' => [ // faction API endpoint dont have "raceId" data, but race API endpoint has
|
||||
'has-one' => ['Model\Universe\RaceModel', 'factionId']
|
||||
],
|
||||
'alliances' => [
|
||||
'has-many' => ['Model\Universe\AllianceModel', 'factionId']
|
||||
],
|
||||
@@ -82,7 +85,7 @@ class FactionModel extends AbstractUniverseModel {
|
||||
*/
|
||||
protected function loadData(int $id, string $accessToken = '', array $additionalOptions = []){
|
||||
$data = self::getF3()->ccpClient()->getUniverseFactionData($id);
|
||||
if(!empty($data)){
|
||||
if(!empty($data) && !isset($data['error'])){
|
||||
$this->copyfrom($data, ['id', 'name', 'description', 'sizeFactor', 'stationCount', 'stationSystemCount']);
|
||||
$this->save();
|
||||
}
|
||||
|
||||
@@ -75,21 +75,6 @@ class PlanetModel extends AbstractUniverseModel {
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* setter for positions array (x/y/z)
|
||||
* @param $position
|
||||
* @return null
|
||||
*/
|
||||
public function set_position($position){
|
||||
$position = (array)$position;
|
||||
if(count($position) === 3){
|
||||
$this->x = $position['x'];
|
||||
$this->y = $position['y'];
|
||||
$this->z = $position['z'];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $id
|
||||
* @param string $accessToken
|
||||
|
||||
82
app/main/model/universe/racemodel.php
Normal file
@@ -0,0 +1,82 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: Exodus 4D
|
||||
* Date: 22.10.2019
|
||||
* Time: 03:21
|
||||
*/
|
||||
|
||||
namespace Model\Universe;
|
||||
|
||||
use DB\SQL\Schema;
|
||||
|
||||
class RaceModel extends AbstractUniverseModel {
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $table = 'race';
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $fieldConf = [
|
||||
'name' => [
|
||||
'type' => Schema::DT_VARCHAR128,
|
||||
'nullable' => false,
|
||||
'default' => ''
|
||||
],
|
||||
'description' => [
|
||||
'type' => Schema::DT_TEXT
|
||||
],
|
||||
'factionId' => [
|
||||
'type' => Schema::DT_INT,
|
||||
'index' => true,
|
||||
'belongs-to-one' => 'Model\Universe\FactionModel',
|
||||
'constraint' => [
|
||||
[
|
||||
'table' => 'faction',
|
||||
'on-delete' => 'CASCADE'
|
||||
]
|
||||
],
|
||||
'validate' => 'notDry'
|
||||
],
|
||||
'stations' => [
|
||||
'has-many' => ['Model\Universe\StationModel', 'raceId']
|
||||
]
|
||||
];
|
||||
|
||||
/**
|
||||
* get data
|
||||
* @return \stdClass
|
||||
*/
|
||||
public function getData(){
|
||||
$data = (object) [];
|
||||
$data->id = $this->_id;
|
||||
$data->name = $this->name;
|
||||
$data->faction = $this->factionId->getData();
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* load data from API into $this and save $this
|
||||
* @param int $id
|
||||
* @param string $accessToken
|
||||
* @param array $additionalOptions
|
||||
*/
|
||||
protected function loadData(int $id, string $accessToken = '', array $additionalOptions = []){
|
||||
$data = self::getF3()->ccpClient()->getUniverseRaceData($id);
|
||||
if(!empty($data) && !isset($data['error'])){
|
||||
/**
|
||||
* @var $faction FactionModel
|
||||
*/
|
||||
$faction = $this->rel('factionId');
|
||||
$faction->loadById($data['factionId'], $accessToken, $additionalOptions);
|
||||
$data['factionId'] = $faction;
|
||||
|
||||
$this->copyfrom($data, ['id', 'name', 'description', 'factionId']);
|
||||
$this->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -74,7 +74,6 @@ class StargateModel extends AbstractUniverseModel {
|
||||
];
|
||||
|
||||
public function getData(){
|
||||
|
||||
$stargateData = (object) [];
|
||||
$stargateData->id = $this->_id;
|
||||
$stargateData->type = $this->typeId->name;
|
||||
@@ -83,21 +82,6 @@ class StargateModel extends AbstractUniverseModel {
|
||||
return $stargateData;
|
||||
}
|
||||
|
||||
/**
|
||||
* setter for positions array (x/y/z)
|
||||
* @param $position
|
||||
* @return null
|
||||
*/
|
||||
public function set_position($position){
|
||||
$position = (array)$position;
|
||||
if(count($position) === 3){
|
||||
$this->x = $position['x'];
|
||||
$this->y = $position['y'];
|
||||
$this->z = $position['z'];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $id
|
||||
* @param string $accessToken
|
||||
|
||||
165
app/main/model/universe/stationmodel.php
Normal file
@@ -0,0 +1,165 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: Exodus 4D
|
||||
* Date: 22.10.2019
|
||||
* Time: 03:00
|
||||
*/
|
||||
|
||||
namespace Model\Universe;
|
||||
|
||||
use DB\SQL\Schema;
|
||||
|
||||
class StationModel extends AbstractUniverseModel {
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $table = 'station';
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $fieldConf = [
|
||||
'name' => [
|
||||
'type' => Schema::DT_VARCHAR128,
|
||||
'nullable' => false,
|
||||
'default' => ''
|
||||
],
|
||||
'systemId' => [
|
||||
'type' => Schema::DT_INT,
|
||||
'index' => true,
|
||||
'belongs-to-one' => 'Model\Universe\SystemModel',
|
||||
'constraint' => [
|
||||
[
|
||||
'table' => 'system',
|
||||
'on-delete' => 'CASCADE'
|
||||
]
|
||||
],
|
||||
'validate' => 'notDry'
|
||||
],
|
||||
'typeId' => [
|
||||
'type' => Schema::DT_INT,
|
||||
'index' => true,
|
||||
'belongs-to-one' => 'Model\Universe\TypeModel',
|
||||
'constraint' => [
|
||||
[
|
||||
'table' => 'type',
|
||||
'on-delete' => 'CASCADE'
|
||||
]
|
||||
],
|
||||
'validate' => 'notDry'
|
||||
],
|
||||
'corporationId' => [
|
||||
'type' => Schema::DT_INT,
|
||||
'index' => true,
|
||||
'belongs-to-one' => 'Model\Universe\CorporationModel',
|
||||
'constraint' => [
|
||||
[
|
||||
'table' => 'corporation',
|
||||
'on-delete' => 'CASCADE'
|
||||
]
|
||||
]
|
||||
],
|
||||
'raceId' => [
|
||||
'type' => Schema::DT_INT,
|
||||
'index' => true,
|
||||
'belongs-to-one' => 'Model\Universe\RaceModel',
|
||||
'constraint' => [
|
||||
[
|
||||
'table' => 'race',
|
||||
'on-delete' => 'CASCADE'
|
||||
]
|
||||
]
|
||||
],
|
||||
'services' => [
|
||||
'type' => self::DT_JSON
|
||||
],
|
||||
'x' => [
|
||||
'type' => Schema::DT_BIGINT,
|
||||
'nullable' => false,
|
||||
'default' => 0
|
||||
],
|
||||
'y' => [
|
||||
'type' => Schema::DT_BIGINT,
|
||||
'nullable' => false,
|
||||
'default' => 0
|
||||
],
|
||||
'z' => [
|
||||
'type' => Schema::DT_BIGINT,
|
||||
'nullable' => false,
|
||||
'default' => 0
|
||||
]
|
||||
];
|
||||
|
||||
/**
|
||||
* get data
|
||||
* @return \stdClass
|
||||
*/
|
||||
public function getData(){
|
||||
$data = (object) [];
|
||||
$data->id = $this->_id;
|
||||
$data->name = $this->name;
|
||||
$data->type = $this->typeId->getData();
|
||||
$data->services = $this->services ? : [];
|
||||
|
||||
// according to ESIs Swagger conf, "raceId" AND "corporationId"(= "owner") are optional
|
||||
// -> I haven´t seen any imported NPC station data where "raceId" OR "corporationId" not exist
|
||||
if($this->corporationId){
|
||||
$data->corporation = $this->corporationId->getData();
|
||||
}
|
||||
|
||||
if($this->raceId){
|
||||
$data->race = $this->raceId->getData();
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* load data from API into $this and save $this
|
||||
* @param int $id
|
||||
* @param string $accessToken
|
||||
* @param array $additionalOptions
|
||||
*/
|
||||
protected function loadData(int $id, string $accessToken = '', array $additionalOptions = []){
|
||||
$data = self::getF3()->ccpClient()->getUniverseStationData($id);
|
||||
if(!empty($data) && !isset($data['error'])){
|
||||
/**
|
||||
* @var $system SystemModel
|
||||
*/
|
||||
$system = $this->rel('systemId');
|
||||
$system->loadById($data['systemId'], $accessToken, $additionalOptions);
|
||||
$data['systemId'] = $system;
|
||||
|
||||
/**
|
||||
* @var $type TypeModel
|
||||
*/
|
||||
$type = $this->rel('typeId');
|
||||
$type->loadById($data['typeId'], $accessToken, $additionalOptions);
|
||||
$data['typeId'] = $type;
|
||||
|
||||
if($data['corporationId']){
|
||||
/**
|
||||
* @var $faction CorporationModel
|
||||
*/
|
||||
$corporation = $this->rel('corporationId');
|
||||
$corporation->loadById($data['corporationId'], $accessToken, $additionalOptions);
|
||||
$data['corporationId'] = $corporation;
|
||||
}
|
||||
|
||||
if($data['raceId']){
|
||||
/**
|
||||
* @var $race RaceModel
|
||||
*/
|
||||
$race = $this->rel('raceId');
|
||||
$race->loadById($data['raceId'], $accessToken, $additionalOptions);
|
||||
$data['raceId'] = $race;
|
||||
}
|
||||
|
||||
$this->copyfrom($data, ['id', 'name', 'systemId', 'typeId', 'corporationId', 'raceId', 'services', 'position']);
|
||||
$this->save();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -13,8 +13,14 @@ use DB\SQL\Schema;
|
||||
|
||||
class StructureModel extends AbstractUniverseModel {
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $table = 'structure';
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $fieldConf = [
|
||||
'name' => [
|
||||
'type' => Schema::DT_VARCHAR128,
|
||||
@@ -23,9 +29,15 @@ class StructureModel extends AbstractUniverseModel {
|
||||
],
|
||||
'systemId' => [
|
||||
'type' => Schema::DT_INT,
|
||||
'nullable' => false,
|
||||
'default' => 0,
|
||||
'index' => true
|
||||
'index' => true,
|
||||
'belongs-to-one' => 'Model\Universe\SystemModel',
|
||||
'constraint' => [
|
||||
[
|
||||
'table' => 'system',
|
||||
'on-delete' => 'CASCADE'
|
||||
]
|
||||
],
|
||||
'validate' => 'notDry'
|
||||
],
|
||||
'typeId' => [
|
||||
'type' => Schema::DT_INT,
|
||||
@@ -63,9 +75,10 @@ class StructureModel extends AbstractUniverseModel {
|
||||
*/
|
||||
public function getData(): \stdClass {
|
||||
$data = (object) [];
|
||||
if(!$this->dry()){
|
||||
$data->id = $this->_id;
|
||||
if($this->valid()){
|
||||
$data->id = $this->_id;
|
||||
$data->name = $this->name;
|
||||
$data->type = $this->typeId->getData();
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
@@ -78,7 +91,7 @@ class StructureModel extends AbstractUniverseModel {
|
||||
*/
|
||||
protected function loadData(int $id, string $accessToken = '', array $additionalOptions = []){
|
||||
$data = self::getF3()->ccpClient()->getUniverseStructureData($id, $accessToken);
|
||||
if(!empty($data)){
|
||||
if(!empty($data) && !isset($data['error'])){
|
||||
/**
|
||||
* @var $type TypeModel
|
||||
*/
|
||||
|
||||
@@ -93,6 +93,9 @@ class SystemModel extends AbstractUniverseModel {
|
||||
'stargates' => [
|
||||
'has-many' => ['Model\Universe\StargateModel', 'systemId']
|
||||
],
|
||||
'stations' => [
|
||||
'has-many' => ['Model\Universe\StationModel', 'systemId']
|
||||
],
|
||||
'structures' => [
|
||||
'has-many' => ['Model\Universe\StructureModel', 'systemId']
|
||||
],
|
||||
@@ -154,6 +157,10 @@ class SystemModel extends AbstractUniverseModel {
|
||||
$data->stargates = $stargatesData;
|
||||
}
|
||||
|
||||
if( !empty($stationsData = $this->getStationsData()) ){
|
||||
$data->stations = $stationsData;
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
@@ -227,25 +234,12 @@ class SystemModel extends AbstractUniverseModel {
|
||||
return $effect ? : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* setter for positions array (x/y/z)
|
||||
* @param $position
|
||||
* @return null
|
||||
*/
|
||||
public function set_position($position){
|
||||
$position = (array)$position;
|
||||
if(count($position) === 3){
|
||||
$this->x = $position['x'];
|
||||
$this->y = $position['y'];
|
||||
$this->z = $position['z'];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $sovData
|
||||
* @return bool true if sovereignty data changed
|
||||
*/
|
||||
public function updateSovereigntyData(array $sovData = []){
|
||||
public function updateSovereigntyData(array $sovData = []) : bool {
|
||||
$hasChanged = false;
|
||||
$systemId = (int)$sovData['systemId'];
|
||||
$factionId = (int)$sovData['factionId'];
|
||||
$allianceId = (int)$sovData['allianceId'];
|
||||
@@ -260,7 +254,7 @@ class SystemModel extends AbstractUniverseModel {
|
||||
/**
|
||||
* @var $sovereignty SovereigntyMapModel
|
||||
*/
|
||||
if( !($sovereignty = $this->sovereignty) ){
|
||||
if(!$sovereignty = $this->sovereignty){
|
||||
// insert new sovereignty data
|
||||
$sovereignty = $this->rel('sovereignty');
|
||||
}
|
||||
@@ -305,20 +299,31 @@ class SystemModel extends AbstractUniverseModel {
|
||||
}
|
||||
|
||||
$sovereignty->copyfrom($sovData, ['systemId', 'factionId', 'allianceId', 'corporationId']);
|
||||
|
||||
// must be called before save(). Changed fields get reset after save() is called!
|
||||
if($sovereignty->changed()){
|
||||
$hasChanged = true;
|
||||
}
|
||||
|
||||
$sovereignty->save();
|
||||
}elseif($this->sovereignty){
|
||||
// delete existing sov data
|
||||
// -> hint: WH - systems never have sovereignty data
|
||||
$this->sovereignty->erase();
|
||||
$hasChanged = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $hasChanged;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $fwData
|
||||
* @return bool true if faction warfare data changed
|
||||
*/
|
||||
public function updateFactionWarData(array $fwData = []){
|
||||
public function updateFactionWarData(array $fwData = []) : bool {
|
||||
$hasChanged = false;
|
||||
$systemId = (int)$fwData['systemId'];
|
||||
$ownerFactionId = (int)$fwData['ownerFactionId'];
|
||||
$occupierFactionId = (int)$fwData['occupierFactionId'];
|
||||
@@ -328,7 +333,7 @@ class SystemModel extends AbstractUniverseModel {
|
||||
/**
|
||||
* @var $factionWar FactionWarSystemModel
|
||||
*/
|
||||
if( !($factionWar = $this->factionWar) ){
|
||||
if(!$factionWar = $this->factionWar){
|
||||
// insert new faction war data
|
||||
$factionWar = $this->rel('factionWar');
|
||||
}
|
||||
@@ -354,9 +359,17 @@ class SystemModel extends AbstractUniverseModel {
|
||||
}
|
||||
|
||||
$factionWar->copyfrom($fwData, ['systemId', 'ownerFactionId', 'occupierFactionId', 'contested', 'victoryPoints', 'victoryPointsThreshold']);
|
||||
|
||||
// must be called before save(). Changed fields get reset after save() is called!
|
||||
if($factionWar->changed()){
|
||||
$hasChanged = true;
|
||||
}
|
||||
|
||||
$factionWar->save();
|
||||
}
|
||||
}
|
||||
|
||||
return $hasChanged;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -379,10 +392,10 @@ class SystemModel extends AbstractUniverseModel {
|
||||
$planetsData = [];
|
||||
|
||||
if($this->planets){
|
||||
/**
|
||||
* @var $planet PlanetModel
|
||||
*/
|
||||
foreach($this->planets as &$planet){
|
||||
/**
|
||||
* @var $planet PlanetModel
|
||||
*/
|
||||
$planetsData[] = $planet->getData();
|
||||
}
|
||||
}
|
||||
@@ -397,10 +410,10 @@ class SystemModel extends AbstractUniverseModel {
|
||||
$staticsData = [];
|
||||
|
||||
if($this->statics){
|
||||
/**
|
||||
* @var $static SystemStaticModel
|
||||
*/
|
||||
foreach($this->statics as &$static){
|
||||
/**
|
||||
* @var $static SystemStaticModel
|
||||
*/
|
||||
$staticsData[] = $static->getData();
|
||||
}
|
||||
}
|
||||
@@ -415,16 +428,53 @@ class SystemModel extends AbstractUniverseModel {
|
||||
$stargatesData = [];
|
||||
|
||||
if($this->stargates){
|
||||
/**
|
||||
* @var $stargate StargateModel
|
||||
*/
|
||||
foreach($this->stargates as &$stargate){
|
||||
/**
|
||||
* @var $stargate StargateModel
|
||||
*/
|
||||
$stargatesData[] = $stargate->getData();
|
||||
}
|
||||
}
|
||||
return $stargatesData;
|
||||
}
|
||||
|
||||
/**
|
||||
* get data from all stations
|
||||
* @return array
|
||||
*/
|
||||
protected function getStationsData() : array {
|
||||
$stationsData = [];
|
||||
|
||||
if($this->stations){
|
||||
/**
|
||||
* @var $station StationModel
|
||||
*/
|
||||
foreach($this->stations as &$station){
|
||||
$data = $station->getData();
|
||||
if(!$data->race){
|
||||
// should never happen NPC stations always have a owning race
|
||||
$data->race = (object) [];
|
||||
$data->race->id = 0;
|
||||
$data->race->name = 'unknown';
|
||||
$data->race->faction = (object) [];
|
||||
$data->race->faction->id = 0;
|
||||
$data->race->faction->name = 'unknown';
|
||||
}
|
||||
|
||||
if(!array_key_exists($data->race->faction->id, $stationsData)){
|
||||
$stationsData[$data->race->faction->id] = [
|
||||
'id' => $data->race->faction->id,
|
||||
'name' => $data->race->name,
|
||||
'stations' => []
|
||||
];
|
||||
}
|
||||
|
||||
$stationsData[$data->race->faction->id]['stations'][] = $data;
|
||||
}
|
||||
}
|
||||
return $stationsData;
|
||||
}
|
||||
|
||||
/**
|
||||
* update system from ESI
|
||||
*/
|
||||
@@ -505,4 +555,23 @@ class SystemModel extends AbstractUniverseModel {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* load NPC owned stations for this system
|
||||
*/
|
||||
public function loadStationsData(){
|
||||
if($this->valid()){
|
||||
$data = self::getF3()->ccpClient()->getUniverseSystemData($this->_id);
|
||||
if($data['stations']){
|
||||
foreach((array)$data['stations'] as $stationId){
|
||||
/**
|
||||
* @var $station SystemModel
|
||||
*/
|
||||
$station = $this->rel('stations');
|
||||
$station->loadById($stationId);
|
||||
$station->reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -103,6 +103,9 @@ class TypeModel extends AbstractUniverseModel {
|
||||
'default' => 0,
|
||||
'index' => true
|
||||
],
|
||||
'stations' => [
|
||||
'has-many' => ['Model\Universe\StationModel', 'typeId']
|
||||
],
|
||||
'structures' => [
|
||||
'has-many' => ['Model\Universe\StructureModel', 'typeId']
|
||||
],
|
||||
@@ -220,7 +223,7 @@ class TypeModel extends AbstractUniverseModel {
|
||||
* -> more fields can be added in here if needed
|
||||
* @return \stdClass
|
||||
*/
|
||||
public function getShipData(): \stdClass {
|
||||
public function getShipData() : \stdClass {
|
||||
$shipData = (object) [];
|
||||
if($this->valid()){
|
||||
$shipData->typeId = $this->_id;
|
||||
|
||||
@@ -377,6 +377,9 @@ LOG_LINES = 1000
|
||||
[PATHFINDER.API]
|
||||
CCP_IMAGE_SERVER = https://image.eveonline.com
|
||||
Z_KILLBOARD = https://zkillboard.com/api
|
||||
EVEEYE = https://eveeye.com
|
||||
DOTLAN = http://evemaps.dotlan.net
|
||||
ANOIK = http://anoik.is
|
||||
; GitHub Developer API
|
||||
GIT_HUB = https://api.github.com
|
||||
|
||||
|
||||
@@ -137,7 +137,8 @@ define([
|
||||
|
||||
// mark as init
|
||||
tableElement.attr('data-counter', 'init');
|
||||
let refreshIntervalId = window.setInterval(() => {
|
||||
|
||||
let updateTableCount = () => {
|
||||
tableApi.cells(null, columnSelector).every(function(rowIndex, colIndex, tableLoopCount, cellLoopCount){
|
||||
let cell = this;
|
||||
let node = cell.node();
|
||||
@@ -148,7 +149,9 @@ define([
|
||||
updateDateDiff( cell.nodes().to$(), date, round);
|
||||
}
|
||||
});
|
||||
}, 500);
|
||||
};
|
||||
|
||||
let refreshIntervalId = window.setInterval(updateTableCount, 500);
|
||||
|
||||
tableElement.data('interval', refreshIntervalId);
|
||||
};
|
||||
|
||||
@@ -163,7 +163,7 @@ define([
|
||||
{icon: 'fa-route', action: 'find_route', text: 'find route'},
|
||||
{icon: 'fa-object-group', action: 'select_connections', text: 'select connections'},
|
||||
{icon: 'fa-reply fa-rotate-180', text: 'waypoints', subitems: [
|
||||
{subIcon: 'fa-flag-checkered', subAction: 'set_destination', subText: 'set destination'},
|
||||
{subIcon: 'fa-flag', subAction: 'set_destination', subText: 'set destination'},
|
||||
{subDivider: true, action: ''},
|
||||
{subIcon: 'fa-step-backward', subAction: 'add_first_waypoint', subText: 'add new [start]'},
|
||||
{subIcon: 'fa-step-forward', subAction: 'add_last_waypoint', subText: 'add new [end]'}
|
||||
|
||||
@@ -422,7 +422,7 @@ define([
|
||||
_: (data, type, row, meta) => {
|
||||
let value = data.typeName;
|
||||
if(type === 'display'){
|
||||
value = '<img src="' + Util.eveImageUrl('render', data.typeId) + '_32.png"/>';
|
||||
value = '<img src="' + Util.eveImageUrl('render', data.typeId) + '"/>';
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -1763,6 +1763,91 @@ define([
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* add station services tooltip
|
||||
* @param services
|
||||
* @param options
|
||||
* @returns {*}
|
||||
*/
|
||||
$.fn.addStationServiceTooltip = function(services, options){
|
||||
let getServiceIcon = service => {
|
||||
switch(service){
|
||||
case 'bounty-missions': return false;
|
||||
case 'assasination-missions': return false;
|
||||
case 'courier-missions': return false;
|
||||
case 'interbus': return false;
|
||||
case 'reprocessing-plant': return 'reprocess';
|
||||
case 'refinery': return false;
|
||||
case 'market': return 'market';
|
||||
case 'black-market': return false;
|
||||
case 'stock-exchange': return false;
|
||||
case 'cloning': return 'clonebay';
|
||||
case 'surgery': return false;
|
||||
case 'dna-therapy': return false;
|
||||
case 'repair-facilities': return 'repairshop';
|
||||
case 'factory': return 'industry';
|
||||
case 'labratory': return 'research';
|
||||
case 'gambling': return false;
|
||||
case 'fitting': return 'fitting';
|
||||
case 'paintshop': return 'skins';
|
||||
case 'news': return false;
|
||||
case 'storage': return false;
|
||||
case 'insurance': return 'insurance';
|
||||
case 'docking': return 'docking';
|
||||
case 'office-rental': return false;
|
||||
case 'jump-clone-facility': return 'jumpclones';
|
||||
case 'loyalty-point-store': return 'lpstore';
|
||||
case 'navy-offices': return 'factionalwarfare';
|
||||
case 'security-offices': return 'concord';
|
||||
default: return false;
|
||||
}
|
||||
};
|
||||
|
||||
let getStationServicesTable = services => {
|
||||
let content = '';
|
||||
for(let i = 0; i < services.length; i++){
|
||||
let icon = getServiceIcon(services[i]);
|
||||
if(icon){
|
||||
content += '<img class="' + Util.config.popoverListIconClass + '" src="/public/img/icons/client/ui/window/' + icon + '.png" alt="' + services[i] + '">';
|
||||
}
|
||||
}
|
||||
return content;
|
||||
};
|
||||
|
||||
let content = getStationServicesTable(services);
|
||||
|
||||
let title = '<i class="fas fa-tools fa-fw"></i> Services';
|
||||
|
||||
let defaultOptions = {
|
||||
placement: 'top',
|
||||
html: true,
|
||||
trigger: 'hover',
|
||||
container: 'body',
|
||||
title: title,
|
||||
content: '',
|
||||
delay: {
|
||||
show: 150,
|
||||
hide: 0
|
||||
},
|
||||
};
|
||||
|
||||
options = $.extend({}, defaultOptions, options);
|
||||
|
||||
return this.each(function(){
|
||||
let element = $(this);
|
||||
element.popover(options);
|
||||
|
||||
// set new popover content
|
||||
let popover = element.data('bs.popover');
|
||||
popover.options.content = content;
|
||||
popover.tip().addClass(Util.config.popoverClass);
|
||||
|
||||
if(options.show){
|
||||
element.popover('show');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* add system effect tooltip
|
||||
* @param security
|
||||
@@ -1807,7 +1892,6 @@ define([
|
||||
* @returns {*}
|
||||
*/
|
||||
$.fn.addSystemPlanetsTooltip = function(planets, options){
|
||||
|
||||
let content = Util.getSystemPlanetsTable(planets);
|
||||
|
||||
let defaultOptions = {
|
||||
|
||||
@@ -1012,7 +1012,13 @@ define([
|
||||
if(changes.charactersIds){
|
||||
updateTasks.push(updateHeaderCharacterSwitch(userData, changes.characterId));
|
||||
}
|
||||
if(changes.characterSystemId || changes.characterShipType || changes.characterLogHistory){
|
||||
if(
|
||||
changes.characterSystemId ||
|
||||
changes.characterShipType ||
|
||||
changes.characterStationId ||
|
||||
changes.characterStructureId ||
|
||||
changes.characterLogHistory
|
||||
){
|
||||
updateTasks.push(updateHeaderCharacterLocation(userData, changes.characterShipType));
|
||||
}
|
||||
|
||||
@@ -1087,6 +1093,16 @@ define([
|
||||
let shipTypeId = Util.getObjVal(shipData, 'typeId') || 0;
|
||||
let shipTypeName = Util.getObjVal(shipData, 'typeName') || '';
|
||||
|
||||
let stationData = Util.getObjVal(userData, 'character.log.station');
|
||||
let stationId = Util.getObjVal(stationData, 'id') || 0;
|
||||
let stationName = Util.getObjVal(stationData, 'name') || '';
|
||||
|
||||
let structureData = Util.getObjVal(userData, 'character.log.structure');
|
||||
let structureTypeId = Util.getObjVal(structureData, 'type.id') || 0;
|
||||
let structureTypeName = Util.getObjVal(structureData, 'type.name') || '';
|
||||
let structureId = Util.getObjVal(structureData, 'id') || 0;
|
||||
let structureName = Util.getObjVal(structureData, 'name') || '';
|
||||
|
||||
logDataAll.push(logData);
|
||||
|
||||
// check for log history data as well
|
||||
@@ -1116,6 +1132,12 @@ define([
|
||||
|
||||
if(isCurrentLocation){
|
||||
breadcrumbHtml += '<i class="fas fa-fw fa-map-marker-alt" title="current location"></i>';
|
||||
|
||||
if(stationId > 0){
|
||||
breadcrumbHtml += '<i class="fas fa-home" title="' + stationName + '"></i>';
|
||||
}else if(structureId > 0){
|
||||
breadcrumbHtml += '<i class="fas fa-industry" title="' + structureTypeName + ' "' + structureName + '""></i>';
|
||||
}
|
||||
}
|
||||
|
||||
breadcrumbHtml += systemName;
|
||||
|
||||
@@ -205,7 +205,7 @@ define([
|
||||
let systemsElement = $(this).empty();
|
||||
|
||||
let systemTable = $('<table>', {
|
||||
id: Util.getTableId(config.tableId, mapData.config.id, '', 'systems'),
|
||||
id: Util.getTableId(config.tableId, 'systems', mapData.config.id, ''),
|
||||
class: ['compact', 'stripe', 'order-column', 'row-border'].join(' ')
|
||||
});
|
||||
systemsElement.append(systemTable);
|
||||
@@ -864,7 +864,7 @@ define([
|
||||
}
|
||||
},
|
||||
createdCell: function(cell, cellData, rowData, rowIndex, colIndex){
|
||||
// open character information window (ingame)
|
||||
// open corporation information window (ingame)
|
||||
$(cell).on('click', { tableApi: this.api() }, function(e){
|
||||
let cellData = e.data.tableApi.cell(this).data();
|
||||
Util.openIngameWindow(cellData.id);
|
||||
|
||||
@@ -188,6 +188,61 @@ define([
|
||||
moduleElement.find('.' + config.systemSovSectionClass + ' .' + Util.config.dynamicAreaClass).hideLoadingAnimation();
|
||||
};
|
||||
|
||||
/**
|
||||
* @param pages
|
||||
* @param systemData
|
||||
*/
|
||||
let getThirdPartySystemLinks = (pages, systemData) => {
|
||||
let urls = {};
|
||||
let isWormhole = MapUtil.getSystemTypeInfo(Util.getObjVal(systemData, 'type.id'), 'name') === 'w-space';
|
||||
let systemName = Util.getObjVal(systemData, 'name') || '';
|
||||
let regionName = Util.getObjVal(systemData, 'region.name') || '';
|
||||
|
||||
let validUrls = 0;
|
||||
for(let i = 0; i < pages.length; i++){
|
||||
let url = false;
|
||||
let domain = Util.getObjVal(Init, 'url.' + pages[i]);
|
||||
if(domain || pages[i] === 'eve'){
|
||||
switch(pages[i]){
|
||||
case 'eve':
|
||||
url = 'https://client'; // fake url
|
||||
break;
|
||||
case 'dotlan':
|
||||
systemName = systemName.replace(/ /g, '_');
|
||||
regionName = regionName.replace(/ /g, '_');
|
||||
if(isWormhole){
|
||||
url = domain + '/system/' + systemName;
|
||||
}else{
|
||||
url = domain + '/map/' + regionName + '/' + systemName;
|
||||
}
|
||||
break;
|
||||
case 'eveeye':
|
||||
if(!isWormhole){
|
||||
url = domain + '/?m=' + encodeURIComponent(regionName) + '&s=' + encodeURIComponent(systemName.replace(/ /g, '_'));
|
||||
url += '&t=eswkc&o=thera,con_svc,node_sov,sub_sec,sector_fac,tag_mk';
|
||||
}
|
||||
break;
|
||||
case 'anoik':
|
||||
if(isWormhole){
|
||||
url = domain + '/systems/' + systemName;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if(url){
|
||||
let urlObj = new URL(url);
|
||||
urls[++validUrls + '_url'] = {
|
||||
page: pages[i],
|
||||
domain: urlObj.hostname,
|
||||
url: url
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return urls;
|
||||
};
|
||||
|
||||
/**
|
||||
* get module element
|
||||
* @param parentElement
|
||||
@@ -294,7 +349,6 @@ define([
|
||||
|
||||
systemUrl: MapUtil.getMapDeeplinkUrl(mapId, systemData.id),
|
||||
systemTypeName: MapUtil.getSystemTypeInfo(systemData.type.id, 'name'),
|
||||
systemIsWormhole: MapUtil.getSystemTypeInfo(systemData.type.id, 'name') === 'w-space',
|
||||
systemStatusId: systemData.status.id,
|
||||
systemStatusClass: Util.getStatusInfoForSystem(systemData.status.id, 'class'),
|
||||
systemStatusLabel: Util.getStatusInfoForSystem(systemData.status.id, 'label'),
|
||||
@@ -326,6 +380,7 @@ define([
|
||||
systemTypeLinkClass: config.typeLinkClass,
|
||||
systemUrlLinkClass: config.urlLinkClass,
|
||||
ccpImageServerUrl: Init.url.ccpImageServer,
|
||||
thirdPartyLinks: getThirdPartySystemLinks(['eve', 'dotlan', 'eveeye', 'anoik'], systemData)
|
||||
};
|
||||
|
||||
requirejs(['text!templates/modules/system_info.html', 'mustache', 'summernote.loader'], (template, Mustache, Summernote) => {
|
||||
|
||||
@@ -7,8 +7,9 @@ define([
|
||||
'app/init',
|
||||
'app/util',
|
||||
'bootbox',
|
||||
'app/counter'
|
||||
], ($, Init, Util, bootbox, Counter) => {
|
||||
'app/counter',
|
||||
'app/map/util',
|
||||
], ($, Init, Util, bootbox, Counter, MapUtil) => {
|
||||
'use strict';
|
||||
|
||||
let config = {
|
||||
@@ -18,7 +19,7 @@ define([
|
||||
moduleHeadClass: 'pf-module-head', // class for module header
|
||||
moduleHandlerClass: 'pf-module-handler-drag', // class for "drag" handler
|
||||
|
||||
// system info module
|
||||
// system intel module
|
||||
moduleTypeClass: 'pf-system-intel-module', // class for this module
|
||||
|
||||
// headline toolbar
|
||||
@@ -28,10 +29,14 @@ define([
|
||||
moduleHeadlineIconRefreshClass: 'pf-module-icon-button-refresh', // class for "refresh" icon
|
||||
|
||||
// system intel module
|
||||
systemStructuresTableClass: 'pf-system-structure-table', // class for route tables
|
||||
intelTableId: 'pf-intel-table-', // id prefix for all tables in module
|
||||
intelTableRowIdPrefix: 'pf-intel-row-', // id prefix for table rows
|
||||
systemStationsTableClass: 'pf-system-station-table', // class for NPC owned stations table
|
||||
systemStructuresTableClass: 'pf-system-structure-table', // class for player owned structures table
|
||||
|
||||
// structure dialog
|
||||
structureDialogId: 'pf-structure-dialog', // id for "structure" dialog
|
||||
nameInputId: 'pf-structure-dialog-name-input', // id for "name" input
|
||||
statusSelectId: 'pf-structure-dialog-status-select', // id for "status" select
|
||||
typeSelectId: 'pf-structure-dialog-type-select', // id for "type" select
|
||||
corporationSelectId: 'pf-structure-dialog-corporation-select', // id for "corporation" select
|
||||
@@ -39,11 +44,12 @@ define([
|
||||
descriptionTextareaCharCounter: 'pf-form-field-char-count', // class for "character counter" element for form field
|
||||
|
||||
// dataTable
|
||||
tableRowIdPrefix: 'pf-structure-row_', // id prefix for table rows
|
||||
tableCellImageClass: 'pf-table-image-smaller-cell', // class for table "image" cells
|
||||
tableCellCounterClass: 'pf-table-counter-cell', // class for table "counter" cells
|
||||
tableCellEllipsisClass: 'pf-table-cell-ellipses-auto', // class for table "ellipsis" cells
|
||||
dataTableActionCellClass: 'pf-table-action-cell' // class for "action" cells
|
||||
tableCellActionClass: 'pf-table-action-cell', // class for "action" cells
|
||||
tableCellActionIconClass: 'pf-table-action-icon-cell', // class for table "action" icon (icon is part of cell content)
|
||||
tableCellServicesClass: 'pf-table-services-cell' // class for table station "services" cells
|
||||
};
|
||||
|
||||
let maxDescriptionLength = 512;
|
||||
@@ -53,26 +59,102 @@ define([
|
||||
* @param statusData
|
||||
* @returns {string}
|
||||
*/
|
||||
let getStatusData = statusData => {
|
||||
let getIconForStatusData = statusData => {
|
||||
return '<i class="fas fa-fw fa-circle ' + statusData.class + '" title="' + statusData.label + '"></i>';
|
||||
};
|
||||
|
||||
/**
|
||||
* get icon that marks a table cell as clickable
|
||||
* @returns {string}
|
||||
*/
|
||||
let getIconForInformationWindow = () => {
|
||||
return '<i class="fas fa-fw fa-id-card ' + config.tableCellActionIconClass + '" title="open ingame" data-toggle="tooltip"></i>';
|
||||
};
|
||||
|
||||
/**
|
||||
* get dataTable id
|
||||
* @param mapId
|
||||
* @param systemId
|
||||
* @param tableType
|
||||
* @returns {string}
|
||||
*/
|
||||
let getTableId = (tableType, mapId, systemId) => Util.getTableId(config.intelTableId, tableType, mapId, systemId);
|
||||
|
||||
/**
|
||||
* get dataTable row id
|
||||
* @param tableType
|
||||
* @param id
|
||||
* @returns {string}
|
||||
*/
|
||||
let getRowId = (tableType, id) => Util.getTableRowId(config.intelTableRowIdPrefix, tableType, id);
|
||||
|
||||
/**
|
||||
* get <tr> DOM id by id
|
||||
* @param tableApi
|
||||
* @param id
|
||||
* @returns {*}
|
||||
*/
|
||||
let getRowId = (tableApi, id) => {
|
||||
return tableApi.rows().ids().toArray().find(rowId => rowId === config.tableRowIdPrefix + id);
|
||||
let getRowById = (tableApi, id) => {
|
||||
return tableApi.rows().ids().toArray().find(rowId => rowId === getRowId(Util.getObjVal(getTableMetaData(tableApi), 'type'), id));
|
||||
};
|
||||
|
||||
/**
|
||||
* callback -> add structure rows from systemData
|
||||
* @param context
|
||||
* @param systemData
|
||||
* get custom "metaData" from dataTables API
|
||||
* @param tableApi
|
||||
* @returns {*}
|
||||
*/
|
||||
let callbackUpdateStructureRows = (context, systemData) => {
|
||||
let getTableMetaData = tableApi => {
|
||||
let data = null;
|
||||
if(tableApi){
|
||||
data = tableApi.init().pfMeta;
|
||||
}
|
||||
return data;
|
||||
};
|
||||
|
||||
/**
|
||||
* vormat roman numeric string to int
|
||||
* -> e.g. 'VII' => 7
|
||||
* @param str
|
||||
* @returns {number}
|
||||
*/
|
||||
let romanToInt = str => {
|
||||
let charToTnt = char => {
|
||||
switch (char) {
|
||||
case 'I': return 1;
|
||||
case 'V': return 5;
|
||||
case 'X': return 10;
|
||||
case 'L': return 50;
|
||||
case 'C': return 100;
|
||||
case 'D': return 500;
|
||||
case 'M': return 1000;
|
||||
default: return -1;
|
||||
}
|
||||
};
|
||||
|
||||
if(str == null) return -1;
|
||||
let num = charToTnt(str.charAt(0));
|
||||
let pre, curr;
|
||||
|
||||
for(let i = 1; i < str.length; i++){
|
||||
curr = charToTnt(str.charAt(i));
|
||||
pre = charToTnt(str.charAt(i - 1));
|
||||
if(curr <= pre){
|
||||
num += curr;
|
||||
}else{
|
||||
num = num - pre * 2 + curr;
|
||||
}
|
||||
}
|
||||
|
||||
return num;
|
||||
};
|
||||
|
||||
/**
|
||||
* callback -> add table rows from grouped tableData
|
||||
* @param context
|
||||
* @param tableData
|
||||
* @param groupedDataKey
|
||||
*/
|
||||
let callbackUpdateTableRows = (context, tableData, groupedDataKey = 'structures') => {
|
||||
let touchedRows = [];
|
||||
let hadData = context.tableApi.rows().any();
|
||||
let notificationCounter = {
|
||||
@@ -81,41 +163,39 @@ define([
|
||||
deleted: 0
|
||||
};
|
||||
|
||||
if(systemData){
|
||||
let corporations = Util.getObjVal(systemData, 'structures');
|
||||
if(corporations){
|
||||
for(let [corporationId, corporationData] of Object.entries(corporations)){
|
||||
if(corporationData.structures && corporationData.structures.length){
|
||||
for(let structureData of corporationData.structures){
|
||||
let rowId = getRowId(context.tableApi, structureData.id);
|
||||
if(tableData){
|
||||
for(let [rowGroupId, rowGroupData] of Object.entries(tableData)){
|
||||
if(rowGroupData[groupedDataKey] && rowGroupData[groupedDataKey].length){
|
||||
for(let rowData of rowGroupData[groupedDataKey]){
|
||||
let rowId = getRowById(context.tableApi, rowData.id);
|
||||
|
||||
// add corporation data
|
||||
structureData.corporation = {
|
||||
id: corporationData.id,
|
||||
name: corporationData.name
|
||||
};
|
||||
// add rowGroupData as well to each rowData
|
||||
rowData.rowGroupData = {
|
||||
id: rowGroupData.id,
|
||||
name: rowGroupData.name,
|
||||
groupedDataKey: groupedDataKey
|
||||
};
|
||||
|
||||
if(rowId){
|
||||
// update row
|
||||
let api = context.tableApi.row('#' + rowId);
|
||||
let rowData = api.data();
|
||||
if(rowId){
|
||||
// update row
|
||||
let api = context.tableApi.row('#' + rowId);
|
||||
let rowDataCurrent = api.data();
|
||||
|
||||
// check for update
|
||||
if(rowData.updated.updated !== structureData.updated.updated){
|
||||
// row data changed -> update
|
||||
api.data(structureData);
|
||||
notificationCounter.changed++;
|
||||
}
|
||||
|
||||
touchedRows.push(api.id());
|
||||
}else{
|
||||
// insert new row
|
||||
let api = context.tableApi.row.add(structureData);
|
||||
api.nodes().to$().data('animationStatus', 'added');
|
||||
notificationCounter.added++;
|
||||
|
||||
touchedRows.push(api.id());
|
||||
// check for update
|
||||
if(rowDataCurrent.updated.updated !== rowData.updated.updated){
|
||||
// row data changed -> update
|
||||
api.data(rowData);
|
||||
notificationCounter.changed++;
|
||||
}
|
||||
|
||||
touchedRows.push(api.id());
|
||||
}else{
|
||||
// insert new row
|
||||
let api = context.tableApi.row.add(rowData);
|
||||
api.nodes().to$().data('animationStatus', 'added');
|
||||
notificationCounter.added++;
|
||||
|
||||
touchedRows.push(api.id());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -156,7 +236,7 @@ define([
|
||||
let deletedCounter = 0;
|
||||
if(structureIds && structureIds.length){
|
||||
for(let structureId of structureIds){
|
||||
let rowId = getRowId(context.tableApi, structureId);
|
||||
let rowId = getRowById(context.tableApi, structureId);
|
||||
if(rowId){
|
||||
context.tableApi.row('#' + rowId).remove();
|
||||
deletedCounter++;
|
||||
@@ -214,10 +294,36 @@ define([
|
||||
return data;
|
||||
});
|
||||
|
||||
// if current user is currently docked at a structure (not station)
|
||||
// -> add a modal button for pre-fill modal with it
|
||||
// -> systemId must match systemId from current character log
|
||||
let currentUserData = Util.getCurrentUserData();
|
||||
let isCurrentLocation = false;
|
||||
let characterStructureId = Util.getObjVal(currentUserData, 'character.log.structure.id') || 0;
|
||||
let characterStructureName = Util.getObjVal(currentUserData, 'character.log.structure.name') || '';
|
||||
let characterStructureTypeId = Util.getObjVal(currentUserData, 'character.log.structure.type.id') || 0;
|
||||
let characterStructureTypeName = Util.getObjVal(currentUserData, 'character.log.structure.type.name') || '';
|
||||
|
||||
if(systemId === Util.getObjVal(currentUserData, 'character.log.system.id')){
|
||||
isCurrentLocation = true;
|
||||
}
|
||||
|
||||
let disableButtonAutoFill = true;
|
||||
let buttonLabelAutoFill = '<i class="fas fa-fw fa-map-marker-alt"></i> ';
|
||||
if(characterStructureId){
|
||||
buttonLabelAutoFill += characterStructureTypeName + ' "' + characterStructureName + '"';
|
||||
if(isCurrentLocation){
|
||||
disableButtonAutoFill = false;
|
||||
}
|
||||
}else{
|
||||
buttonLabelAutoFill += 'unknown structure';
|
||||
}
|
||||
|
||||
let data = {
|
||||
id: config.structureDialogId,
|
||||
structureData: structureData,
|
||||
structureStatus: statusData,
|
||||
nameInputId: config.nameInputId,
|
||||
statusSelectId: config.statusSelectId,
|
||||
typeSelectId: config.typeSelectId,
|
||||
corporationSelectId: config.corporationSelectId,
|
||||
@@ -236,7 +342,18 @@ define([
|
||||
buttons: {
|
||||
close: {
|
||||
label: 'cancel',
|
||||
className: 'btn-default'
|
||||
className: 'btn-default pull-left'
|
||||
},
|
||||
autoFill: {
|
||||
label: buttonLabelAutoFill,
|
||||
className: 'btn-primary' + (disableButtonAutoFill ? ' pf-font-italic disabled' : ''),
|
||||
callback: function(){
|
||||
let form = this.find('form');
|
||||
form.find('#' + config.nameInputId).val(characterStructureName);
|
||||
form.find('#' + config.statusSelectId).val(2).trigger('change');
|
||||
form.find('#' + config.typeSelectId).val(characterStructureTypeId).trigger('change');
|
||||
return false;
|
||||
}
|
||||
},
|
||||
success: {
|
||||
label: '<i class="fas fa-fw fa-check"></i> save',
|
||||
@@ -268,7 +385,7 @@ define([
|
||||
},
|
||||
context => context.moduleElement.hideLoadingAnimation()
|
||||
).then(
|
||||
payload => callbackUpdateStructureRows(payload.context, {structures: payload.data}),
|
||||
payload => callbackUpdateTableRows(payload.context, payload.data),
|
||||
Util.handleAjaxErrorResponse
|
||||
);
|
||||
}else{
|
||||
@@ -361,6 +478,83 @@ define([
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* init station services tooltips
|
||||
* @param element
|
||||
* @param tableApi
|
||||
*/
|
||||
let initStationServiceTooltip = (element, tableApi) => {
|
||||
element.hoverIntent({
|
||||
over: function(e){
|
||||
let cellElement = $(this);
|
||||
let rowData = tableApi.row(cellElement.parents('tr')).data();
|
||||
cellElement.addStationServiceTooltip(Util.getObjVal(rowData, 'services'), {
|
||||
placement: 'left',
|
||||
trigger: 'manual',
|
||||
show: true
|
||||
});
|
||||
},
|
||||
out: function(e){
|
||||
$(this).destroyPopover();
|
||||
},
|
||||
selector: 'td.' + config.tableCellServicesClass
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* get dataTables default options for intel tables
|
||||
* @returns {*}
|
||||
*/
|
||||
let getDataTableDefaults = () => {
|
||||
return {
|
||||
paging: false,
|
||||
lengthChange: false,
|
||||
ordering: true,
|
||||
info: false,
|
||||
searching: false,
|
||||
hover: false,
|
||||
autoWidth: false,
|
||||
drawCallback: function (settings) {
|
||||
let tableApi = this.api();
|
||||
let columnCount = tableApi.columns(':visible').count();
|
||||
let rows = tableApi.rows({page: 'current'}).nodes();
|
||||
let last = null;
|
||||
|
||||
tableApi.column('rowGroupData:name', {page: 'current'}).data().each(function (group, i) {
|
||||
if (!last || last.id !== group.id) {
|
||||
// "stations" are grouped by "raceId" with its "factionId"
|
||||
// "structures" are grouped by "corporationId" that ADDED it (not the ingame "owner" of it)
|
||||
let imgType = 'stations' === group.groupedDataKey ? 'alliance' : 'corporation';
|
||||
|
||||
$(rows).eq(i).before(
|
||||
'<tr class="group">' +
|
||||
'<td></td>' +
|
||||
'<td class="text-right ' + config.tableCellImageClass + '">' +
|
||||
'<img src="' + Util.eveImageUrl(imgType, group.id) + '"/>' +
|
||||
'</td>' +
|
||||
'<td colspan="' + Math.max((columnCount - 2), 1) + '">' + group.name + '</td>' +
|
||||
'</tr>'
|
||||
);
|
||||
last = group;
|
||||
}
|
||||
});
|
||||
|
||||
let animationRows = rows.to$().filter(function () {
|
||||
return (
|
||||
$(this).data('animationStatus') ||
|
||||
$(this).data('animationTimer')
|
||||
);
|
||||
});
|
||||
|
||||
for (let i = 0; i < animationRows.length; i++) {
|
||||
let animationRow = $(animationRows[i]);
|
||||
animationRow.pulseBackgroundColor(animationRow.data('animationStatus'));
|
||||
animationRow.removeData('animationStatus');
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* get module element
|
||||
* @param parentElement
|
||||
@@ -369,6 +563,7 @@ define([
|
||||
* @returns {jQuery}
|
||||
*/
|
||||
let getModule = (parentElement, mapId, systemData) => {
|
||||
let showStationTable = ['H', 'L', '0.0', 'C12'].includes(Util.getObjVal(systemData, 'security'));
|
||||
let corporationId = Util.getCurrentUserInfo('corporationId');
|
||||
|
||||
let moduleElement = $('<div>').append(
|
||||
@@ -395,35 +590,29 @@ define([
|
||||
}).attr('data-html', 'true').attr('data-toggle', 'tooltip')
|
||||
),
|
||||
$('<h5>', {
|
||||
text: 'Intel'
|
||||
text: 'Structures'
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
let table = $('<table>', {
|
||||
// "Structures" table -----------------------------------------------------------------------------------------
|
||||
let structureTable = $('<table>', {
|
||||
id: getTableId('structure', mapId, systemData.id),
|
||||
class: ['compact', 'stripe', 'order-column', 'row-border', 'pf-table-fixed', config.systemStructuresTableClass].join(' ')
|
||||
});
|
||||
moduleElement.append(table);
|
||||
moduleElement.append(structureTable);
|
||||
|
||||
let tableApi = table.DataTable({
|
||||
paging: false,
|
||||
lengthChange: false,
|
||||
ordering: true,
|
||||
order: [[ 10, 'desc' ], [ 0, 'asc' ]],
|
||||
info: false,
|
||||
searching: false,
|
||||
hover: false,
|
||||
autoWidth: false,
|
||||
rowId: rowData => config.tableRowIdPrefix + rowData.id,
|
||||
let structureDataTableOptions = {
|
||||
pfMeta: {
|
||||
type: 'structures'
|
||||
},
|
||||
order: [[10, 'desc' ], [0, 'asc' ]],
|
||||
rowId: rowData => getRowId('structures', rowData.id),
|
||||
language: {
|
||||
emptyTable: 'No structures recorded',
|
||||
info: '_START_ to _END_ of _MAX_',
|
||||
infoEmpty: ''
|
||||
},
|
||||
rowGroup: {
|
||||
enable: true,
|
||||
dataSrc: 'systemId'
|
||||
},
|
||||
columnDefs: [
|
||||
{
|
||||
targets: 0,
|
||||
@@ -433,17 +622,17 @@ define([
|
||||
className: ['text-center', 'all'].join(' '),
|
||||
data: 'status',
|
||||
render: {
|
||||
display: data => getStatusData(data),
|
||||
display: data => getIconForStatusData(data),
|
||||
sort: data => data.id
|
||||
},
|
||||
createdCell: function(cell, cellData, rowData, rowIndex, colIndex){
|
||||
$(cell).find('i').tooltip();
|
||||
$(cell).find('i').tooltip();
|
||||
}
|
||||
},{
|
||||
targets: 1,
|
||||
name: 'structureImage',
|
||||
title: '',
|
||||
width: 26,
|
||||
width: 24,
|
||||
orderable: false,
|
||||
className: [config.tableCellImageClass, 'text-center', 'all'].join(' '),
|
||||
data: 'structure.id',
|
||||
@@ -476,7 +665,7 @@ define([
|
||||
targets: 4,
|
||||
name: 'ownerImage',
|
||||
title: '',
|
||||
width: 26,
|
||||
width: 24,
|
||||
orderable: false,
|
||||
className: [config.tableCellImageClass, 'text-center', 'all'].join(' '),
|
||||
data: 'owner.id',
|
||||
@@ -519,12 +708,12 @@ define([
|
||||
title: '',
|
||||
orderable: false,
|
||||
width: 10,
|
||||
className: ['text-center', config.dataTableActionCellClass, config.moduleHeadlineIconClass, 'all'].join(' '),
|
||||
className: ['text-center', config.tableCellActionClass, config.moduleHeadlineIconClass, 'all'].join(' '),
|
||||
data: null,
|
||||
render: {
|
||||
display: data => {
|
||||
let icon = '<i class="fas fa-pen"></i>';
|
||||
if(data.corporation.id !== corporationId){
|
||||
if(data.rowGroupData.id !== corporationId){
|
||||
icon = '';
|
||||
}
|
||||
return icon;
|
||||
@@ -534,7 +723,7 @@ define([
|
||||
let tableApi = this.api();
|
||||
|
||||
if($(cell).is(':empty')){
|
||||
$(cell).removeClass(config.dataTableActionCellClass + ' ' + config.moduleHeadlineIconClass);
|
||||
$(cell).removeClass(config.tableCellActionClass + ' ' + config.moduleHeadlineIconClass);
|
||||
}else{
|
||||
$(cell).on('click', function(e){
|
||||
// get current row data (important!)
|
||||
@@ -550,12 +739,12 @@ define([
|
||||
title: '',
|
||||
orderable: false,
|
||||
width: 10,
|
||||
className: ['text-center', config.dataTableActionCellClass, 'all'].join(' '),
|
||||
className: ['text-center', config.tableCellActionClass, 'all'].join(' '),
|
||||
data: null,
|
||||
render: {
|
||||
display: data => {
|
||||
let icon = '<i class="fas fa-times txt-color txt-color-redDarker"></i>';
|
||||
if(data.corporation.id !== corporationId){
|
||||
if(data.rowGroupData.id !== corporationId){
|
||||
icon = '<i class="fas fa-ban txt-color txt-color-grayLight" title="restricted" data-placement="left"></i>';
|
||||
}
|
||||
return icon;
|
||||
@@ -565,7 +754,7 @@ define([
|
||||
let tableApi = this.api();
|
||||
|
||||
if($(cell).find('.fa-ban').length){
|
||||
$(cell).removeClass(config.dataTableActionCellClass + ' ' + config.moduleHeadlineIconClass);
|
||||
$(cell).removeClass(config.tableCellActionClass + ' ' + config.moduleHeadlineIconClass);
|
||||
$(cell).find('i').tooltip();
|
||||
}else{
|
||||
let confirmationSettings = {
|
||||
@@ -602,9 +791,9 @@ define([
|
||||
}
|
||||
},{
|
||||
targets: 10,
|
||||
name: 'corporation',
|
||||
name: 'rowGroupData',
|
||||
className: 'never', // never show this column. see: https://datatables.net/extensions/responsive/classes
|
||||
data: 'corporation',
|
||||
data: 'rowGroupData',
|
||||
visible: false,
|
||||
render: {
|
||||
sort: function(data){
|
||||
@@ -613,40 +802,6 @@ define([
|
||||
}
|
||||
}
|
||||
],
|
||||
drawCallback: function(settings){
|
||||
let tableApi = this.api();
|
||||
let columnCount = tableApi.columns(':visible').count();
|
||||
let rows = tableApi.rows( {page:'current'} ).nodes();
|
||||
let last= null;
|
||||
|
||||
tableApi.column('corporation:name', {page:'current'} ).data().each( function(group, i ){
|
||||
if( !last || last.id !== group.id ){
|
||||
$(rows).eq(i).before(
|
||||
'<tr class="group">' +
|
||||
'<td></td>' +
|
||||
'<td class="' + config.tableCellImageClass + '">' +
|
||||
'<img src="' + Util.eveImageUrl('corporation', group.id) + '"/>' +
|
||||
'</td>' +
|
||||
'<td colspan="' + (columnCount - 2 ) + '">' + group.name + '</td>' +
|
||||
'</tr>'
|
||||
);
|
||||
last = group;
|
||||
}
|
||||
});
|
||||
|
||||
let animationRows = rows.to$().filter(function(){
|
||||
return (
|
||||
$(this).data('animationStatus') ||
|
||||
$(this).data('animationTimer')
|
||||
);
|
||||
});
|
||||
|
||||
for(let i = 0; i < animationRows.length; i++){
|
||||
let animationRow = $(animationRows[i]);
|
||||
animationRow.pulseBackgroundColor(animationRow.data('animationStatus'));
|
||||
animationRow.removeData('animationStatus');
|
||||
}
|
||||
},
|
||||
initComplete: function(settings){
|
||||
// table data is load in updateModule() method
|
||||
// -> no need to trigger additional ajax call here for data
|
||||
@@ -655,15 +810,259 @@ define([
|
||||
|
||||
Counter.initTableCounter(this, ['updated:name'], 'd');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
new $.fn.dataTable.Responsive(tableApi);
|
||||
$.extend(true, structureDataTableOptions, getDataTableDefaults());
|
||||
let tableApiStructure = structureTable.DataTable(structureDataTableOptions);
|
||||
|
||||
tableApi.on('responsive-resize', function(e, tableApi, columns){
|
||||
new $.fn.dataTable.Responsive(tableApiStructure);
|
||||
|
||||
tableApiStructure.on('responsive-resize', function(e, tableApi, columns){
|
||||
// rowGroup length changes as well -> trigger draw() updates rowGroup length (see drawCallback())
|
||||
tableApi.draw();
|
||||
});
|
||||
|
||||
if(showStationTable){
|
||||
// "Stations" table ---------------------------------------------------------------------------------------
|
||||
|
||||
moduleElement.append(
|
||||
$('<div>', {
|
||||
class: config.moduleHeadClass
|
||||
}).append(
|
||||
$('<h5>', {
|
||||
class: config.moduleHandlerClass
|
||||
}),
|
||||
$('<h5>', {
|
||||
text: 'Stations'
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
let stationTable = $('<table>', {
|
||||
id: getTableId('station', mapId, systemData.id),
|
||||
class: ['compact', 'stripe', 'order-column', 'row-border', 'pf-table-fixed', config.systemStationsTableClass].join(' ')
|
||||
});
|
||||
moduleElement.append(stationTable);
|
||||
|
||||
let stationDataTableOptions = {
|
||||
pfMeta: {
|
||||
type: 'stations'
|
||||
},
|
||||
order: [[1, 'asc' ], [8, 'asc' ]],
|
||||
rowId: rowData => getRowId('stations', rowData.id),
|
||||
language: {
|
||||
emptyTable: 'No stations found',
|
||||
info: '_START_ to _END_ of _MAX_',
|
||||
infoEmpty: ''
|
||||
},
|
||||
columnDefs: [
|
||||
{
|
||||
targets: 0,
|
||||
name: 'stationImage',
|
||||
title: '',
|
||||
width: 24,
|
||||
orderable: false,
|
||||
className: [config.tableCellImageClass, 'text-center', 'all'].join(' '),
|
||||
data: 'type.id',
|
||||
defaultContent: '<i class="fas fa-question txt-color txt-color-orangeDark"></i>',
|
||||
render: {
|
||||
_: function(data, type, row, meta){
|
||||
let value = data;
|
||||
if(type === 'display' && value){
|
||||
value = '<img src="' + Util.eveImageUrl('type', value) +'"/>';
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
},{
|
||||
targets: 1,
|
||||
name: 'count',
|
||||
title: '',
|
||||
width: 5,
|
||||
className: ['text-center', 'all'].join(' '),
|
||||
data: 'name',
|
||||
render: {
|
||||
_: function(cellData, type, rowData, meta){
|
||||
let value = '';
|
||||
if(cellData){
|
||||
let matches = /^(?<system>[a-z0-9\s\-]+) (?<count>[MDCLXVI]+) .*$/i.exec(cellData);
|
||||
let count = Util.getObjVal(matches, 'groups.count');
|
||||
|
||||
if(type === 'display'){
|
||||
value = count || 0;
|
||||
}else{
|
||||
value = romanToInt(count) || '';
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
}
|
||||
},{
|
||||
targets: 2,
|
||||
name: 'name',
|
||||
title: 'station',
|
||||
className: [config.tableCellEllipsisClass, 'all'].join(' '),
|
||||
data: 'name',
|
||||
render: {
|
||||
_: function(cellData, type, rowData, meta){
|
||||
let value = cellData;
|
||||
if(cellData){
|
||||
let matches = /^(?<system>[a-z0-9\s\-]+) (?<count>[MDCLXVI]+) (?<label>\(\w+\)\s)?\- (?<moon>moon (?<moonCount>\d)+)?.*$/i.exec(cellData);
|
||||
let systemName = Util.getObjVal(matches, 'groups.system');
|
||||
let count = Util.getObjVal(matches, 'groups.count');
|
||||
let moon = Util.getObjVal(matches, 'groups.moon');
|
||||
if(systemName === (Util.getObjVal(systemData, 'name') || '')){
|
||||
value = value.slice(systemName.length).trim();
|
||||
if(count){
|
||||
value = value.slice(count.length).trimLeftChars(' \-');
|
||||
}
|
||||
if(moon){
|
||||
let moonCount = Util.getObjVal(matches, 'groups.moonCount');
|
||||
value = value.replace(moon, 'M' + moonCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
},{
|
||||
targets: 3,
|
||||
name: 'stationType',
|
||||
title: 'type',
|
||||
width: 100,
|
||||
className: [config.tableCellEllipsisClass, 'not-screen-l'].join(' '),
|
||||
data: 'type.name',
|
||||
defaultContent: '<i class="fas fa-question txt-color txt-color-orangeDark"></i>',
|
||||
render: {
|
||||
display: (cellData, type, rowData, meta) => {
|
||||
let value = cellData;
|
||||
if(value){
|
||||
let rowGroupDataName = Util.getObjVal(rowData, 'rowGroupData.name') || '';
|
||||
if(value.indexOf(rowGroupDataName) === 0){
|
||||
value = value.slice(rowGroupDataName.length).trim();
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
},{
|
||||
targets: 4,
|
||||
name: 'ownerImage',
|
||||
title: '',
|
||||
width: 24,
|
||||
orderable: false,
|
||||
className: [config.tableCellImageClass, 'text-center', 'all'].join(' '),
|
||||
data: 'corporation.id',
|
||||
defaultContent: '<i class="fas fa-question txt-color txt-color-orangeDark"></i>',
|
||||
render: {
|
||||
_: function(data, type, row, meta){
|
||||
let value = data;
|
||||
if(type === 'display' && value){
|
||||
value = '<a href="https://zkillboard.com/corporation/' + data + '/" target="_blank" rel="noopener">';
|
||||
value += '<img src="' + Util.eveImageUrl('corporation', data) + '"/>';
|
||||
value += '</a>';
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
},{
|
||||
targets: 5,
|
||||
name: 'ownerName',
|
||||
title: 'owner',
|
||||
width: 80,
|
||||
className: [config.tableCellActionClass, config.tableCellEllipsisClass, 'all'].join(' '),
|
||||
data: 'corporation',
|
||||
defaultContent: '<i class="fas fa-question txt-color txt-color-orangeDark"></i>',
|
||||
render: {
|
||||
_: function(data, type, row, meta){
|
||||
let value = data.name;
|
||||
if(type === 'display'){
|
||||
value += ' ' + getIconForInformationWindow();
|
||||
}
|
||||
return value;
|
||||
}
|
||||
},
|
||||
createdCell: function(cell, cellData, rowData, rowIndex, colIndex){
|
||||
// open corporation information window (ingame)
|
||||
$(cell).on('click', { tableApi: this.api() }, function(e){
|
||||
let cellData = e.data.tableApi.cell(this).data();
|
||||
Util.openIngameWindow(cellData.id);
|
||||
});
|
||||
}
|
||||
},{
|
||||
targets: 6,
|
||||
title: '<i title="set destination" data-toggle="tooltip" class="fas fa-flag text-right"></i>',
|
||||
orderable: false,
|
||||
searchable: false,
|
||||
width: 10,
|
||||
class: [config.tableCellActionClass, config.moduleHeadlineIconClass, 'text-center', 'all'].join(' '),
|
||||
data: 'id',
|
||||
render: {
|
||||
display: (cellData, type, rowData, meta) => {
|
||||
if(cellData){
|
||||
return '<i class="fas fa-flag"></i>';
|
||||
}
|
||||
}
|
||||
},
|
||||
createdCell: function(cell, cellData, rowData, rowIndex, colIndex){
|
||||
$(cell).on('click', function(e){
|
||||
Util.setDestination('set_destination', 'station', {id: cellData, name: rowData.name});
|
||||
});
|
||||
}
|
||||
},{
|
||||
targets: 7,
|
||||
title: '<i title="services" data-toggle="tooltip" class="fas fa-tools text-right"></i>',
|
||||
orderable: false,
|
||||
searchable: false,
|
||||
width: 10,
|
||||
class: [config.tableCellActionClass, config.moduleHeadlineIconClass, config.tableCellServicesClass, Util.config.popoverTriggerClass, 'text-center', 'all'].join(' '),
|
||||
data: 'services',
|
||||
defaultContent: '<i class="fas fa-ban txt-color txt-color-grayLight"></i>',
|
||||
render: {
|
||||
display: (cellData, type, rowData, meta) => {
|
||||
if(cellData && cellData.length){
|
||||
return '<i class="fas fa-tools"></i>';
|
||||
}
|
||||
}
|
||||
},
|
||||
createdCell: function(cell, cellData, rowData, rowIndex, colIndex){
|
||||
let cellElement = $(cell);
|
||||
if(cellElement.find('.fa-ban').length){
|
||||
cellElement.removeClass(config.tableCellActionClass + ' ' + config.moduleHeadlineIconClass);
|
||||
}
|
||||
}
|
||||
},{
|
||||
targets: 8,
|
||||
name: 'rowGroupData',
|
||||
className: 'never', // never show this column. see: https://datatables.net/extensions/responsive/classes
|
||||
data: 'rowGroupData',
|
||||
visible: false,
|
||||
render: {
|
||||
sort: function(data){
|
||||
return data.name;
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
initComplete: function(settings, json){
|
||||
let tableApi = this.api();
|
||||
|
||||
initStationServiceTooltip(this, tableApi);
|
||||
}
|
||||
};
|
||||
|
||||
$.extend(true, stationDataTableOptions, getDataTableDefaults());
|
||||
let tableApiStation = stationTable.DataTable(stationDataTableOptions);
|
||||
|
||||
new $.fn.dataTable.Responsive(tableApiStation);
|
||||
|
||||
tableApiStation.on('responsive-resize', function(e, tableApi, columns){
|
||||
// rowGroup length changes as well -> trigger draw() updates rowGroup length (see drawCallback())
|
||||
tableApi.draw();
|
||||
});
|
||||
}
|
||||
|
||||
// init tooltips for this module
|
||||
let tooltipElements = moduleElement.find('[data-toggle="tooltip"]');
|
||||
tooltipElements.tooltip({
|
||||
@@ -743,7 +1142,7 @@ define([
|
||||
|
||||
Util.request('POST', 'structure', [], structureData, context, context => context.moduleElement.hideLoadingAnimation())
|
||||
.then(
|
||||
payload => callbackUpdateStructureRows(payload.context, {structures: payload.data}),
|
||||
payload => callbackUpdateTableRows(payload.context, payload.data),
|
||||
Util.handleAjaxErrorResponse
|
||||
);
|
||||
};
|
||||
@@ -782,16 +1181,27 @@ define([
|
||||
*/
|
||||
let updateModule = (moduleElement, systemData) => {
|
||||
|
||||
// update structure table data
|
||||
let structureTableElement = moduleElement.find('.' + config.systemStructuresTableClass);
|
||||
let tableApi = structureTableElement.DataTable();
|
||||
// update structure table data --------------------------------------------------------------------------------
|
||||
let structureTable = moduleElement.find('.' + config.systemStructuresTableClass);
|
||||
let tableApiStructure = structureTable.DataTable();
|
||||
|
||||
let context = {
|
||||
tableApi: tableApi,
|
||||
let structureContext = {
|
||||
tableApi: tableApiStructure,
|
||||
removeMissing: true
|
||||
};
|
||||
|
||||
callbackUpdateStructureRows(context, systemData);
|
||||
callbackUpdateTableRows(structureContext, Util.getObjVal(systemData, 'structures'));
|
||||
|
||||
// update station table data ----------------------------------------------------------------------------------
|
||||
let stationTable = moduleElement.find('.' + config.systemStationsTableClass);
|
||||
let tableApiStation = stationTable.DataTable();
|
||||
|
||||
let stationContext = {
|
||||
tableApi: tableApiStation,
|
||||
removeMissing: false
|
||||
};
|
||||
|
||||
callbackUpdateTableRows(stationContext, Util.getObjVal(systemData, 'stations'), 'stations');
|
||||
|
||||
moduleElement.hideLoadingAnimation();
|
||||
};
|
||||
@@ -803,7 +1213,6 @@ define([
|
||||
* @param systemData
|
||||
*/
|
||||
let initModule = (moduleElement, mapId, systemData) => {
|
||||
|
||||
let structureTableElement = moduleElement.find('.' + config.systemStructuresTableClass);
|
||||
let tableApi = structureTableElement.DataTable();
|
||||
|
||||
@@ -828,7 +1237,7 @@ define([
|
||||
removeMissing: true
|
||||
},
|
||||
context => context.moduleElement.hideLoadingAnimation()
|
||||
).then(payload => callbackUpdateStructureRows(payload.context, payload.data));
|
||||
).then(payload => callbackUpdateTableRows(payload.context, Util.getObjVal(payload.data, 'structures')));
|
||||
});
|
||||
|
||||
// init listener for global "past" dScan into this page -------------------------------------------------------
|
||||
@@ -845,9 +1254,12 @@ define([
|
||||
* @param moduleElement
|
||||
*/
|
||||
let beforeDestroy = moduleElement => {
|
||||
let structureTableElement = moduleElement.find('.' + config.systemStructuresTableClass);
|
||||
let tableApi = structureTableElement.DataTable();
|
||||
tableApi.destroy();
|
||||
let structureTable = moduleElement.find('.' + config.systemStructuresTableClass);
|
||||
let stationTable = moduleElement.find('.' + config.systemStationsTableClass);
|
||||
let tableApiStructure = structureTable.DataTable();
|
||||
let tableApiStation = stationTable.DataTable();
|
||||
tableApiStructure.destroy();
|
||||
tableApiStation.destroy();
|
||||
};
|
||||
|
||||
return {
|
||||
|
||||
@@ -1219,7 +1219,7 @@ define([
|
||||
placement: 'top',
|
||||
container: 'body',
|
||||
content: content
|
||||
}).data('bs.popover').tip().addClass('pf-popover');
|
||||
}).data('bs.popover').tip().addClass(Util.config.popoverClass);
|
||||
});
|
||||
|
||||
// set popup "close" observer
|
||||
|
||||
@@ -169,7 +169,7 @@ define([
|
||||
* @param tableType
|
||||
* @returns {string}
|
||||
*/
|
||||
let getTableId = (mapId, systemId, tableType) => Util.getTableId(config.sigTableId, mapId, systemId, tableType);
|
||||
let getTableId = (tableType, mapId, systemId) => Util.getTableId(config.sigTableId, tableType, mapId, systemId);
|
||||
|
||||
/**
|
||||
* get a dataTableApi instance from global cache
|
||||
@@ -2169,7 +2169,7 @@ define([
|
||||
let infoElement = $(dialogElement).find('#' + config.sigInfoId);
|
||||
|
||||
let table = $('<table>', {
|
||||
id: getTableId(mapId, systemData.id, 'info'),
|
||||
id: getTableId('info', mapId, systemData.id),
|
||||
class: ['display', 'compact', 'nowrap', config.sigTableClass, config.sigTableInfoClass].join(' ')
|
||||
});
|
||||
|
||||
@@ -2216,7 +2216,7 @@ define([
|
||||
|
||||
// create "empty table for new signature
|
||||
let table = $('<table>', {
|
||||
id: getTableId(mapId, systemData.id, 'secondary'),
|
||||
id: getTableId('secondary', mapId, systemData.id),
|
||||
class: ['stripe', 'row-border', 'compact', 'nowrap', config.sigTableClass, config.sigTableSecondaryClass].join(' ')
|
||||
});
|
||||
|
||||
@@ -2497,7 +2497,7 @@ define([
|
||||
};
|
||||
|
||||
/**
|
||||
* init character info Tooltips
|
||||
* init character info tooltips
|
||||
* -> e.g. table cell 'question mark' icon
|
||||
* @param element
|
||||
* @param tableApi
|
||||
@@ -2528,7 +2528,7 @@ define([
|
||||
*/
|
||||
let drawSignatureTable = (moduleElement, mapId, systemData) => {
|
||||
let table = $('<table>', {
|
||||
id: getTableId(mapId, systemData.id, 'primary'),
|
||||
id: getTableId('primary', mapId, systemData.id),
|
||||
class: ['display', 'compact', 'nowrap', config.sigTableClass, config.sigTablePrimaryClass].join(' ')
|
||||
});
|
||||
|
||||
|
||||
@@ -78,9 +78,11 @@ define([
|
||||
animationPulseClassPrefix: 'pf-animation-pulse-', // class prefix for "pulse" background animation
|
||||
|
||||
// popover
|
||||
popoverClass: 'pf-popover', // class for "popover" - custom modifier
|
||||
popoverTriggerClass: 'pf-popover-trigger', // class for "popover" trigger elements
|
||||
popoverSmallClass: 'popover-small', // class for small "popover"
|
||||
popoverCharacterClass: 'pf-popover-character', // class for character "popover"
|
||||
popoverListIconClass: 'pf-popover-list-icon', // class for list "icon"s in "
|
||||
|
||||
// Summernote
|
||||
summernoteClass: 'pf-summernote', // class for Summernote "WYSIWYG" elements
|
||||
@@ -606,7 +608,7 @@ define([
|
||||
container: 'body',
|
||||
content: content,
|
||||
animation: false
|
||||
}).data('bs.popover').tip().addClass('pf-popover');
|
||||
}).data('bs.popover').tip().addClass(config.popoverClass);
|
||||
|
||||
button.popover('show');
|
||||
|
||||
@@ -1013,6 +1015,22 @@ define([
|
||||
return hash;
|
||||
};
|
||||
|
||||
String.prototype.trimLeftChars = function(charList){
|
||||
if(charList === undefined)
|
||||
charList = '\\s';
|
||||
return this.replace(new RegExp('^[' + charList + ']+'), '');
|
||||
};
|
||||
|
||||
String.prototype.trimRightChars = function(charList){
|
||||
if(charList === undefined)
|
||||
charList = '\\s';
|
||||
return this.replace(new RegExp('[' + charList + ']+$'), '');
|
||||
};
|
||||
|
||||
String.prototype.trimChars = function(charList){
|
||||
return this.trimLeftChars(charList).trimRightChars(charList);
|
||||
};
|
||||
|
||||
initPassiveEvents();
|
||||
};
|
||||
|
||||
@@ -1786,6 +1804,8 @@ define([
|
||||
characterLogLocation: valueChanged('character.logLocation'),
|
||||
characterSystemId: valueChanged('character.log.system.id'),
|
||||
characterShipType: valueChanged('character.log.ship.typeId'),
|
||||
characterStationId: valueChanged('character.log.station.id'),
|
||||
characterStructureId: valueChanged('character.log.structure.id'),
|
||||
charactersIds: oldCharactersIds.toString() !== newCharactersIds.toString(),
|
||||
characterLogHistory: oldHistoryLogStamps.toString() !== newHistoryLogStamps.toString()
|
||||
};
|
||||
@@ -2886,11 +2906,12 @@ define([
|
||||
};
|
||||
|
||||
/**
|
||||
* set new destination for a system
|
||||
* @param systemData
|
||||
* set new destination for a system/station/structure
|
||||
* @param type
|
||||
* @param destType
|
||||
* @param destData
|
||||
*/
|
||||
let setDestination = (systemData, type) => {
|
||||
let setDestination = (type, destType, destData) => {
|
||||
let description = '';
|
||||
switch(type){
|
||||
case 'set_destination':
|
||||
@@ -2910,22 +2931,20 @@ define([
|
||||
data: {
|
||||
clearOtherWaypoints: (type === 'set_destination') ? 1 : 0,
|
||||
first: (type === 'add_last_waypoint') ? 0 : 1,
|
||||
systemData: [{
|
||||
systemId: systemData.systemId,
|
||||
name: systemData.name
|
||||
}]
|
||||
destData: [destData]
|
||||
},
|
||||
context: {
|
||||
destType: destType,
|
||||
description: description
|
||||
},
|
||||
dataType: 'json'
|
||||
}).done(function(responseData){
|
||||
if(
|
||||
responseData.systemData &&
|
||||
responseData.systemData.length > 0
|
||||
responseData.destData &&
|
||||
responseData.destData.length > 0
|
||||
){
|
||||
for(let j = 0; j < responseData.systemData.length; j++){
|
||||
showNotify({title: this.description, text: 'System: ' + responseData.systemData[j].name, type: 'success'});
|
||||
for(let j = 0; j < responseData.destData.length; j++){
|
||||
showNotify({title: this.description, text: this.destType + ': ' + responseData.destData[j].name, type: 'success'});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2934,7 +2953,7 @@ define([
|
||||
responseData.error.length > 0
|
||||
){
|
||||
for(let i = 0; i < responseData.error.length; i++){
|
||||
showNotify({title: this.description + ' error', text: 'System: ' + responseData.error[i].message, type: 'error'});
|
||||
showNotify({title: this.description + ' error', text: this.destType + ': ' + responseData.error[i].message, type: 'error'});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3254,7 +3273,16 @@ define([
|
||||
* @param tableType
|
||||
* @returns {string}
|
||||
*/
|
||||
let getTableId = (prefix, mapId, systemId, tableType) => prefix + [mapId, systemId, tableType].join('-');
|
||||
let getTableId = (prefix, tableType, mapId, systemId) => prefix + [tableType, mapId, systemId].join('-');
|
||||
|
||||
/**
|
||||
* get dataTable row id
|
||||
* @param prefix
|
||||
* @param tableType
|
||||
* @param rowId
|
||||
* @returns {string}
|
||||
*/
|
||||
let getTableRowId = (prefix, tableType, rowId) => prefix + [tableType, rowId].join('-');
|
||||
|
||||
/**
|
||||
* get a dataTableApi instance from global cache
|
||||
@@ -3266,7 +3294,7 @@ define([
|
||||
*/
|
||||
let getDataTableInstance = (prefix, mapId, systemId, tableType) => {
|
||||
let instance = null;
|
||||
let table = $.fn.dataTable.tables({ visible: false, api: true }).table('#' + getTableId(prefix, mapId, systemId, tableType));
|
||||
let table = $.fn.dataTable.tables({ visible: false, api: true }).table('#' + getTableId(prefix, tableType, mapId, systemId));
|
||||
if(table.node()){
|
||||
instance = table;
|
||||
}
|
||||
@@ -3522,6 +3550,7 @@ define([
|
||||
getBrowserTabId: getBrowserTabId,
|
||||
singleDoubleClick: singleDoubleClick,
|
||||
getTableId: getTableId,
|
||||
getTableRowId: getTableRowId,
|
||||
getDataTableInstance: getDataTableInstance,
|
||||
htmlEncode: htmlEncode,
|
||||
htmlDecode: htmlDecode,
|
||||
|
||||
|
Before Width: | Height: | Size: 1.2 KiB |
BIN
public/img/icons/client/ui/window/charcustomization.png
Normal file
|
After Width: | Height: | Size: 958 B |
BIN
public/img/icons/client/ui/window/clonebay.png
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
public/img/icons/client/ui/window/concord.png
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
public/img/icons/client/ui/window/docking.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
public/img/icons/client/ui/window/factionalwarfare.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
public/img/icons/client/ui/window/fitting.png
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
public/img/icons/client/ui/window/industry.png
Normal file
|
After Width: | Height: | Size: 653 B |
BIN
public/img/icons/client/ui/window/insurance.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
public/img/icons/client/ui/window/jumpclones.png
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
BIN
public/img/icons/client/ui/window/lpstore.png
Normal file
|
After Width: | Height: | Size: 2.5 KiB |
BIN
public/img/icons/client/ui/window/market.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
public/img/icons/client/ui/window/repairshop.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
public/img/icons/client/ui/window/reprocess.png
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
public/img/icons/client/ui/window/research.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
public/img/icons/client/ui/window/skins.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 3.5 KiB |
BIN
public/img/icons/logo_anoik.png
Normal file
|
After Width: | Height: | Size: 4.4 KiB |
BIN
public/img/icons/logo_dotlan.png
Normal file
|
After Width: | Height: | Size: 4.9 KiB |
BIN
public/img/icons/logo_eve.png
Normal file
|
After Width: | Height: | Size: 4.1 KiB |
BIN
public/img/icons/logo_eveeye.png
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
@@ -137,7 +137,8 @@ define([
|
||||
|
||||
// mark as init
|
||||
tableElement.attr('data-counter', 'init');
|
||||
let refreshIntervalId = window.setInterval(() => {
|
||||
|
||||
let updateTableCount = () => {
|
||||
tableApi.cells(null, columnSelector).every(function(rowIndex, colIndex, tableLoopCount, cellLoopCount){
|
||||
let cell = this;
|
||||
let node = cell.node();
|
||||
@@ -148,7 +149,9 @@ define([
|
||||
updateDateDiff( cell.nodes().to$(), date, round);
|
||||
}
|
||||
});
|
||||
}, 500);
|
||||
};
|
||||
|
||||
let refreshIntervalId = window.setInterval(updateTableCount, 500);
|
||||
|
||||
tableElement.data('interval', refreshIntervalId);
|
||||
};
|
||||
|
||||
@@ -163,7 +163,7 @@ define([
|
||||
{icon: 'fa-route', action: 'find_route', text: 'find route'},
|
||||
{icon: 'fa-object-group', action: 'select_connections', text: 'select connections'},
|
||||
{icon: 'fa-reply fa-rotate-180', text: 'waypoints', subitems: [
|
||||
{subIcon: 'fa-flag-checkered', subAction: 'set_destination', subText: 'set destination'},
|
||||
{subIcon: 'fa-flag', subAction: 'set_destination', subText: 'set destination'},
|
||||
{subDivider: true, action: ''},
|
||||
{subIcon: 'fa-step-backward', subAction: 'add_first_waypoint', subText: 'add new [start]'},
|
||||
{subIcon: 'fa-step-forward', subAction: 'add_last_waypoint', subText: 'add new [end]'}
|
||||
|
||||
@@ -422,7 +422,7 @@ define([
|
||||
_: (data, type, row, meta) => {
|
||||
let value = data.typeName;
|
||||
if(type === 'display'){
|
||||
value = '<img src="' + Util.eveImageUrl('render', data.typeId) + '_32.png"/>';
|
||||
value = '<img src="' + Util.eveImageUrl('render', data.typeId) + '"/>';
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -1763,6 +1763,91 @@ define([
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* add station services tooltip
|
||||
* @param services
|
||||
* @param options
|
||||
* @returns {*}
|
||||
*/
|
||||
$.fn.addStationServiceTooltip = function(services, options){
|
||||
let getServiceIcon = service => {
|
||||
switch(service){
|
||||
case 'bounty-missions': return false;
|
||||
case 'assasination-missions': return false;
|
||||
case 'courier-missions': return false;
|
||||
case 'interbus': return false;
|
||||
case 'reprocessing-plant': return 'reprocess';
|
||||
case 'refinery': return false;
|
||||
case 'market': return 'market';
|
||||
case 'black-market': return false;
|
||||
case 'stock-exchange': return false;
|
||||
case 'cloning': return 'clonebay';
|
||||
case 'surgery': return false;
|
||||
case 'dna-therapy': return false;
|
||||
case 'repair-facilities': return 'repairshop';
|
||||
case 'factory': return 'industry';
|
||||
case 'labratory': return 'research';
|
||||
case 'gambling': return false;
|
||||
case 'fitting': return 'fitting';
|
||||
case 'paintshop': return 'skins';
|
||||
case 'news': return false;
|
||||
case 'storage': return false;
|
||||
case 'insurance': return 'insurance';
|
||||
case 'docking': return 'docking';
|
||||
case 'office-rental': return false;
|
||||
case 'jump-clone-facility': return 'jumpclones';
|
||||
case 'loyalty-point-store': return 'lpstore';
|
||||
case 'navy-offices': return 'factionalwarfare';
|
||||
case 'security-offices': return 'concord';
|
||||
default: return false;
|
||||
}
|
||||
};
|
||||
|
||||
let getStationServicesTable = services => {
|
||||
let content = '';
|
||||
for(let i = 0; i < services.length; i++){
|
||||
let icon = getServiceIcon(services[i]);
|
||||
if(icon){
|
||||
content += '<img class="' + Util.config.popoverListIconClass + '" src="/public/img/icons/client/ui/window/' + icon + '.png" alt="' + services[i] + '">';
|
||||
}
|
||||
}
|
||||
return content;
|
||||
};
|
||||
|
||||
let content = getStationServicesTable(services);
|
||||
|
||||
let title = '<i class="fas fa-tools fa-fw"></i> Services';
|
||||
|
||||
let defaultOptions = {
|
||||
placement: 'top',
|
||||
html: true,
|
||||
trigger: 'hover',
|
||||
container: 'body',
|
||||
title: title,
|
||||
content: '',
|
||||
delay: {
|
||||
show: 150,
|
||||
hide: 0
|
||||
},
|
||||
};
|
||||
|
||||
options = $.extend({}, defaultOptions, options);
|
||||
|
||||
return this.each(function(){
|
||||
let element = $(this);
|
||||
element.popover(options);
|
||||
|
||||
// set new popover content
|
||||
let popover = element.data('bs.popover');
|
||||
popover.options.content = content;
|
||||
popover.tip().addClass(Util.config.popoverClass);
|
||||
|
||||
if(options.show){
|
||||
element.popover('show');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* add system effect tooltip
|
||||
* @param security
|
||||
@@ -1807,7 +1892,6 @@ define([
|
||||
* @returns {*}
|
||||
*/
|
||||
$.fn.addSystemPlanetsTooltip = function(planets, options){
|
||||
|
||||
let content = Util.getSystemPlanetsTable(planets);
|
||||
|
||||
let defaultOptions = {
|
||||
|
||||
@@ -1012,7 +1012,13 @@ define([
|
||||
if(changes.charactersIds){
|
||||
updateTasks.push(updateHeaderCharacterSwitch(userData, changes.characterId));
|
||||
}
|
||||
if(changes.characterSystemId || changes.characterShipType || changes.characterLogHistory){
|
||||
if(
|
||||
changes.characterSystemId ||
|
||||
changes.characterShipType ||
|
||||
changes.characterStationId ||
|
||||
changes.characterStructureId ||
|
||||
changes.characterLogHistory
|
||||
){
|
||||
updateTasks.push(updateHeaderCharacterLocation(userData, changes.characterShipType));
|
||||
}
|
||||
|
||||
@@ -1087,6 +1093,16 @@ define([
|
||||
let shipTypeId = Util.getObjVal(shipData, 'typeId') || 0;
|
||||
let shipTypeName = Util.getObjVal(shipData, 'typeName') || '';
|
||||
|
||||
let stationData = Util.getObjVal(userData, 'character.log.station');
|
||||
let stationId = Util.getObjVal(stationData, 'id') || 0;
|
||||
let stationName = Util.getObjVal(stationData, 'name') || '';
|
||||
|
||||
let structureData = Util.getObjVal(userData, 'character.log.structure');
|
||||
let structureTypeId = Util.getObjVal(structureData, 'type.id') || 0;
|
||||
let structureTypeName = Util.getObjVal(structureData, 'type.name') || '';
|
||||
let structureId = Util.getObjVal(structureData, 'id') || 0;
|
||||
let structureName = Util.getObjVal(structureData, 'name') || '';
|
||||
|
||||
logDataAll.push(logData);
|
||||
|
||||
// check for log history data as well
|
||||
@@ -1116,6 +1132,12 @@ define([
|
||||
|
||||
if(isCurrentLocation){
|
||||
breadcrumbHtml += '<i class="fas fa-fw fa-map-marker-alt" title="current location"></i>';
|
||||
|
||||
if(stationId > 0){
|
||||
breadcrumbHtml += '<i class="fas fa-home" title="' + stationName + '"></i>';
|
||||
}else if(structureId > 0){
|
||||
breadcrumbHtml += '<i class="fas fa-industry" title="' + structureTypeName + ' "' + structureName + '""></i>';
|
||||
}
|
||||
}
|
||||
|
||||
breadcrumbHtml += systemName;
|
||||
|
||||
@@ -205,7 +205,7 @@ define([
|
||||
let systemsElement = $(this).empty();
|
||||
|
||||
let systemTable = $('<table>', {
|
||||
id: Util.getTableId(config.tableId, mapData.config.id, '', 'systems'),
|
||||
id: Util.getTableId(config.tableId, 'systems', mapData.config.id, ''),
|
||||
class: ['compact', 'stripe', 'order-column', 'row-border'].join(' ')
|
||||
});
|
||||
systemsElement.append(systemTable);
|
||||
@@ -864,7 +864,7 @@ define([
|
||||
}
|
||||
},
|
||||
createdCell: function(cell, cellData, rowData, rowIndex, colIndex){
|
||||
// open character information window (ingame)
|
||||
// open corporation information window (ingame)
|
||||
$(cell).on('click', { tableApi: this.api() }, function(e){
|
||||
let cellData = e.data.tableApi.cell(this).data();
|
||||
Util.openIngameWindow(cellData.id);
|
||||
|
||||
@@ -188,6 +188,61 @@ define([
|
||||
moduleElement.find('.' + config.systemSovSectionClass + ' .' + Util.config.dynamicAreaClass).hideLoadingAnimation();
|
||||
};
|
||||
|
||||
/**
|
||||
* @param pages
|
||||
* @param systemData
|
||||
*/
|
||||
let getThirdPartySystemLinks = (pages, systemData) => {
|
||||
let urls = {};
|
||||
let isWormhole = MapUtil.getSystemTypeInfo(Util.getObjVal(systemData, 'type.id'), 'name') === 'w-space';
|
||||
let systemName = Util.getObjVal(systemData, 'name') || '';
|
||||
let regionName = Util.getObjVal(systemData, 'region.name') || '';
|
||||
|
||||
let validUrls = 0;
|
||||
for(let i = 0; i < pages.length; i++){
|
||||
let url = false;
|
||||
let domain = Util.getObjVal(Init, 'url.' + pages[i]);
|
||||
if(domain || pages[i] === 'eve'){
|
||||
switch(pages[i]){
|
||||
case 'eve':
|
||||
url = 'https://client'; // fake url
|
||||
break;
|
||||
case 'dotlan':
|
||||
systemName = systemName.replace(/ /g, '_');
|
||||
regionName = regionName.replace(/ /g, '_');
|
||||
if(isWormhole){
|
||||
url = domain + '/system/' + systemName;
|
||||
}else{
|
||||
url = domain + '/map/' + regionName + '/' + systemName;
|
||||
}
|
||||
break;
|
||||
case 'eveeye':
|
||||
if(!isWormhole){
|
||||
url = domain + '/?m=' + encodeURIComponent(regionName) + '&s=' + encodeURIComponent(systemName.replace(/ /g, '_'));
|
||||
url += '&t=eswkc&o=thera,con_svc,node_sov,sub_sec,sector_fac,tag_mk';
|
||||
}
|
||||
break;
|
||||
case 'anoik':
|
||||
if(isWormhole){
|
||||
url = domain + '/systems/' + systemName;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if(url){
|
||||
let urlObj = new URL(url);
|
||||
urls[++validUrls + '_url'] = {
|
||||
page: pages[i],
|
||||
domain: urlObj.hostname,
|
||||
url: url
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return urls;
|
||||
};
|
||||
|
||||
/**
|
||||
* get module element
|
||||
* @param parentElement
|
||||
@@ -294,7 +349,6 @@ define([
|
||||
|
||||
systemUrl: MapUtil.getMapDeeplinkUrl(mapId, systemData.id),
|
||||
systemTypeName: MapUtil.getSystemTypeInfo(systemData.type.id, 'name'),
|
||||
systemIsWormhole: MapUtil.getSystemTypeInfo(systemData.type.id, 'name') === 'w-space',
|
||||
systemStatusId: systemData.status.id,
|
||||
systemStatusClass: Util.getStatusInfoForSystem(systemData.status.id, 'class'),
|
||||
systemStatusLabel: Util.getStatusInfoForSystem(systemData.status.id, 'label'),
|
||||
@@ -326,6 +380,7 @@ define([
|
||||
systemTypeLinkClass: config.typeLinkClass,
|
||||
systemUrlLinkClass: config.urlLinkClass,
|
||||
ccpImageServerUrl: Init.url.ccpImageServer,
|
||||
thirdPartyLinks: getThirdPartySystemLinks(['eve', 'dotlan', 'eveeye', 'anoik'], systemData)
|
||||
};
|
||||
|
||||
requirejs(['text!templates/modules/system_info.html', 'mustache', 'summernote.loader'], (template, Mustache, Summernote) => {
|
||||
|
||||
@@ -7,8 +7,9 @@ define([
|
||||
'app/init',
|
||||
'app/util',
|
||||
'bootbox',
|
||||
'app/counter'
|
||||
], ($, Init, Util, bootbox, Counter) => {
|
||||
'app/counter',
|
||||
'app/map/util',
|
||||
], ($, Init, Util, bootbox, Counter, MapUtil) => {
|
||||
'use strict';
|
||||
|
||||
let config = {
|
||||
@@ -18,7 +19,7 @@ define([
|
||||
moduleHeadClass: 'pf-module-head', // class for module header
|
||||
moduleHandlerClass: 'pf-module-handler-drag', // class for "drag" handler
|
||||
|
||||
// system info module
|
||||
// system intel module
|
||||
moduleTypeClass: 'pf-system-intel-module', // class for this module
|
||||
|
||||
// headline toolbar
|
||||
@@ -28,10 +29,14 @@ define([
|
||||
moduleHeadlineIconRefreshClass: 'pf-module-icon-button-refresh', // class for "refresh" icon
|
||||
|
||||
// system intel module
|
||||
systemStructuresTableClass: 'pf-system-structure-table', // class for route tables
|
||||
intelTableId: 'pf-intel-table-', // id prefix for all tables in module
|
||||
intelTableRowIdPrefix: 'pf-intel-row-', // id prefix for table rows
|
||||
systemStationsTableClass: 'pf-system-station-table', // class for NPC owned stations table
|
||||
systemStructuresTableClass: 'pf-system-structure-table', // class for player owned structures table
|
||||
|
||||
// structure dialog
|
||||
structureDialogId: 'pf-structure-dialog', // id for "structure" dialog
|
||||
nameInputId: 'pf-structure-dialog-name-input', // id for "name" input
|
||||
statusSelectId: 'pf-structure-dialog-status-select', // id for "status" select
|
||||
typeSelectId: 'pf-structure-dialog-type-select', // id for "type" select
|
||||
corporationSelectId: 'pf-structure-dialog-corporation-select', // id for "corporation" select
|
||||
@@ -39,11 +44,12 @@ define([
|
||||
descriptionTextareaCharCounter: 'pf-form-field-char-count', // class for "character counter" element for form field
|
||||
|
||||
// dataTable
|
||||
tableRowIdPrefix: 'pf-structure-row_', // id prefix for table rows
|
||||
tableCellImageClass: 'pf-table-image-smaller-cell', // class for table "image" cells
|
||||
tableCellCounterClass: 'pf-table-counter-cell', // class for table "counter" cells
|
||||
tableCellEllipsisClass: 'pf-table-cell-ellipses-auto', // class for table "ellipsis" cells
|
||||
dataTableActionCellClass: 'pf-table-action-cell' // class for "action" cells
|
||||
tableCellActionClass: 'pf-table-action-cell', // class for "action" cells
|
||||
tableCellActionIconClass: 'pf-table-action-icon-cell', // class for table "action" icon (icon is part of cell content)
|
||||
tableCellServicesClass: 'pf-table-services-cell' // class for table station "services" cells
|
||||
};
|
||||
|
||||
let maxDescriptionLength = 512;
|
||||
@@ -53,26 +59,102 @@ define([
|
||||
* @param statusData
|
||||
* @returns {string}
|
||||
*/
|
||||
let getStatusData = statusData => {
|
||||
let getIconForStatusData = statusData => {
|
||||
return '<i class="fas fa-fw fa-circle ' + statusData.class + '" title="' + statusData.label + '"></i>';
|
||||
};
|
||||
|
||||
/**
|
||||
* get icon that marks a table cell as clickable
|
||||
* @returns {string}
|
||||
*/
|
||||
let getIconForInformationWindow = () => {
|
||||
return '<i class="fas fa-fw fa-id-card ' + config.tableCellActionIconClass + '" title="open ingame" data-toggle="tooltip"></i>';
|
||||
};
|
||||
|
||||
/**
|
||||
* get dataTable id
|
||||
* @param mapId
|
||||
* @param systemId
|
||||
* @param tableType
|
||||
* @returns {string}
|
||||
*/
|
||||
let getTableId = (tableType, mapId, systemId) => Util.getTableId(config.intelTableId, tableType, mapId, systemId);
|
||||
|
||||
/**
|
||||
* get dataTable row id
|
||||
* @param tableType
|
||||
* @param id
|
||||
* @returns {string}
|
||||
*/
|
||||
let getRowId = (tableType, id) => Util.getTableRowId(config.intelTableRowIdPrefix, tableType, id);
|
||||
|
||||
/**
|
||||
* get <tr> DOM id by id
|
||||
* @param tableApi
|
||||
* @param id
|
||||
* @returns {*}
|
||||
*/
|
||||
let getRowId = (tableApi, id) => {
|
||||
return tableApi.rows().ids().toArray().find(rowId => rowId === config.tableRowIdPrefix + id);
|
||||
let getRowById = (tableApi, id) => {
|
||||
return tableApi.rows().ids().toArray().find(rowId => rowId === getRowId(Util.getObjVal(getTableMetaData(tableApi), 'type'), id));
|
||||
};
|
||||
|
||||
/**
|
||||
* callback -> add structure rows from systemData
|
||||
* @param context
|
||||
* @param systemData
|
||||
* get custom "metaData" from dataTables API
|
||||
* @param tableApi
|
||||
* @returns {*}
|
||||
*/
|
||||
let callbackUpdateStructureRows = (context, systemData) => {
|
||||
let getTableMetaData = tableApi => {
|
||||
let data = null;
|
||||
if(tableApi){
|
||||
data = tableApi.init().pfMeta;
|
||||
}
|
||||
return data;
|
||||
};
|
||||
|
||||
/**
|
||||
* vormat roman numeric string to int
|
||||
* -> e.g. 'VII' => 7
|
||||
* @param str
|
||||
* @returns {number}
|
||||
*/
|
||||
let romanToInt = str => {
|
||||
let charToTnt = char => {
|
||||
switch (char) {
|
||||
case 'I': return 1;
|
||||
case 'V': return 5;
|
||||
case 'X': return 10;
|
||||
case 'L': return 50;
|
||||
case 'C': return 100;
|
||||
case 'D': return 500;
|
||||
case 'M': return 1000;
|
||||
default: return -1;
|
||||
}
|
||||
};
|
||||
|
||||
if(str == null) return -1;
|
||||
let num = charToTnt(str.charAt(0));
|
||||
let pre, curr;
|
||||
|
||||
for(let i = 1; i < str.length; i++){
|
||||
curr = charToTnt(str.charAt(i));
|
||||
pre = charToTnt(str.charAt(i - 1));
|
||||
if(curr <= pre){
|
||||
num += curr;
|
||||
}else{
|
||||
num = num - pre * 2 + curr;
|
||||
}
|
||||
}
|
||||
|
||||
return num;
|
||||
};
|
||||
|
||||
/**
|
||||
* callback -> add table rows from grouped tableData
|
||||
* @param context
|
||||
* @param tableData
|
||||
* @param groupedDataKey
|
||||
*/
|
||||
let callbackUpdateTableRows = (context, tableData, groupedDataKey = 'structures') => {
|
||||
let touchedRows = [];
|
||||
let hadData = context.tableApi.rows().any();
|
||||
let notificationCounter = {
|
||||
@@ -81,41 +163,39 @@ define([
|
||||
deleted: 0
|
||||
};
|
||||
|
||||
if(systemData){
|
||||
let corporations = Util.getObjVal(systemData, 'structures');
|
||||
if(corporations){
|
||||
for(let [corporationId, corporationData] of Object.entries(corporations)){
|
||||
if(corporationData.structures && corporationData.structures.length){
|
||||
for(let structureData of corporationData.structures){
|
||||
let rowId = getRowId(context.tableApi, structureData.id);
|
||||
if(tableData){
|
||||
for(let [rowGroupId, rowGroupData] of Object.entries(tableData)){
|
||||
if(rowGroupData[groupedDataKey] && rowGroupData[groupedDataKey].length){
|
||||
for(let rowData of rowGroupData[groupedDataKey]){
|
||||
let rowId = getRowById(context.tableApi, rowData.id);
|
||||
|
||||
// add corporation data
|
||||
structureData.corporation = {
|
||||
id: corporationData.id,
|
||||
name: corporationData.name
|
||||
};
|
||||
// add rowGroupData as well to each rowData
|
||||
rowData.rowGroupData = {
|
||||
id: rowGroupData.id,
|
||||
name: rowGroupData.name,
|
||||
groupedDataKey: groupedDataKey
|
||||
};
|
||||
|
||||
if(rowId){
|
||||
// update row
|
||||
let api = context.tableApi.row('#' + rowId);
|
||||
let rowData = api.data();
|
||||
if(rowId){
|
||||
// update row
|
||||
let api = context.tableApi.row('#' + rowId);
|
||||
let rowDataCurrent = api.data();
|
||||
|
||||
// check for update
|
||||
if(rowData.updated.updated !== structureData.updated.updated){
|
||||
// row data changed -> update
|
||||
api.data(structureData);
|
||||
notificationCounter.changed++;
|
||||
}
|
||||
|
||||
touchedRows.push(api.id());
|
||||
}else{
|
||||
// insert new row
|
||||
let api = context.tableApi.row.add(structureData);
|
||||
api.nodes().to$().data('animationStatus', 'added');
|
||||
notificationCounter.added++;
|
||||
|
||||
touchedRows.push(api.id());
|
||||
// check for update
|
||||
if(rowDataCurrent.updated.updated !== rowData.updated.updated){
|
||||
// row data changed -> update
|
||||
api.data(rowData);
|
||||
notificationCounter.changed++;
|
||||
}
|
||||
|
||||
touchedRows.push(api.id());
|
||||
}else{
|
||||
// insert new row
|
||||
let api = context.tableApi.row.add(rowData);
|
||||
api.nodes().to$().data('animationStatus', 'added');
|
||||
notificationCounter.added++;
|
||||
|
||||
touchedRows.push(api.id());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -156,7 +236,7 @@ define([
|
||||
let deletedCounter = 0;
|
||||
if(structureIds && structureIds.length){
|
||||
for(let structureId of structureIds){
|
||||
let rowId = getRowId(context.tableApi, structureId);
|
||||
let rowId = getRowById(context.tableApi, structureId);
|
||||
if(rowId){
|
||||
context.tableApi.row('#' + rowId).remove();
|
||||
deletedCounter++;
|
||||
@@ -214,10 +294,36 @@ define([
|
||||
return data;
|
||||
});
|
||||
|
||||
// if current user is currently docked at a structure (not station)
|
||||
// -> add a modal button for pre-fill modal with it
|
||||
// -> systemId must match systemId from current character log
|
||||
let currentUserData = Util.getCurrentUserData();
|
||||
let isCurrentLocation = false;
|
||||
let characterStructureId = Util.getObjVal(currentUserData, 'character.log.structure.id') || 0;
|
||||
let characterStructureName = Util.getObjVal(currentUserData, 'character.log.structure.name') || '';
|
||||
let characterStructureTypeId = Util.getObjVal(currentUserData, 'character.log.structure.type.id') || 0;
|
||||
let characterStructureTypeName = Util.getObjVal(currentUserData, 'character.log.structure.type.name') || '';
|
||||
|
||||
if(systemId === Util.getObjVal(currentUserData, 'character.log.system.id')){
|
||||
isCurrentLocation = true;
|
||||
}
|
||||
|
||||
let disableButtonAutoFill = true;
|
||||
let buttonLabelAutoFill = '<i class="fas fa-fw fa-map-marker-alt"></i> ';
|
||||
if(characterStructureId){
|
||||
buttonLabelAutoFill += characterStructureTypeName + ' "' + characterStructureName + '"';
|
||||
if(isCurrentLocation){
|
||||
disableButtonAutoFill = false;
|
||||
}
|
||||
}else{
|
||||
buttonLabelAutoFill += 'unknown structure';
|
||||
}
|
||||
|
||||
let data = {
|
||||
id: config.structureDialogId,
|
||||
structureData: structureData,
|
||||
structureStatus: statusData,
|
||||
nameInputId: config.nameInputId,
|
||||
statusSelectId: config.statusSelectId,
|
||||
typeSelectId: config.typeSelectId,
|
||||
corporationSelectId: config.corporationSelectId,
|
||||
@@ -236,7 +342,18 @@ define([
|
||||
buttons: {
|
||||
close: {
|
||||
label: 'cancel',
|
||||
className: 'btn-default'
|
||||
className: 'btn-default pull-left'
|
||||
},
|
||||
autoFill: {
|
||||
label: buttonLabelAutoFill,
|
||||
className: 'btn-primary' + (disableButtonAutoFill ? ' pf-font-italic disabled' : ''),
|
||||
callback: function(){
|
||||
let form = this.find('form');
|
||||
form.find('#' + config.nameInputId).val(characterStructureName);
|
||||
form.find('#' + config.statusSelectId).val(2).trigger('change');
|
||||
form.find('#' + config.typeSelectId).val(characterStructureTypeId).trigger('change');
|
||||
return false;
|
||||
}
|
||||
},
|
||||
success: {
|
||||
label: '<i class="fas fa-fw fa-check"></i> save',
|
||||
@@ -268,7 +385,7 @@ define([
|
||||
},
|
||||
context => context.moduleElement.hideLoadingAnimation()
|
||||
).then(
|
||||
payload => callbackUpdateStructureRows(payload.context, {structures: payload.data}),
|
||||
payload => callbackUpdateTableRows(payload.context, payload.data),
|
||||
Util.handleAjaxErrorResponse
|
||||
);
|
||||
}else{
|
||||
@@ -361,6 +478,83 @@ define([
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* init station services tooltips
|
||||
* @param element
|
||||
* @param tableApi
|
||||
*/
|
||||
let initStationServiceTooltip = (element, tableApi) => {
|
||||
element.hoverIntent({
|
||||
over: function(e){
|
||||
let cellElement = $(this);
|
||||
let rowData = tableApi.row(cellElement.parents('tr')).data();
|
||||
cellElement.addStationServiceTooltip(Util.getObjVal(rowData, 'services'), {
|
||||
placement: 'left',
|
||||
trigger: 'manual',
|
||||
show: true
|
||||
});
|
||||
},
|
||||
out: function(e){
|
||||
$(this).destroyPopover();
|
||||
},
|
||||
selector: 'td.' + config.tableCellServicesClass
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* get dataTables default options for intel tables
|
||||
* @returns {*}
|
||||
*/
|
||||
let getDataTableDefaults = () => {
|
||||
return {
|
||||
paging: false,
|
||||
lengthChange: false,
|
||||
ordering: true,
|
||||
info: false,
|
||||
searching: false,
|
||||
hover: false,
|
||||
autoWidth: false,
|
||||
drawCallback: function (settings) {
|
||||
let tableApi = this.api();
|
||||
let columnCount = tableApi.columns(':visible').count();
|
||||
let rows = tableApi.rows({page: 'current'}).nodes();
|
||||
let last = null;
|
||||
|
||||
tableApi.column('rowGroupData:name', {page: 'current'}).data().each(function (group, i) {
|
||||
if (!last || last.id !== group.id) {
|
||||
// "stations" are grouped by "raceId" with its "factionId"
|
||||
// "structures" are grouped by "corporationId" that ADDED it (not the ingame "owner" of it)
|
||||
let imgType = 'stations' === group.groupedDataKey ? 'alliance' : 'corporation';
|
||||
|
||||
$(rows).eq(i).before(
|
||||
'<tr class="group">' +
|
||||
'<td></td>' +
|
||||
'<td class="text-right ' + config.tableCellImageClass + '">' +
|
||||
'<img src="' + Util.eveImageUrl(imgType, group.id) + '"/>' +
|
||||
'</td>' +
|
||||
'<td colspan="' + Math.max((columnCount - 2), 1) + '">' + group.name + '</td>' +
|
||||
'</tr>'
|
||||
);
|
||||
last = group;
|
||||
}
|
||||
});
|
||||
|
||||
let animationRows = rows.to$().filter(function () {
|
||||
return (
|
||||
$(this).data('animationStatus') ||
|
||||
$(this).data('animationTimer')
|
||||
);
|
||||
});
|
||||
|
||||
for (let i = 0; i < animationRows.length; i++) {
|
||||
let animationRow = $(animationRows[i]);
|
||||
animationRow.pulseBackgroundColor(animationRow.data('animationStatus'));
|
||||
animationRow.removeData('animationStatus');
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* get module element
|
||||
* @param parentElement
|
||||
@@ -369,6 +563,7 @@ define([
|
||||
* @returns {jQuery}
|
||||
*/
|
||||
let getModule = (parentElement, mapId, systemData) => {
|
||||
let showStationTable = ['H', 'L', '0.0', 'C12'].includes(Util.getObjVal(systemData, 'security'));
|
||||
let corporationId = Util.getCurrentUserInfo('corporationId');
|
||||
|
||||
let moduleElement = $('<div>').append(
|
||||
@@ -395,35 +590,29 @@ define([
|
||||
}).attr('data-html', 'true').attr('data-toggle', 'tooltip')
|
||||
),
|
||||
$('<h5>', {
|
||||
text: 'Intel'
|
||||
text: 'Structures'
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
let table = $('<table>', {
|
||||
// "Structures" table -----------------------------------------------------------------------------------------
|
||||
let structureTable = $('<table>', {
|
||||
id: getTableId('structure', mapId, systemData.id),
|
||||
class: ['compact', 'stripe', 'order-column', 'row-border', 'pf-table-fixed', config.systemStructuresTableClass].join(' ')
|
||||
});
|
||||
moduleElement.append(table);
|
||||
moduleElement.append(structureTable);
|
||||
|
||||
let tableApi = table.DataTable({
|
||||
paging: false,
|
||||
lengthChange: false,
|
||||
ordering: true,
|
||||
order: [[ 10, 'desc' ], [ 0, 'asc' ]],
|
||||
info: false,
|
||||
searching: false,
|
||||
hover: false,
|
||||
autoWidth: false,
|
||||
rowId: rowData => config.tableRowIdPrefix + rowData.id,
|
||||
let structureDataTableOptions = {
|
||||
pfMeta: {
|
||||
type: 'structures'
|
||||
},
|
||||
order: [[10, 'desc' ], [0, 'asc' ]],
|
||||
rowId: rowData => getRowId('structures', rowData.id),
|
||||
language: {
|
||||
emptyTable: 'No structures recorded',
|
||||
info: '_START_ to _END_ of _MAX_',
|
||||
infoEmpty: ''
|
||||
},
|
||||
rowGroup: {
|
||||
enable: true,
|
||||
dataSrc: 'systemId'
|
||||
},
|
||||
columnDefs: [
|
||||
{
|
||||
targets: 0,
|
||||
@@ -433,17 +622,17 @@ define([
|
||||
className: ['text-center', 'all'].join(' '),
|
||||
data: 'status',
|
||||
render: {
|
||||
display: data => getStatusData(data),
|
||||
display: data => getIconForStatusData(data),
|
||||
sort: data => data.id
|
||||
},
|
||||
createdCell: function(cell, cellData, rowData, rowIndex, colIndex){
|
||||
$(cell).find('i').tooltip();
|
||||
$(cell).find('i').tooltip();
|
||||
}
|
||||
},{
|
||||
targets: 1,
|
||||
name: 'structureImage',
|
||||
title: '',
|
||||
width: 26,
|
||||
width: 24,
|
||||
orderable: false,
|
||||
className: [config.tableCellImageClass, 'text-center', 'all'].join(' '),
|
||||
data: 'structure.id',
|
||||
@@ -476,7 +665,7 @@ define([
|
||||
targets: 4,
|
||||
name: 'ownerImage',
|
||||
title: '',
|
||||
width: 26,
|
||||
width: 24,
|
||||
orderable: false,
|
||||
className: [config.tableCellImageClass, 'text-center', 'all'].join(' '),
|
||||
data: 'owner.id',
|
||||
@@ -519,12 +708,12 @@ define([
|
||||
title: '',
|
||||
orderable: false,
|
||||
width: 10,
|
||||
className: ['text-center', config.dataTableActionCellClass, config.moduleHeadlineIconClass, 'all'].join(' '),
|
||||
className: ['text-center', config.tableCellActionClass, config.moduleHeadlineIconClass, 'all'].join(' '),
|
||||
data: null,
|
||||
render: {
|
||||
display: data => {
|
||||
let icon = '<i class="fas fa-pen"></i>';
|
||||
if(data.corporation.id !== corporationId){
|
||||
if(data.rowGroupData.id !== corporationId){
|
||||
icon = '';
|
||||
}
|
||||
return icon;
|
||||
@@ -534,7 +723,7 @@ define([
|
||||
let tableApi = this.api();
|
||||
|
||||
if($(cell).is(':empty')){
|
||||
$(cell).removeClass(config.dataTableActionCellClass + ' ' + config.moduleHeadlineIconClass);
|
||||
$(cell).removeClass(config.tableCellActionClass + ' ' + config.moduleHeadlineIconClass);
|
||||
}else{
|
||||
$(cell).on('click', function(e){
|
||||
// get current row data (important!)
|
||||
@@ -550,12 +739,12 @@ define([
|
||||
title: '',
|
||||
orderable: false,
|
||||
width: 10,
|
||||
className: ['text-center', config.dataTableActionCellClass, 'all'].join(' '),
|
||||
className: ['text-center', config.tableCellActionClass, 'all'].join(' '),
|
||||
data: null,
|
||||
render: {
|
||||
display: data => {
|
||||
let icon = '<i class="fas fa-times txt-color txt-color-redDarker"></i>';
|
||||
if(data.corporation.id !== corporationId){
|
||||
if(data.rowGroupData.id !== corporationId){
|
||||
icon = '<i class="fas fa-ban txt-color txt-color-grayLight" title="restricted" data-placement="left"></i>';
|
||||
}
|
||||
return icon;
|
||||
@@ -565,7 +754,7 @@ define([
|
||||
let tableApi = this.api();
|
||||
|
||||
if($(cell).find('.fa-ban').length){
|
||||
$(cell).removeClass(config.dataTableActionCellClass + ' ' + config.moduleHeadlineIconClass);
|
||||
$(cell).removeClass(config.tableCellActionClass + ' ' + config.moduleHeadlineIconClass);
|
||||
$(cell).find('i').tooltip();
|
||||
}else{
|
||||
let confirmationSettings = {
|
||||
@@ -602,9 +791,9 @@ define([
|
||||
}
|
||||
},{
|
||||
targets: 10,
|
||||
name: 'corporation',
|
||||
name: 'rowGroupData',
|
||||
className: 'never', // never show this column. see: https://datatables.net/extensions/responsive/classes
|
||||
data: 'corporation',
|
||||
data: 'rowGroupData',
|
||||
visible: false,
|
||||
render: {
|
||||
sort: function(data){
|
||||
@@ -613,40 +802,6 @@ define([
|
||||
}
|
||||
}
|
||||
],
|
||||
drawCallback: function(settings){
|
||||
let tableApi = this.api();
|
||||
let columnCount = tableApi.columns(':visible').count();
|
||||
let rows = tableApi.rows( {page:'current'} ).nodes();
|
||||
let last= null;
|
||||
|
||||
tableApi.column('corporation:name', {page:'current'} ).data().each( function(group, i ){
|
||||
if( !last || last.id !== group.id ){
|
||||
$(rows).eq(i).before(
|
||||
'<tr class="group">' +
|
||||
'<td></td>' +
|
||||
'<td class="' + config.tableCellImageClass + '">' +
|
||||
'<img src="' + Util.eveImageUrl('corporation', group.id) + '"/>' +
|
||||
'</td>' +
|
||||
'<td colspan="' + (columnCount - 2 ) + '">' + group.name + '</td>' +
|
||||
'</tr>'
|
||||
);
|
||||
last = group;
|
||||
}
|
||||
});
|
||||
|
||||
let animationRows = rows.to$().filter(function(){
|
||||
return (
|
||||
$(this).data('animationStatus') ||
|
||||
$(this).data('animationTimer')
|
||||
);
|
||||
});
|
||||
|
||||
for(let i = 0; i < animationRows.length; i++){
|
||||
let animationRow = $(animationRows[i]);
|
||||
animationRow.pulseBackgroundColor(animationRow.data('animationStatus'));
|
||||
animationRow.removeData('animationStatus');
|
||||
}
|
||||
},
|
||||
initComplete: function(settings){
|
||||
// table data is load in updateModule() method
|
||||
// -> no need to trigger additional ajax call here for data
|
||||
@@ -655,15 +810,259 @@ define([
|
||||
|
||||
Counter.initTableCounter(this, ['updated:name'], 'd');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
new $.fn.dataTable.Responsive(tableApi);
|
||||
$.extend(true, structureDataTableOptions, getDataTableDefaults());
|
||||
let tableApiStructure = structureTable.DataTable(structureDataTableOptions);
|
||||
|
||||
tableApi.on('responsive-resize', function(e, tableApi, columns){
|
||||
new $.fn.dataTable.Responsive(tableApiStructure);
|
||||
|
||||
tableApiStructure.on('responsive-resize', function(e, tableApi, columns){
|
||||
// rowGroup length changes as well -> trigger draw() updates rowGroup length (see drawCallback())
|
||||
tableApi.draw();
|
||||
});
|
||||
|
||||
if(showStationTable){
|
||||
// "Stations" table ---------------------------------------------------------------------------------------
|
||||
|
||||
moduleElement.append(
|
||||
$('<div>', {
|
||||
class: config.moduleHeadClass
|
||||
}).append(
|
||||
$('<h5>', {
|
||||
class: config.moduleHandlerClass
|
||||
}),
|
||||
$('<h5>', {
|
||||
text: 'Stations'
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
let stationTable = $('<table>', {
|
||||
id: getTableId('station', mapId, systemData.id),
|
||||
class: ['compact', 'stripe', 'order-column', 'row-border', 'pf-table-fixed', config.systemStationsTableClass].join(' ')
|
||||
});
|
||||
moduleElement.append(stationTable);
|
||||
|
||||
let stationDataTableOptions = {
|
||||
pfMeta: {
|
||||
type: 'stations'
|
||||
},
|
||||
order: [[1, 'asc' ], [8, 'asc' ]],
|
||||
rowId: rowData => getRowId('stations', rowData.id),
|
||||
language: {
|
||||
emptyTable: 'No stations found',
|
||||
info: '_START_ to _END_ of _MAX_',
|
||||
infoEmpty: ''
|
||||
},
|
||||
columnDefs: [
|
||||
{
|
||||
targets: 0,
|
||||
name: 'stationImage',
|
||||
title: '',
|
||||
width: 24,
|
||||
orderable: false,
|
||||
className: [config.tableCellImageClass, 'text-center', 'all'].join(' '),
|
||||
data: 'type.id',
|
||||
defaultContent: '<i class="fas fa-question txt-color txt-color-orangeDark"></i>',
|
||||
render: {
|
||||
_: function(data, type, row, meta){
|
||||
let value = data;
|
||||
if(type === 'display' && value){
|
||||
value = '<img src="' + Util.eveImageUrl('type', value) +'"/>';
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
},{
|
||||
targets: 1,
|
||||
name: 'count',
|
||||
title: '',
|
||||
width: 5,
|
||||
className: ['text-center', 'all'].join(' '),
|
||||
data: 'name',
|
||||
render: {
|
||||
_: function(cellData, type, rowData, meta){
|
||||
let value = '';
|
||||
if(cellData){
|
||||
let matches = /^(?<system>[a-z0-9\s\-]+) (?<count>[MDCLXVI]+) .*$/i.exec(cellData);
|
||||
let count = Util.getObjVal(matches, 'groups.count');
|
||||
|
||||
if(type === 'display'){
|
||||
value = count || 0;
|
||||
}else{
|
||||
value = romanToInt(count) || '';
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
}
|
||||
},{
|
||||
targets: 2,
|
||||
name: 'name',
|
||||
title: 'station',
|
||||
className: [config.tableCellEllipsisClass, 'all'].join(' '),
|
||||
data: 'name',
|
||||
render: {
|
||||
_: function(cellData, type, rowData, meta){
|
||||
let value = cellData;
|
||||
if(cellData){
|
||||
let matches = /^(?<system>[a-z0-9\s\-]+) (?<count>[MDCLXVI]+) (?<label>\(\w+\)\s)?\- (?<moon>moon (?<moonCount>\d)+)?.*$/i.exec(cellData);
|
||||
let systemName = Util.getObjVal(matches, 'groups.system');
|
||||
let count = Util.getObjVal(matches, 'groups.count');
|
||||
let moon = Util.getObjVal(matches, 'groups.moon');
|
||||
if(systemName === (Util.getObjVal(systemData, 'name') || '')){
|
||||
value = value.slice(systemName.length).trim();
|
||||
if(count){
|
||||
value = value.slice(count.length).trimLeftChars(' \-');
|
||||
}
|
||||
if(moon){
|
||||
let moonCount = Util.getObjVal(matches, 'groups.moonCount');
|
||||
value = value.replace(moon, 'M' + moonCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
},{
|
||||
targets: 3,
|
||||
name: 'stationType',
|
||||
title: 'type',
|
||||
width: 100,
|
||||
className: [config.tableCellEllipsisClass, 'not-screen-l'].join(' '),
|
||||
data: 'type.name',
|
||||
defaultContent: '<i class="fas fa-question txt-color txt-color-orangeDark"></i>',
|
||||
render: {
|
||||
display: (cellData, type, rowData, meta) => {
|
||||
let value = cellData;
|
||||
if(value){
|
||||
let rowGroupDataName = Util.getObjVal(rowData, 'rowGroupData.name') || '';
|
||||
if(value.indexOf(rowGroupDataName) === 0){
|
||||
value = value.slice(rowGroupDataName.length).trim();
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
},{
|
||||
targets: 4,
|
||||
name: 'ownerImage',
|
||||
title: '',
|
||||
width: 24,
|
||||
orderable: false,
|
||||
className: [config.tableCellImageClass, 'text-center', 'all'].join(' '),
|
||||
data: 'corporation.id',
|
||||
defaultContent: '<i class="fas fa-question txt-color txt-color-orangeDark"></i>',
|
||||
render: {
|
||||
_: function(data, type, row, meta){
|
||||
let value = data;
|
||||
if(type === 'display' && value){
|
||||
value = '<a href="https://zkillboard.com/corporation/' + data + '/" target="_blank" rel="noopener">';
|
||||
value += '<img src="' + Util.eveImageUrl('corporation', data) + '"/>';
|
||||
value += '</a>';
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
},{
|
||||
targets: 5,
|
||||
name: 'ownerName',
|
||||
title: 'owner',
|
||||
width: 80,
|
||||
className: [config.tableCellActionClass, config.tableCellEllipsisClass, 'all'].join(' '),
|
||||
data: 'corporation',
|
||||
defaultContent: '<i class="fas fa-question txt-color txt-color-orangeDark"></i>',
|
||||
render: {
|
||||
_: function(data, type, row, meta){
|
||||
let value = data.name;
|
||||
if(type === 'display'){
|
||||
value += ' ' + getIconForInformationWindow();
|
||||
}
|
||||
return value;
|
||||
}
|
||||
},
|
||||
createdCell: function(cell, cellData, rowData, rowIndex, colIndex){
|
||||
// open corporation information window (ingame)
|
||||
$(cell).on('click', { tableApi: this.api() }, function(e){
|
||||
let cellData = e.data.tableApi.cell(this).data();
|
||||
Util.openIngameWindow(cellData.id);
|
||||
});
|
||||
}
|
||||
},{
|
||||
targets: 6,
|
||||
title: '<i title="set destination" data-toggle="tooltip" class="fas fa-flag text-right"></i>',
|
||||
orderable: false,
|
||||
searchable: false,
|
||||
width: 10,
|
||||
class: [config.tableCellActionClass, config.moduleHeadlineIconClass, 'text-center', 'all'].join(' '),
|
||||
data: 'id',
|
||||
render: {
|
||||
display: (cellData, type, rowData, meta) => {
|
||||
if(cellData){
|
||||
return '<i class="fas fa-flag"></i>';
|
||||
}
|
||||
}
|
||||
},
|
||||
createdCell: function(cell, cellData, rowData, rowIndex, colIndex){
|
||||
$(cell).on('click', function(e){
|
||||
Util.setDestination('set_destination', 'station', {id: cellData, name: rowData.name});
|
||||
});
|
||||
}
|
||||
},{
|
||||
targets: 7,
|
||||
title: '<i title="services" data-toggle="tooltip" class="fas fa-tools text-right"></i>',
|
||||
orderable: false,
|
||||
searchable: false,
|
||||
width: 10,
|
||||
class: [config.tableCellActionClass, config.moduleHeadlineIconClass, config.tableCellServicesClass, Util.config.popoverTriggerClass, 'text-center', 'all'].join(' '),
|
||||
data: 'services',
|
||||
defaultContent: '<i class="fas fa-ban txt-color txt-color-grayLight"></i>',
|
||||
render: {
|
||||
display: (cellData, type, rowData, meta) => {
|
||||
if(cellData && cellData.length){
|
||||
return '<i class="fas fa-tools"></i>';
|
||||
}
|
||||
}
|
||||
},
|
||||
createdCell: function(cell, cellData, rowData, rowIndex, colIndex){
|
||||
let cellElement = $(cell);
|
||||
if(cellElement.find('.fa-ban').length){
|
||||
cellElement.removeClass(config.tableCellActionClass + ' ' + config.moduleHeadlineIconClass);
|
||||
}
|
||||
}
|
||||
},{
|
||||
targets: 8,
|
||||
name: 'rowGroupData',
|
||||
className: 'never', // never show this column. see: https://datatables.net/extensions/responsive/classes
|
||||
data: 'rowGroupData',
|
||||
visible: false,
|
||||
render: {
|
||||
sort: function(data){
|
||||
return data.name;
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
initComplete: function(settings, json){
|
||||
let tableApi = this.api();
|
||||
|
||||
initStationServiceTooltip(this, tableApi);
|
||||
}
|
||||
};
|
||||
|
||||
$.extend(true, stationDataTableOptions, getDataTableDefaults());
|
||||
let tableApiStation = stationTable.DataTable(stationDataTableOptions);
|
||||
|
||||
new $.fn.dataTable.Responsive(tableApiStation);
|
||||
|
||||
tableApiStation.on('responsive-resize', function(e, tableApi, columns){
|
||||
// rowGroup length changes as well -> trigger draw() updates rowGroup length (see drawCallback())
|
||||
tableApi.draw();
|
||||
});
|
||||
}
|
||||
|
||||
// init tooltips for this module
|
||||
let tooltipElements = moduleElement.find('[data-toggle="tooltip"]');
|
||||
tooltipElements.tooltip({
|
||||
@@ -743,7 +1142,7 @@ define([
|
||||
|
||||
Util.request('POST', 'structure', [], structureData, context, context => context.moduleElement.hideLoadingAnimation())
|
||||
.then(
|
||||
payload => callbackUpdateStructureRows(payload.context, {structures: payload.data}),
|
||||
payload => callbackUpdateTableRows(payload.context, payload.data),
|
||||
Util.handleAjaxErrorResponse
|
||||
);
|
||||
};
|
||||
@@ -782,16 +1181,27 @@ define([
|
||||
*/
|
||||
let updateModule = (moduleElement, systemData) => {
|
||||
|
||||
// update structure table data
|
||||
let structureTableElement = moduleElement.find('.' + config.systemStructuresTableClass);
|
||||
let tableApi = structureTableElement.DataTable();
|
||||
// update structure table data --------------------------------------------------------------------------------
|
||||
let structureTable = moduleElement.find('.' + config.systemStructuresTableClass);
|
||||
let tableApiStructure = structureTable.DataTable();
|
||||
|
||||
let context = {
|
||||
tableApi: tableApi,
|
||||
let structureContext = {
|
||||
tableApi: tableApiStructure,
|
||||
removeMissing: true
|
||||
};
|
||||
|
||||
callbackUpdateStructureRows(context, systemData);
|
||||
callbackUpdateTableRows(structureContext, Util.getObjVal(systemData, 'structures'));
|
||||
|
||||
// update station table data ----------------------------------------------------------------------------------
|
||||
let stationTable = moduleElement.find('.' + config.systemStationsTableClass);
|
||||
let tableApiStation = stationTable.DataTable();
|
||||
|
||||
let stationContext = {
|
||||
tableApi: tableApiStation,
|
||||
removeMissing: false
|
||||
};
|
||||
|
||||
callbackUpdateTableRows(stationContext, Util.getObjVal(systemData, 'stations'), 'stations');
|
||||
|
||||
moduleElement.hideLoadingAnimation();
|
||||
};
|
||||
@@ -803,7 +1213,6 @@ define([
|
||||
* @param systemData
|
||||
*/
|
||||
let initModule = (moduleElement, mapId, systemData) => {
|
||||
|
||||
let structureTableElement = moduleElement.find('.' + config.systemStructuresTableClass);
|
||||
let tableApi = structureTableElement.DataTable();
|
||||
|
||||
@@ -828,7 +1237,7 @@ define([
|
||||
removeMissing: true
|
||||
},
|
||||
context => context.moduleElement.hideLoadingAnimation()
|
||||
).then(payload => callbackUpdateStructureRows(payload.context, payload.data));
|
||||
).then(payload => callbackUpdateTableRows(payload.context, Util.getObjVal(payload.data, 'structures')));
|
||||
});
|
||||
|
||||
// init listener for global "past" dScan into this page -------------------------------------------------------
|
||||
@@ -845,9 +1254,12 @@ define([
|
||||
* @param moduleElement
|
||||
*/
|
||||
let beforeDestroy = moduleElement => {
|
||||
let structureTableElement = moduleElement.find('.' + config.systemStructuresTableClass);
|
||||
let tableApi = structureTableElement.DataTable();
|
||||
tableApi.destroy();
|
||||
let structureTable = moduleElement.find('.' + config.systemStructuresTableClass);
|
||||
let stationTable = moduleElement.find('.' + config.systemStationsTableClass);
|
||||
let tableApiStructure = structureTable.DataTable();
|
||||
let tableApiStation = stationTable.DataTable();
|
||||
tableApiStructure.destroy();
|
||||
tableApiStation.destroy();
|
||||
};
|
||||
|
||||
return {
|
||||
|
||||
@@ -1219,7 +1219,7 @@ define([
|
||||
placement: 'top',
|
||||
container: 'body',
|
||||
content: content
|
||||
}).data('bs.popover').tip().addClass('pf-popover');
|
||||
}).data('bs.popover').tip().addClass(Util.config.popoverClass);
|
||||
});
|
||||
|
||||
// set popup "close" observer
|
||||
|
||||
@@ -169,7 +169,7 @@ define([
|
||||
* @param tableType
|
||||
* @returns {string}
|
||||
*/
|
||||
let getTableId = (mapId, systemId, tableType) => Util.getTableId(config.sigTableId, mapId, systemId, tableType);
|
||||
let getTableId = (tableType, mapId, systemId) => Util.getTableId(config.sigTableId, tableType, mapId, systemId);
|
||||
|
||||
/**
|
||||
* get a dataTableApi instance from global cache
|
||||
@@ -2169,7 +2169,7 @@ define([
|
||||
let infoElement = $(dialogElement).find('#' + config.sigInfoId);
|
||||
|
||||
let table = $('<table>', {
|
||||
id: getTableId(mapId, systemData.id, 'info'),
|
||||
id: getTableId('info', mapId, systemData.id),
|
||||
class: ['display', 'compact', 'nowrap', config.sigTableClass, config.sigTableInfoClass].join(' ')
|
||||
});
|
||||
|
||||
@@ -2216,7 +2216,7 @@ define([
|
||||
|
||||
// create "empty table for new signature
|
||||
let table = $('<table>', {
|
||||
id: getTableId(mapId, systemData.id, 'secondary'),
|
||||
id: getTableId('secondary', mapId, systemData.id),
|
||||
class: ['stripe', 'row-border', 'compact', 'nowrap', config.sigTableClass, config.sigTableSecondaryClass].join(' ')
|
||||
});
|
||||
|
||||
@@ -2497,7 +2497,7 @@ define([
|
||||
};
|
||||
|
||||
/**
|
||||
* init character info Tooltips
|
||||
* init character info tooltips
|
||||
* -> e.g. table cell 'question mark' icon
|
||||
* @param element
|
||||
* @param tableApi
|
||||
@@ -2528,7 +2528,7 @@ define([
|
||||
*/
|
||||
let drawSignatureTable = (moduleElement, mapId, systemData) => {
|
||||
let table = $('<table>', {
|
||||
id: getTableId(mapId, systemData.id, 'primary'),
|
||||
id: getTableId('primary', mapId, systemData.id),
|
||||
class: ['display', 'compact', 'nowrap', config.sigTableClass, config.sigTablePrimaryClass].join(' ')
|
||||
});
|
||||
|
||||
|
||||
@@ -78,9 +78,11 @@ define([
|
||||
animationPulseClassPrefix: 'pf-animation-pulse-', // class prefix for "pulse" background animation
|
||||
|
||||
// popover
|
||||
popoverClass: 'pf-popover', // class for "popover" - custom modifier
|
||||
popoverTriggerClass: 'pf-popover-trigger', // class for "popover" trigger elements
|
||||
popoverSmallClass: 'popover-small', // class for small "popover"
|
||||
popoverCharacterClass: 'pf-popover-character', // class for character "popover"
|
||||
popoverListIconClass: 'pf-popover-list-icon', // class for list "icon"s in "
|
||||
|
||||
// Summernote
|
||||
summernoteClass: 'pf-summernote', // class for Summernote "WYSIWYG" elements
|
||||
@@ -606,7 +608,7 @@ define([
|
||||
container: 'body',
|
||||
content: content,
|
||||
animation: false
|
||||
}).data('bs.popover').tip().addClass('pf-popover');
|
||||
}).data('bs.popover').tip().addClass(config.popoverClass);
|
||||
|
||||
button.popover('show');
|
||||
|
||||
@@ -1013,6 +1015,22 @@ define([
|
||||
return hash;
|
||||
};
|
||||
|
||||
String.prototype.trimLeftChars = function(charList){
|
||||
if(charList === undefined)
|
||||
charList = '\\s';
|
||||
return this.replace(new RegExp('^[' + charList + ']+'), '');
|
||||
};
|
||||
|
||||
String.prototype.trimRightChars = function(charList){
|
||||
if(charList === undefined)
|
||||
charList = '\\s';
|
||||
return this.replace(new RegExp('[' + charList + ']+$'), '');
|
||||
};
|
||||
|
||||
String.prototype.trimChars = function(charList){
|
||||
return this.trimLeftChars(charList).trimRightChars(charList);
|
||||
};
|
||||
|
||||
initPassiveEvents();
|
||||
};
|
||||
|
||||
@@ -1786,6 +1804,8 @@ define([
|
||||
characterLogLocation: valueChanged('character.logLocation'),
|
||||
characterSystemId: valueChanged('character.log.system.id'),
|
||||
characterShipType: valueChanged('character.log.ship.typeId'),
|
||||
characterStationId: valueChanged('character.log.station.id'),
|
||||
characterStructureId: valueChanged('character.log.structure.id'),
|
||||
charactersIds: oldCharactersIds.toString() !== newCharactersIds.toString(),
|
||||
characterLogHistory: oldHistoryLogStamps.toString() !== newHistoryLogStamps.toString()
|
||||
};
|
||||
@@ -2886,11 +2906,12 @@ define([
|
||||
};
|
||||
|
||||
/**
|
||||
* set new destination for a system
|
||||
* @param systemData
|
||||
* set new destination for a system/station/structure
|
||||
* @param type
|
||||
* @param destType
|
||||
* @param destData
|
||||
*/
|
||||
let setDestination = (systemData, type) => {
|
||||
let setDestination = (type, destType, destData) => {
|
||||
let description = '';
|
||||
switch(type){
|
||||
case 'set_destination':
|
||||
@@ -2910,22 +2931,20 @@ define([
|
||||
data: {
|
||||
clearOtherWaypoints: (type === 'set_destination') ? 1 : 0,
|
||||
first: (type === 'add_last_waypoint') ? 0 : 1,
|
||||
systemData: [{
|
||||
systemId: systemData.systemId,
|
||||
name: systemData.name
|
||||
}]
|
||||
destData: [destData]
|
||||
},
|
||||
context: {
|
||||
destType: destType,
|
||||
description: description
|
||||
},
|
||||
dataType: 'json'
|
||||
}).done(function(responseData){
|
||||
if(
|
||||
responseData.systemData &&
|
||||
responseData.systemData.length > 0
|
||||
responseData.destData &&
|
||||
responseData.destData.length > 0
|
||||
){
|
||||
for(let j = 0; j < responseData.systemData.length; j++){
|
||||
showNotify({title: this.description, text: 'System: ' + responseData.systemData[j].name, type: 'success'});
|
||||
for(let j = 0; j < responseData.destData.length; j++){
|
||||
showNotify({title: this.description, text: this.destType + ': ' + responseData.destData[j].name, type: 'success'});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2934,7 +2953,7 @@ define([
|
||||
responseData.error.length > 0
|
||||
){
|
||||
for(let i = 0; i < responseData.error.length; i++){
|
||||
showNotify({title: this.description + ' error', text: 'System: ' + responseData.error[i].message, type: 'error'});
|
||||
showNotify({title: this.description + ' error', text: this.destType + ': ' + responseData.error[i].message, type: 'error'});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3254,7 +3273,16 @@ define([
|
||||
* @param tableType
|
||||
* @returns {string}
|
||||
*/
|
||||
let getTableId = (prefix, mapId, systemId, tableType) => prefix + [mapId, systemId, tableType].join('-');
|
||||
let getTableId = (prefix, tableType, mapId, systemId) => prefix + [tableType, mapId, systemId].join('-');
|
||||
|
||||
/**
|
||||
* get dataTable row id
|
||||
* @param prefix
|
||||
* @param tableType
|
||||
* @param rowId
|
||||
* @returns {string}
|
||||
*/
|
||||
let getTableRowId = (prefix, tableType, rowId) => prefix + [tableType, rowId].join('-');
|
||||
|
||||
/**
|
||||
* get a dataTableApi instance from global cache
|
||||
@@ -3266,7 +3294,7 @@ define([
|
||||
*/
|
||||
let getDataTableInstance = (prefix, mapId, systemId, tableType) => {
|
||||
let instance = null;
|
||||
let table = $.fn.dataTable.tables({ visible: false, api: true }).table('#' + getTableId(prefix, mapId, systemId, tableType));
|
||||
let table = $.fn.dataTable.tables({ visible: false, api: true }).table('#' + getTableId(prefix, tableType, mapId, systemId));
|
||||
if(table.node()){
|
||||
instance = table;
|
||||
}
|
||||
@@ -3522,6 +3550,7 @@ define([
|
||||
getBrowserTabId: getBrowserTabId,
|
||||
singleDoubleClick: singleDoubleClick,
|
||||
getTableId: getTableId,
|
||||
getTableRowId: getTableRowId,
|
||||
getDataTableInstance: getDataTableInstance,
|
||||
htmlEncode: htmlEncode,
|
||||
htmlDecode: htmlDecode,
|
||||
|
||||
@@ -340,7 +340,7 @@
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-xs-12 col-md-6">
|
||||
<h4 id="pf-manual-scrollspy-anchor-system-waypoint"><i class="fas fa-flag-checkered fa-fw"></i> Waypoints</h4>
|
||||
<h4 id="pf-manual-scrollspy-anchor-system-waypoint"><i class="fas fa-flag fa-fw"></i> Waypoints</h4>
|
||||
<p>
|
||||
Waypoints can be set to systems. Waypoint options are identical to their in game options.
|
||||
</p>
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
<div class="row">
|
||||
<div class="col-xs-6 ">
|
||||
<div class="form-group">
|
||||
<label for="form_name" class="col-sm-2 control-label">Name</label>
|
||||
<label for="{{nameInputId}}" class="col-sm-2 control-label">Name</label>
|
||||
<div class="col-sm-10">
|
||||
<input name="name" type="text" class="form-control" id="form_name" value="{{structureData.name}}" data-error="Name required" data-minlength="3" data-minlength-error="Min. of 3 characters" required>
|
||||
<input name="name" type="text" class="form-control" id="{{nameInputId}}" value="{{structureData.name}}" data-error="Name required" data-minlength="3" data-minlength-error="Min. of 3 characters" required>
|
||||
<span class="note help-block with-errors"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -20,17 +20,6 @@
|
||||
<i class="fas fa-fw fa-lock" data-toggle="tooltip" title="locked"></i>
|
||||
{{/system.locked}}
|
||||
</h5>
|
||||
|
||||
{{#systemIsWormhole}}
|
||||
<a href="{{#formatUrl}}http://evemaps.dotlan.net/system/{{system.name}}{{/formatUrl}}" class="pf-icon pf-icon-dotlan" data-toggle="tooltip" title="dotlan" target="_blank" rel="noopener"></a>
|
||||
{{/systemIsWormhole}}
|
||||
{{^systemIsWormhole}}
|
||||
<a href="{{#formatUrl}}http://evemaps.dotlan.net/map/{{system.region.name}}/{{system.name}}{{/formatUrl}}" class="pf-icon pf-icon-dotlan" data-toggle="tooltip" title="dotlan" target="_blank" rel="noopener"></a>
|
||||
{{/systemIsWormhole}}
|
||||
|
||||
{{#systemIsWormhole}}
|
||||
<a href="{{#formatUrl}}http://anoik.is/systems/{{system.name}}{{/formatUrl}}" class="pf-icon pf-icon-anoik" data-toggle="tooltip" title="anoik" target="_blank" rel="noopener"></a>
|
||||
{{/systemIsWormhole}}
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
@@ -41,7 +30,7 @@
|
||||
{{systemStatusLabel}}
|
||||
</span>
|
||||
|
||||
<div class="pf-dynamic-area">
|
||||
<div class="pf-dynamic-area" data-resizebar>
|
||||
<table class="table table-condensed pf-table-fixed {{infoTableClass}}">
|
||||
<thead>
|
||||
<tr>
|
||||
@@ -90,6 +79,49 @@
|
||||
{{/static}}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<div class="pf-resizearea">
|
||||
<table class="table table-condensed pf-table-fixed {{infoTableClass}}">
|
||||
<colgroup>
|
||||
<col/>
|
||||
<col style="width: 40px;"/>
|
||||
<col style="width: 40px;"/>
|
||||
<col style="width: 40px;"/>
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Links</th>
|
||||
<th class="pf-table-cell-bg-image" rowspan="2">
|
||||
{{#thirdPartyLinks.1_url}}
|
||||
<a class="pf-table-cell-bg-image-wrapper smaller" style="--bg-image: url('/public/img/icons/logo_{{page}}.png');" data-toggle="tooltip" title="{{ domain }}" href="{{ url }}" target="_blank" rel="noopener"></a>
|
||||
{{/thirdPartyLinks.1_url}}
|
||||
</th>
|
||||
<th class="pf-table-cell-bg-image" rowspan="2">
|
||||
{{#thirdPartyLinks.2_url}}
|
||||
<a class="pf-table-cell-bg-image-wrapper smaller" style="--bg-image: url('/public/img/icons/logo_{{page}}.png');" data-toggle="tooltip" title="{{ domain }}" href="{{ url }}" target="_blank" rel="noopener"></a>
|
||||
{{/thirdPartyLinks.2_url}}
|
||||
</th>
|
||||
<th class="pf-table-cell-bg-image" rowspan="2">
|
||||
{{#thirdPartyLinks.3_url}}
|
||||
<a class="pf-table-cell-bg-image-wrapper smaller" style="--bg-image: url('/public/img/icons/logo_{{page}}.png');" data-toggle="tooltip" title="{{ domain }}" href="{{ url }}" target="_blank" rel="noopener"></a>
|
||||
{{/thirdPartyLinks.3_url}}
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th> </th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="pf-dynamic-area-statusbar">
|
||||
<div class="pf-dynamic-area-resizebar">
|
||||
<div class="pf-resizebar-bar"></div>
|
||||
<div class="pf-resizebar-bar"></div>
|
||||
<div class="pf-resizebar-bar"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<div class="list-group">
|
||||
<a class="list-group-item" href="javascript:void(0);" data-name="{{ systemToData.name }}" data-systemid="{{ systemToData.systemId }}">
|
||||
<i class="fas fa-flag-checkered fa-fw"></i>set destination
|
||||
<i class="fas fa-flag fa-fw"></i>set destination
|
||||
</a>
|
||||
</div>
|
||||
@@ -8,7 +8,6 @@
|
||||
@import "_map";
|
||||
@import "_system-info";
|
||||
@import "_forms";
|
||||
@import "_images";
|
||||
@import "_dialogs";
|
||||
@import "_log";
|
||||
@import "_timeline";
|
||||
|
||||
@@ -95,7 +95,7 @@ $breadcrumb-arrow-size: 15px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
&>.fas{
|
||||
&>.fas:last-of-type{
|
||||
margin-right: 5px !important;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
.pf-icon{
|
||||
display: inline-block;
|
||||
|
||||
&.disabled{
|
||||
opacity: 0.5;
|
||||
color: $gray-light;
|
||||
}
|
||||
}
|
||||
|
||||
.pf-icon-dotlan,.pf-icon-anoik{
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
width: 17px;
|
||||
height: 17px;
|
||||
opacity: 0.8;
|
||||
margin: -5px 0px 0 10px;
|
||||
}
|
||||
|
||||
.pf-icon-dotlan:after{
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 17px;
|
||||
width: 17px;
|
||||
margin-top: 4px;
|
||||
background: inline-image("/icons/dotlan_logo.png") no-repeat;
|
||||
}
|
||||
.pf-icon-anoik:after{
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 17px;
|
||||
width: 17px;
|
||||
margin-top: 4px;
|
||||
background: inline-image("/icons/anoik_logo.png") no-repeat;
|
||||
}
|
||||
@@ -32,7 +32,8 @@ a, .pf-link{
|
||||
}
|
||||
}
|
||||
|
||||
em{
|
||||
em,
|
||||
.pf-font-italic{
|
||||
font-style: italic;
|
||||
|
||||
&.pf-brand{
|
||||
@@ -428,6 +429,10 @@ select:active, select:hover {
|
||||
font-size: 9px !important; // should not be "so big" (10px default)
|
||||
}
|
||||
|
||||
> .label{
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
&.pf-table-link-cell{
|
||||
cursor: pointer;
|
||||
@extend .txt-color;
|
||||
@@ -479,11 +484,12 @@ select:active, select:hover {
|
||||
|
||||
&.pf-table-image-smaller-cell{
|
||||
padding: 0 !important;
|
||||
border-right: 1px solid transparent;
|
||||
img{
|
||||
width: 25px; // smaller image (default 32)
|
||||
width: 23px; // smaller image (default 32)
|
||||
// overwrite "default" border for image cells
|
||||
border-left: 1px solid transparent;
|
||||
border-right: 1px solid transparent;
|
||||
//border-left: 1px solid transparent;
|
||||
//border-right: 1px solid transparent;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -633,6 +639,7 @@ table{
|
||||
border-top-color: transparent !important;
|
||||
|
||||
.pf-table-cell-bg-image-wrapper{
|
||||
display: block;
|
||||
background-size: contain;
|
||||
background-origin: content-box;
|
||||
background-repeat: no-repeat;
|
||||
@@ -642,6 +649,10 @@ table{
|
||||
width: auto;
|
||||
height: 40px;
|
||||
padding: 2px 0;
|
||||
|
||||
&.smaller{
|
||||
height: 30px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -897,6 +908,7 @@ table{
|
||||
will-change: height, transform, opacity;
|
||||
overflow: hidden;
|
||||
@include border-radius(5px);
|
||||
border-top-left-radius: 0;
|
||||
|
||||
&:before{
|
||||
content: '';
|
||||
@@ -1533,6 +1545,64 @@ td.pf-popover-trigger{
|
||||
> [class~='alert']:last-of-type{
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
&[data-resizebar]{
|
||||
padding-bottom: 15px;
|
||||
|
||||
&:hover{
|
||||
.pf-resizearea{
|
||||
@include transition-delay(.15s);
|
||||
height: 40px;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.pf-resizebar-bar{
|
||||
border-top: 1px solid $orange !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&:not([data-resizebar]){
|
||||
.pf-dynamic-area-resizebar{
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.pf-resizearea{
|
||||
height: 0;
|
||||
opacity: 0;
|
||||
@include transition(height .12s ease-out, opacity .12s ease-out);
|
||||
will-change: height, opacity;
|
||||
}
|
||||
|
||||
.pf-dynamic-area-statusbar{
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
background-color: $gray-dark;
|
||||
padding: 1px 0;
|
||||
|
||||
.pf-dynamic-area-resizebar{
|
||||
width: 100%;
|
||||
height: 9px;
|
||||
padding-top: 1px;
|
||||
cursor: ns-resize;
|
||||
|
||||
&:hover{
|
||||
.pf-resizebar-bar{
|
||||
border-top: 1px solid $orange;
|
||||
}
|
||||
}
|
||||
|
||||
.pf-resizebar-bar{
|
||||
border-top: 1px solid $gray-light;
|
||||
transition: border-top 0.15s ease-out;
|
||||
width: 20px;
|
||||
margin: 1px auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// code highlighting ==============================================================================
|
||||
|
||||
@@ -131,6 +131,19 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.pf-popover-list-icon{
|
||||
width: 28px;
|
||||
margin: 5px 0;
|
||||
|
||||
&:first-child{
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
&:last-child{
|
||||
margin-right: 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// character popover --------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// system info module ======================================================
|
||||
$pfSystemSectionMinHeight: 124px;
|
||||
$pfSystemSectionMinHeight: 123px;
|
||||
|
||||
.pf-system-info-module{
|
||||
|
||||
@@ -8,20 +8,25 @@ $pfSystemSectionMinHeight: 124px;
|
||||
text-transform: capitalize;
|
||||
}
|
||||
|
||||
.pf-system-sov-section{
|
||||
@media (max-width: $screen-xs-max) {
|
||||
margin: 10px 0;
|
||||
}
|
||||
@media (min-width: $screen-sm-min) {
|
||||
> .row {
|
||||
> div:not(:first-child){
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.pf-system-sov-section{
|
||||
.pf-dynamic-area{
|
||||
min-height: $pfSystemSectionMinHeight;
|
||||
}
|
||||
}
|
||||
|
||||
.pf-system-description-section{
|
||||
@media (max-width: $screen-xs-max) {
|
||||
padding-left: 10px !important;
|
||||
margin-top: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.pf-system-info-name-cell{
|
||||
user-select: all;
|
||||
}
|
||||
@@ -287,9 +292,14 @@ $pfSystemSectionMinHeight: 124px;
|
||||
// intel module ============================================================
|
||||
.pf-system-intel-module{
|
||||
|
||||
.pf-system-station-table,
|
||||
.pf-system-structure-table{
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
.pf-module-head:not(:first-child){
|
||||
margin-top: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
// killboard module ========================================================
|
||||
|
||||