@@ -1,54 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App;
|
||||
|
||||
class Cortex extends Controller
|
||||
{
|
||||
function get()
|
||||
{
|
||||
$f3 = \Base::instance();
|
||||
$f3->set('AUTOLOAD', $f3->get('AUTOLOAD').';app/cortex/');
|
||||
$f3->set('QUIET', false);
|
||||
|
||||
$dbs = array(
|
||||
'sql' => new \DB\SQL('mysql:host=localhost;port=3306;dbname=fatfree', 'fatfree', ''),
|
||||
// 'sql-sqlite' => new \DB\SQL('sqlite:data/sqlite.db'),
|
||||
// 'sql-pgsql' => new \DB\SQL('pgsql:host=localhost;dbname=fatfree', 'fatfree', 'fatfree'),
|
||||
'jig' => new \DB\Jig('data/'),
|
||||
'mongo' => new \DB\Mongo('mongodb://localhost:27017', 'testdb'),
|
||||
// 'sqlsrv2012' => new \DB\SQL('sqlsrv:SERVER=LOCALHOST\SQLEXPRESS2012;Database=fatfree','fatfree', 'fatfree'),
|
||||
// 'sqlsrv2008' => new \DB\SQL('sqlsrv:SERVER=LOCALHOST\SQLEXPRESS2008;Database=fatfree','fatfree', 'fatfree'),
|
||||
);
|
||||
$results = array();
|
||||
|
||||
// Test Syntax
|
||||
foreach ($dbs as $type => $db) {
|
||||
$test = new \Test_Syntax();
|
||||
$results = array_merge((array) $results, (array) $test->run($db, $type));
|
||||
}
|
||||
|
||||
// Test Relations
|
||||
foreach ($dbs as $type => $db) {
|
||||
$f3->set('DB',$db);
|
||||
$test = new \Test_Relation();
|
||||
$results = array_merge((array) $results, (array) $test->run($db, $type));
|
||||
}
|
||||
|
||||
// Test Filter
|
||||
foreach ($dbs as $type => $db) {
|
||||
$f3->set('DB',$db);
|
||||
$test = new \Test_Filter();
|
||||
$results = array_merge((array) $results, (array) $test->run($db, $type));
|
||||
}
|
||||
|
||||
// Further Common Tests
|
||||
if (isset($dbs['sql'])) {
|
||||
$test = new \Test_Common();
|
||||
$f3->set('DB', $dbs['sql']);
|
||||
$results = array_merge((array) $results, (array) $test->run());
|
||||
}
|
||||
$f3->set('results', $results);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
<?php
|
||||
|
||||
class AuthorModel extends \DB\Cortex {
|
||||
|
||||
protected
|
||||
$fieldConf = array(
|
||||
'name' => array(
|
||||
'type' => \DB\SQL\Schema::DT_VARCHAR256
|
||||
),
|
||||
'mail' => array(
|
||||
'type' => \DB\SQL\Schema::DT_VARCHAR256
|
||||
),
|
||||
'website' => array(
|
||||
'type' => \DB\SQL\Schema::DT_VARCHAR256
|
||||
),
|
||||
'news' => array(
|
||||
'has-many' => array('\NewsModel','author'),
|
||||
),
|
||||
'profile' => array(
|
||||
'has-one' => array('\ProfileModel','author'),
|
||||
),
|
||||
),
|
||||
// $primary = 'aid',
|
||||
$table = 'author',
|
||||
$db = 'DB';
|
||||
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
<?php
|
||||
|
||||
class NewsModel extends \DB\Cortex {
|
||||
|
||||
protected
|
||||
$fieldConf = array(
|
||||
'title' => array(
|
||||
'type' => \DB\SQL\Schema::DT_VARCHAR128
|
||||
),
|
||||
'text' => array(
|
||||
'type' => \DB\SQL\Schema::DT_TEXT
|
||||
),
|
||||
'author' => array(
|
||||
'belongs-to-one' => '\AuthorModel',
|
||||
),
|
||||
'tags' => array(
|
||||
'belongs-to-many' => '\TagModel',
|
||||
),
|
||||
'tags2' => array(
|
||||
'has-many' => array('\TagModel','news','news_tags'),
|
||||
// 'has-many' => array('\TagModel','news'),
|
||||
),
|
||||
),
|
||||
// $primary='nid',
|
||||
$table = 'news',
|
||||
$db = 'DB';
|
||||
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
<?php
|
||||
|
||||
class ProfileModel extends \DB\Cortex {
|
||||
|
||||
protected
|
||||
$fieldConf = array(
|
||||
'message' => array(
|
||||
'type' => \DB\SQL\Schema::DT_TEXT
|
||||
),
|
||||
'image' => array(
|
||||
'type' => \DB\SQL\Schema::DT_VARCHAR256
|
||||
),
|
||||
'author' => array(
|
||||
'belongs-to-one' => '\AuthorModel'
|
||||
)
|
||||
),
|
||||
// $primary = 'profile_id',
|
||||
$table = 'profile',
|
||||
$db = 'DB';
|
||||
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
<?php
|
||||
|
||||
class TagModel extends \DB\Cortex {
|
||||
|
||||
protected
|
||||
$fieldConf = array(
|
||||
'title' => array(
|
||||
'type' => \DB\SQL\Schema::DT_VARCHAR128
|
||||
),
|
||||
'news' => array(
|
||||
'has-many' => array('\NewsModel','tags2','news_tags'),
|
||||
),
|
||||
),
|
||||
// $primary = 'tid',
|
||||
$table = 'tags',
|
||||
$db = 'DB';
|
||||
|
||||
}
|
||||
@@ -1,125 +0,0 @@
|
||||
<?php
|
||||
|
||||
use App\Controller;
|
||||
|
||||
class Test_Common {
|
||||
|
||||
function run()
|
||||
{
|
||||
$test = new \Test();
|
||||
/** @var \Base $f3 */
|
||||
$f3 = \Base::instance();
|
||||
|
||||
$news = new NewsModel();
|
||||
$news->load();
|
||||
|
||||
$dummy = array(
|
||||
'title'=>'copy test',
|
||||
'text'=>'Lorem ipsum dolor sit amet.',
|
||||
'author'=>1,
|
||||
'tags'=>array(3)
|
||||
);
|
||||
$f3->set('record1', $dummy);
|
||||
$news->copyto('record2');
|
||||
|
||||
$test->expect(
|
||||
$f3->exists('record2'),
|
||||
'copyto: raw record copied to hive'
|
||||
);
|
||||
|
||||
$news->reset();
|
||||
|
||||
$news->copyfrom('record1');
|
||||
|
||||
$test->expect(
|
||||
$news->title = 'copy test' &&
|
||||
$news->text = 'Lorem ipsum dolor sit amet.',
|
||||
'copyfrom: hydrate from hive key'
|
||||
);
|
||||
$test->expect(
|
||||
$news->author instanceof AuthorModel
|
||||
&& !$news->author->dry() &&
|
||||
$news->tags instanceof \DB\CortexCollection,
|
||||
'copyfrom: relations hydrated successful'
|
||||
);
|
||||
|
||||
$test->expect(
|
||||
$news->get('author',true) == 1,
|
||||
'get raw data from relational field'
|
||||
);
|
||||
|
||||
$news->reset();
|
||||
$news->copyfrom('record2','title;author');
|
||||
|
||||
$test->expect(
|
||||
$news->title = 'Responsive Images' &&
|
||||
$news->get('author',true) == 2 &&
|
||||
$news->text == NULL,
|
||||
'copyfrom: limit fields with split-able string'
|
||||
);
|
||||
|
||||
$news->reset();
|
||||
$news->copyfrom('record2',array('title'));
|
||||
|
||||
$test->expect(
|
||||
$news->title = 'Responsive Images' && $news->text == NULL,
|
||||
'copyfrom: limit fields by array'
|
||||
);
|
||||
|
||||
$news->reset();
|
||||
$news->copyfrom($dummy,function($fields) {
|
||||
return array_intersect_key($fields,array_flip(array('title')));
|
||||
});
|
||||
|
||||
$test->expect(
|
||||
$news->title = 'copy test',
|
||||
'copyfrom: copy from array instead of hive key'
|
||||
);
|
||||
|
||||
$test->expect(
|
||||
$news->title = 'copy test' && $news->text == NULL,
|
||||
'copyfrom: limit fields by callback function'
|
||||
);
|
||||
|
||||
$all = $news->find();
|
||||
$allTitle = $all->getAll('title');
|
||||
|
||||
$test->expect(
|
||||
count($allTitle) == 3 &&
|
||||
$allTitle[0] == 'Responsive Images' &&
|
||||
$allTitle[1] == 'CSS3 Showcase' &&
|
||||
$allTitle[2] == 'Touchable Interfaces',
|
||||
'collection getAll returns all values of selected field'
|
||||
);
|
||||
|
||||
$newsByID = $all->getBy('_id');
|
||||
$test->expect(
|
||||
array_keys($newsByID) == array(1,2,3),
|
||||
'collection getBy sorts by given field'
|
||||
);
|
||||
|
||||
$newsByAuthorID = $all->getBy('author',true);
|
||||
$test->expect(
|
||||
array_keys($newsByAuthorID) == array(2, 1) &&
|
||||
count($newsByAuthorID[2]) == 2 &&
|
||||
count($newsByAuthorID[1]) == 1,
|
||||
'collection getBy nested sort by author'
|
||||
);
|
||||
|
||||
$allTitle = array();
|
||||
foreach($all as $record)
|
||||
$allTitle[] = $record->title;
|
||||
|
||||
$test->expect(
|
||||
count($allTitle) == 3 &&
|
||||
$allTitle[0] == 'Responsive Images' &&
|
||||
$allTitle[1] == 'CSS3 Showcase' &&
|
||||
$allTitle[2] == 'Touchable Interfaces',
|
||||
'collection is traversable'
|
||||
);
|
||||
|
||||
|
||||
///////////////////////////////////
|
||||
return $test->results();
|
||||
}
|
||||
}
|
||||
@@ -1,302 +0,0 @@
|
||||
<?php
|
||||
|
||||
use App\Controller;
|
||||
|
||||
class Test_Filter {
|
||||
|
||||
function run($db,$type)
|
||||
{
|
||||
$test = new \Test();
|
||||
|
||||
// setup
|
||||
///////////////////////////////////
|
||||
$author = new \AuthorModel();
|
||||
$news = new \NewsModel();
|
||||
$profile = new \ProfileModel();
|
||||
$tag = new \TagModel();
|
||||
|
||||
$ac=$author::resolveConfiguration();
|
||||
$author_pk = (is_int(strpos($type,'sql'))?$ac['primary']:'_id');
|
||||
|
||||
$nc=$news::resolveConfiguration();
|
||||
$news_pk = (is_int(strpos($type,'sql'))?$nc['primary']:'_id');
|
||||
|
||||
$tc=$tag::resolveConfiguration();
|
||||
$tag_pk = (is_int(strpos($type,'sql'))?$tc['primary']:'_id');
|
||||
|
||||
$authorIDs = $author->find()->getAll('_id');
|
||||
$all = $news->find();
|
||||
$newsIDs = $all->getAll('_id');
|
||||
$profileIDs = $profile->find()->getAll('_id');
|
||||
$tagIDs = $tag->find()->getAll('_id');
|
||||
|
||||
// add another relation
|
||||
$news->load(array('title = ?','CSS3 Showcase'));
|
||||
$news->author = $author->load(array($author_pk.' = ?',$authorIDs[0]));
|
||||
$news->save();
|
||||
$news->reset();
|
||||
$author->reset();
|
||||
|
||||
|
||||
// has-filter on belongs-to relation
|
||||
///////////////////////////////////
|
||||
|
||||
$result = $author->has('news', array('title like ?', '%Image%'))->afind();
|
||||
|
||||
$test->expect(
|
||||
count($result) == 1 &&
|
||||
$result[0]['name'] == 'Johnny English',
|
||||
$type.': has filter on many-to-one field'
|
||||
);
|
||||
$test->expect(
|
||||
count($result[0]['news']) == 2 &&
|
||||
$result[0]['news'][0]['title'] == 'Responsive Images' &&
|
||||
$result[0]['news'][1]['title'] == 'CSS3 Showcase',
|
||||
$type.': has filter does not prune relation set'
|
||||
);
|
||||
|
||||
$result = $news->has('author', array('name = ?', 'Johnny English'))->afind();
|
||||
$test->expect(
|
||||
count($result) == 2 && // has 2 news
|
||||
$result[0]['title'] == 'Responsive Images' &&
|
||||
$result[1]['title'] == 'CSS3 Showcase',
|
||||
$type.': has filter on one-to-many field'
|
||||
);
|
||||
|
||||
// add another profile
|
||||
$profile->message = 'Beam me up, Scotty!';
|
||||
$profile->author = $authorIDs[2];
|
||||
$profile->save();
|
||||
$profile->reset();
|
||||
|
||||
$result = $author->has('profile',array('message LIKE ?','%Scotty%'))->afind();
|
||||
$test->expect(
|
||||
count($result) == 1 &&
|
||||
$result[0]['name'] == 'James T. Kirk' &&
|
||||
$result[0]['profile']['message'] == 'Beam me up, Scotty!',
|
||||
$type.': has filter on one-to-one field'
|
||||
);
|
||||
|
||||
$result = $profile->has('author',array('name LIKE ?','%Kirk%'))->afind();
|
||||
$test->expect(
|
||||
count($result) == 1 &&
|
||||
$result[0]['message'] == 'Beam me up, Scotty!' &&
|
||||
$result[0]['author']['name'] == 'James T. Kirk',
|
||||
$type.': has filter on one-to-one field, inverse'
|
||||
);
|
||||
|
||||
// add mm tags
|
||||
$news->load(array('title = ?','Responsive Images'));
|
||||
$news->tags2 = array($tagIDs[0],$tagIDs[1]);
|
||||
$news->save();
|
||||
$news->load(array('title = ?','CSS3 Showcase'));
|
||||
$news->tags2 = array($tagIDs[1],$tagIDs[2]);
|
||||
$news->save();
|
||||
$news->reset();
|
||||
|
||||
$result = $news->has('tags2',array('title like ?','%Design%'))->find();
|
||||
$test->expect(
|
||||
count($result) == 1 &&
|
||||
$result[0]['title'] == 'Responsive Images',
|
||||
$type.': has filter on many-to-many field'
|
||||
);
|
||||
|
||||
$result = $news->has('tags2',array('title = ?','Responsive'))->find();
|
||||
$test->expect(
|
||||
count($result) == 2 &&
|
||||
$result[0]['title'] == 'Responsive Images' &&
|
||||
$result[1]['title'] == 'CSS3 Showcase',
|
||||
$type.': has filter on many-to-many field, additional test'
|
||||
);
|
||||
|
||||
|
||||
$result = $tag->has('news',array('title = ?','Responsive Images'))->find();
|
||||
$test->expect(
|
||||
count($result) == 2 &&
|
||||
$result[0]['title'] == 'Web Design' &&
|
||||
$result[1]['title'] == 'Responsive',
|
||||
$type.': has filter on many-to-many field, inverse'
|
||||
);
|
||||
|
||||
// add another tag
|
||||
$news->load(array('title = ?', 'Touchable Interfaces'));
|
||||
$news->tags2 = array($tagIDs[1]);
|
||||
$news->save();
|
||||
$news->reset();
|
||||
|
||||
$tag->has('news',array('text LIKE ? and title LIKE ?', '%Lorem%', '%Interface%'));
|
||||
$result = $tag->find();
|
||||
$test->expect(
|
||||
count($result) == 1 &&
|
||||
$result[0]['title'] == 'Responsive',
|
||||
$type.': has filter with multiple conditions'
|
||||
);
|
||||
|
||||
$news->has('tags2', array('title = ? OR title = ?', 'Usability', 'Web Design'));
|
||||
$result = $news->afind(array('text = ?', 'Lorem Ipsun'));
|
||||
$test->expect(
|
||||
count($result) == 1 &&
|
||||
$result[0]['title'] == 'Responsive Images',
|
||||
$type.': find with condition and has filter'
|
||||
);
|
||||
|
||||
$news->load(array('title = ?', 'Responsive Images'));
|
||||
$news->author = $authorIDs[1];
|
||||
$news->save();
|
||||
$news->reset();
|
||||
|
||||
|
||||
$news->has('tags2', array('title = ? OR title = ?', 'Usability', 'Web Design'));
|
||||
$news->has('author', array('name = ?', 'Ridley Scott'));
|
||||
$result = $news->afind();
|
||||
$test->expect(
|
||||
count($result) == 1 &&
|
||||
$result[0]['title'] == 'Responsive Images',
|
||||
$type.': find with multiple has filters on different relations'
|
||||
);
|
||||
|
||||
// add another news to author 2
|
||||
$news->load(array($news_pk.' = ?',$newsIDs[2]));
|
||||
$news->author = $authorIDs[1];
|
||||
$news->save();
|
||||
|
||||
$news->reset();
|
||||
$news->has('author', array('name = ?', 'Ridley Scott'));
|
||||
$news->load();
|
||||
$res = array();
|
||||
while (!$news->dry()) {
|
||||
$res[] = $news->title;
|
||||
$news->next();
|
||||
}
|
||||
|
||||
$test->expect(
|
||||
count($res) == 2 &&
|
||||
$res[0] == 'Responsive Images' &&
|
||||
$res[1] == 'Touchable Interfaces'
|
||||
,
|
||||
$type.': has filter in load context'
|
||||
);
|
||||
|
||||
$news->reset();
|
||||
$news->fields(array('title'));
|
||||
$news->load();
|
||||
|
||||
$test->expect(
|
||||
!empty($news->title) &&
|
||||
empty($news->author) &&
|
||||
empty($news->text) &&
|
||||
empty($news->tags) &&
|
||||
empty($news->tags2),
|
||||
$type.': use a whitelist to restrict fields'
|
||||
);
|
||||
|
||||
unset($news);
|
||||
$news = new \NewsModel();
|
||||
|
||||
$news->fields(array('title','tags','tags2','author'),true);
|
||||
$news->load();
|
||||
|
||||
$test->expect(
|
||||
empty($news->title) &&
|
||||
empty($news->author) &&
|
||||
!empty($news->text) &&
|
||||
empty($news->tags) &&
|
||||
empty($news->tags2),
|
||||
$type.': use a blacklist to restrict fields'
|
||||
);
|
||||
|
||||
unset($news);
|
||||
$news = new \NewsModel();
|
||||
|
||||
$news->fields(array('tags.title'));
|
||||
$news->load();
|
||||
|
||||
$test->expect(
|
||||
!empty($news->tags[0]->title) &&
|
||||
empty($news->tags[0]->news),
|
||||
$type.': set restricted fields to related mappers'
|
||||
);
|
||||
|
||||
$news->filter('tags2',null,array('order'=>'title ASC'));
|
||||
$news->load(array('title = ?','Responsive Images'));
|
||||
$test->expect(
|
||||
$news->tags2[0]->title == 'Responsive' &&
|
||||
$news->tags2[1]->title == 'Web Design',
|
||||
$type.': filter with sorting of related records'
|
||||
);
|
||||
|
||||
// get all tags sorted by their usage in news articles
|
||||
$tag->reset();
|
||||
$tag->countRel('news');
|
||||
$result = $tag->find(null,array('order'=>'count_news DESC, title'))->castAll(0);
|
||||
|
||||
$test->expect(
|
||||
$result[0]['title'] == 'Responsive' &&
|
||||
$result[0]['count_news'] == 3 &&
|
||||
$result[1]['title'] == 'Usability' &&
|
||||
$result[1]['count_news'] == 1 &&
|
||||
$result[2]['title'] == 'Web Design' &&
|
||||
$result[2]['count_news'] == 1,
|
||||
$type.': count and sort on many-to-many relation'
|
||||
);
|
||||
|
||||
// get all authors sorted by the amount of news they have written
|
||||
$author->reset();
|
||||
$author->countRel('news');
|
||||
$result = $author->find(null,array('order'=>'count_news DESC'))->castAll(0);
|
||||
|
||||
$test->expect(
|
||||
$result[0]['name'] == 'Ridley Scott' &&
|
||||
$result[0]['count_news'] == 2 &&
|
||||
$result[1]['name'] == 'Johnny English' &&
|
||||
$result[1]['count_news'] == 1 &&
|
||||
$result[2]['name'] == 'James T. Kirk' &&
|
||||
$result[2]['count_news'] == null,
|
||||
$type.': count and sort on one-to-many relation'
|
||||
);
|
||||
|
||||
$tag->reset();
|
||||
$tag->countRel('news');
|
||||
$result = $tag->find(null,array('order'=>'count_news DESC, title DESC','limit'=>1,'offset'=>1))->castAll(0);
|
||||
|
||||
$test->expect(
|
||||
$result[0]['title'] == 'Web Design' &&
|
||||
$result[0]['count_news'] == 1,
|
||||
$type.': apply limit and offset on aggregated collection'
|
||||
);
|
||||
|
||||
|
||||
$author->reset();
|
||||
$author->countRel('news');
|
||||
$author->has('news',array('text like ?','%Lorem%'));
|
||||
$result = $author->find()->castAll(0);
|
||||
|
||||
$test->expect(
|
||||
count($result) == 1 &&
|
||||
$result[0]['name'] == 'Ridley Scott' &&
|
||||
$result[0]['count_news'] == 2 ,
|
||||
$type.': has-filter and 1:M relation counter'
|
||||
);
|
||||
|
||||
|
||||
$author->reset();
|
||||
$id = $author->load()->next()->_id;
|
||||
$tag->reset();
|
||||
$tag->countRel('news');
|
||||
$tag->has('news',array('author = ?',$id));
|
||||
$result = $tag->find(null,array('order'=>'count_news desc'))->castAll(0);
|
||||
|
||||
$test->expect(
|
||||
count($result) == 2 &&
|
||||
$result[0]['title'] == 'Responsive' &&
|
||||
$result[0]['count_news'] == 3 &&
|
||||
$result[1]['title'] == 'Web Design' &&
|
||||
$result[1]['count_news'] == 1,
|
||||
$type.': has-filter and M:M relation counter'
|
||||
);
|
||||
|
||||
///////////////////////////////////
|
||||
return $test->results();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,335 +0,0 @@
|
||||
<?php
|
||||
|
||||
use App\Controller;
|
||||
|
||||
class Test_Relation {
|
||||
|
||||
/**
|
||||
* unify results for better comparison
|
||||
*/
|
||||
private function getResult($result)
|
||||
{
|
||||
$out = array();
|
||||
foreach ($result as $row) {
|
||||
if(is_object($row))
|
||||
$row = $row->cast();
|
||||
unset($row['_id']);
|
||||
unset($row['id']);
|
||||
unset($row['aid']);
|
||||
unset($row['uid']);
|
||||
unset($row['nid']);
|
||||
unset($row['tid']);
|
||||
unset($row['pid']);
|
||||
unset($row['profile_id']);
|
||||
foreach ($row as $col => $val) {
|
||||
if (empty($val) || is_null($val))
|
||||
unset($row[$col]);
|
||||
}
|
||||
$out[] = $row;
|
||||
}
|
||||
return $out;
|
||||
}
|
||||
|
||||
function run($db,$type)
|
||||
{
|
||||
$test = new \Test();
|
||||
|
||||
// clear existing data
|
||||
\AuthorModel::setdown();
|
||||
\TagModel::setdown();
|
||||
\NewsModel::setdown();
|
||||
\ProfileModel::setdown();
|
||||
|
||||
// setup models
|
||||
\AuthorModel::setup();
|
||||
\TagModel::setup();
|
||||
\NewsModel::setup();
|
||||
\ProfileModel::setup();
|
||||
|
||||
// setup Author
|
||||
///////////////////////////////////
|
||||
$author_id = array();
|
||||
|
||||
$author = new \AuthorModel();
|
||||
$ac=$author::resolveConfiguration();
|
||||
$author_pk = (is_int(strpos($type,'sql'))?$ac['primary']:'_id');
|
||||
|
||||
$author->name = 'Johnny English';
|
||||
$author->save();
|
||||
$author_id[] = $author->_id;
|
||||
$author->reset();
|
||||
$author->name = 'Ridley Scott';
|
||||
$author->save();
|
||||
$author_id[] = $author->_id;
|
||||
$author->reset();
|
||||
$author->name = 'James T. Kirk';
|
||||
$author->save();
|
||||
$author_id[] = $author->_id;
|
||||
$author->reset();
|
||||
|
||||
$allauthors = $author->find()->castAll();
|
||||
$allauthors = $this->getResult($allauthors);
|
||||
$test->expect(
|
||||
json_encode($allauthors) ==
|
||||
'[{"name":"Johnny English"},{"name":"Ridley Scott"},{"name":"James T. Kirk"}]',
|
||||
$type.': all AuthorModel items created'
|
||||
);
|
||||
|
||||
// setup Tags
|
||||
///////////////////////////////////
|
||||
$tag_id = array();
|
||||
|
||||
$tag = new \TagModel();
|
||||
$tc=$tag::resolveConfiguration();
|
||||
$tag_pk = (is_int(strpos($type,'sql'))?$tc['primary']:'_id');
|
||||
|
||||
$tag->title = 'Web Design';
|
||||
$tag->save();
|
||||
$tag_id[] = $tag->_id;
|
||||
$tag->reset();
|
||||
$tag->title = 'Responsive';
|
||||
$tag->save();
|
||||
$tag_id[] = $tag->_id;
|
||||
$tag->reset();
|
||||
$tag->title = 'Usability';
|
||||
$tag->save();
|
||||
$tag_id[] = $tag->_id;
|
||||
$tag->reset();
|
||||
|
||||
$allTags = $this->getResult($tag->find());
|
||||
$test->expect(
|
||||
json_encode($allTags) ==
|
||||
'[{"title":"Web Design"},{"title":"Responsive"},{"title":"Usability"}]',
|
||||
$type.': all TagModel items created'
|
||||
);
|
||||
|
||||
// setup News
|
||||
///////////////////////////////////
|
||||
$news_id = array();
|
||||
|
||||
$news = new \NewsModel();
|
||||
$nc=$news::resolveConfiguration();
|
||||
$news_pk = (is_int(strpos($type,'sql'))?$nc['primary']:'_id');
|
||||
|
||||
$news->title = 'Responsive Images';
|
||||
$news->text = 'Lorem Ipsun';
|
||||
$news->save();
|
||||
$news_id[] = $news->_id;
|
||||
$news->reset();
|
||||
$news->title = 'CSS3 Showcase';
|
||||
$news->text = 'News Text 2';
|
||||
$news->save();
|
||||
$news_id[] = $news->_id;
|
||||
$news->reset();
|
||||
$news->title = 'Touchable Interfaces';
|
||||
$news->text = 'Lorem Foo';
|
||||
$news->save();
|
||||
$news_id[] = $news->_id;
|
||||
$news->reset();
|
||||
|
||||
$allnews = $this->getResult($news->find());
|
||||
$test->expect(
|
||||
json_encode($allnews) ==
|
||||
'[{"title":"Responsive Images","text":"Lorem Ipsun"},{"title":"CSS3 Showcase","text":"News Text 2"},{"title":"Touchable Interfaces","text":"Lorem Foo"}]',
|
||||
$type.': all NewsModel items created'
|
||||
);
|
||||
|
||||
// belongs-to author relation
|
||||
///////////////////////////////////
|
||||
|
||||
$author->load();
|
||||
$news->load(array($news_pk.' = ?',$news_id[0]));
|
||||
$news->author = $author;
|
||||
$news->save();
|
||||
$news->reset();
|
||||
$news->load(array($news_pk.' = ?', $news_id[0]));
|
||||
$test->expect(
|
||||
$news->author->name == 'Johnny English',
|
||||
$type.': belongs-to-one: author relation created'
|
||||
);
|
||||
|
||||
$news->author = NULL;
|
||||
$news->save();
|
||||
$news->reset();
|
||||
$news->load(array($news_pk.' = ?', $news_id[0]));
|
||||
$test->expect(
|
||||
empty($news->author),
|
||||
$type.': belongs-to-one: author relation released'
|
||||
);
|
||||
|
||||
$news->author = $author->_id;
|
||||
$news->save();
|
||||
$news->reset();
|
||||
$news->load(array($news_pk.' = ?', $news_id[0]));
|
||||
$test->expect(
|
||||
$news->author->name == 'Johnny English',
|
||||
$type.': belongs-to-one: relation created by raw id'
|
||||
);
|
||||
|
||||
// belongs-to-many tag relation
|
||||
///////////////////////////////////
|
||||
|
||||
$tag1 = new \TagModel();
|
||||
$tag1->load(array($tag_pk.' = ?', $tag_id[0]));
|
||||
$tag2 = new \TagModel();
|
||||
$tag2->load(array($tag_pk.' = ?', $tag_id[1]));
|
||||
$news->tags = array($tag1,$tag2);
|
||||
$news->save();
|
||||
$news->reset();
|
||||
$news->load(array($news_pk.' = ?', $news_id[0]));
|
||||
$test->expect(
|
||||
$news->tags[0]->title == 'Web Design' && $news->tags[1]->title == 'Responsive',
|
||||
$type.': belongs-to-many: relations created with array of mapper objects'
|
||||
);
|
||||
|
||||
$news->reset();
|
||||
$news->load(array($news_pk.' = ?', $news_id[1]));
|
||||
$news->tags = array($tag_id[1],$tag_id[2]);
|
||||
$news->save();
|
||||
$news->reset();
|
||||
$news->load(array($news_pk.' = ?', $news_id[1]));
|
||||
$test->expect(
|
||||
$news->tags[0]->title == 'Responsive' && $news->tags[1]->title == 'Usability',
|
||||
$type.': belongs-to-many: relations created with array of IDs'
|
||||
);
|
||||
|
||||
$news->tags = null;
|
||||
$news->save();
|
||||
$news->reset();
|
||||
$news->load(array($news_pk.' = ?', $news_id[1]));
|
||||
$test->expect(
|
||||
empty($news->tags),
|
||||
$type.': belongs-to-many: relations released'
|
||||
);
|
||||
|
||||
$tag->reset();
|
||||
$news->load(array($news_pk.' = ?', $news_id[1]));
|
||||
$news->tags = $tag->load(array($tag_pk.' != ?',$tag_id[0]));
|
||||
$news->save();
|
||||
$news->reset();
|
||||
$news->load(array($news_pk.' = ?', $news_id[1]));
|
||||
$test->expect(
|
||||
$news->tags[0]->title == 'Responsive' && $news->tags[1]->title == 'Usability',
|
||||
$type.': belongs-to-many: relations created with hydrated mapper'
|
||||
);
|
||||
|
||||
|
||||
$news->reset();
|
||||
$tag->reset();
|
||||
$news->load(array($news_pk.' = ?', $news_id[2]));
|
||||
$news->tags = $tag_id[0].';'.$tag_id[2];
|
||||
$news->save();
|
||||
$news->reset();
|
||||
$news->load(array($news_pk.' = ?', $news_id[2]));
|
||||
$test->expect(
|
||||
$news->tags[0]->title == 'Web Design' && $news->tags[1]->title == 'Usability',
|
||||
$type.': belongs-to-many: relations created with split-able string'
|
||||
);
|
||||
$test->expect(
|
||||
is_object($news->tags) && $news->tags instanceof \DB\CortexCollection,
|
||||
$type.': belongs-to-many: result is collection'
|
||||
);
|
||||
|
||||
|
||||
// has-one relation
|
||||
///////////////////////////////////
|
||||
$profile = new ProfileModel();
|
||||
$pc=$profile::resolveConfiguration();
|
||||
$profile_pk = (is_int(strpos($type,'sql'))?$pc['primary']:'_id');
|
||||
|
||||
$profile->message = 'Hello World';
|
||||
$profile->author = $author->load(array($author_pk.' = ?',$author_id[0]));
|
||||
$profile->save();
|
||||
$profile_id = $profile->_id;
|
||||
$profile->reset();
|
||||
$author->reset();
|
||||
$author->load(array($author_pk.' = ?', $author_id[0]));
|
||||
$profile->load(array($profile_pk.' = ?', $profile_id));
|
||||
$test->expect(
|
||||
$author->profile->message == 'Hello World' &&
|
||||
$profile->author->name == "Johnny English",
|
||||
$type.': has-one: relation assigned'
|
||||
);
|
||||
|
||||
$profile->reset();
|
||||
$profile->message = 'I\'m feeling lucky';
|
||||
$profile->image = 'lolcat.jpg';
|
||||
$author->reset();
|
||||
$author->load(array($author_pk.' = ?',$author_id[1]));
|
||||
$author->profile = $profile;
|
||||
$author->save();
|
||||
$profile->reset();
|
||||
$author->reset();
|
||||
$author->load(array($author_pk.' = ?', $author_id[1]));
|
||||
$test->expect(
|
||||
$author->profile->message == 'I\'m feeling lucky',
|
||||
$type.': has-one: inverse relation'
|
||||
);
|
||||
|
||||
|
||||
// has-many relation
|
||||
///////////////////////////////////
|
||||
|
||||
$author->load(array($author_pk.' = ?', $author_id[0]));
|
||||
$result = $this->getResult($author->news);
|
||||
$test->expect(
|
||||
$result[0]['title'] == "Responsive Images" &&
|
||||
$result[0]['tags'][0]['title'] == 'Web Design' &&
|
||||
$result[0]['tags'][1]['title'] == 'Responsive',
|
||||
$type.': has-many inverse relation'
|
||||
);
|
||||
|
||||
// many to many relation
|
||||
///////////////////////////////////
|
||||
|
||||
$news->load(array($news_pk.' = ?',$news_id[0]));
|
||||
$news->tags2 = array($tag_id[0],$tag_id[1]);
|
||||
$news->save();
|
||||
$news->reset();
|
||||
$news->load(array($news_pk.' = ?',$news_id[0]));
|
||||
$test->expect(
|
||||
$news->tags2[0]['title'] == 'Web Design' &&
|
||||
$news->tags2[1]['title'] == 'Responsive',
|
||||
$type.': many-to-many relation created'
|
||||
);
|
||||
|
||||
$test->expect(
|
||||
is_object($news->tags2) && $news->tags2 instanceof \DB\CortexCollection,
|
||||
$type.': many-to-many: result is collection'
|
||||
);
|
||||
|
||||
$news->load(array($news_pk.' = ?', $news_id[0]));
|
||||
$news->tags2 = NULL;
|
||||
$news->save();
|
||||
$news->reset();
|
||||
$news->load(array($news_pk.' = ?', $news_id[0]));
|
||||
$test->expect(
|
||||
is_null($news->tags2),
|
||||
$type.': many-to-many relation released'
|
||||
);
|
||||
|
||||
$all = $news->find();
|
||||
$test->expect(
|
||||
$all[1]->tags2 === NULL
|
||||
&& $all[2]->author === NULL,
|
||||
$type.': empty relations are NULL'
|
||||
);
|
||||
|
||||
$arr = $news->cast();
|
||||
$test->expect(
|
||||
is_array($arr['tags']),
|
||||
$type.': collection becomes array in casted model'
|
||||
);
|
||||
|
||||
if ($type == 'mongo') {
|
||||
$test->expect(
|
||||
is_string($arr['_id']),
|
||||
$type.': id becomes string in casted model'
|
||||
);
|
||||
}
|
||||
|
||||
///////////////////////////////////
|
||||
return $test->results();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,364 +0,0 @@
|
||||
<?php
|
||||
|
||||
use App\Controller;
|
||||
|
||||
class Test_Syntax {
|
||||
|
||||
function run($db,$type)
|
||||
{
|
||||
$test = new \Test();
|
||||
$tname = 'test_cortex';
|
||||
|
||||
\DB\Cortex::setdown($db, $tname);
|
||||
|
||||
$fields = array(
|
||||
'title' => array('type' => \DB\SQL\Schema::DT_TEXT),
|
||||
'num1' => array('type' => \DB\SQL\Schema::DT_INT4),
|
||||
'num2' => array('type' => \DB\SQL\Schema::DT_INT4),
|
||||
);
|
||||
\DB\Cortex::setup($db, $tname, $fields);
|
||||
|
||||
// adding some testing data
|
||||
$cx = new \DB\Cortex($db, $tname);
|
||||
$cx->title = 'bar1';
|
||||
$cx->save();
|
||||
$cx->reset();
|
||||
|
||||
$cx->title = 'baz2';
|
||||
$cx->num1 = 1;
|
||||
$cx->save();
|
||||
$cx->reset();
|
||||
|
||||
$cx->title = 'foo3';
|
||||
$cx->num1 = 4;
|
||||
$cx->save();
|
||||
$cx->reset();
|
||||
|
||||
$cx->title = 'foo4';
|
||||
$cx->num1 = 3;
|
||||
$cx->save();
|
||||
$cx->reset();
|
||||
|
||||
$cx->title = 'foo5';
|
||||
$cx->num1 = 3;
|
||||
$cx->num2 = 5;
|
||||
$cx->save();
|
||||
$cx->reset();
|
||||
|
||||
$cx->title = 'foo6';
|
||||
$cx->num1 = 3;
|
||||
$cx->num2 = 1;
|
||||
$cx->save();
|
||||
$cx->reset();
|
||||
|
||||
$cx->title = 'foo7';
|
||||
$cx->num1 = 3;
|
||||
$cx->num2 = 10;
|
||||
$cx->save();
|
||||
$cx->reset();
|
||||
|
||||
$cx->title = 'foo8';
|
||||
$cx->num1 = 5;
|
||||
$cx->save();
|
||||
$cx->reset();
|
||||
|
||||
$cx->title = 'foo9';
|
||||
$cx->num1 = 8;
|
||||
$cx->save();
|
||||
$cx->reset();
|
||||
|
||||
$result = $this->getResult($cx->find());
|
||||
|
||||
$expected = array(
|
||||
0 => array(
|
||||
'title' => 'bar1',
|
||||
),
|
||||
1 => array(
|
||||
'num1' => 1,
|
||||
'title' => 'baz2',
|
||||
),
|
||||
2 => array(
|
||||
'num1' => 4,
|
||||
'title' => 'foo3',
|
||||
),
|
||||
3 => array(
|
||||
'num1' => 3,
|
||||
'title' => 'foo4',
|
||||
),
|
||||
4 => array(
|
||||
'num1' => 3,
|
||||
'num2' => 5,
|
||||
'title' => 'foo5',
|
||||
),
|
||||
5 => array(
|
||||
'num1' => 3,
|
||||
'num2' => 1,
|
||||
'title' => 'foo6',
|
||||
),
|
||||
6 => array(
|
||||
'num1' => 3,
|
||||
'num2' => 10,
|
||||
'title' => 'foo7',
|
||||
),
|
||||
7 => array(
|
||||
'num1' => 5,
|
||||
'title' => 'foo8',
|
||||
),
|
||||
8 => array(
|
||||
'num1' => 8,
|
||||
'title' => 'foo9',
|
||||
),
|
||||
);
|
||||
|
||||
$test->expect(
|
||||
json_encode($result) == json_encode($expected),
|
||||
$type.': init mapper, adding records'
|
||||
);
|
||||
|
||||
// operator =
|
||||
$result = $this->getResult($cx->find(array('title = ?', 'foo7')));
|
||||
$expected = array(
|
||||
0 => array(
|
||||
'num1' => 3,
|
||||
'num2' => 10,
|
||||
'title' => 'foo7',
|
||||
),
|
||||
);
|
||||
$test->expect(
|
||||
json_encode($result) == json_encode($expected),
|
||||
$type.': operator check: ='
|
||||
);
|
||||
|
||||
// operator >
|
||||
$result = $this->getResult($cx->find(array('num1 > ?', 4)));
|
||||
$expected = array(
|
||||
0 => array(
|
||||
'num1' => 5,
|
||||
'title' => 'foo8',
|
||||
),
|
||||
1 => array(
|
||||
'num1' => 8,
|
||||
'title' => 'foo9',
|
||||
),
|
||||
);
|
||||
$test->expect(
|
||||
json_encode($result) == json_encode($expected),
|
||||
$type.': operator check: >'
|
||||
);
|
||||
|
||||
// operator >=
|
||||
$result = $this->getResult($cx->find(array('num1 >= ?', 5)));
|
||||
$test->expect(
|
||||
json_encode($result) == json_encode($expected),
|
||||
$type.': operator check: >='
|
||||
);
|
||||
|
||||
// operator <
|
||||
$result = $this->getResult($cx->find(array('num2 < ?', 2)));
|
||||
$expected = array(
|
||||
0 => array(
|
||||
'num1' => 3,
|
||||
'num2' => 1,
|
||||
'title' => 'foo6',
|
||||
),
|
||||
);
|
||||
$test->expect(
|
||||
json_encode($result) == json_encode($expected),
|
||||
$type.': operator check: <'
|
||||
);
|
||||
|
||||
// operator <=
|
||||
$result = $this->getResult($cx->find(array('num2 <= ?', 1)));
|
||||
$test->expect(
|
||||
json_encode($result) == json_encode($expected),
|
||||
$type.': operator check: <='
|
||||
);
|
||||
|
||||
// operator without binding
|
||||
$result = $this->getResult($cx->find(array('num1 > 4')));
|
||||
$expected = array(
|
||||
0 => array(
|
||||
'num1' => 5,
|
||||
'title' => 'foo8',
|
||||
),
|
||||
1 => array(
|
||||
'num1' => 8,
|
||||
'title' => 'foo9',
|
||||
),
|
||||
);
|
||||
$test->expect(
|
||||
json_encode($result) == json_encode($expected),
|
||||
$type.': operator without binding'
|
||||
);
|
||||
|
||||
// field comparision
|
||||
$result = $this->getResult($cx->find(
|
||||
array('num2 > num1', 1)));
|
||||
$expected = array(
|
||||
0 => array(
|
||||
'num1' => 3,
|
||||
'num2' => 5,
|
||||
'title' => 'foo5',
|
||||
),
|
||||
1 => array(
|
||||
'num1' => 3,
|
||||
'num2' => 10,
|
||||
'title' => 'foo7',
|
||||
),
|
||||
);
|
||||
$test->expect(
|
||||
json_encode($result) == json_encode($expected),
|
||||
$type.': check field comparision'
|
||||
);
|
||||
|
||||
// lookahead search
|
||||
$result = $this->getResult($cx->find(array('title like ?', '%o6')));
|
||||
$expected = array(
|
||||
0 => array(
|
||||
'num1' => 3,
|
||||
'num2' => 1,
|
||||
'title' => 'foo6',
|
||||
),
|
||||
);
|
||||
$test->expect(
|
||||
json_encode($result) == json_encode($expected),
|
||||
$type.': lookahead search'
|
||||
);
|
||||
|
||||
// lookbehind search
|
||||
$result = $this->getResult($cx->find(array('title like ?', 'bar%')));
|
||||
$expected = array(
|
||||
0 => array(
|
||||
'title' => 'bar1',
|
||||
),
|
||||
);
|
||||
$test->expect(
|
||||
json_encode($result) == json_encode($expected),
|
||||
$type.': lookbehind search'
|
||||
);
|
||||
|
||||
// full search
|
||||
$result = $this->getResult($cx->find(array('title like ?', '%a%')));
|
||||
$expected = array(
|
||||
0 => array(
|
||||
'title' => 'bar1',
|
||||
),
|
||||
1 => array(
|
||||
'num1' => 1,
|
||||
'title' => 'baz2',
|
||||
),
|
||||
);
|
||||
$test->expect(
|
||||
json_encode($result) == json_encode($expected),
|
||||
$type.': full search'
|
||||
);
|
||||
|
||||
// negated search
|
||||
$result = $this->getResult($cx->find(array('title not like ?', 'foo%')));
|
||||
$test->expect(
|
||||
json_encode($result) == json_encode($expected),
|
||||
$type.': negated search'
|
||||
);
|
||||
|
||||
// AND / OR chaining
|
||||
$result = $this->getResult($cx->find(
|
||||
array('(num2 < ? AND num1 > ?) OR title like ?', 2, 1, '%o9')));
|
||||
$expected = array(
|
||||
0 => array(
|
||||
'num1' => 3,
|
||||
'num2' => 1,
|
||||
'title' => 'foo6',
|
||||
),
|
||||
1 => array(
|
||||
'num1' => 8,
|
||||
'title' => 'foo9',
|
||||
),
|
||||
);
|
||||
$test->expect(
|
||||
json_encode($result) == json_encode($expected),
|
||||
$type.': check logical operator chaining'
|
||||
);
|
||||
|
||||
// check limit
|
||||
$result = $this->getResult($cx->find(
|
||||
null, array('limit' => '2')));
|
||||
$expected = array(
|
||||
0 => array(
|
||||
'title' => 'bar1',
|
||||
),
|
||||
1 => array(
|
||||
'num1' => 1,
|
||||
'title' => 'baz2',
|
||||
),
|
||||
);
|
||||
$test->expect(
|
||||
json_encode($result) == json_encode($expected),
|
||||
$type.': check limit'
|
||||
);
|
||||
|
||||
// check order
|
||||
$result = $this->getResult($cx->find(
|
||||
array('num2 >= ?', 1), array('order' => 'num2 desc')));
|
||||
$expected = array(
|
||||
0 => array(
|
||||
'num1' => 3,
|
||||
'num2' => 10,
|
||||
'title' => 'foo7',
|
||||
),
|
||||
1 => array(
|
||||
'num1' => 3,
|
||||
'num2' => 5,
|
||||
'title' => 'foo5',
|
||||
),
|
||||
2 => array(
|
||||
'num1' => 3,
|
||||
'num2' => 1,
|
||||
'title' => 'foo6',
|
||||
),
|
||||
);
|
||||
|
||||
$test->expect(
|
||||
json_encode($result) == json_encode($expected),
|
||||
$type.': check order'
|
||||
);
|
||||
|
||||
// IN search
|
||||
$rc = $cx->find(array('num1 IN ?',array(4,5,8)));
|
||||
$result = $rc->getAll('title');
|
||||
sort($result);
|
||||
$test->expect(
|
||||
json_encode($result) == json_encode(array('foo3','foo8','foo9')),
|
||||
$type.': IN operator'
|
||||
);
|
||||
|
||||
$rc = $cx->find(array('num1 IN ? && num2 > ? && num2 NOT IN ?',array(3,4),1,array(10)));
|
||||
$result = $rc->getAll('title');
|
||||
$test->expect(
|
||||
json_encode($result) == json_encode(array('foo5')),
|
||||
$type.': enhanced IN, NOT IN operator'
|
||||
);
|
||||
|
||||
///////////////////////////////////
|
||||
return $test->results();
|
||||
}
|
||||
|
||||
/**
|
||||
* unify results for better comparison
|
||||
*/
|
||||
private function getResult($result)
|
||||
{
|
||||
$out = array();
|
||||
foreach ($result as $row) {
|
||||
$row = $row->cast();
|
||||
unset($row['_id']);
|
||||
unset($row['id']);
|
||||
ksort($row);
|
||||
foreach ($row as $col => $val) {
|
||||
if (empty($val) || is_null($val))
|
||||
unset($row[$col]);
|
||||
}
|
||||
$out[] = $row;
|
||||
}
|
||||
return $out;
|
||||
}
|
||||
}
|
||||
@@ -1,668 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App;
|
||||
|
||||
class Schema extends Controller
|
||||
{
|
||||
|
||||
private
|
||||
$roundTime = 0,
|
||||
$current_test = 1,
|
||||
$current_engine,
|
||||
$f3,
|
||||
$test,
|
||||
$tname;
|
||||
|
||||
private function getTime()
|
||||
{
|
||||
$time = microtime(TRUE) - $this->f3->get('timer') - $this->roundTime;
|
||||
$this->roundTime = microtime(TRUE) - $this->f3->get('timer');
|
||||
return ' [ '.sprintf('%.3f', $time).'s ]';
|
||||
}
|
||||
|
||||
private function getTestDesc($text)
|
||||
{
|
||||
return $this->getTime().' '.$this->current_engine.': #'.$this->current_test++.' - '.$text;
|
||||
}
|
||||
|
||||
function get()
|
||||
{
|
||||
$this->f3 = \Base::instance();
|
||||
$this->test = new \Test;
|
||||
|
||||
$this->f3->set('QUIET', false);
|
||||
$this->f3->set('CACHE', false);
|
||||
|
||||
$dbs = array(
|
||||
'mysql' => new \DB\SQL(
|
||||
'mysql:host=localhost;port=3306;dbname=fatfree', 'fatfree', ''
|
||||
),
|
||||
'sqlite' => new \DB\SQL(
|
||||
'sqlite::memory:'
|
||||
// 'sqlite:db/sqlite.db'
|
||||
),
|
||||
'pgsql' => new \DB\SQL(
|
||||
'pgsql:host=localhost;dbname=fatfree', 'fatfree', 'fatfree'
|
||||
),
|
||||
// 'sqlsrv2012' => new \DB\SQL(
|
||||
// 'sqlsrv:SERVER=LOCALHOST\SQLEXPRESS2012;Database=fatfree','fatfree', 'fatfree'
|
||||
// ),
|
||||
// 'sqlsrv2008' => new \DB\SQL(
|
||||
// 'sqlsrv:SERVER=LOCALHOST\SQLEXPRESS2008;Database=fatfree','fatfree', 'fatfree'
|
||||
// )
|
||||
);
|
||||
|
||||
$this->roundTime = microtime(TRUE) - \Base::instance()->get('timer');
|
||||
$this->tname = 'test_table';
|
||||
|
||||
foreach ($dbs as $type => $db) {
|
||||
$this->current_engine = $type;
|
||||
$this->runTestSuite($db);
|
||||
$this->current_test = 1;
|
||||
}
|
||||
$this->f3->set('results', $this->test->results());
|
||||
}
|
||||
|
||||
private function runTestSuite($db)
|
||||
{
|
||||
$schema = new \DB\SQL\Schema($db);
|
||||
|
||||
$schema->dropTable($this->tname);
|
||||
|
||||
// create table
|
||||
$table = $schema->createTable($this->tname);
|
||||
$table = $table->build();
|
||||
$result = $schema->getTables();
|
||||
$this->test->expect(
|
||||
in_array($this->tname, $result),
|
||||
$this->getTestDesc('create default table')
|
||||
);
|
||||
unset($result);
|
||||
|
||||
$this->test->expect(
|
||||
$table instanceof \DB\SQL\TableModifier,
|
||||
$this->getTestDesc('$table->build() returns TableModifier')
|
||||
);
|
||||
|
||||
// drop table
|
||||
$table->drop();
|
||||
$this->test->expect(
|
||||
in_array($this->tname, $schema->getTables()) == false,
|
||||
$this->getTestDesc('drop table')
|
||||
);
|
||||
unset($table);
|
||||
|
||||
// create table with columns
|
||||
$table = $schema->createTable($this->tname);
|
||||
$table->addColumn('title')->type($schema::DT_VARCHAR128);
|
||||
$table->addColumn('number')->type($schema::DT_INT4);
|
||||
$table = $table->build();
|
||||
$r1 = $schema->getTables();
|
||||
$r2 = $table->getCols();
|
||||
$this->test->expect(
|
||||
in_array($this->tname, $r1) && in_array('id', $r2)
|
||||
&& in_array('title', $r2) && in_array('number', $r2),
|
||||
$this->getTestDesc('create new table with additional columns')
|
||||
);
|
||||
unset($r1,$r2);
|
||||
|
||||
// testing all datatypes
|
||||
foreach (array_keys($schema->dataTypes) as $index => $field) {
|
||||
// testing column type
|
||||
$table->addColumn('column_'.$index)->type($field);
|
||||
$table->build();
|
||||
$r1 = $table->getCols();
|
||||
$this->test->expect(
|
||||
in_array('column_'.$index, $r1),
|
||||
$this->getTestDesc('adding column ['.$field.'], nullable')
|
||||
);
|
||||
}
|
||||
|
||||
$r1 = $table->getCols(true);
|
||||
foreach (array_keys($schema->dataTypes) as $index => $field) {
|
||||
if (isset($r1['column_'.$index])) {
|
||||
$datType=$schema->findQuery($schema->dataTypes[$field]);
|
||||
$compatible = $schema->isCompatible($field,$r1['column_'.$index]['type']);
|
||||
$this->test->expect(
|
||||
$compatible,
|
||||
$this->getTestDesc('reverse lookup compatible: '.
|
||||
($compatible?'YES':'NO').
|
||||
', '.$field.': ['.$datType.' > '.$r1['column_'.$index]['type'].']')
|
||||
);
|
||||
}
|
||||
}
|
||||
unset($r1);
|
||||
|
||||
|
||||
// adding some testing data
|
||||
$mapper = new \DB\SQL\Mapper($db, $this->tname);
|
||||
$mapper->column_5 = 123.456;
|
||||
$mapper->column_6 = 123456.789012;
|
||||
$mapper->column_7 = 'hello world';
|
||||
$mapper->save();
|
||||
$mapper->reset();
|
||||
$result = $mapper->findone(array('column_7 = ?', 'hello world'))->cast();
|
||||
unset($mapper);
|
||||
$this->test->expect(
|
||||
$result['column_7'] == 'hello world',
|
||||
$this->getTestDesc('mapping dummy data')
|
||||
);
|
||||
$this->test->expect(
|
||||
$result['column_5'] == 123.456,
|
||||
$this->getTestDesc('testing float value: '.$result['column_5'])
|
||||
);
|
||||
$this->test->expect(
|
||||
$result['column_6'] == 123456.789012,
|
||||
$this->getTestDesc('testing decimal value: '.$result['column_6'])
|
||||
);
|
||||
|
||||
|
||||
$mapper = new \DB\SQL\Mapper($db, $this->tname);
|
||||
$mapper->load();
|
||||
$num = $this->current_engine == 'sqlite' ? '123456789.012345' : '123456789012.345678';
|
||||
$mapper->column_6 = $num;
|
||||
$mapper->save();
|
||||
$mapper->reset();
|
||||
$result = $mapper->findone(array('column_7 = ?', 'hello world'))->cast();
|
||||
$this->test->expect(
|
||||
$result['column_6'] == $num,
|
||||
$this->getTestDesc('testing max decimal precision: '.$result['column_6'])
|
||||
);
|
||||
unset($mapper);
|
||||
|
||||
// default value text, not nullable
|
||||
$table->addColumn('text_default_not_null')
|
||||
->type($schema::DT_VARCHAR128)
|
||||
->nullable(false)->defaults('foo bar');
|
||||
$table->build();
|
||||
$r1 = $table->getCols(true);
|
||||
$this->test->expect(
|
||||
in_array('text_default_not_null', array_keys($r1)) &&
|
||||
$r1['text_default_not_null']['default'] == 'foo bar' &&
|
||||
$r1['text_default_not_null']['nullable'] == false,
|
||||
$this->getTestDesc('adding column [VARCHAR128], not nullable with default value')
|
||||
);
|
||||
unset($r1);
|
||||
|
||||
// some testing dummy data
|
||||
$mapper = new \DB\SQL\Mapper($db, $this->tname);
|
||||
$mapper->column_7 = 'tanduay';
|
||||
$mapper->save();
|
||||
$mapper->reset();
|
||||
$result = $mapper->findone(array('column_7 = ?','tanduay'))->cast();
|
||||
$this->test->expect(
|
||||
$result['column_7'] == 'tanduay' &&
|
||||
$result['text_default_not_null'] == 'foo bar',
|
||||
$this->getTestDesc('mapping dummy data')
|
||||
);
|
||||
unset($mapper,$result);
|
||||
|
||||
// default value numeric, not nullable
|
||||
$table->addColumn('int_default_not_null')
|
||||
->type($schema::DT_INT4)->nullable(false)->defaults(123);
|
||||
$table->build();
|
||||
$r1 = $table->getCols(true);
|
||||
$this->test->expect(
|
||||
in_array('int_default_not_null', array_keys($r1)) &&
|
||||
$r1['int_default_not_null']['default'] == 123 &&
|
||||
$r1['int_default_not_null']['nullable'] == false,
|
||||
$this->getTestDesc('adding column [INT4], not nullable with default value')
|
||||
);
|
||||
unset($r1);
|
||||
|
||||
// adding testing data
|
||||
$mapper = new \DB\SQL\Mapper($db, $this->tname);
|
||||
$mapper->column_7 = 'test3';
|
||||
$mapper->save();
|
||||
$mapper->reset();
|
||||
$r1 = $mapper->findone(array('column_7 = ?','test3'))->cast();
|
||||
$this->test->expect(
|
||||
$r1['column_7'] == 'test3' &&
|
||||
$r1['int_default_not_null'] == 123,
|
||||
$this->getTestDesc('mapping dummy data')
|
||||
);
|
||||
unset($mapper,$r1);
|
||||
|
||||
|
||||
// default value text, nullable
|
||||
$table->addColumn('text_default_nullable')
|
||||
->type($schema::DT_VARCHAR128)
|
||||
->defaults('foo bar');
|
||||
$table->build();
|
||||
$r1 = $table->getCols(true);
|
||||
$this->test->expect(
|
||||
in_array('text_default_nullable', array_keys($r1)) &&
|
||||
$r1['text_default_nullable']['default'] == 'foo bar',
|
||||
$this->getTestDesc('adding column [VARCHAR128], nullable with default value')
|
||||
);
|
||||
unset($r1);
|
||||
|
||||
// adding some dummy data
|
||||
$mapper = new \DB\SQL\Mapper($db, $this->tname);
|
||||
$mapper->column_7 = 'test4';
|
||||
$mapper->save();
|
||||
$mapper->reset();
|
||||
$mapper->column_7 = 'test5';
|
||||
$mapper->text_default_nullable = null;
|
||||
$mapper->save();
|
||||
$mapper->reset();
|
||||
$result = $mapper->find(array('column_7 = ? OR column_7 = ?','test4','test5'));
|
||||
foreach ($result as &$r)
|
||||
$r = $r->cast();
|
||||
|
||||
$this->test->expect(
|
||||
array_key_exists(0, $result) && array_key_exists(1, $result) &&
|
||||
$result[0]['column_7'] == 'test4' && $result[0]['text_default_nullable'] == 'foo bar' &&
|
||||
$result[1]['column_7'] == 'test5' && $result[1]['text_default_nullable'] === null,
|
||||
$this->getTestDesc('mapping dummy data')
|
||||
);
|
||||
unset($mapper, $result);
|
||||
|
||||
// default value numeric, nullable
|
||||
$table->addColumn('int_default_nullable')->type($schema::DT_INT4)->defaults(123);
|
||||
$table->build();
|
||||
$r1 = $table->getCols(true);
|
||||
$this->test->expect(
|
||||
in_array('int_default_nullable', array_keys($r1)) == true &&
|
||||
$r1['int_default_nullable']['default'] == 123,
|
||||
$this->getTestDesc('adding column [INT4], nullable with default value')
|
||||
);
|
||||
unset($r1);
|
||||
|
||||
// adding dummy data
|
||||
$mapper = new \DB\SQL\Mapper($db, $this->tname);
|
||||
$mapper->column_7 = 'test6';
|
||||
$mapper->save();
|
||||
$mapper->reset();
|
||||
$mapper->column_7 = 'test7';
|
||||
$mapper->int_default_nullable = null;
|
||||
$mapper->save();
|
||||
$mapper->reset();
|
||||
$result = $mapper->find(array('column_7 = ? OR column_7 = ?', 'test6', 'test7'));
|
||||
foreach ($result as &$r)
|
||||
$r = $r->cast();
|
||||
|
||||
$this->test->expect(
|
||||
array_key_exists(0, $result) && array_key_exists(1, $result) &&
|
||||
$result[0]['column_7'] == 'test6' && $result[0]['int_default_nullable'] === 123 &&
|
||||
$result[1]['column_7'] == 'test7' && $result[1]['int_default_nullable'] === null,
|
||||
$this->getTestDesc('mapping dummy data')
|
||||
);
|
||||
unset($mapper, $result);
|
||||
|
||||
// current timestamp
|
||||
$table->addColumn('stamp')
|
||||
->type($schema::DT_TIMESTAMP)
|
||||
->nullable(false)
|
||||
->defaults($schema::DF_CURRENT_TIMESTAMP);
|
||||
$table->build();
|
||||
$r1 = $table->getCols(true);
|
||||
$this->test->expect(
|
||||
in_array('stamp', array_keys($r1)) &&
|
||||
$r1['stamp']['default'] == $schema::DF_CURRENT_TIMESTAMP,
|
||||
$this->getTestDesc(
|
||||
'adding column [TIMESTAMP], not nullable with current_timestamp default value')
|
||||
);
|
||||
unset($r1);
|
||||
|
||||
|
||||
// datetime nullable
|
||||
$table->addColumn('datetime')->type_datetime()->nullable(true);
|
||||
$table->build();
|
||||
$r1 = $table->getCols(true);
|
||||
$this->test->expect(
|
||||
in_array('datetime', array_keys($r1)) &&
|
||||
$r1['datetime']['nullable'] == true,
|
||||
$this->getTestDesc(
|
||||
'adding column [DATETIME], nullable, no default')
|
||||
);
|
||||
unset($r1);
|
||||
|
||||
|
||||
// adding dummy data
|
||||
$mapper = new \DB\SQL\Mapper($db, $this->tname);
|
||||
$mapper->column_7 = 'test_datetime';
|
||||
$mapper->datetime = NULL;
|
||||
$mapper->save();
|
||||
$mapper->reset();
|
||||
$result = $mapper->find(array('column_7 = ?', 'test_datetime'));
|
||||
foreach ($result as &$r)
|
||||
$r = $r->cast();
|
||||
|
||||
$this->test->expect(
|
||||
array_key_exists(0, $result) && $result[0]['column_7'] == 'test_datetime' &&
|
||||
$result[0]['datetime'] === null,
|
||||
$this->getTestDesc('mapping dummy data')
|
||||
);
|
||||
unset($mapper, $result);
|
||||
|
||||
|
||||
// rename column
|
||||
$table->renameColumn('text_default_not_null', 'title123');
|
||||
$table->build();
|
||||
$r1 = $table->getCols();
|
||||
$this->test->expect(
|
||||
in_array('title123', $r1) && !in_array('text_default_not_null', $r1),
|
||||
$this->getTestDesc('renaming column')
|
||||
);
|
||||
unset($r1);
|
||||
|
||||
// adding dummy data
|
||||
$mapper = new \DB\SQL\Mapper($db, $this->tname);
|
||||
$mapper->title123 = 'test8';
|
||||
$mapper->save();
|
||||
$mapper->reset();
|
||||
$result = $mapper->findone(array('title123 = ?','test8'));
|
||||
$this->test->expect(
|
||||
!$result->dry(),
|
||||
$this->getTestDesc('mapping dummy data')
|
||||
);
|
||||
$table->renameColumn('title123', 'text_default_not_null');
|
||||
$table->build();
|
||||
unset($result,$mapper);
|
||||
|
||||
// remove column
|
||||
$table->dropColumn('column_1');
|
||||
$table->build();
|
||||
$r1 = $table->getCols();
|
||||
$this->test->expect(
|
||||
!in_array('column_1', $r1),
|
||||
$this->getTestDesc('removing column')
|
||||
);
|
||||
unset($r1);
|
||||
|
||||
// rename table
|
||||
$schema->dropTable('test123');
|
||||
$table->rename('test123');
|
||||
$result = $schema->getTables();
|
||||
$this->test->expect(
|
||||
in_array('test123', $result) && !in_array($this->tname, $result),
|
||||
$this->getTestDesc('renaming table')
|
||||
);
|
||||
$table->rename($this->tname);
|
||||
unset($result);
|
||||
|
||||
// check record count
|
||||
$mapper = new \DB\SQL\Mapper($db, $this->tname);
|
||||
$this->test->expect(
|
||||
count($mapper->find()) == 9,
|
||||
$this->getTestDesc('check record count')
|
||||
);
|
||||
unset($mapper);
|
||||
|
||||
// adding composite primary keys
|
||||
$table->addColumn('version')->type($schema::DT_INT4)->nullable(false)->defaults(1);
|
||||
$table->primary(array('id', 'version'));
|
||||
$table->build();
|
||||
$r1 = $table->getCols(true);
|
||||
$this->test->expect(!empty($r1) && isset($r1['version']) &&
|
||||
$r1['id']['pkey'] == true && $r1['version']['pkey'] == true,
|
||||
$this->getTestDesc('adding composite primary-keys')
|
||||
);
|
||||
unset($r1);
|
||||
|
||||
// check record count
|
||||
$mapper = new \DB\SQL\Mapper($db, $this->tname);
|
||||
$this->test->expect(
|
||||
count($mapper->find()) == 9,
|
||||
$this->getTestDesc('check record count')
|
||||
);
|
||||
unset($mapper);
|
||||
|
||||
// drop table
|
||||
$schema->dropTable($this->tname);
|
||||
$this->test->expect(
|
||||
!in_array($this->tname, $schema->getTables()),
|
||||
$this->getTestDesc('drop table')
|
||||
);
|
||||
|
||||
// adding composite primary keys
|
||||
$table = $schema->createTable($this->tname);
|
||||
$table->addColumn('version')->type($schema::DT_INT4)
|
||||
->defaults(1)->nullable(false);
|
||||
$table->primary(array('id', 'version'));
|
||||
$table = $table->build();
|
||||
$r1 = $table->getCols(true);
|
||||
|
||||
$this->test->expect(!empty($r1) &&
|
||||
$r1['id']['pkey'] == true && $r1['version']['pkey'] == true,
|
||||
$this->getTestDesc('creating new table with composite key')
|
||||
);
|
||||
$this->test->expect(!empty($r1) &&
|
||||
$r1['version']['default'] == '1',
|
||||
$this->getTestDesc('default value on composite primary key')
|
||||
);
|
||||
unset($r1);
|
||||
|
||||
// more fields to composite primary key table
|
||||
$table->addColumn('title')->type($schema::DT_VARCHAR256);
|
||||
$table->addColumn('title2')->type($schema::DT_TEXT);
|
||||
$table->addColumn('title_notnull')
|
||||
->type($schema::DT_VARCHAR128)->nullable(false)->defaults("foo");
|
||||
$table->build();
|
||||
$r1 = $table->getCols(true);
|
||||
$this->test->expect(
|
||||
array_key_exists('title', $r1) &&
|
||||
array_key_exists('title_notnull', $r1) &&
|
||||
$r1['id']['pkey'] == true && $r1['version']['pkey'] == true,
|
||||
$this->getTestDesc('adding more fields to composite pk table')
|
||||
);
|
||||
unset($r1);
|
||||
|
||||
// testing primary keys with inserted data
|
||||
$mapper = new \DB\SQL\Mapper($db, $this->tname);
|
||||
$mapper->title = 'test1';
|
||||
$mapper->save();
|
||||
$mapper->reset();
|
||||
|
||||
$mapper->id = 1;
|
||||
$mapper->title = 'nullable';
|
||||
$mapper->version = 2;
|
||||
$mapper->save();
|
||||
$mapper->reset();
|
||||
|
||||
$mapper->title = 'test3';
|
||||
$mapper->title2 = 'foobar';
|
||||
$mapper->title_notnull = 'bar';
|
||||
$mapper->save();
|
||||
|
||||
$result = array_map(array($mapper,'cast'),$mapper->find());
|
||||
|
||||
$cpk_expected = array(
|
||||
0=>array(
|
||||
'id' => 1,
|
||||
'version' => 1,
|
||||
'title' => 'test1',
|
||||
'title2' => NULL,
|
||||
'title_notnull' => 'foo',
|
||||
),
|
||||
1=>array(
|
||||
'id' => 1,
|
||||
'version' => 2,
|
||||
'title' => 'nullable',
|
||||
'title2' => NULL,
|
||||
'title_notnull' => 'foo',
|
||||
),
|
||||
2=>array(
|
||||
'id' => 2,
|
||||
'version' => 1,
|
||||
'title' => 'test3',
|
||||
'title2' => 'foobar',
|
||||
'title_notnull' => 'bar',
|
||||
),
|
||||
);
|
||||
foreach ($result as &$r)
|
||||
ksort($r);
|
||||
foreach ($cpk_expected as &$r)
|
||||
ksort($r);
|
||||
$this->test->expect(
|
||||
json_encode($result) == json_encode($cpk_expected),
|
||||
$this->getTestDesc('adding items with composite primary-keys')
|
||||
);
|
||||
|
||||
$mapper = new \DB\SQL\Mapper($db, $this->tname);
|
||||
$mapper->load();
|
||||
$rec_count_cur = $mapper->loaded();
|
||||
$schema->truncateTable($this->tname);
|
||||
$mapper->reset();
|
||||
$mapper->load();
|
||||
$rec_count_new = $mapper->loaded();
|
||||
$this->test->expect(
|
||||
$rec_count_cur==3 && $rec_count_new == 0,
|
||||
$this->getTestDesc('truncate table')
|
||||
);
|
||||
|
||||
$schema->dropTable($this->tname);
|
||||
|
||||
// indexes
|
||||
$table = $schema->createTable($this->tname);
|
||||
$table->addColumn('rawtest', array('type' => $schema::DT_VARCHAR256, 'default' => 'foo'));
|
||||
$table->addColumn('text')->type($schema::DT_TEXT);
|
||||
$table->addColumn('foo')->type($schema::DT_VARCHAR128)->index();
|
||||
$table = $table->build();
|
||||
$r1 = $table->getCols(true);
|
||||
$this->test->expect(
|
||||
isset($r1['rawtest']) && $r1['rawtest']['default'] = 'foo',
|
||||
$this->getTestDesc('adding column with options array')
|
||||
);
|
||||
$indexes = $table->listIndex();
|
||||
$this->test->expect(
|
||||
isset($indexes[$table->name.'___foo']),
|
||||
$this->getTestDesc('column index on table creation')
|
||||
);
|
||||
$table->addColumn('bar')->type($schema::DT_VARCHAR128)->index(true);
|
||||
$table->addColumn('baz')->type($schema::DT_VARCHAR128);
|
||||
$table->addIndex(array('foo', 'baz'));
|
||||
$table->build();
|
||||
$indexes = $table->listIndex();
|
||||
$this->test->expect(
|
||||
isset($indexes[$table->name.'___bar']),
|
||||
$this->getTestDesc('column index on table alteration')
|
||||
);
|
||||
$this->test->expect(
|
||||
isset($indexes[$table->name.'___bar']) && $indexes[$table->name.'___bar']['unique'] == true,
|
||||
$this->getTestDesc('unique index')
|
||||
);
|
||||
$this->test->expect(
|
||||
isset($indexes[$table->name.'___foo__baz']),
|
||||
$this->getTestDesc('index on combined columns')
|
||||
);
|
||||
|
||||
if($this->current_engine == 'sqlite') {
|
||||
$table->dropColumn('rawtest');
|
||||
$table->build();
|
||||
$indexes = $table->listIndex();
|
||||
$this->test->expect(
|
||||
isset($indexes[$table->name.'___foo__baz']) && isset($indexes[$table->name.'___bar'])
|
||||
&& $indexes[$table->name.'___bar']['unique'],
|
||||
$this->getTestDesc('preserve indexes after table rebuild')
|
||||
);
|
||||
}
|
||||
|
||||
$table->dropIndex($table->name.'___bar');
|
||||
$table->build();
|
||||
$indexes = $table->listIndex();
|
||||
$this->test->expect(
|
||||
!array_key_exists($table->name.'___bar',$indexes),
|
||||
$this->getTestDesc('drop index')
|
||||
);
|
||||
|
||||
// update column
|
||||
$table->updateColumn('bar',$schema::DT_TEXT);
|
||||
$table->build();
|
||||
$r1 = $table->getCols(true);
|
||||
$text = preg_match('/sybase|dblib|odbc|sqlsrv/',$this->current_engine)
|
||||
? 'nvarchar' : 'text';
|
||||
$this->test->expect(
|
||||
array_key_exists('bar', $r1) && $r1['bar']['type'] == $text,
|
||||
$this->getTestDesc('update column')
|
||||
);
|
||||
|
||||
// update column
|
||||
$cols = $table->getCols(true);
|
||||
$bar = $cols['bar'];
|
||||
$col = new \DB\SQL\Column('bar',$table);
|
||||
$col->copyfrom($bar);
|
||||
$col->type_varchar(60);
|
||||
$col->defaults('great');
|
||||
$table->updateColumn('bar',$col);
|
||||
$table->build();
|
||||
$r1 = $table->getCols(true);
|
||||
$this->test->expect(
|
||||
array_key_exists('bar', $r1)
|
||||
&& $r1['bar']['default'] == 'great',
|
||||
$this->getTestDesc('update column and default')
|
||||
);
|
||||
|
||||
// update column default only
|
||||
$cols = $table->getCols(true);
|
||||
$bar = $cols['bar'];
|
||||
$col = new \DB\SQL\Column('bar',$table);
|
||||
$col->copyfrom($bar);
|
||||
$col->passThrough();
|
||||
$col->defaults('');
|
||||
$table->updateColumn('bar',$col);
|
||||
$table->build();
|
||||
$r1 = $table->getCols(true);
|
||||
$this->test->expect(
|
||||
array_key_exists('bar', $r1) && $r1['bar']['default'] == '',
|
||||
$this->getTestDesc('update default value')
|
||||
);
|
||||
|
||||
$col->nullable(false);
|
||||
$table->updateColumn('bar',$col);
|
||||
$table->build();
|
||||
$r1 = $table->getCols(true);
|
||||
$this->test->expect(
|
||||
array_key_exists('bar', $r1) && $r1['bar']['nullable'] == false,
|
||||
$this->getTestDesc('update nullable flag')
|
||||
);
|
||||
|
||||
|
||||
// create table with text not nullable column
|
||||
$table2 = $schema->createTable($this->tname.'_notnulltext');
|
||||
$table2->addColumn('desc')->type($schema::DT_TEXT)->nullable(false);
|
||||
$table2 = $table2->build();
|
||||
$r1 = $schema->getTables();
|
||||
$r2 = $table2->getCols(true);
|
||||
$this->test->expect(
|
||||
in_array($this->tname.'_notnulltext', $r1) && array_key_exists('desc', $r2)
|
||||
&& $r2['desc']['nullable']==false,
|
||||
$this->getTestDesc('create new table with not nullable text column')
|
||||
);
|
||||
$table2->drop();
|
||||
|
||||
// boolean fields are actually bit/tinyint
|
||||
$schema->dropTable($this->tname.'_notnullbool');
|
||||
$table2 = $schema->createTable($this->tname.'_notnullbool');
|
||||
$table2->addColumn('active')->type($schema::DT_BOOL)->nullable(false);
|
||||
$table2 = $table2->build();
|
||||
$r1 = $schema->getTables();
|
||||
$r2 = $table2->getCols(true);
|
||||
$this->test->expect(
|
||||
in_array($this->tname.'_notnullbool', $r1) && array_key_exists('active', $r2)
|
||||
&& $r2['active']['nullable']==false,
|
||||
$this->getTestDesc('create new table with not nullable boolean column')
|
||||
);
|
||||
|
||||
$table2->addColumn('active2')->type($schema::DT_BOOL)->nullable(false)->defaults(0);
|
||||
$table2->addColumn('active3')->type($schema::DT_BOOL)->nullable(false)->defaults(1);
|
||||
$table2->build();
|
||||
$r1 = $schema->getTables();
|
||||
$r2 = $table2->getCols(true);
|
||||
$this->test->expect(
|
||||
in_array($this->tname.'_notnullbool', $r1)
|
||||
&& array_key_exists('active2', $r2) && $r2['active2']['nullable']==false &&
|
||||
((int)$r2['active2']['default']==0||$r2['active2']['default']=='false')
|
||||
&& array_key_exists('active3', $r2) && $r2['active3']['nullable']==false &&
|
||||
((int)$r2['active3']['default']==1||$r2['active3']['default']=='true'),
|
||||
$this->getTestDesc('add not nullable boolean columns with default to existing table')
|
||||
);
|
||||
|
||||
|
||||
$table2->drop();
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -19,6 +19,9 @@ class AccessController extends Controller {
|
||||
* @param \Base $f3
|
||||
* @param $params
|
||||
* @return bool
|
||||
* @throws \Exception
|
||||
* @throws \Exception\PathfinderException
|
||||
* @throws \ZMQSocketException
|
||||
*/
|
||||
function beforeroute(\Base $f3, $params): bool {
|
||||
if($return = parent::beforeroute($f3, $params)){
|
||||
@@ -47,6 +50,8 @@ class AccessController extends Controller {
|
||||
* get current character and check if it is a valid character
|
||||
* @param \Base $f3
|
||||
* @return bool
|
||||
* @throws \Exception
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
protected function isLoggedIn(\Base $f3): bool {
|
||||
$loginCheck = false;
|
||||
@@ -66,6 +71,7 @@ class AccessController extends Controller {
|
||||
* @param \Base $f3
|
||||
* @param Model\CharacterModel $character
|
||||
* @return bool
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
private function checkLogTimer(\Base $f3, Model\CharacterModel $character){
|
||||
$loginCheck = false;
|
||||
@@ -97,6 +103,9 @@ class AccessController extends Controller {
|
||||
* -> send over TCP Socket
|
||||
* @param Model\MapModel $map
|
||||
* @return int (number of active connections for this map)
|
||||
* @throws \Exception
|
||||
* @throws \Exception\PathfinderException
|
||||
* @throws \ZMQSocketException
|
||||
*/
|
||||
protected function broadcastMapData(Model\MapModel $map){
|
||||
$mapData = $this->getFormattedMapData($map);
|
||||
@@ -107,6 +116,8 @@ class AccessController extends Controller {
|
||||
* get formatted Map Data
|
||||
* @param Model\MapModel $map
|
||||
* @return array
|
||||
* @throws \Exception
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
protected function getFormattedMapData(Model\MapModel $map){
|
||||
$mapData = $map->getData();
|
||||
|
||||
@@ -34,6 +34,8 @@ class Admin extends Controller{
|
||||
* @param \Base $f3
|
||||
* @param $params
|
||||
* @return bool
|
||||
* @throws \Exception
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
function beforeroute(\Base $f3, $params): bool {
|
||||
$return = parent::beforeroute($f3, $params);
|
||||
@@ -63,6 +65,7 @@ class Admin extends Controller{
|
||||
/**
|
||||
* event handler after routing
|
||||
* @param \Base $f3
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
public function afterroute(\Base $f3) {
|
||||
// js view (file)
|
||||
@@ -81,6 +84,7 @@ class Admin extends Controller{
|
||||
* returns valid admin $characterModel for current user
|
||||
* @param \Base $f3
|
||||
* @return CharacterModel|null
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function getAdminCharacter(\Base $f3){
|
||||
$adminCharacter = null;
|
||||
@@ -148,6 +152,7 @@ class Admin extends Controller{
|
||||
* @param \Base $f3
|
||||
* @param array $params
|
||||
* @param null $character
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
public function dispatch(\Base $f3, $params, $character = null){
|
||||
if($character instanceof CharacterModel){
|
||||
@@ -191,6 +196,7 @@ class Admin extends Controller{
|
||||
* @param CharacterModel $character
|
||||
* @param int $kickCharacterId
|
||||
* @param int $minutes
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
protected function kickCharacter(CharacterModel $character, $kickCharacterId, $minutes){
|
||||
$kickOptions = self::KICK_OPTIONS;
|
||||
@@ -220,6 +226,7 @@ class Admin extends Controller{
|
||||
* @param CharacterModel $character
|
||||
* @param int $banCharacterId
|
||||
* @param int $value
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
protected function banCharacter(CharacterModel $character, $banCharacterId, $value){
|
||||
$banCharacters = $this->filterValidCharacters($character, $banCharacterId);
|
||||
@@ -267,6 +274,7 @@ class Admin extends Controller{
|
||||
* get log file for "admin" logs
|
||||
* @param string $type
|
||||
* @return \Log
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
static function getLogger($type = 'ADMIN'){
|
||||
return parent::getLogger('ADMIN');
|
||||
|
||||
@@ -17,6 +17,7 @@ class Access extends Controller\AccessController {
|
||||
* search character/corporation or alliance by name
|
||||
* @param \Base $f3
|
||||
* @param $params
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function search($f3, $params){
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ class Connection extends Controller\AccessController {
|
||||
* save a new connection or updates an existing (drag/drop) between two systems
|
||||
* if a connection is changed (drag&drop) to another system. -> this function is called for update
|
||||
* @param \Base $f3
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function save(\Base $f3){
|
||||
$postData = (array)$f3->get('POST');
|
||||
|
||||
@@ -21,6 +21,7 @@ class GitHub extends Controller\Controller {
|
||||
/**
|
||||
* get HTTP request options for API (curl) request
|
||||
* @return array
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
protected function getRequestOptions(){
|
||||
$requestOptions = [
|
||||
@@ -36,6 +37,7 @@ class GitHub extends Controller\Controller {
|
||||
/**
|
||||
* get release information from GitHub
|
||||
* @param $f3
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
public function releases($f3){
|
||||
$cacheKey = 'CACHE_GITHUB_RELEASES';
|
||||
|
||||
@@ -71,6 +71,8 @@ class Map extends Controller\AccessController {
|
||||
/**
|
||||
* Get all required static config data for program initialization
|
||||
* @param \Base $f3
|
||||
* @throws Exception
|
||||
* @throws Exception\PathfinderException
|
||||
*/
|
||||
public function init(\Base $f3){
|
||||
// expire time in seconds
|
||||
@@ -159,6 +161,15 @@ class Map extends Controller\AccessController {
|
||||
}
|
||||
$return->connectionScopes = $connectionScopeData;
|
||||
|
||||
// get available wormhole types ---------------------------------------------------------------------------
|
||||
$wormholes = Model\BasicModel::getNew('WormholeModel');
|
||||
$rows = $wormholes->find('id > 0', null, $expireTimeSQL);
|
||||
$wormholesData = [];
|
||||
foreach((array)$rows as $rowData){
|
||||
$wormholesData[$rowData->name] = $rowData->getData();
|
||||
}
|
||||
$return->wormholes = $wormholesData;
|
||||
|
||||
// get available character status -------------------------------------------------------------------------
|
||||
$characterStatus = Model\BasicModel::getNew('CharacterStatusModel');
|
||||
$rows = $characterStatus->find('active = 1', null, $expireTimeSQL);
|
||||
@@ -223,6 +234,7 @@ class Map extends Controller\AccessController {
|
||||
/**
|
||||
* import new map data
|
||||
* @param \Base $f3
|
||||
* @throws Exception
|
||||
*/
|
||||
public function import(\Base $f3){
|
||||
$importData = (array)$f3->get('POST');
|
||||
@@ -367,6 +379,7 @@ class Map extends Controller\AccessController {
|
||||
/**
|
||||
* save a new map or update an existing map
|
||||
* @param \Base $f3
|
||||
* @throws Exception
|
||||
*/
|
||||
public function save(\Base $f3){
|
||||
$formData = (array)$f3->get('POST.formData');
|
||||
@@ -563,6 +576,7 @@ class Map extends Controller\AccessController {
|
||||
/**
|
||||
* delete a map and all dependencies
|
||||
* @param \Base $f3
|
||||
* @throws Exception
|
||||
*/
|
||||
public function delete(\Base $f3){
|
||||
$mapData = (array)$f3->get('POST.mapData');
|
||||
@@ -597,6 +611,9 @@ class Map extends Controller\AccessController {
|
||||
* -> if characters with map access found -> broadcast mapData to them
|
||||
* @param Model\MapModel $map
|
||||
* @param array $characterIds
|
||||
* @throws Exception
|
||||
* @throws Exception\PathfinderException
|
||||
* @throws \ZMQSocketException
|
||||
*/
|
||||
protected function broadcastMapAccess($map, $characterIds){
|
||||
$mapAccess = [
|
||||
@@ -614,6 +631,7 @@ class Map extends Controller\AccessController {
|
||||
* broadcast map delete information to clients
|
||||
* @param int $mapId
|
||||
* @return bool|string
|
||||
* @throws \ZMQSocketException
|
||||
*/
|
||||
protected function broadcastMapDeleted($mapId){
|
||||
return (new Socket( Config::getSocketUri() ))->sendData('mapDeleted', $mapId);
|
||||
@@ -623,6 +641,7 @@ class Map extends Controller\AccessController {
|
||||
* get map access tokens for current character
|
||||
* -> send access tokens via TCP Socket for WebSocket auth
|
||||
* @param \Base $f3
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getAccessData(\Base $f3){
|
||||
$return = (object) [];
|
||||
@@ -656,6 +675,8 @@ class Map extends Controller\AccessController {
|
||||
* update map data
|
||||
* -> function is called continuously (trigger) by any active client
|
||||
* @param \Base $f3
|
||||
* @throws Exception
|
||||
* @throws Exception\PathfinderException
|
||||
*/
|
||||
public function updateData(\Base $f3){
|
||||
$mapData = (array)$f3->get('POST.mapData');
|
||||
@@ -805,6 +826,8 @@ class Map extends Controller\AccessController {
|
||||
* get formatted map data
|
||||
* @param Model\MapModel[] $mapModels
|
||||
* @return array
|
||||
* @throws Exception
|
||||
* @throws Exception\PathfinderException
|
||||
*/
|
||||
protected function getFormattedMapsData($mapModels){
|
||||
$mapData = [];
|
||||
@@ -819,6 +842,8 @@ class Map extends Controller\AccessController {
|
||||
* update map data api
|
||||
* -> function is called continuously by any active client
|
||||
* @param \Base $f3
|
||||
* @throws Exception
|
||||
* @throws Exception\PathfinderException
|
||||
*/
|
||||
public function updateUserData(\Base $f3){
|
||||
$return = (object) [];
|
||||
@@ -896,6 +921,7 @@ class Map extends Controller\AccessController {
|
||||
* @param Model\CharacterModel $character
|
||||
* @param Model\MapModel $map
|
||||
* @return Model\MapModel
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function updateMapData(Model\CharacterModel $character, Model\MapModel $map){
|
||||
|
||||
@@ -1056,21 +1082,34 @@ class Map extends Controller\AccessController {
|
||||
}
|
||||
}
|
||||
|
||||
// save connection ------------------------------------------------------------------------------------
|
||||
if(
|
||||
$addConnection &&
|
||||
$sourceExists &&
|
||||
$targetExists &&
|
||||
$sourceSystem &&
|
||||
$targetSystem &&
|
||||
!$map->searchConnection( $sourceSystem, $targetSystem )
|
||||
$targetSystem
|
||||
){
|
||||
$connection = $map->getNewConnection($sourceSystem, $targetSystem);
|
||||
$connection = $map->saveConnection($connection, $character);
|
||||
// get updated maps object
|
||||
if($connection){
|
||||
$map = $connection->mapId;
|
||||
$mapDataChanged = true;
|
||||
$connection = $map->searchConnection( $sourceSystem, $targetSystem);
|
||||
|
||||
// save connection --------------------------------------------------------------------------------
|
||||
if(
|
||||
$addConnection &&
|
||||
!$connection
|
||||
){
|
||||
$connection = $map->getNewConnection($sourceSystem, $targetSystem);
|
||||
$connection = $map->saveConnection($connection, $character);
|
||||
// get updated maps object
|
||||
if($connection){
|
||||
$map = $connection->mapId;
|
||||
$mapDataChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
// log jump mass ----------------------------------------------------------------------------------
|
||||
if(
|
||||
$connection &&
|
||||
$connection->isWormhole()
|
||||
){
|
||||
$connection->logMass($log);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1087,9 +1126,13 @@ class Map extends Controller\AccessController {
|
||||
/**
|
||||
* get connectionData
|
||||
* @param \Base $f3
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getConnectionData (\Base $f3){
|
||||
$postData = (array)$f3->get('POST');
|
||||
|
||||
$addData = (array)$postData['addData'];
|
||||
$filterData = (array)$postData['filterData'];
|
||||
$connectionData = [];
|
||||
|
||||
if($mapId = (int)$postData['mapId']){
|
||||
@@ -1102,13 +1145,27 @@ class Map extends Controller\AccessController {
|
||||
$map->getById($mapId);
|
||||
|
||||
if($map->hasAccess($activeCharacter)){
|
||||
$connections = $map->getConnections('wh');
|
||||
foreach($connections as $connection){
|
||||
$data = $connection->getData(true);
|
||||
// skip connections whiteout signature data
|
||||
if($data->signatures){
|
||||
$connectionData[] = $data;
|
||||
// get specific connections by id
|
||||
$connectionIds = null;
|
||||
if(is_array($postData['connectionIds'])){
|
||||
$connectionIds = $postData['connectionIds'];
|
||||
}
|
||||
|
||||
$connections = $map->getConnections($connectionIds, 'wh');
|
||||
foreach($connections as $connection){
|
||||
$check = true;
|
||||
$data = $connection->getData(in_array('signatures', $addData), in_array('logs', $addData));
|
||||
// filter result
|
||||
if(in_array('signatures', $filterData) && !$data->signatures){
|
||||
$check = false;
|
||||
}
|
||||
|
||||
if(in_array('logs', $filterData) && !$data->logs){
|
||||
$check = false;
|
||||
}
|
||||
|
||||
if($check){
|
||||
$connectionData[] = $data;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1120,6 +1177,8 @@ class Map extends Controller\AccessController {
|
||||
/**
|
||||
* get map log data
|
||||
* @param \Base $f3
|
||||
* @throws Exception
|
||||
* @throws Exception\PathfinderException
|
||||
*/
|
||||
public function getLogData(\Base $f3){
|
||||
$postData = (array)$f3->get('POST');
|
||||
|
||||
@@ -509,6 +509,8 @@ class Route extends Controller\AccessController {
|
||||
/**
|
||||
* search multiple route between two systems
|
||||
* @param \Base $f3
|
||||
* @throws \Exception
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
public function search($f3){
|
||||
$requestData = (array)$f3->get('POST');
|
||||
|
||||
@@ -18,6 +18,7 @@ class Signature extends Controller\AccessController {
|
||||
* get signature data for systems
|
||||
* -> return value of this is limited to a "SINGLE" system
|
||||
* @param \Base $f3
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function getAll(\Base $f3){
|
||||
$signatureData = [];
|
||||
@@ -50,6 +51,7 @@ class Signature extends Controller\AccessController {
|
||||
* save or update a full signature data set
|
||||
* or save/update just single or multiple signature data
|
||||
* @param \Base $f3
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function save(\Base $f3){
|
||||
$requestData = $f3->get('POST');
|
||||
@@ -221,6 +223,7 @@ class Signature extends Controller\AccessController {
|
||||
/**
|
||||
* delete signatures
|
||||
* @param \Base $f3
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function delete(\Base $f3){
|
||||
$signatureIds = $f3->get('POST.signatureIds');
|
||||
|
||||
@@ -123,6 +123,7 @@ class Statistic extends Controller\AccessController {
|
||||
* @param int $yearEnd
|
||||
* @param int $weekEnd
|
||||
* @return array
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
protected function queryStatistic( CharacterModel $character, $typeId, $yearStart, $weekStart, $yearEnd, $weekEnd){
|
||||
$data = [];
|
||||
@@ -231,6 +232,7 @@ class Statistic extends Controller\AccessController {
|
||||
/**
|
||||
* get statistics data
|
||||
* @param \Base $f3
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function getData(\Base $f3){
|
||||
$postData = (array)$f3->get('POST');
|
||||
|
||||
@@ -175,6 +175,7 @@ class System extends Controller\AccessController {
|
||||
/**
|
||||
* save a new system to a a map
|
||||
* @param \Base $f3
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function save(\Base $f3){
|
||||
$postData = (array)$f3->get('POST');
|
||||
@@ -278,6 +279,7 @@ class System extends Controller\AccessController {
|
||||
* get system log data from CCP API import
|
||||
* system Kills, Jumps,....
|
||||
* @param \Base $f3
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function graphData(\Base $f3){
|
||||
$graphData = [];
|
||||
@@ -329,6 +331,8 @@ class System extends Controller\AccessController {
|
||||
* get system data for all systems within a constellation
|
||||
* @param \Base $f3
|
||||
* @param array $params
|
||||
* @throws \Exception
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
public function constellationData(\Base $f3, $params){
|
||||
$return = (object) [];
|
||||
@@ -363,6 +367,7 @@ class System extends Controller\AccessController {
|
||||
/**
|
||||
* set destination for specific systemIds
|
||||
* @param \Base $f3
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function setDestination(\Base $f3){
|
||||
$postData = (array)$f3->get('POST');
|
||||
@@ -405,6 +410,8 @@ class System extends Controller\AccessController {
|
||||
/**
|
||||
* send Rally Point poke
|
||||
* @param \Base $f3
|
||||
* @throws \Exception
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
public function pokeRally(\Base $f3){
|
||||
$rallyData = (array)$f3->get('POST');
|
||||
@@ -437,6 +444,7 @@ class System extends Controller\AccessController {
|
||||
* delete systems and all its connections from map
|
||||
* -> set "active" flag
|
||||
* @param \Base $f3
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function delete(\Base $f3){
|
||||
$mapId = (int)$f3->get('POST.mapId');
|
||||
@@ -455,11 +463,20 @@ class System extends Controller\AccessController {
|
||||
$map->getById($mapId);
|
||||
|
||||
if($map->hasAccess($activeCharacter)){
|
||||
$newSystemModel = Model\BasicModel::getNew('SystemModel');
|
||||
foreach($systemIds as $systemId){
|
||||
if( $system = $map->getSystemById($systemId) ){
|
||||
// check whether system should be deleted OR set "inactive"
|
||||
if( $this->checkDeleteMode($map, $system) ){
|
||||
$system->erase();
|
||||
// delete log
|
||||
// -> first set updatedCharacterId -> required for activity log
|
||||
$system->updatedCharacterId = $activeCharacter;
|
||||
$system->update();
|
||||
|
||||
// ... now get fresh object and delete..
|
||||
$newSystemModel->getById( $system->id, 0);
|
||||
$newSystemModel->erase();
|
||||
$newSystemModel->reset();
|
||||
}else{
|
||||
// keep data -> set "inactive"
|
||||
$system->setActive(false);
|
||||
|
||||
@@ -42,10 +42,10 @@ class User extends Controller\Controller{
|
||||
/**
|
||||
* login a valid character
|
||||
* @param Model\CharacterModel $characterModel
|
||||
* @param string $browserTabId
|
||||
* @return bool
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function loginByCharacter(Model\CharacterModel &$characterModel, string $browserTabId){
|
||||
protected function loginByCharacter(Model\CharacterModel &$characterModel){
|
||||
$login = false;
|
||||
|
||||
if($user = $characterModel->getUser()){
|
||||
@@ -96,7 +96,7 @@ class User extends Controller\Controller{
|
||||
|
||||
// set temp character data ------------------------------------------------------------
|
||||
// -> pass character data over for next http request (reroute())
|
||||
$this->setTempCharacterData($characterModel->_id, $browserTabId);
|
||||
$this->setTempCharacterData($characterModel->_id);
|
||||
|
||||
$login = true;
|
||||
}
|
||||
@@ -108,6 +108,8 @@ class User extends Controller\Controller{
|
||||
* validate cookie character information
|
||||
* -> return character data (if valid)
|
||||
* @param \Base $f3
|
||||
* @throws Exception
|
||||
* @throws Exception\PathfinderException
|
||||
*/
|
||||
public function getCookieCharacter(\Base $f3){
|
||||
$data = $f3->get('POST');
|
||||
@@ -188,6 +190,7 @@ class User extends Controller\Controller{
|
||||
/**
|
||||
* delete the character log entry for the current active (main) character
|
||||
* @param \Base $f3
|
||||
* @throws Exception
|
||||
*/
|
||||
public function deleteLog(\Base $f3){
|
||||
if($activeCharacter = $this->getCharacter()){
|
||||
@@ -198,6 +201,8 @@ class User extends Controller\Controller{
|
||||
/**
|
||||
* log the current user out + clear character system log data
|
||||
* @param \Base $f3
|
||||
* @throws Exception
|
||||
* @throws \ZMQSocketException
|
||||
*/
|
||||
public function logout(\Base $f3){
|
||||
$this->logoutCharacter(false, true, true, true);
|
||||
@@ -211,6 +216,7 @@ class User extends Controller\Controller{
|
||||
* remote open ingame information window (character, corporation or alliance) Id
|
||||
* -> the type is auto-recognized by CCP
|
||||
* @param \Base $f3
|
||||
* @throws Exception
|
||||
*/
|
||||
public function openIngameWindow(\Base $f3){
|
||||
$data = $f3->get('POST');
|
||||
@@ -241,6 +247,7 @@ class User extends Controller\Controller{
|
||||
* -> a fresh user automatically generated on first login with a new character
|
||||
* -> see SSO login
|
||||
* @param \Base $f3
|
||||
* @throws Exception
|
||||
*/
|
||||
public function saveAccount(\Base $f3){
|
||||
$data = $f3->get('POST');
|
||||
@@ -361,6 +368,8 @@ class User extends Controller\Controller{
|
||||
/**
|
||||
* delete current user account from DB
|
||||
* @param \Base $f3
|
||||
* @throws Exception
|
||||
* @throws \ZMQSocketException
|
||||
*/
|
||||
public function deleteAccount(\Base $f3){
|
||||
$data = $f3->get('POST.formData');
|
||||
|
||||
@@ -34,7 +34,6 @@ class Sso extends Api\User{
|
||||
const SESSION_KEY_SSO_ERROR = 'SESSION.SSO.ERROR';
|
||||
const SESSION_KEY_SSO_STATE = 'SESSION.SSO.STATE';
|
||||
const SESSION_KEY_SSO_FROM = 'SESSION.SSO.FROM';
|
||||
const SESSION_KEY_SSO_TAB_ID = 'SESSION.SSO.TABID';
|
||||
|
||||
// error messages
|
||||
const ERROR_CCP_SSO_URL = 'Invalid "ENVIRONMENT.[ENVIRONMENT].CCP_SSO_URL" url. %s';
|
||||
@@ -52,10 +51,10 @@ class Sso extends Api\User{
|
||||
* redirect user to CCP SSO page and request authorization
|
||||
* -> cf. Controller->getCookieCharacters() ( equivalent cookie based login)
|
||||
* @param \Base $f3
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
public function requestAdminAuthorization($f3){
|
||||
// store browser tabId to be "targeted" after login
|
||||
$f3->set(self::SESSION_KEY_SSO_TAB_ID, '');
|
||||
$f3->set(self::SESSION_KEY_SSO_FROM, 'admin');
|
||||
|
||||
$scopes = self::getScopesByAuthType('admin');
|
||||
@@ -66,13 +65,11 @@ class Sso extends Api\User{
|
||||
* redirect user to CCP SSO page and request authorization
|
||||
* -> cf. Controller->getCookieCharacters() ( equivalent cookie based login)
|
||||
* @param \Base $f3
|
||||
* @throws \Exception
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
public function requestAuthorization($f3){
|
||||
$params = $f3->get('GET');
|
||||
$browserTabId = trim((string)$params['tabId']);
|
||||
|
||||
// store browser tabId to be "targeted" after login
|
||||
$f3->set(self::SESSION_KEY_SSO_TAB_ID, $browserTabId);
|
||||
|
||||
if(
|
||||
isset($params['characterId']) &&
|
||||
@@ -108,7 +105,7 @@ class Sso extends Api\User{
|
||||
$character->hasUserCharacter() &&
|
||||
($character->isAuthorized() === 'OK')
|
||||
){
|
||||
$loginCheck = $this->loginByCharacter($character, $browserTabId);
|
||||
$loginCheck = $this->loginByCharacter($character);
|
||||
|
||||
if($loginCheck){
|
||||
// set "login" cookie
|
||||
@@ -135,6 +132,7 @@ class Sso extends Api\User{
|
||||
* @param \Base $f3
|
||||
* @param array $scopes
|
||||
* @param string $rootAlias
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
private function rerouteAuthorization(\Base $f3, $scopes = [], $rootAlias = 'login'){
|
||||
if( !empty( Controller\Controller::getEnvironmentData('CCP_SSO_CLIENT_ID') ) ){
|
||||
@@ -166,6 +164,8 @@ class Sso extends Api\User{
|
||||
* callback handler for CCP SSO user Auth
|
||||
* -> see requestAuthorization()
|
||||
* @param \Base $f3
|
||||
* @throws \Exception
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
public function callbackAuthorization($f3){
|
||||
$getParams = (array)$f3->get('GET');
|
||||
@@ -178,8 +178,6 @@ class Sso extends Api\User{
|
||||
$rootAlias = $f3->get(self::SESSION_KEY_SSO_FROM);
|
||||
}
|
||||
|
||||
$browserTabId = (string)$f3->get(self::SESSION_KEY_SSO_TAB_ID) ;
|
||||
|
||||
if($f3->exists(self::SESSION_KEY_SSO_STATE)){
|
||||
// check response and validate 'state'
|
||||
if(
|
||||
@@ -192,7 +190,6 @@ class Sso extends Api\User{
|
||||
// clear 'state' for new next login request
|
||||
$f3->clear(self::SESSION_KEY_SSO_STATE);
|
||||
$f3->clear(self::SESSION_KEY_SSO_FROM);
|
||||
$f3->clear(self::SESSION_KEY_SSO_TAB_ID);
|
||||
|
||||
$accessData = $this->getSsoAccessData($getParams['code']);
|
||||
|
||||
@@ -259,7 +256,7 @@ class Sso extends Api\User{
|
||||
$characterModel = $userCharactersModel->getCharacter();
|
||||
|
||||
// login by character
|
||||
$loginCheck = $this->loginByCharacter($characterModel, $browserTabId);
|
||||
$loginCheck = $this->loginByCharacter($characterModel);
|
||||
|
||||
if($loginCheck){
|
||||
// set "login" cookie
|
||||
@@ -305,11 +302,12 @@ class Sso extends Api\User{
|
||||
/**
|
||||
* login by cookie name
|
||||
* @param \Base $f3
|
||||
* @throws \Exception
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
public function login(\Base $f3){
|
||||
$data = (array)$f3->get('GET');
|
||||
$cookieName = empty($data['cookie']) ? '' : $data['cookie'];
|
||||
$browserTabId = empty($data['tabId']) ? '' : $data['tabId'];
|
||||
$character = null;
|
||||
|
||||
if( !empty($cookieName) ){
|
||||
@@ -324,7 +322,7 @@ class Sso extends Api\User{
|
||||
|
||||
if( is_object($character)){
|
||||
// login by character
|
||||
$loginCheck = $this->loginByCharacter($character, $browserTabId);
|
||||
$loginCheck = $this->loginByCharacter($character);
|
||||
if($loginCheck){
|
||||
// route to "map"
|
||||
$f3->reroute(['map']);
|
||||
@@ -343,6 +341,7 @@ class Sso extends Api\User{
|
||||
* -> else try to refresh auth and get fresh "access_token"
|
||||
* @param bool $authCode
|
||||
* @return null|\stdClass
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
public function getSsoAccessData($authCode){
|
||||
$accessData = null;
|
||||
@@ -362,6 +361,7 @@ class Sso extends Api\User{
|
||||
* verify authorization code, and get an "access_token" data
|
||||
* @param $authCode
|
||||
* @return \stdClass
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
protected function verifyAuthorizationCode($authCode){
|
||||
$requestParams = [
|
||||
@@ -377,6 +377,7 @@ class Sso extends Api\User{
|
||||
* -> if "access_token" is expired, this function gets a fresh one
|
||||
* @param $refreshToken
|
||||
* @return \stdClass
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
public function refreshAccessToken($refreshToken){
|
||||
$requestParams = [
|
||||
@@ -393,6 +394,7 @@ class Sso extends Api\User{
|
||||
* OR by providing a valid "refresh_token"
|
||||
* @param $requestParams
|
||||
* @return \stdClass
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
protected function requestAccessData($requestParams){
|
||||
$verifyAuthCodeUrl = self::getVerifyAuthorizationCodeEndpoint();
|
||||
@@ -457,6 +459,7 @@ class Sso extends Api\User{
|
||||
* -> if more character information is required, use ESI "characters" endpoints request instead
|
||||
* @param $accessToken
|
||||
* @return mixed|null
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
public function verifyCharacterData($accessToken){
|
||||
$verifyUserUrl = self::getVerifyUserEndpoint();
|
||||
@@ -492,6 +495,7 @@ class Sso extends Api\User{
|
||||
* get character data
|
||||
* @param int $characterId
|
||||
* @return object
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function getCharacterData($characterId){
|
||||
$characterData = (object) [];
|
||||
@@ -601,6 +605,7 @@ class Sso extends Api\User{
|
||||
* get CCP SSO url from configuration file
|
||||
* -> throw error if url is broken/missing
|
||||
* @return string
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
static function getSsoUrlRoot(){
|
||||
$url = '';
|
||||
@@ -630,6 +635,7 @@ class Sso extends Api\User{
|
||||
/**
|
||||
* get logger for SSO logging
|
||||
* @return \Log
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
static function getSSOLogger(){
|
||||
return parent::getLogger('SSO');
|
||||
|
||||
@@ -17,6 +17,7 @@ class Universe extends Controller {
|
||||
/**
|
||||
* Set up "Universe" Database
|
||||
* @param \Base $f3
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function setupDB(\Base $f3){
|
||||
$this->setupRegions($f3);
|
||||
@@ -26,6 +27,7 @@ class Universe extends Controller {
|
||||
/**
|
||||
* get all regions from CCP and store region data
|
||||
* @param \Base $f3
|
||||
* @throws \Exception
|
||||
*/
|
||||
private function setupRegions(\Base $f3){
|
||||
$this->getDB('UNIVERSE');
|
||||
@@ -50,6 +52,7 @@ class Universe extends Controller {
|
||||
/**
|
||||
* get all constellations from CCP and store constellation data
|
||||
* @param \Base $f3
|
||||
* @throws \Exception
|
||||
*/
|
||||
private function setupConstellations(\Base $f3){
|
||||
$this->getDB('UNIVERSE');
|
||||
|
||||
@@ -63,6 +63,7 @@ class Controller {
|
||||
* @param \Base $f3
|
||||
* @param $params
|
||||
* @return bool
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
function beforeroute(\Base $f3, $params): bool {
|
||||
// initiate DB connection
|
||||
@@ -107,6 +108,7 @@ class Controller {
|
||||
|
||||
/**
|
||||
* init new Session handler
|
||||
* @param \Base $f3
|
||||
*/
|
||||
protected function initSession(\Base $f3){
|
||||
$sessionCacheKey = $f3->get('SESSION_CACHE');
|
||||
@@ -117,6 +119,7 @@ class Controller {
|
||||
* @param $session
|
||||
* @param $sid
|
||||
* @return bool
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
$onSuspect = function($session, $sid){
|
||||
self::getLogger('SESSION_SUSPECT')->write( sprintf(
|
||||
@@ -181,6 +184,7 @@ class Controller {
|
||||
* set/update logged in cookie by character model
|
||||
* -> store validation data in DB
|
||||
* @param Model\CharacterModel $character
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
protected function setLoginCookie(Model\CharacterModel $character){
|
||||
if( $this->getCookieState() ){
|
||||
@@ -237,6 +241,8 @@ class Controller {
|
||||
* @param array $cookieData
|
||||
* @param bool $checkAuthorization
|
||||
* @return Model\CharacterModel[]
|
||||
* @throws \Exception
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
protected function getCookieCharacters($cookieData = [], $checkAuthorization = true){
|
||||
$characters = [];
|
||||
@@ -339,8 +345,8 @@ class Controller {
|
||||
|
||||
/**
|
||||
* get current character data from session
|
||||
* ->
|
||||
* @return array
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function getSessionCharacterData(){
|
||||
$data = [];
|
||||
@@ -348,35 +354,16 @@ class Controller {
|
||||
if($user = $this->getUser()){
|
||||
$header = self::getRequestHeaders();
|
||||
$requestedCharacterId = (int)$header['Pf-Character'];
|
||||
$browserTabId = (string)$header['Pf-Tab-Id'];
|
||||
$tempCharacterData = (array)$this->getF3()->get(Api\User::SESSION_KEY_TEMP_CHARACTER_DATA);
|
||||
|
||||
if($this->getF3()->get('AJAX')){
|
||||
if( !$this->getF3()->get('AJAX') ){
|
||||
$requestedCharacterId = (int)$_COOKIE['old_char_id'];
|
||||
if(!$requestedCharacterId){
|
||||
$tempCharacterData = (array)$this->getF3()->get(Api\User::SESSION_KEY_TEMP_CHARACTER_DATA);
|
||||
if((int)$tempCharacterData['ID'] > 0){
|
||||
$requestedCharacterId = (int)$tempCharacterData['ID'];
|
||||
}
|
||||
|
||||
// _blank browser tab don´t have a $browserTabId jet..
|
||||
// first Ajax call from that new tab with empty $requestedCharacterId -> bind to that new tab
|
||||
if(
|
||||
!empty($browserTabId) &&
|
||||
$requestedCharacterId <= 0 &&
|
||||
(int)$tempCharacterData['ID'] > 0 &&
|
||||
empty($tempCharacterData['TAB_ID'])
|
||||
){
|
||||
$tempCharacterData['TAB_ID'] = $browserTabId;
|
||||
// update tempCharacterData (SESSION)
|
||||
$this->setTempCharacterData($tempCharacterData['ID'], $tempCharacterData['TAB_ID']);
|
||||
}
|
||||
|
||||
if(
|
||||
!empty($browserTabId) &&
|
||||
!empty($tempCharacterData['TAB_ID']) &&
|
||||
(int)$tempCharacterData['ID'] > 0 &&
|
||||
$browserTabId === $tempCharacterData['TAB_ID']
|
||||
){
|
||||
$requestedCharacterId = (int)$tempCharacterData['ID'];
|
||||
}
|
||||
|
||||
}elseif((int)$tempCharacterData['ID'] > 0){
|
||||
$requestedCharacterId = (int)$tempCharacterData['ID'];
|
||||
}
|
||||
|
||||
$data = $user->getSessionCharacterData($requestedCharacterId);
|
||||
@@ -417,6 +404,7 @@ class Controller {
|
||||
* get current user
|
||||
* @param int $ttl
|
||||
* @return Model\UserModel|null
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function getUser($ttl = 0){
|
||||
$user = null;
|
||||
@@ -442,14 +430,12 @@ class Controller {
|
||||
/**
|
||||
* set temp login character data (required during HTTP redirects on login)
|
||||
* @param int $characterId
|
||||
* @param string $browserTabId
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function setTempCharacterData(int $characterId, string $browserTabId){
|
||||
protected function setTempCharacterData(int $characterId){
|
||||
if($characterId > 0){
|
||||
$tempCharacterData = [
|
||||
'ID' => $characterId,
|
||||
'TAB_ID' => trim($browserTabId)
|
||||
'ID' => $characterId
|
||||
];
|
||||
$this->getF3()->set(Api\User::SESSION_KEY_TEMP_CHARACTER_DATA, $tempCharacterData);
|
||||
}else{
|
||||
@@ -463,6 +449,8 @@ class Controller {
|
||||
* @param bool $deleteSession
|
||||
* @param bool $deleteLog
|
||||
* @param bool $deleteCookie
|
||||
* @throws \Exception
|
||||
* @throws \ZMQSocketException
|
||||
*/
|
||||
protected function logoutCharacter(bool $all = false, bool $deleteSession = true, bool $deleteLog = true, bool $deleteCookie = false){
|
||||
$sessionCharacterData = (array)$this->getF3()->get(Api\User::SESSION_KEY_CHARACTERS);
|
||||
@@ -581,6 +569,7 @@ class Controller {
|
||||
/**
|
||||
* get a custom userAgent string for API calls
|
||||
* @return string
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
protected function getUserAgent(){
|
||||
$userAgent = '';
|
||||
@@ -598,6 +587,7 @@ class Controller {
|
||||
* -> on HTTP request -> render error page
|
||||
* @param \Base $f3
|
||||
* @return bool
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
public function showError(\Base $f3){
|
||||
|
||||
@@ -817,6 +807,7 @@ class Controller {
|
||||
* get the current registration status
|
||||
* 0=registration stop |1=new registration allowed
|
||||
* @return int
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
static function getRegistrationStatus(){
|
||||
return (int)Config::getPathfinderData('registration.status');
|
||||
@@ -827,6 +818,7 @@ class Controller {
|
||||
* -> set in pathfinder.ini
|
||||
* @param string $type
|
||||
* @return \Log|null
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
static function getLogger($type){
|
||||
return LogController::getLogger($type);
|
||||
@@ -856,6 +848,7 @@ class Controller {
|
||||
* health check for ICP socket -> ping request
|
||||
* @param $ttl
|
||||
* @param $load
|
||||
* @throws \ZMQSocketException
|
||||
*/
|
||||
static function checkTcpSocket($ttl, $load){
|
||||
(new Socket( Config::getSocketUri(), $ttl ))->sendData('healthCheck', $load);
|
||||
|
||||
@@ -34,6 +34,7 @@ class LogController extends \Prefab {
|
||||
/**
|
||||
* get columns from ActivityLogModel that can be uses as counter
|
||||
* @return array
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function getActivityLogColumns(): array{
|
||||
if(empty($this->activityLogColumns)){
|
||||
@@ -56,6 +57,7 @@ class LogController extends \Prefab {
|
||||
* -> this buffered data can be stored somewhere (e.g. DB) before HTTP response
|
||||
* -> should be cleared afterwards!
|
||||
* @param MapLog $log
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function push(MapLog $log){
|
||||
$action = $log->getAction();
|
||||
@@ -161,6 +163,7 @@ class LogController extends \Prefab {
|
||||
* get Logger instance
|
||||
* @param string $type
|
||||
* @return \Log|null
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
public static function getLogger($type){
|
||||
$logFiles = Config::getPathfinderData('logfiles');
|
||||
|
||||
@@ -15,10 +15,15 @@ class MapController extends AccessController {
|
||||
|
||||
/**
|
||||
* @param \Base $f3
|
||||
* @throws \Exception
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
public function init(\Base $f3) {
|
||||
$character = $this->getCharacter();
|
||||
|
||||
// characterId
|
||||
$f3->set('tplCharacterId', $character->id);
|
||||
|
||||
// page title
|
||||
$f3->set('tplPageTitle', $character->name . ' | ' . Config::getPathfinderData('name'));
|
||||
|
||||
|
||||
@@ -85,6 +85,7 @@ class Setup extends Controller {
|
||||
'Model\ConstellationWormholeModel',
|
||||
|
||||
'Model\ConnectionModel',
|
||||
'Model\ConnectionLogModel',
|
||||
'Model\SystemSignatureModel',
|
||||
|
||||
'Model\ActivityLogModel',
|
||||
@@ -139,6 +140,7 @@ class Setup extends Controller {
|
||||
* @param \Base $f3
|
||||
* @param array $params
|
||||
* @return bool
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
function beforeroute(\Base $f3, $params): bool {
|
||||
// init dbLib class. Manages all DB connections
|
||||
@@ -161,6 +163,7 @@ class Setup extends Controller {
|
||||
|
||||
/**
|
||||
* @param \Base $f3
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
public function afterroute(\Base $f3) {
|
||||
// js view (file)
|
||||
@@ -194,6 +197,7 @@ class Setup extends Controller {
|
||||
* works as dispatcher for setup functions
|
||||
* -> for security reasons all /setup "routes" are dispatched by GET params
|
||||
* @param \Base $f3
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function init(\Base $f3){
|
||||
$params = $f3->get('GET');
|
||||
@@ -760,6 +764,7 @@ class Setup extends Controller {
|
||||
* get default map config
|
||||
* @param \Base $f3
|
||||
* @return array
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
protected function getMapsDefaultConfig(\Base $f3): array {
|
||||
$matrix = \Matrix::instance();
|
||||
@@ -1245,6 +1250,7 @@ class Setup extends Controller {
|
||||
/**
|
||||
* get Socket information (TCP (internal)), (WebSocket (clients))
|
||||
* @return array
|
||||
* @throws \ZMQSocketException
|
||||
*/
|
||||
protected function getSocketInformation(){
|
||||
// $ttl for health check
|
||||
@@ -1298,6 +1304,7 @@ class Setup extends Controller {
|
||||
|
||||
/** get indexed (cache) data information
|
||||
* @return array
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function getIndexData(){
|
||||
// active DB and tables are required for obtain index data
|
||||
@@ -1509,6 +1516,7 @@ class Setup extends Controller {
|
||||
/**
|
||||
* clear all character authentication (Cookie) data
|
||||
* @param \Base $f3
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function invalidateCookies(\Base $f3){
|
||||
$this->getDB('PF');
|
||||
|
||||
@@ -38,6 +38,7 @@ class CharacterUpdate {
|
||||
* -> see deactivateLogData()
|
||||
* >> php index.php "/cron/deleteLogData"
|
||||
* @param \Base $f3
|
||||
* @throws \Exception
|
||||
*/
|
||||
function deleteLogData(\Base $f3){
|
||||
DB\Database::instance()->getDB('PF');
|
||||
@@ -80,6 +81,7 @@ class CharacterUpdate {
|
||||
* clean up outdated character data e.g. kicked until status
|
||||
* >> php index.php "/cron/cleanUpCharacterData"
|
||||
* @param \Base $f3
|
||||
* @throws \Exception
|
||||
*/
|
||||
function cleanUpCharacterData(\Base $f3){
|
||||
DB\Database::instance()->getDB('PF');
|
||||
@@ -111,6 +113,7 @@ class CharacterUpdate {
|
||||
* authentication data is used for cookie based login
|
||||
* >> php index.php "/cron/deleteAuthenticationData"
|
||||
* @param \Base $f3
|
||||
* @throws \Exception
|
||||
*/
|
||||
function deleteAuthenticationData($f3){
|
||||
DB\Database::instance()->getDB('PF');
|
||||
|
||||
@@ -22,6 +22,7 @@ class MapUpdate {
|
||||
* deactivate all "private" maps whose lifetime is over
|
||||
* >> php index.php "/cron/deactivateMapData"
|
||||
* @param \Base $f3
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
function deactivateMapData(\Base $f3){
|
||||
$privateMapLifetime = (int)Config::getMapsDefaultConfig('private.lifetime');
|
||||
@@ -45,6 +46,7 @@ class MapUpdate {
|
||||
* delete all deactivated maps
|
||||
* >> php index.php "/cron/deleteMapData"
|
||||
* @param \Base $f3
|
||||
* @throws \Exception
|
||||
*/
|
||||
function deleteMapData(\Base $f3){
|
||||
$pfDB = DB\Database::instance()->getDB('PF');
|
||||
@@ -82,6 +84,7 @@ class MapUpdate {
|
||||
* delete expired EOL connections
|
||||
* >> php index.php "/cron/deleteEolConnections"
|
||||
* @param \Base $f3
|
||||
* @throws \Exception
|
||||
*/
|
||||
function deleteEolConnections(\Base $f3){
|
||||
$eolExpire = (int)$f3->get('PATHFINDER.CACHE.EXPIRE_CONNECTIONS_EOL');
|
||||
@@ -125,6 +128,7 @@ class MapUpdate {
|
||||
* delete expired WH connections after max lifetime for wormholes is reached
|
||||
* >> php index.php "/cron/deleteExpiredConnections"
|
||||
* @param \Base $f3
|
||||
* @throws \Exception
|
||||
*/
|
||||
function deleteExpiredConnections(\Base $f3){
|
||||
$whExpire = (int)$f3->get('PATHFINDER.CACHE.EXPIRE_CONNECTIONS_WH');
|
||||
|
||||
@@ -116,6 +116,7 @@ class Database extends \Prefab {
|
||||
* @param string $password
|
||||
* @param string $alias
|
||||
* @return SQL|null
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
protected function connect($dns, $name, $user, $password, $alias){
|
||||
$db = null;
|
||||
@@ -285,6 +286,7 @@ class Database extends \Prefab {
|
||||
/**
|
||||
* get logger for DB logging
|
||||
* @return \Log
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
static function getLogger(){
|
||||
return LogController::getLogger('ERROR');
|
||||
|
||||
@@ -67,6 +67,7 @@ class Monolog extends \Prefab {
|
||||
* -> this buffered data can be stored/logged somewhere (e.g. DB/file) at any time
|
||||
* -> should be cleared afterwards!
|
||||
* @param Logging\AbstractLog $log
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function push(Logging\AbstractLog $log){
|
||||
// check whether $log should be "grouped" by common handlers
|
||||
|
||||
@@ -24,6 +24,7 @@ class CcpClient extends \Prefab {
|
||||
* get ApiClient instance
|
||||
* @param \Base $f3
|
||||
* @return ApiClient|null
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
protected function getClient(\Base $f3){
|
||||
$client = null;
|
||||
@@ -43,6 +44,7 @@ class CcpClient extends \Prefab {
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
protected function getUserAgent(){
|
||||
$userAgent = '';
|
||||
@@ -68,6 +70,7 @@ class CcpClient extends \Prefab {
|
||||
* @param $name
|
||||
* @param $arguments
|
||||
* @return array|mixed
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
public function __call($name, $arguments){
|
||||
$return = [];
|
||||
|
||||
@@ -208,6 +208,7 @@ class Config extends \Prefab {
|
||||
/**
|
||||
* get SMTP config values
|
||||
* @return \stdClass
|
||||
* @throws Exception\PathfinderException
|
||||
*/
|
||||
static function getSMTPConfig(): \stdClass{
|
||||
$config = new \stdClass();
|
||||
@@ -252,6 +253,7 @@ class Config extends \Prefab {
|
||||
* get email for notifications by hive key
|
||||
* @param $key
|
||||
* @return mixed
|
||||
* @throws Exception\PathfinderException
|
||||
*/
|
||||
static function getNotificationMail($key){
|
||||
return self::getPathfinderData('notification' . ($key ? '.' . $key : ''));
|
||||
@@ -262,6 +264,7 @@ class Config extends \Prefab {
|
||||
* -> read from pathfinder.ini
|
||||
* @param string $mapType
|
||||
* @return mixed
|
||||
* @throws Exception\PathfinderException
|
||||
*/
|
||||
static function getMapsDefaultConfig($mapType = ''){
|
||||
if( $mapConfig = self::getPathfinderData('map' . ($mapType ? '.' . $mapType : '')) ){
|
||||
|
||||
@@ -68,6 +68,7 @@ abstract class AbstractCharacterLog extends AbstractChannelLog{
|
||||
/**
|
||||
* get character thumbnailUrl
|
||||
* @return string
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
protected function getThumbUrl(): string {
|
||||
$url = '';
|
||||
|
||||
@@ -426,6 +426,7 @@ abstract class AbstractLog implements LogInterface {
|
||||
/**
|
||||
* get __construct() parameters for ZMQHandler() call
|
||||
* @return array
|
||||
* @throws \ZMQSocketException
|
||||
*/
|
||||
protected function getHandlerParamsZMQ(): array {
|
||||
$params = [];
|
||||
|
||||
@@ -60,6 +60,7 @@ class LogCollection extends AbstractLog {
|
||||
/**
|
||||
* add a new log object to this collection
|
||||
* @param AbstractLog $log
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function addLog(AbstractLog $log){
|
||||
if(!$this->collection->contains($log)){
|
||||
@@ -113,6 +114,7 @@ class LogCollection extends AbstractLog {
|
||||
|
||||
/**
|
||||
* @param string $tag
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function setTag(string $tag){
|
||||
$currentTag = parent::getTag();
|
||||
@@ -147,6 +149,7 @@ class LogCollection extends AbstractLog {
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function getChannelName() : string{
|
||||
return $this->getPrimaryLog()->getChannelName();
|
||||
@@ -154,6 +157,7 @@ class LogCollection extends AbstractLog {
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function getLevel() : string{
|
||||
return $this->getPrimaryLog()->getLevel();
|
||||
@@ -161,6 +165,7 @@ class LogCollection extends AbstractLog {
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function hasBuffer() : bool{
|
||||
return $this->getPrimaryLog()->hasBuffer();
|
||||
@@ -168,6 +173,7 @@ class LogCollection extends AbstractLog {
|
||||
|
||||
/**
|
||||
* @return array
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function getTempData() : array{
|
||||
return $this->getPrimaryLog()->getTempData();
|
||||
|
||||
@@ -37,6 +37,7 @@ class RallyLog extends AbstractCharacterLog{
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
protected function getThumbUrl() : string{
|
||||
$url = '';
|
||||
|
||||
@@ -179,6 +179,7 @@ abstract class AbstractSlackWebhookHandler extends Handler\AbstractProcessingHan
|
||||
* @param array $attachment
|
||||
* @param array $characterData
|
||||
* @return array
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
protected function setAuthor(array $attachment, array $characterData): array {
|
||||
if( !empty($characterData['id']) && !empty($characterData['name'])){
|
||||
|
||||
@@ -15,6 +15,7 @@ class SlackMapWebhookHandler extends AbstractSlackWebhookHandler {
|
||||
/**
|
||||
* @param array $record
|
||||
* @return array
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
protected function getSlackData(array $record) : array{
|
||||
$postData = parent::getSlackData($record);
|
||||
|
||||
@@ -15,6 +15,7 @@ class SlackRallyWebhookHandler extends AbstractSlackWebhookHandler {
|
||||
/**
|
||||
* @param array $record
|
||||
* @return array
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
protected function getSlackData(array $record) : array{
|
||||
$postData = parent::getSlackData($record);
|
||||
|
||||
@@ -87,9 +87,10 @@ class Socket {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $task
|
||||
* @param string $task
|
||||
* @param string $load
|
||||
* @return bool|string
|
||||
* @throws \ZMQSocketException
|
||||
*/
|
||||
public function sendData(string $task, $load = ''){
|
||||
$response = false;
|
||||
|
||||
@@ -100,6 +100,7 @@ class Web extends \Web {
|
||||
* @param array $additionalOptions
|
||||
* @param int $retryCount request counter for failed call
|
||||
* @return array|FALSE|mixed
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
public function request($url,array $options = null, $additionalOptions = [], $retryCount = 0 ) {
|
||||
$f3 = \Base::instance();
|
||||
|
||||
@@ -52,6 +52,7 @@ abstract class AbstractMapTrackingModel extends BasicModel implements LogModelIn
|
||||
* @param $key
|
||||
* @param $val
|
||||
* @return bool
|
||||
* @throws \Exception\ValidationException
|
||||
*/
|
||||
protected function validate_notDry($key, $val): bool {
|
||||
$valid = true;
|
||||
@@ -92,7 +93,7 @@ abstract class AbstractMapTrackingModel extends BasicModel implements LogModelIn
|
||||
/**
|
||||
* validates all required columns of this class
|
||||
* @return bool
|
||||
* @throws \Exception\ValidationException
|
||||
* @throws \Exception\DatabaseException
|
||||
*/
|
||||
public function isValid(): bool {
|
||||
if($valid = parent::isValid()){
|
||||
|
||||
@@ -57,6 +57,7 @@ class AllianceModel extends BasicModel {
|
||||
/**
|
||||
* get all maps for this alliance
|
||||
* @return array|mixed
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
public function getMaps(){
|
||||
$maps = [];
|
||||
|
||||
@@ -822,6 +822,7 @@ abstract class BasicModel extends \DB\Cortex {
|
||||
* debug log function
|
||||
* @param string $text
|
||||
* @param string $type
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
public static function log($text, $type = 'DEBUG'){
|
||||
Controller\LogController::getLogger($type)->write($text);
|
||||
|
||||
@@ -139,25 +139,25 @@ class CharacterLogModel extends BasicModel {
|
||||
*/
|
||||
public function getData(){
|
||||
|
||||
$logData = (object) [];
|
||||
$logData->system = (object) [];
|
||||
$logData->system->id = (int)$this->systemId;
|
||||
$logData->system->name = $this->systemName;
|
||||
$logData = (object) [];
|
||||
$logData->system = (object) [];
|
||||
$logData->system->id = (int)$this->systemId;
|
||||
$logData->system->name = $this->systemName;
|
||||
|
||||
$logData->ship = (object) [];
|
||||
$logData->ship->typeId = (int)$this->shipTypeId;
|
||||
$logData->ship->typeName = $this->shipTypeName;
|
||||
$logData->ship->id = $this->shipId;
|
||||
$logData->ship->name = $this->shipName;
|
||||
$logData->ship->mass = $this->shipMass;
|
||||
$logData->ship = (object) [];
|
||||
$logData->ship->typeId = (int)$this->shipTypeId;
|
||||
$logData->ship->typeName = $this->shipTypeName;
|
||||
$logData->ship->id = $this->shipId;
|
||||
$logData->ship->name = $this->shipName;
|
||||
$logData->ship->mass = $this->shipMass;
|
||||
|
||||
$logData->station = (object) [];
|
||||
$logData->station->id = (int)$this->stationId;
|
||||
$logData->station->name = $this->stationName;
|
||||
$logData->station = (object) [];
|
||||
$logData->station->id = (int)$this->stationId;
|
||||
$logData->station->name = $this->stationName;
|
||||
|
||||
$logData->structure = (object) [];
|
||||
$logData->structure->id = (int)$this->structureId;
|
||||
$logData->structure->name = $this->structureName;
|
||||
$logData->structure = (object) [];
|
||||
$logData->structure->id = (int)$this->structureId;
|
||||
$logData->structure->name = $this->structureName;
|
||||
|
||||
return $logData;
|
||||
}
|
||||
@@ -166,6 +166,7 @@ class CharacterLogModel extends BasicModel {
|
||||
* setter for systemId
|
||||
* @param int $systemId
|
||||
* @return int
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function set_systemId($systemId){
|
||||
if($systemId > 0){
|
||||
@@ -219,6 +220,7 @@ class CharacterLogModel extends BasicModel {
|
||||
/**
|
||||
* update session data for active character
|
||||
* @param int $systemId
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function updateCharacterSessionLocation(int $systemId){
|
||||
$controller = new Controller();
|
||||
|
||||
@@ -471,6 +471,7 @@ class CharacterModel extends BasicModel {
|
||||
/**
|
||||
* get ESI API "access_token" from OAuth
|
||||
* @return bool|string
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
public function getAccessToken(){
|
||||
$accessToken = false;
|
||||
@@ -541,6 +542,7 @@ class CharacterModel extends BasicModel {
|
||||
* checks whether this character is authorized to log in
|
||||
* -> check corp/ally whitelist config (pathfinder.ini)
|
||||
* @return bool
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
public function isAuthorized(){
|
||||
$authStatus = 'UNKNOWN';
|
||||
@@ -596,6 +598,7 @@ class CharacterModel extends BasicModel {
|
||||
/**
|
||||
* get pathfinder roleId
|
||||
* @return int
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
public function requestRoleId(){
|
||||
$roleId = self::ROLES['MEMBER'];
|
||||
@@ -614,6 +617,7 @@ class CharacterModel extends BasicModel {
|
||||
/**
|
||||
* request all corporation roles granted to this character
|
||||
* @return array
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
protected function requestRoles(){
|
||||
$rolesData = [];
|
||||
@@ -655,6 +659,7 @@ class CharacterModel extends BasicModel {
|
||||
* -> API request for character log data
|
||||
* @param array $additionalOptions (optional) request options for cURL request
|
||||
* @return CharacterModel
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function updateLog($additionalOptions = []){
|
||||
$deleteLog = false;
|
||||
@@ -874,6 +879,7 @@ class CharacterModel extends BasicModel {
|
||||
/**
|
||||
* update character data from CCPs ESI API
|
||||
* @return array (some status messages)
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function updateFromESI(){
|
||||
$status = [];
|
||||
@@ -938,6 +944,7 @@ class CharacterModel extends BasicModel {
|
||||
* get mapModel by id and check if user has access
|
||||
* @param $mapId
|
||||
* @return MapModel|null
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function getMap($mapId){
|
||||
/**
|
||||
@@ -957,6 +964,7 @@ class CharacterModel extends BasicModel {
|
||||
/**
|
||||
* get all accessible map models for this character
|
||||
* @return MapModel[]
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
public function getMaps(){
|
||||
$this->filter(
|
||||
|
||||
@@ -57,6 +57,7 @@ class CharacterStatusModel extends BasicModel {
|
||||
* @param null $table
|
||||
* @param null $fields
|
||||
* @return bool
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function setup($db=null, $table=null, $fields=null){
|
||||
$status = parent::setup($db,$table,$fields);
|
||||
|
||||
84
app/main/model/connectionlogmodel.php
Normal file
84
app/main/model/connectionlogmodel.php
Normal file
@@ -0,0 +1,84 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: exodu
|
||||
* Date: 05.11.2017
|
||||
* Time: 17:51
|
||||
*/
|
||||
|
||||
namespace Model;
|
||||
|
||||
use DB\SQL\Schema;
|
||||
|
||||
class ConnectionLogModel extends BasicModel {
|
||||
|
||||
protected $table = 'connection_log';
|
||||
|
||||
protected $fieldConf = [
|
||||
'active' => [
|
||||
'type' => Schema::DT_BOOL,
|
||||
'nullable' => false,
|
||||
'default' => 1,
|
||||
'index' => true
|
||||
],
|
||||
'connectionId' => [
|
||||
'type' => Schema::DT_INT,
|
||||
'index' => true,
|
||||
'belongs-to-one' => 'Model\ConnectionModel',
|
||||
'constraint' => [
|
||||
[
|
||||
'table' => 'connection',
|
||||
'on-delete' => 'CASCADE'
|
||||
]
|
||||
]
|
||||
],
|
||||
'shipTypeId' => [
|
||||
'type' => Schema::DT_INT,
|
||||
'index' => true
|
||||
],
|
||||
'shipTypeName' => [
|
||||
'type' => Schema::DT_VARCHAR128,
|
||||
'nullable' => false,
|
||||
'default' => ''
|
||||
],
|
||||
'shipMass' => [
|
||||
'type' => Schema::DT_FLOAT,
|
||||
'nullable' => false,
|
||||
'default' => 0
|
||||
],
|
||||
'characterId' => [
|
||||
'type' => Schema::DT_INT,
|
||||
'index' => true
|
||||
],
|
||||
'characterName' => [
|
||||
'type' => Schema::DT_VARCHAR128,
|
||||
'nullable' => false,
|
||||
'default' => ''
|
||||
]
|
||||
];
|
||||
|
||||
/**
|
||||
* get connection log data
|
||||
* @return \stdClass
|
||||
*/
|
||||
public function getData() : \stdClass {
|
||||
$logData = (object) [];
|
||||
$logData->id = $this->id;
|
||||
|
||||
$logData->connection = (object) [];
|
||||
$logData->connection->id = $this->get('connectionId', true);
|
||||
|
||||
$logData->ship = (object) [];
|
||||
$logData->ship->typeId = (int)$this->shipTypeId;
|
||||
$logData->ship->typeName = $this->shipTypeName;
|
||||
$logData->ship->mass = $this->shipMass;
|
||||
|
||||
$logData->created = (object) [];
|
||||
$logData->created->created = strtotime($this->created);
|
||||
$logData->created->character = (object) [];
|
||||
$logData->created->character->id = $this->characterId;
|
||||
$logData->created->character->name = $this->characterName;
|
||||
|
||||
return $logData;
|
||||
}
|
||||
}
|
||||
@@ -74,6 +74,9 @@ class ConnectionModel extends AbstractMapTrackingModel {
|
||||
],
|
||||
'signatures' => [
|
||||
'has-many' => ['Model\SystemSignatureModel', 'connectionId']
|
||||
],
|
||||
'connectionLog' => [
|
||||
'has-many' => ['Model\ConnectionLogModel', 'connectionId']
|
||||
]
|
||||
];
|
||||
|
||||
@@ -101,20 +104,21 @@ class ConnectionModel extends AbstractMapTrackingModel {
|
||||
}
|
||||
|
||||
/**
|
||||
* get connection data as array
|
||||
* get connection data
|
||||
* @param bool $addSignatureData
|
||||
* @param bool $addLogData
|
||||
* @return \stdClass
|
||||
*/
|
||||
public function getData($addSignatureData = false){
|
||||
public function getData($addSignatureData = false, $addLogData = false){
|
||||
$connectionData = (object) [];
|
||||
$connectionData->id = $this->id;
|
||||
$connectionData->source = $this->source->id;
|
||||
$connectionData->target = $this->target->id;
|
||||
$connectionData->scope = $this->scope;
|
||||
$connectionData->type = $this->type;
|
||||
$connectionData->updated = strtotime($this->updated);
|
||||
$connectionData->created = strtotime($this->created);
|
||||
$connectionData->eolUpdated = strtotime($this->eolUpdated);
|
||||
$connectionData->id = $this->id;
|
||||
$connectionData->source = $this->source->id;
|
||||
$connectionData->target = $this->target->id;
|
||||
$connectionData->scope = $this->scope;
|
||||
$connectionData->type = $this->type;
|
||||
$connectionData->updated = strtotime($this->updated);
|
||||
$connectionData->created = strtotime($this->created);
|
||||
$connectionData->eolUpdated = strtotime($this->eolUpdated);
|
||||
|
||||
if($addSignatureData){
|
||||
if( !empty($signaturesData = $this->getSignaturesData()) ){
|
||||
@@ -122,6 +126,12 @@ class ConnectionModel extends AbstractMapTrackingModel {
|
||||
}
|
||||
}
|
||||
|
||||
if($addLogData){
|
||||
if( !empty($logsData = $this->getLogsData()) ){
|
||||
$connectionData->logs = $logsData;
|
||||
}
|
||||
}
|
||||
|
||||
return $connectionData;
|
||||
}
|
||||
|
||||
@@ -193,6 +203,7 @@ class ConnectionModel extends AbstractMapTrackingModel {
|
||||
/**
|
||||
* check whether this model is valid or not
|
||||
* @return bool
|
||||
* @throws \Exception\DatabaseException
|
||||
*/
|
||||
public function isValid(): bool {
|
||||
if($valid = parent::isValid()){
|
||||
@@ -218,6 +229,7 @@ class ConnectionModel extends AbstractMapTrackingModel {
|
||||
* @param ConnectionModel $self
|
||||
* @param $pkeys
|
||||
* @return bool
|
||||
* @throws \Exception\DatabaseException
|
||||
*/
|
||||
public function beforeInsertEvent($self, $pkeys){
|
||||
// check for "default" connection type and add them if missing
|
||||
@@ -269,6 +281,7 @@ class ConnectionModel extends AbstractMapTrackingModel {
|
||||
/**
|
||||
* @param string $action
|
||||
* @return Logging\LogInterface
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
public function newLog($action = ''): Logging\LogInterface{
|
||||
return $this->getMap()->newLog($action)->setTempData($this->getLogObjectData());
|
||||
@@ -330,11 +343,29 @@ class ConnectionModel extends AbstractMapTrackingModel {
|
||||
return $signatures;
|
||||
}
|
||||
|
||||
/**
|
||||
* get all jump logs that are connected with this connection
|
||||
* @return array|mixed
|
||||
*/
|
||||
public function getLogs(){
|
||||
$logs = [];
|
||||
$this->filter('connectionLog', [
|
||||
'active = :active',
|
||||
':active' => 1
|
||||
]);
|
||||
|
||||
if($this->connectionLog){
|
||||
$logs = $this->connectionLog;
|
||||
}
|
||||
|
||||
return $logs;
|
||||
}
|
||||
|
||||
/**
|
||||
* get all signature data linked to this connection
|
||||
* @return array
|
||||
*/
|
||||
public function getSignaturesData(){
|
||||
public function getSignaturesData() : array {
|
||||
$signaturesData = [];
|
||||
$signatures = $this->getSignatures();
|
||||
|
||||
@@ -345,6 +376,36 @@ class ConnectionModel extends AbstractMapTrackingModel {
|
||||
return $signaturesData;
|
||||
}
|
||||
|
||||
/**
|
||||
* get all connection log data linked to this connection
|
||||
* @return array
|
||||
*/
|
||||
public function getLogsData() : array{
|
||||
$logsData = [];
|
||||
$logs = $this->getLogs();
|
||||
|
||||
foreach($logs as $log){
|
||||
$logsData[] = $log->getData();
|
||||
}
|
||||
|
||||
return $logsData;
|
||||
}
|
||||
|
||||
public function logMass(CharacterLogModel $characterLog){
|
||||
if( !$characterLog->dry() ){
|
||||
$log = $this->rel('connectionLog');
|
||||
$log->shipTypeId = $characterLog->shipTypeId;
|
||||
$log->shipTypeName = $characterLog->shipTypeName;
|
||||
$log->shipMass = $characterLog->shipMass;
|
||||
$log->characterId = $characterLog->characterId->_id;
|
||||
$log->characterName = $characterLog->characterId->name;
|
||||
$log->connectionId = $this;
|
||||
$log->save();
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* overwrites parent
|
||||
* @param null $db
|
||||
|
||||
@@ -66,6 +66,7 @@ class ConnectionScopeModel extends BasicModel{
|
||||
* @param null $table
|
||||
* @param null $fields
|
||||
* @return bool
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function setup($db=null, $table=null, $fields=null){
|
||||
$status = parent::setup($db,$table,$fields);
|
||||
|
||||
@@ -128,6 +128,7 @@ class CorporationModel extends BasicModel {
|
||||
/**
|
||||
* get all maps for this corporation
|
||||
* @return MapModel[]
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
public function getMaps(){
|
||||
$maps = [];
|
||||
|
||||
@@ -181,6 +181,8 @@ class MapModel extends AbstractMapTrackingModel {
|
||||
* get map data
|
||||
* -> this includes system and connection data as well!
|
||||
* @return \stdClass
|
||||
* @throws PathfinderException
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function getData(){
|
||||
// check if there is cached data
|
||||
@@ -294,6 +296,7 @@ class MapModel extends AbstractMapTrackingModel {
|
||||
* @param string $key
|
||||
* @param string $val
|
||||
* @return bool
|
||||
* @throws \Exception\ValidationException
|
||||
*/
|
||||
protected function validate_name(string $key, string $val): bool {
|
||||
$valid = true;
|
||||
@@ -309,6 +312,7 @@ class MapModel extends AbstractMapTrackingModel {
|
||||
* @param string $key
|
||||
* @param string $val
|
||||
* @return bool
|
||||
* @throws \Exception\ValidationException
|
||||
*/
|
||||
protected function validate_slackWebHookURL(string $key, string $val): bool {
|
||||
$valid = true;
|
||||
@@ -401,6 +405,7 @@ class MapModel extends AbstractMapTrackingModel {
|
||||
* -> check for "inactive" systems on this map first!
|
||||
* @param int $systemId
|
||||
* @return SystemModel
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function getNewSystem($systemId){
|
||||
// check for "inactive" system
|
||||
@@ -510,6 +515,7 @@ class MapModel extends AbstractMapTrackingModel {
|
||||
/**
|
||||
* get all system data for all systems in this map
|
||||
* @return \stdClass[]
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function getSystemData(){
|
||||
$systemData = [];
|
||||
@@ -545,10 +551,11 @@ class MapModel extends AbstractMapTrackingModel {
|
||||
|
||||
/**
|
||||
* get all connections in this map
|
||||
* @param null $connectionIds
|
||||
* @param string $scope
|
||||
* @return ConnectionModel[]
|
||||
*/
|
||||
public function getConnections($scope = ''){
|
||||
public function getConnections($connectionIds = null, $scope = ''){
|
||||
$connections = [];
|
||||
|
||||
$query = [
|
||||
@@ -561,6 +568,11 @@ class MapModel extends AbstractMapTrackingModel {
|
||||
$query[':scope'] = $scope;
|
||||
}
|
||||
|
||||
if(!empty($connectionIds)){
|
||||
$query[0] .= ' AND id IN (?)';
|
||||
$query[] = $connectionIds;
|
||||
}
|
||||
|
||||
$this->filter('connections', $query);
|
||||
|
||||
if($this->connections){
|
||||
@@ -591,6 +603,7 @@ class MapModel extends AbstractMapTrackingModel {
|
||||
/**
|
||||
* set map access for an object (character, corporation or alliance)
|
||||
* @param $obj
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function setAccess($obj){
|
||||
|
||||
@@ -689,6 +702,7 @@ class MapModel extends AbstractMapTrackingModel {
|
||||
* checks whether a character has access to this map or not
|
||||
* @param CharacterModel $characterModel
|
||||
* @return bool
|
||||
* @throws PathfinderException
|
||||
*/
|
||||
public function hasAccess(CharacterModel $characterModel){
|
||||
$hasAccess = false;
|
||||
@@ -834,6 +848,7 @@ class MapModel extends AbstractMapTrackingModel {
|
||||
/**
|
||||
* @param string $action
|
||||
* @return Logging\LogInterface
|
||||
* @throws PathfinderException
|
||||
*/
|
||||
public function newLog($action = ''): Logging\LogInterface{
|
||||
$logChannelData = $this->getLogChannelData();
|
||||
@@ -901,6 +916,7 @@ class MapModel extends AbstractMapTrackingModel {
|
||||
/**
|
||||
* check if "activity logging" is enabled for this map type
|
||||
* @return bool
|
||||
* @throws PathfinderException
|
||||
*/
|
||||
public function isActivityLogEnabled(): bool {
|
||||
return $this->logActivity && (bool) Config::getMapsDefaultConfig($this->typeId->name)['log_activity_enabled'];
|
||||
@@ -909,6 +925,7 @@ class MapModel extends AbstractMapTrackingModel {
|
||||
/**
|
||||
* check if "history logging" is enabled for this map type
|
||||
* @return bool
|
||||
* @throws PathfinderException
|
||||
*/
|
||||
public function isHistoryLogEnabled(): bool {
|
||||
return $this->logHistory && (bool) Config::getMapsDefaultConfig($this->typeId->name)['log_history_enabled'];
|
||||
@@ -946,6 +963,7 @@ class MapModel extends AbstractMapTrackingModel {
|
||||
* check if "E-Mail" Log is enabled for this map
|
||||
* @param string $type
|
||||
* @return bool
|
||||
* @throws PathfinderException
|
||||
*/
|
||||
public function isMailSendEnabled(string $type): bool{
|
||||
$enabled = false;
|
||||
@@ -1005,6 +1023,7 @@ class MapModel extends AbstractMapTrackingModel {
|
||||
* @param string $type
|
||||
* @param bool $addJson
|
||||
* @return \stdClass
|
||||
* @throws PathfinderException
|
||||
*/
|
||||
public function getSMTPConfig(string $type, bool $addJson = true): \stdClass{
|
||||
$config = Config::getSMTPConfig();
|
||||
@@ -1141,6 +1160,8 @@ class MapModel extends AbstractMapTrackingModel {
|
||||
* get all active characters (with active log)
|
||||
* grouped by systems
|
||||
* @return \stdClass
|
||||
* @throws PathfinderException
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function getUserData(){
|
||||
|
||||
|
||||
@@ -59,6 +59,7 @@ class MapScopeModel extends BasicModel{
|
||||
* @param null $table
|
||||
* @param null $fields
|
||||
* @return bool
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function setup($db=null, $table=null, $fields=null){
|
||||
$status = parent::setup($db,$table,$fields);
|
||||
|
||||
@@ -87,6 +87,7 @@ class MapTypeModel extends BasicModel{
|
||||
* @param null $table
|
||||
* @param null $fields
|
||||
* @return bool
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function setup($db=null, $table=null, $fields=null){
|
||||
$status = parent::setup($db,$table,$fields);
|
||||
|
||||
@@ -410,6 +410,7 @@ class SystemModel extends AbstractMapTrackingModel {
|
||||
/**
|
||||
* @param string $action
|
||||
* @return Logging\LogInterface
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
public function newLog($action = ''): Logging\LogInterface{
|
||||
return $this->getMap()->newLog($action)->setTempData($this->getLogObjectData());
|
||||
@@ -567,6 +568,7 @@ class SystemModel extends AbstractMapTrackingModel {
|
||||
* -> send to an Email
|
||||
* @param array $rallyData
|
||||
* @param CharacterModel $characterModel
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
public function sendRallyPoke(array $rallyData, CharacterModel $characterModel){
|
||||
// rally log needs at least one handler to be valid
|
||||
|
||||
@@ -169,6 +169,7 @@ class SystemSignatureModel extends AbstractMapTrackingModel {
|
||||
* @param string $key
|
||||
* @param string $val
|
||||
* @return bool
|
||||
* @throws \Exception\ValidationException
|
||||
*/
|
||||
protected function validate_name(string $key, string $val): bool {
|
||||
$valid = true;
|
||||
@@ -182,6 +183,7 @@ class SystemSignatureModel extends AbstractMapTrackingModel {
|
||||
/**
|
||||
* @param string $action
|
||||
* @return Logging\LogInterface
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
public function newLog($action = ''): Logging\LogInterface{
|
||||
return $this->getMap()->newLog($action)->setTempData($this->getLogObjectData());
|
||||
|
||||
@@ -83,6 +83,7 @@ class SystemStatusModel extends BasicModel {
|
||||
* @param null $table
|
||||
* @param null $fields
|
||||
* @return bool
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function setup($db=null, $table=null, $fields=null){
|
||||
$status = parent::setup($db,$table,$fields);
|
||||
|
||||
@@ -45,6 +45,7 @@ class SystemTypeModel extends BasicModel {
|
||||
* @param null $table
|
||||
* @param null $fields
|
||||
* @return bool
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function setup($db=null, $table=null, $fields=null){
|
||||
$status = parent::setup($db,$table,$fields);
|
||||
|
||||
@@ -54,4 +54,13 @@ class ConstellationModel extends BasicUniverseModel {
|
||||
]
|
||||
];
|
||||
|
||||
/**
|
||||
* @param int $id
|
||||
* @param string $accessToken
|
||||
* @param array $additionalOptions
|
||||
*/
|
||||
protected function loadData(int $id, string $accessToken = '', array $additionalOptions = []){
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -33,4 +33,13 @@ class RegionModel extends BasicUniverseModel {
|
||||
'has-many' => ['Model\Universe\ConstellationModel', 'regionId']
|
||||
],
|
||||
];
|
||||
|
||||
/**
|
||||
* @param int $id
|
||||
* @param string $accessToken
|
||||
* @param array $additionalOptions
|
||||
*/
|
||||
protected function loadData(int $id, string $accessToken = '', array $additionalOptions = []){
|
||||
|
||||
}
|
||||
}
|
||||
@@ -49,6 +49,7 @@ class UserModel extends BasicModel {
|
||||
* -> ! caution ! this function returns sensitive data! (e.g. email,..)
|
||||
* -> user getSimpleData() for faster performance and public user data
|
||||
* @return \stdClass
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getData(){
|
||||
|
||||
@@ -93,6 +94,7 @@ class UserModel extends BasicModel {
|
||||
* @param UserModel $self
|
||||
* @param $pkeys
|
||||
* @return bool
|
||||
* @throws Exception\PathfinderException
|
||||
* @throws Exception\RegistrationException
|
||||
*/
|
||||
public function beforeInsertEvent($self, $pkeys){
|
||||
@@ -135,6 +137,7 @@ class UserModel extends BasicModel {
|
||||
/**
|
||||
* checks whether user has a valid email address and pathfinder has a valid SMTP config
|
||||
* @return bool
|
||||
* @throws Exception\PathfinderException
|
||||
*/
|
||||
protected function isMailSendEnabled() : bool{
|
||||
return Config::isValidSMTPConfig($this->getSMTPConfig());
|
||||
@@ -143,6 +146,7 @@ class UserModel extends BasicModel {
|
||||
/**
|
||||
* get SMTP config for this user
|
||||
* @return \stdClass
|
||||
* @throws Exception\PathfinderException
|
||||
*/
|
||||
protected function getSMTPConfig() : \stdClass{
|
||||
$config = Config::getSMTPConfig();
|
||||
@@ -155,6 +159,7 @@ class UserModel extends BasicModel {
|
||||
* @param string $key
|
||||
* @param string $val
|
||||
* @return bool
|
||||
* @throws Exception\ValidationException
|
||||
*/
|
||||
protected function validate_name(string $key, string $val): bool {
|
||||
$valid = true;
|
||||
@@ -173,6 +178,7 @@ class UserModel extends BasicModel {
|
||||
* @param string $key
|
||||
* @param string $val
|
||||
* @return bool
|
||||
* @throws Exception\ValidationException
|
||||
*/
|
||||
protected function validate_email(string $key, string $val): bool {
|
||||
$valid = true;
|
||||
@@ -207,6 +213,7 @@ class UserModel extends BasicModel {
|
||||
* @param int $characterId
|
||||
* @param bool $objectCheck
|
||||
* @return array
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getSessionCharacterData($characterId = 0, $objectCheck = true){
|
||||
$data = [];
|
||||
@@ -289,6 +296,7 @@ class UserModel extends BasicModel {
|
||||
* -> EITHER - the current active one for the current user
|
||||
* -> OR - get the first active one
|
||||
* @return null|CharacterModel
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getActiveCharacter(){
|
||||
$activeCharacter = null;
|
||||
|
||||
@@ -59,47 +59,27 @@ class WormholeModel extends BasicModel {
|
||||
*/
|
||||
protected $addStaticFields = false;
|
||||
|
||||
/**
|
||||
* format mass values
|
||||
* - no decimal separator
|
||||
* - char '.' for thousands separator
|
||||
* @param $value
|
||||
* @return string
|
||||
*/
|
||||
static function formatMassValue($value){
|
||||
return number_format( $value, 0, '', '.' );
|
||||
}
|
||||
|
||||
/**
|
||||
* get wormhole data as object
|
||||
* @return object
|
||||
*/
|
||||
public function getData(){
|
||||
|
||||
$systemStaticData = (object) [];
|
||||
$systemStaticData->name = $this->name;
|
||||
$systemStaticData->security = $this->security;
|
||||
|
||||
// total (max) available wormhole mass
|
||||
$systemStaticData->massTotal = (object) [];
|
||||
$systemStaticData->massTotal->value = $this->massTotal;
|
||||
$systemStaticData->massTotal->format = self::formatMassValue($this->massTotal) . ' Kg';
|
||||
$systemStaticData->massTotal = $this->massTotal;
|
||||
|
||||
// individual jump mass (max) per jump
|
||||
$systemStaticData->massIndividual = (object) [];
|
||||
$systemStaticData->massIndividual->value = $this->massIndividual;
|
||||
$systemStaticData->massIndividual->format = self::formatMassValue($this->massIndividual) . ' Kg';
|
||||
$systemStaticData->massIndividual = $this->massIndividual;
|
||||
|
||||
// lifetime (max) for this wormhole
|
||||
$systemStaticData->maxStableTime = (object) [];
|
||||
$systemStaticData->maxStableTime->value = $this->maxStableTime;
|
||||
$systemStaticData->maxStableTime->format = $this->maxStableTime . ' h';
|
||||
$systemStaticData->maxStableTime = $this->maxStableTime;
|
||||
|
||||
// mass regeneration value per day
|
||||
if($this->massRegeneration > 0){
|
||||
$systemStaticData->massRegeneration = (object) [];
|
||||
$systemStaticData->massRegeneration->value = $this->massRegeneration;
|
||||
$systemStaticData->massRegeneration->format = self::formatMassValue($this->massRegeneration) . ' Kg/day';
|
||||
$systemStaticData->massRegeneration = $this->massRegeneration;
|
||||
}
|
||||
|
||||
return $systemStaticData;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
[PATHFINDER]
|
||||
NAME = Pathfinder
|
||||
; installed version (used for CSS/JS cache busting)
|
||||
VERSION = v1.3.0
|
||||
VERSION = v1.3.1
|
||||
; contact information [optional]
|
||||
CONTACT = https://github.com/exodus4d
|
||||
; public contact email [optional]
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
}],
|
||||
"require": {
|
||||
"php-64bit": ">=7.0",
|
||||
"ext-curl": ">=7.0",
|
||||
"ext-curl": "*",
|
||||
"ext-zmq": ">=1.1.3",
|
||||
"react/zmq": "0.3.*",
|
||||
"monolog/monolog": "1.*",
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
}],
|
||||
"require": {
|
||||
"php-64bit": ">=7.0",
|
||||
"ext-curl": ">=7.0",
|
||||
"ext-curl": "*",
|
||||
"ext-zmq": ">=1.1.3",
|
||||
"react/zmq": "0.3.*",
|
||||
"monolog/monolog": "1.*",
|
||||
|
||||
135
gulpfile.js
135
gulpfile.js
@@ -177,12 +177,14 @@ let CONF = {
|
||||
JS: {
|
||||
UGLIFY: options.hasOwnProperty('jsUglify') ? options.jsUglify === 'true': undefined,
|
||||
SOURCEMAPS: options.hasOwnProperty('jsSourcemaps') ? options.jsSourcemaps === 'true': undefined,
|
||||
GZIP: options.hasOwnProperty('jsGzip') ? options.jsGzip === 'true': undefined,
|
||||
BROTLI: options.hasOwnProperty('jsBrotli') ? options.jsBrotli === 'true': undefined
|
||||
},
|
||||
CSS: {
|
||||
SOURCEMAPS: options.hasOwnProperty('cssSourcemaps') ? options.cssSourcemaps === 'true': undefined,
|
||||
GZIP: options.hasOwnProperty('cssGzip') ? options.cssGzip === 'true': undefined,
|
||||
BROTLI: options.hasOwnProperty('cssBrotli') ? options.cssBrotli === 'true': undefined
|
||||
},
|
||||
GZIP: options.hasOwnProperty('gzip') ? options.gzip === 'true': undefined,
|
||||
BROTLI: options.hasOwnProperty('brotli') ? options.brotli === 'true': undefined,
|
||||
DEBUG: false
|
||||
};
|
||||
|
||||
@@ -271,18 +273,21 @@ let printHelp = () => {
|
||||
${chalk.cyan('tasks:')}
|
||||
${chalk.gray('help')} This view
|
||||
${chalk.gray('default')} Development environment. Working with row src files and file watcher, default:
|
||||
${chalk.gray('')} ${chalk.gray('--jsUglify=false --jsSourcemaps=false --cssSourcemaps=false --gzip=false --brotli=false')}
|
||||
${chalk.gray('')} ${chalk.gray('--jsUglify=false --jsSourcemaps=false --cssSourcemaps=false --jsGzip=false --cssGzip=false --jsBrotli=false --cssBrotli=false')}
|
||||
${chalk.gray('production')} Production build. Concat and uglify static resources, default:
|
||||
${chalk.gray('')} ${chalk.gray('--jsUglify=true --jsSourcemaps=true --cssSourcemaps=true --gzip=true --brotli=true')}
|
||||
${chalk.gray('')} ${chalk.gray('--jsUglify=true --jsSourcemaps=true --cssSourcemaps=true --jsGzip=true --cssGzip=true --jsBrotli=true --cssBrotli=true')}
|
||||
|
||||
${chalk.cyan('options:')}
|
||||
${chalk.gray('--tag')} Set build version. ${chalk.gray('default: --tag="v1.2.4" -> dest path: public/js/v1.2.4')}
|
||||
${chalk.gray('--jsUglify')} Set js uglification. ${chalk.gray('(true || false)')}
|
||||
${chalk.gray('--jsSourcemaps')} Set js sourcemaps generation. ${chalk.gray('(true || false)')}
|
||||
${chalk.gray('--cssSourcemaps')} Set CSS sourcemaps generation. ${chalk.gray('(true || false)')}
|
||||
${chalk.gray('--gzip')} Set "gzip" compression mode. ${chalk.gray('(true || false)')}
|
||||
${chalk.gray('--brotli')} Set "brotli" compression mode. ${chalk.gray('(true || false)')}
|
||||
${chalk.gray('--debug')} Set debug mode (more output). ${chalk.gray('(true || false)')}
|
||||
${chalk.gray('--tag')} Set build version. ${chalk.gray('default: --tag="v1.2.4" -> dest path: public/js/v1.2.4')}
|
||||
${chalk.gray('--jsUglify')} Set js uglification. ${chalk.gray('(true || false)')}
|
||||
${chalk.gray('--jsSourcemaps')} Set js sourcemaps generation. ${chalk.gray('(true || false)')}
|
||||
${chalk.gray('--jsGzip')} Set js "gzip" compression mode. ${chalk.gray('(true || false)')}
|
||||
${chalk.gray('--jsBrotli')} Set js "brotli" compression mode. ${chalk.gray('(true || false)')}
|
||||
|
||||
${chalk.gray('--cssSourcemaps')} Set CSS sourcemaps generation. ${chalk.gray('(true || false)')}
|
||||
${chalk.gray('--cssGzip')} Set CSS "gzip" compression mode. ${chalk.gray('(true || false)')}
|
||||
${chalk.gray('--cssBrotli')} Set CSS "brotli" compression mode. ${chalk.gray('(true || false)')}
|
||||
${chalk.gray('--debug')} Set debug mode (more output). ${chalk.gray('(true || false)')}
|
||||
`)
|
||||
.log(chalk.cyan('='.repeat(cliBoxLength)))
|
||||
.log('');
|
||||
@@ -295,8 +300,8 @@ let printJsSummary = () => {
|
||||
let tableHead = trackTable.cols;
|
||||
let byteCols = [1,3,6,9,12];
|
||||
let percentCols = [2, 5, 8, 10];
|
||||
let sortCol = (CONF.BROTLI || CONF.GZIP || CONF.JS.UGLIFY) ? 10 : CONF.JS.SOURCEMAPS ? 3 : 1;
|
||||
let refAllCol = CONF.BROTLI ? 9 : CONF.GZIP ? 6 : CONF.JS.UGLIFY ? 3 : CONF.JS.SOURCEMAPS ? 3 : 1;
|
||||
let sortCol = (CONF.JS.BROTLI || CONF.CSS.BROTLI || CONF.JS.GZIP || CONF.CSS.GZIP || CONF.JS.UGLIFY) ? 10 : CONF.JS.SOURCEMAPS ? 3 : 1;
|
||||
let refAllCol = (CONF.JS.BROTLI || CONF.CSS.BROTLI) ? 9 : (CONF.JS.GZIP || CONF.CSS.GZIP) ? 6 : CONF.JS.UGLIFY ? 3 : CONF.JS.SOURCEMAPS ? 3 : 1;
|
||||
let highLightSections = {src_percent: [], gzip_percent: [], brotli_percent: [], all_percent: []};
|
||||
let highLightRow = {
|
||||
success: JSON.parse(JSON.stringify(highLightSections)),
|
||||
@@ -446,7 +451,7 @@ let printJsSummary = () => {
|
||||
table.removeColumn(12);
|
||||
table.removeColumn(11);
|
||||
|
||||
if(!CONF.BROTLI && !CONF.GZIP){
|
||||
if(!CONF.JS.BROTLI && !CONF.CSS.BROTLI && !CONF.JS.GZIP && !CONF.CSS.GZIP){
|
||||
table.removeColumn(10);
|
||||
|
||||
table.removeColumn(9);
|
||||
@@ -559,16 +564,31 @@ gulp.task('task:diffJS', () => {
|
||||
.pipe(gulp.dest(PATH.JS.DIST_BUILD, {overwrite: false}));
|
||||
});
|
||||
|
||||
gulp.task('task:gzipAssets', () => {
|
||||
let filterGzip = filter(file => CONF.GZIP);
|
||||
let fileExt = ['js', 'css'];
|
||||
let srcModules = [
|
||||
PATH.ASSETS.DIST +'/**/*.{' + fileExt.join(',') + '}',
|
||||
'!' + PATH.ASSETS.DIST + '/js/' + CONF.TAG + '{,/**/*}'
|
||||
];
|
||||
/**
|
||||
* get assets filter options e.g. for gZip or Brotli assets
|
||||
* @param compression
|
||||
* @param fileExt
|
||||
* @returns {{srcModules: *[], fileFilter}}
|
||||
*/
|
||||
let getAssetFilterOptions = (compression, fileExt) => {
|
||||
return {
|
||||
srcModules: [
|
||||
PATH.ASSETS.DIST +'/**/*.' + fileExt,
|
||||
'!' + PATH.ASSETS.DIST + '/js/' + CONF.TAG + '{,/**/*}'
|
||||
],
|
||||
fileFilter: filter(file => CONF[fileExt.toUpperCase()][compression.toUpperCase()])
|
||||
};
|
||||
};
|
||||
|
||||
return gulp.src(srcModules, {base: 'public', since: gulp.lastRun('task:gzipAssets')})
|
||||
.pipe(filterGzip)
|
||||
/**
|
||||
* build gZip or Brotli assets
|
||||
* @param config
|
||||
* @param taskName
|
||||
* @returns {JQuery.PromiseBase<never, never, never, never, never, never, never, never, never, never, never, never>}
|
||||
*/
|
||||
let gzipAssets = (config, taskName) => {
|
||||
return gulp.src(config.srcModules, {base: 'public', since: gulp.lastRun(taskName)})
|
||||
.pipe(config.fileFilter)
|
||||
.pipe(debug({title: 'Gzip asses dest: ', showFiles: false}))
|
||||
.pipe(bytediff.start())
|
||||
.pipe(gzip(gZipOptions))
|
||||
@@ -581,18 +601,17 @@ gulp.task('task:gzipAssets', () => {
|
||||
}
|
||||
}))
|
||||
.pipe(gulp.dest(PATH.ASSETS.DIST));
|
||||
});
|
||||
};
|
||||
|
||||
gulp.task('task:brotliAssets', () => {
|
||||
let filterBrotli = filter(file => CONF.BROTLI);
|
||||
let fileExt = ['js', 'css'];
|
||||
let srcModules = [
|
||||
PATH.ASSETS.DIST +'/**/*.{' + fileExt.join(',') + '}',
|
||||
'!' + PATH.ASSETS.DIST + '/js/' + CONF.TAG + '{,/**/*}'
|
||||
];
|
||||
|
||||
return gulp.src(srcModules, {base: 'public', since: gulp.lastRun('task:brotliAssets')})
|
||||
.pipe(filterBrotli)
|
||||
/**
|
||||
* build Brotli or Brotli assets
|
||||
* @param config
|
||||
* @param taskName
|
||||
* @returns {JQuery.PromiseBase<never, never, never, never, never, never, never, never, never, never, never, never>}
|
||||
*/
|
||||
let brotliAssets = (config, taskName) => {
|
||||
return gulp.src(config.srcModules, {base: 'public', since: gulp.lastRun(taskName)})
|
||||
.pipe(config.fileFilter)
|
||||
.pipe(debug({title: 'Brotli asses dest: ', showFiles: false}))
|
||||
.pipe(bytediff.start())
|
||||
.pipe(brotli.compress(brotliOptions))
|
||||
@@ -605,6 +624,22 @@ gulp.task('task:brotliAssets', () => {
|
||||
}
|
||||
}))
|
||||
.pipe(gulp.dest(PATH.ASSETS.DIST));
|
||||
};
|
||||
|
||||
gulp.task('task:gzipJsAssets', () => {
|
||||
return gzipAssets(getAssetFilterOptions('gzip', 'js'), 'task:gzipJsAssets');
|
||||
});
|
||||
|
||||
gulp.task('task:gzipCssAssets', () => {
|
||||
return gzipAssets(getAssetFilterOptions('gzip', 'css'), 'task:gzipCssAssets');
|
||||
});
|
||||
|
||||
gulp.task('task:brotliJsAssets', () => {
|
||||
return brotliAssets(getAssetFilterOptions('brotli', 'js'), 'task:brotliJsAssets');
|
||||
});
|
||||
|
||||
gulp.task('task:brotliCssAssets', () => {
|
||||
return brotliAssets(getAssetFilterOptions('brotli', 'css'), 'task:brotliCssAssets');
|
||||
});
|
||||
|
||||
/**
|
||||
@@ -714,13 +749,15 @@ gulp.task('task:configDevelop',
|
||||
let CONF_DEVELOP = {
|
||||
JS: {
|
||||
UGLIFY: false,
|
||||
SOURCEMAPS: false
|
||||
SOURCEMAPS: false,
|
||||
GZIP: false,
|
||||
BROTLI: false
|
||||
},
|
||||
CSS: {
|
||||
SOURCEMAPS: false
|
||||
},
|
||||
GZIP: false,
|
||||
BROTLI: false
|
||||
SOURCEMAPS: false,
|
||||
GZIP: false,
|
||||
BROTLI: false
|
||||
}
|
||||
};
|
||||
|
||||
CONF = mergeConf(CONF, CONF_DEVELOP);
|
||||
@@ -739,13 +776,15 @@ gulp.task('task:configProduction',
|
||||
let CONF_PRODUCTION = {
|
||||
JS: {
|
||||
UGLIFY: true,
|
||||
SOURCEMAPS: true
|
||||
SOURCEMAPS: true,
|
||||
GZIP: true,
|
||||
BROTLI: true
|
||||
},
|
||||
CSS: {
|
||||
SOURCEMAPS: true
|
||||
},
|
||||
GZIP: true,
|
||||
BROTLI: true
|
||||
SOURCEMAPS: true,
|
||||
GZIP: true,
|
||||
BROTLI: true
|
||||
}
|
||||
};
|
||||
|
||||
CONF = mergeConf(CONF, CONF_PRODUCTION);
|
||||
@@ -760,8 +799,8 @@ gulp.task('task:configProduction',
|
||||
* updates JS destination move to (final) dir
|
||||
*/
|
||||
gulp.task('task:updateJsDest', gulp.series(
|
||||
'task:gzipAssets',
|
||||
'task:brotliAssets',
|
||||
'task:gzipJsAssets',
|
||||
'task:brotliJsAssets',
|
||||
'task:renameJsDest',
|
||||
'task:printJsSummary',
|
||||
'task:cleanJsBuild'
|
||||
@@ -809,8 +848,8 @@ gulp.task(
|
||||
gulp.series(
|
||||
'task:buildCss',
|
||||
// 'task:cleanCss',
|
||||
'task:gzipAssets',
|
||||
'task:brotliAssets',
|
||||
'task:gzipCssAssets',
|
||||
'task:brotliCssAssets',
|
||||
'task:printJsSummary'
|
||||
)
|
||||
);
|
||||
|
||||
12
js/app.js
12
js/app.js
@@ -1,3 +1,5 @@
|
||||
'use strict';
|
||||
|
||||
// main script path
|
||||
var mainScriptPath = document.body.getAttribute('data-script');
|
||||
|
||||
@@ -40,7 +42,7 @@ requirejs.config({
|
||||
raphael: 'lib/raphael-min', // v2.1.2 Raphaël - required for morris (dependency)
|
||||
bootbox: 'lib/bootbox.min', // v4.4.0 Bootbox.js - custom dialogs - http://bootboxjs.com
|
||||
easyPieChart: 'lib/jquery.easypiechart.min', // v2.1.6 Easy Pie Chart - HTML 5 pie charts - http://rendro.github.io/easy-pie-chart
|
||||
peityInlineChart: 'lib/jquery.peity.min', // v3.2.0 Inline Chart - http://benpickles.github.io/peity/
|
||||
peityInlineChart: 'lib/jquery.peity.min', // v3.2.1 Inline Chart - http://benpickles.github.io/peity/
|
||||
dragToSelect: 'lib/jquery.dragToSelect', // v1.1 Drag to Select - http://andreaslagerkvist.com/jquery/drag-to-select
|
||||
hoverIntent: 'lib/jquery.hoverIntent.minified', // v1.8.0 Hover intention - http://cherne.net/brian/resources/jquery.hoverIntent.html
|
||||
fullScreen: 'lib/jquery.fullscreen.min', // v0.6.0 Full screen mode - https://github.com/private-face/jquery.fullscreen
|
||||
@@ -51,8 +53,9 @@ requirejs.config({
|
||||
blueImpGalleryHelper: 'lib/blueimp-helper', // helper function for Blue Imp Gallery
|
||||
blueImpGalleryBootstrap: 'lib/bootstrap-image-gallery', // v3.4.2 Bootstrap extension for Blue Imp Gallery - https://blueimp.github.io/Bootstrap-Image-Gallery
|
||||
bootstrapConfirmation: 'lib/bootstrap-confirmation', // v1.0.5 Bootstrap extension for inline confirm dialog - https://github.com/tavicu/bs-confirmation
|
||||
bootstrapToggle: 'lib/bootstrap2-toggle.min', // v2.2.0 Bootstrap Toggle (Checkbox) - http://www.bootstraptoggle.com
|
||||
bootstrapToggle: 'lib/bootstrap-toggle.min', // v2.2.0 Bootstrap Toggle (Checkbox) - http://www.bootstraptoggle.com
|
||||
lazyload: 'lib/jquery.lazyload.min', // v1.9.5 LazyLoader images - http://www.appelsiini.net/projects/lazyload
|
||||
sortable: 'lib/sortable.min', // v1.6.0 Sortable - drag&drop reorder - https://github.com/rubaxa/Sortable
|
||||
|
||||
// header animation
|
||||
easePack: 'lib/EasePack.min',
|
||||
@@ -126,7 +129,10 @@ requirejs.config({
|
||||
},
|
||||
morris: {
|
||||
deps: ['jquery', 'raphael'],
|
||||
exports: 'Morris'
|
||||
exports: 'Morris',
|
||||
init: function ($, Raphael) {
|
||||
window.Raphael = Raphael;
|
||||
}
|
||||
},
|
||||
pnotify: {
|
||||
deps : ['jquery']
|
||||
|
||||
@@ -14,49 +14,77 @@ define([
|
||||
* update element with time information
|
||||
* @param element
|
||||
* @param tempDate
|
||||
* @param round
|
||||
*/
|
||||
let updateDateDiff = function(element, tempDate){
|
||||
let updateDateDiff = function(element, tempDate, round){
|
||||
let diff = Util.getTimeDiffParts(tempDate, new Date());
|
||||
let days = diff.days;
|
||||
let hrs = diff.hours;
|
||||
let min = diff.min;
|
||||
let leftSec = diff.sec;
|
||||
let value = [];
|
||||
let parts = [];
|
||||
|
||||
if(
|
||||
days > 0 ||
|
||||
value.length > 0
|
||||
round === 'd' &&
|
||||
days >= 1
|
||||
){
|
||||
value.push('<span class="' + config.counterDigitLargeClass + '">' + days + 'd' + '</span>');
|
||||
}
|
||||
if(
|
||||
hrs > 0 ||
|
||||
value.length > 0
|
||||
){
|
||||
value.push('<span class="' + config.counterDigitSmallClass + '">' + hrs + 'h' + '</span>');
|
||||
}
|
||||
if(
|
||||
min > 0 ||
|
||||
value.length > 0
|
||||
){
|
||||
value.push('<span class="' + config.counterDigitSmallClass + '">' + min + 'm' + '</span>');
|
||||
parts.push('<span class="' + config.counterDigitLargeClass + '">' + '> 1d' + '</span>');
|
||||
}else{
|
||||
if(
|
||||
days > 0 ||
|
||||
parts.length > 0
|
||||
){
|
||||
parts.push('<span class="' + config.counterDigitLargeClass + '">' + days + 'd' + '</span>');
|
||||
}
|
||||
if(
|
||||
hrs > 0 ||
|
||||
parts.length > 0
|
||||
){
|
||||
parts.push('<span class="' + config.counterDigitSmallClass + '">' + hrs + 'h' + '</span>');
|
||||
}
|
||||
if(
|
||||
min > 0 ||
|
||||
parts.length > 0
|
||||
){
|
||||
parts.push('<span class="' + config.counterDigitSmallClass + '">' + min + 'm' + '</span>');
|
||||
}
|
||||
|
||||
if(
|
||||
leftSec >= 0 ||
|
||||
parts.length > 0
|
||||
){
|
||||
parts.push('<span class="' + config.counterDigitSmallClass + '">' + leftSec + 's' + '</span>');
|
||||
}
|
||||
}
|
||||
|
||||
if(
|
||||
leftSec >= 0 ||
|
||||
value.length > 0
|
||||
){
|
||||
value.push('<span class="' + config.counterDigitSmallClass + '">' + leftSec + 's' + '</span>');
|
||||
}
|
||||
|
||||
element.html(value.join(' '));
|
||||
|
||||
element.html(parts.join(' '));
|
||||
};
|
||||
|
||||
/**
|
||||
* destroy all active counter recursive
|
||||
*/
|
||||
$.fn.destroyTimestampCounter = function(){
|
||||
return this.each(function(){
|
||||
let element = $(this);
|
||||
element.find('[data-counter="init"]').each(function(){
|
||||
let interval = $(this).data('interval');
|
||||
if(interval){
|
||||
clearInterval(interval);
|
||||
element.removeAttr('data-counter')
|
||||
.removeData('interval')
|
||||
.removeClass('stopCounter');
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* init a live counter based on a unix timestamp
|
||||
* @returns {*}
|
||||
* @param round string e.g. 'd' => round days
|
||||
*/
|
||||
$.fn.initTimestampCounter = function(){
|
||||
$.fn.initTimestampCounter = function(round){
|
||||
return this.each(function(){
|
||||
let element = $(this);
|
||||
let timestamp = parseInt( element.text() );
|
||||
@@ -68,7 +96,7 @@ define([
|
||||
|
||||
let date = new Date( timestamp * 1000);
|
||||
|
||||
updateDateDiff(element, date);
|
||||
updateDateDiff(element, date, round);
|
||||
|
||||
// show element (if invisible) after first update
|
||||
element.css({'visibility': 'initial'});
|
||||
@@ -77,7 +105,7 @@ define([
|
||||
|
||||
// update element with current time
|
||||
if( !element.hasClass('stopCounter')){
|
||||
updateDateDiff(element, date);
|
||||
updateDateDiff(element, date, round);
|
||||
}else{
|
||||
clearInterval( element.data('interval') );
|
||||
}
|
||||
|
||||
@@ -327,6 +327,9 @@ define(['jquery'], function($) {
|
||||
location: 0.6
|
||||
}]
|
||||
]
|
||||
},
|
||||
active: {
|
||||
cssClass: 'pf-map-connection-active'
|
||||
}
|
||||
},
|
||||
// signature groups
|
||||
|
||||
@@ -205,7 +205,6 @@ define([
|
||||
class: config.dialogDynamicAreaClass
|
||||
}).append( graphElement );
|
||||
|
||||
// headline
|
||||
let headline = $('<h4>', {
|
||||
text: key
|
||||
}).prepend(
|
||||
|
||||
@@ -76,42 +76,6 @@ define([
|
||||
defaultAcceptCookieExpire: 365 // default expire for "accept coolies" cookie
|
||||
};
|
||||
|
||||
/**
|
||||
* set a cookie
|
||||
* @param cname
|
||||
* @param cvalue
|
||||
* @param exdays
|
||||
*/
|
||||
let setCookie = function(cname, cvalue, exdays) {
|
||||
let d = new Date();
|
||||
d.setTime(d.getTime() + (exdays*24*60*60*1000));
|
||||
let expires = 'expires=' + d.toUTCString();
|
||||
let path = 'path=' + Util.getDocumentPath();
|
||||
document.cookie = cname + '=' + cvalue + '; ' + expires + '; ' + path;
|
||||
};
|
||||
|
||||
/**
|
||||
* get cookie value by name
|
||||
* @param cname
|
||||
* @returns {*}
|
||||
*/
|
||||
let getCookie = function(cname) {
|
||||
let name = cname + '=';
|
||||
let ca = document.cookie.split(';');
|
||||
|
||||
for(let i = 0; i <ca.length; i++) {
|
||||
let c = ca[i];
|
||||
while (c.charAt(0) === ' ') {
|
||||
c = c.substring(1);
|
||||
}
|
||||
|
||||
if (c.indexOf(name) === 0) {
|
||||
return c.substring(name.length,c.length);
|
||||
}
|
||||
}
|
||||
return '';
|
||||
};
|
||||
|
||||
/**
|
||||
* set link observer for "version info" dialog
|
||||
*/
|
||||
@@ -146,7 +110,7 @@ define([
|
||||
moveAdminPanel('down');
|
||||
});
|
||||
|
||||
if(getCookie('cookie') !== '1'){
|
||||
if(Util.getCookie('cookie') !== '1'){
|
||||
// hint not excepted
|
||||
cookieHintElement.collapse('show');
|
||||
|
||||
@@ -163,7 +127,7 @@ define([
|
||||
btnCancelIcon: 'fa fa-fw fa-check',
|
||||
onCancel: function(e, target){
|
||||
// "Accept cookies"
|
||||
setCookie('cookie', 1, config.defaultAcceptCookieExpire);
|
||||
Util.setCookie('cookie', 1, config.defaultAcceptCookieExpire, 'd');
|
||||
|
||||
// set "default" href
|
||||
let href = $(target).data('bs.confirmation').getHref();
|
||||
@@ -181,7 +145,7 @@ define([
|
||||
}
|
||||
|
||||
cookieHintElement.find('.btn-success').on('click', function(){
|
||||
setCookie('cookie', 1, config.defaultAcceptCookieExpire);
|
||||
Util.setCookie('cookie', 1, config.defaultAcceptCookieExpire, 'd');
|
||||
});
|
||||
|
||||
// manual -------------------------------------------------------------
|
||||
|
||||
@@ -23,6 +23,7 @@ define([
|
||||
|
||||
let config = {
|
||||
zIndexCounter: 110,
|
||||
maxActiveConnections: 8,
|
||||
|
||||
mapSnapToGrid: false, // "Snap to Grid" feature for drag&drop systems on map (optional)
|
||||
mapWrapperClass: 'pf-map-wrapper', // wrapper div (scrollable)
|
||||
@@ -30,9 +31,9 @@ define([
|
||||
mapClass: 'pf-map', // class for all maps
|
||||
mapIdPrefix: 'pf-map-', // id prefix for all maps
|
||||
systemClass: 'pf-system', // class for all systems
|
||||
systemActiveClass: 'pf-system-active', // class for an active system in a map
|
||||
systemSelectedClass: 'pf-system-selected', // class for selected systems in a map
|
||||
systemLockedClass: 'pf-system-locked', // class for locked systems in a map
|
||||
systemActiveClass: 'pf-system-active', // class for an active system on a map
|
||||
systemSelectedClass: 'pf-system-selected', // class for selected systems on a map
|
||||
systemLockedClass: 'pf-system-locked', // class for locked systems on a map
|
||||
systemHeadClass: 'pf-system-head', // class for system head
|
||||
systemHeadNameClass: 'pf-system-head-name', // class for system name
|
||||
systemHeadExpandClass: 'pf-system-head-expand', // class for system head expand arrow
|
||||
@@ -85,7 +86,7 @@ define([
|
||||
dragOptions:{
|
||||
},
|
||||
connectionsDetachable: true, // dragOptions are set -> allow detaching them
|
||||
maxConnections: 10, // due to isTarget is true, this is the max count of !out!-going connections
|
||||
maxConnections: 10, // due to isTarget is true, this is the max count of !out!-going connections
|
||||
// isSource:true,
|
||||
anchor: 'Continuous'
|
||||
},
|
||||
@@ -93,7 +94,7 @@ define([
|
||||
filter: '.' + config.systemHeadNameClass,
|
||||
isSource:true,
|
||||
//isTarget:true,
|
||||
//allowLoopback: false, // loopback connections are not allowed
|
||||
//allowLoopBack: false, // loopBack connections are not allowed
|
||||
cssClass: config.endpointTargetClass,
|
||||
dropOptions: {
|
||||
hoverClass: config.systemActiveClass,
|
||||
@@ -580,7 +581,8 @@ define([
|
||||
|
||||
if(alias !== data.alias){
|
||||
// alias changed
|
||||
system.find('.' + config.systemHeadNameClass).editable('setValue', data.alias);
|
||||
alias = data.alias ? data.alias : data.name;
|
||||
system.find('.' + config.systemHeadNameClass).editable('setValue', alias);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -626,6 +628,7 @@ define([
|
||||
|
||||
// get map container
|
||||
let mapElement = $( map.getContainer() );
|
||||
let connectionCanvas = $(connection.canvas);
|
||||
|
||||
// if the connection already exists -> do not set it twice
|
||||
connection.unbind('contextmenu').bind('contextmenu', function(component, e) {
|
||||
@@ -646,7 +649,7 @@ define([
|
||||
* init context menu for all connections
|
||||
* must be triggered manually on demand
|
||||
*/
|
||||
$(connection.canvas).contextMenu({
|
||||
connectionCanvas.contextMenu({
|
||||
menuSelector: '#' + config.connectionContextMenuId,
|
||||
menuSelected: function (params){
|
||||
|
||||
@@ -708,6 +711,31 @@ define([
|
||||
}
|
||||
});
|
||||
|
||||
// connection click events ==========================================================================
|
||||
|
||||
let single = function(e){
|
||||
let connection = this;
|
||||
// left mouse button
|
||||
if(e.which === 1){
|
||||
if(e.ctrlKey === true){
|
||||
// an "active" connection is required before adding more "selected" connections
|
||||
let activeConnections = MapUtil.getConnectionsByType(map, 'active');
|
||||
if(activeConnections.length >= config.maxActiveConnections && !connection.hasType('active')){
|
||||
Util.showNotify({title: 'Connection select limit', text: 'You can´t select more connections', type: 'warning'});
|
||||
}else {
|
||||
if(activeConnections.length > 0) {
|
||||
MapUtil.toggleConnectionActive(map, [connection]);
|
||||
}else{
|
||||
MapUtil.showConnectionInfo(map, [connection]);
|
||||
}
|
||||
}
|
||||
}else{
|
||||
MapUtil.showConnectionInfo(map, [connection]);
|
||||
}
|
||||
}
|
||||
}.bind(connection);
|
||||
|
||||
connectionCanvas.singleDoubleClick(single, () => {});
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -921,7 +949,7 @@ define([
|
||||
mapWrapper.append(mapContainer);
|
||||
|
||||
// append mapWrapper to parent element (at the top)
|
||||
$(parentElement).prepend(mapWrapper);
|
||||
parentElement.prepend(mapWrapper);
|
||||
|
||||
// set main Container for current map -> the container exists now in DOM !! very important
|
||||
mapConfig.map.setContainer( config.mapIdPrefix + mapId );
|
||||
@@ -938,12 +966,17 @@ define([
|
||||
* @returns {*}
|
||||
*/
|
||||
let updateMap = function(mapConfig){
|
||||
let mapContainer = mapConfig.map.getContainer();
|
||||
let mapContainer = null;
|
||||
if(!mapConfig.map){
|
||||
// jsPlumb needs to be initialized. This is not the case when switching between map tabs right after refresh
|
||||
return mapContainer;
|
||||
}else{
|
||||
mapContainer = $(mapConfig.map.getContainer());
|
||||
}
|
||||
|
||||
let mapId = mapConfig.config.id;
|
||||
let newSystems = 0;
|
||||
|
||||
mapContainer = $(mapContainer);
|
||||
|
||||
// add additional information for this map
|
||||
if(mapContainer.data('updated') !== mapConfig.config.updated.updated){
|
||||
mapContainer.data('name', mapConfig.config.name);
|
||||
@@ -1650,42 +1683,6 @@ define([
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* get all relevant data for a connection object
|
||||
* @param connection
|
||||
* @returns {{id: Number, source: Number, sourceName: (*|T|JQuery|{}), target: Number, targetName: (*|T|JQuery), scope: *, type: *, updated: Number}}
|
||||
*/
|
||||
let getDataByConnection = function(connection){
|
||||
let source = $(connection.source);
|
||||
let target = $(connection.target);
|
||||
|
||||
let id = connection.getParameter('connectionId');
|
||||
let updated = connection.getParameter('updated');
|
||||
|
||||
let connectionTypes = connection.getType();
|
||||
|
||||
// normalize connection array
|
||||
connectionTypes = $.grep(connectionTypes, function(n){
|
||||
// 'default' is added by jsPlumb by default -_-
|
||||
return ( n.length > 0 && n !== 'default');
|
||||
});
|
||||
|
||||
let data = {
|
||||
id: id ? id : 0,
|
||||
source: parseInt( source.data('id') ),
|
||||
sourceName: source.data('name'),
|
||||
sourceAlias: source.getSystemInfo(['alias']) || source.data('name'),
|
||||
target: parseInt( target.data('id') ),
|
||||
targetName: target.data('name'),
|
||||
targetAlias: target.getSystemInfo(['alias']) || target.data('name'),
|
||||
scope: connection.scope,
|
||||
type: connectionTypes,
|
||||
updated: updated ? updated : 0
|
||||
};
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
/**
|
||||
* stores a connection in database
|
||||
* @param connection
|
||||
@@ -1697,7 +1694,7 @@ define([
|
||||
let mapContainer = $( map.getContainer() );
|
||||
|
||||
let mapId = mapContainer.data('id');
|
||||
let connectionData = getDataByConnection(connection);
|
||||
let connectionData = MapUtil.getDataByConnection(connection);
|
||||
|
||||
let requestData = {
|
||||
mapData: {
|
||||
@@ -1908,7 +1905,7 @@ define([
|
||||
|
||||
]},
|
||||
{divider: true, action: 'delete_connection'},
|
||||
{icon: 'fa-trash', action: 'delete_connection', text: 'delete'}
|
||||
{icon: 'fa-chain-broken', action: 'delete_connection', text: 'detach'}
|
||||
]
|
||||
};
|
||||
|
||||
@@ -1943,6 +1940,7 @@ define([
|
||||
{icon: 'fa-plus', action: 'add_system', text: 'add system'},
|
||||
{icon: 'fa-lock', action: 'lock_system', text: 'lock system'},
|
||||
{icon: 'fa-volume-up', action: 'set_rally', text: 'set rally point'},
|
||||
{icon: 'fa-object-group', action: 'select_connections', text: 'select connections'},
|
||||
{icon: 'fa-tags', text: 'set status', subitems: systemStatus},
|
||||
{icon: 'fa-reply fa-rotate-180', text: 'waypoints', subitems: [
|
||||
{subIcon: 'fa-flag-checkered', subAction: 'set_destination', subText: 'set destination'},
|
||||
@@ -2298,6 +2296,10 @@ define([
|
||||
currentSystem.markAsChanged();
|
||||
}
|
||||
break;
|
||||
case 'select_connections':
|
||||
let connections = MapUtil.searchConnectionsBySystems(map, [currentSystem], '*');
|
||||
MapUtil.showConnectionInfo(map, connections);
|
||||
break;
|
||||
case 'change_status_unknown':
|
||||
case 'change_status_friendly':
|
||||
case 'change_status_occupied':
|
||||
@@ -2362,9 +2364,9 @@ define([
|
||||
if(! system.hasClass('no-click')){
|
||||
if(e.ctrlKey === true){
|
||||
// select system
|
||||
system.toggleSelectSystem(map);
|
||||
MapUtil.toggleSelectSystem(map, [system]);
|
||||
}else{
|
||||
system.showSystemInfo(map);
|
||||
MapUtil.showSystemInfo(map, system);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2412,31 +2414,6 @@ define([
|
||||
return changed;
|
||||
};
|
||||
|
||||
/**
|
||||
* triggers the "showSystemInfo" event, that is responsible for initializing the "map info" panel
|
||||
* @param map
|
||||
*/
|
||||
$.fn.showSystemInfo = function(map){
|
||||
let system = $(this);
|
||||
|
||||
// activate system
|
||||
markSystemActive(map, system);
|
||||
|
||||
// get parent Tab Content and fire update event
|
||||
let tabContentElement = MapUtil.getTabContentElementByMapElement( system );
|
||||
|
||||
// collect all required data from map module to update the info element
|
||||
// store them global and assessable for each module
|
||||
let currentSystemData = {
|
||||
systemData: system.getSystemData(),
|
||||
mapId: parseInt( system.attr('data-mapid') )
|
||||
};
|
||||
|
||||
Util.setCurrentSystemData(currentSystemData);
|
||||
|
||||
$(tabContentElement).trigger('pf:drawSystemModules');
|
||||
};
|
||||
|
||||
/**
|
||||
* select all (selectable) systems on a mapElement
|
||||
*/
|
||||
@@ -2452,35 +2429,13 @@ define([
|
||||
return ( $(el).data('locked') !== true );
|
||||
});
|
||||
|
||||
allSystems.toggleSelectSystem(map);
|
||||
MapUtil.toggleSelectSystem(map, allSystems);
|
||||
|
||||
Util.showNotify({title: allSystems.length + ' systems selected', type: 'success'});
|
||||
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* toggle selectable status of a system
|
||||
*/
|
||||
$.fn.toggleSelectSystem = function(map){
|
||||
|
||||
return this.each(function(){
|
||||
let system = $(this);
|
||||
|
||||
if( system.data('locked') !== true ){
|
||||
|
||||
if( system.hasClass( config.systemSelectedClass ) ){
|
||||
system.removeClass( config.systemSelectedClass );
|
||||
|
||||
map.removeFromDragSelection(system);
|
||||
}else{
|
||||
system.addClass( config.systemSelectedClass );
|
||||
map.addToDragSelection(system);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* toggle log status of a system
|
||||
* @param poke
|
||||
@@ -2904,7 +2859,7 @@ define([
|
||||
tempMapWrapper.mCustomScrollbar('scrollTo', system);
|
||||
|
||||
// select system
|
||||
system.showSystemInfo(map);
|
||||
MapUtil.showSystemInfo(map, system);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -2969,22 +2924,6 @@ define([
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* mark a system as active
|
||||
* @param map
|
||||
* @param system
|
||||
*/
|
||||
let markSystemActive = function(map, system){
|
||||
|
||||
// deactivate all systems in map
|
||||
let mapContainer = $( map.getContainer() );
|
||||
|
||||
mapContainer.find('.' + config.systemClass).removeClass(config.systemActiveClass);
|
||||
|
||||
// set current system active
|
||||
system.addClass(config.systemActiveClass);
|
||||
};
|
||||
|
||||
/**
|
||||
* get system data out of its object
|
||||
* @param info
|
||||
@@ -3051,7 +2990,7 @@ define([
|
||||
// data for header update
|
||||
let headerUpdateData = {
|
||||
mapId: userData.config.id,
|
||||
userCount: 0 // active user in a map
|
||||
userCount: 0 // active user on a map
|
||||
};
|
||||
|
||||
if(
|
||||
@@ -3191,7 +3130,7 @@ define([
|
||||
// format connections
|
||||
for(let j = 0; j < connections.length; j++){
|
||||
let tempConnection = connections[j];
|
||||
let connectionData = getDataByConnection(tempConnection);
|
||||
let connectionData = MapUtil.getDataByConnection(tempConnection);
|
||||
|
||||
// only add valid connections (id is required, this is not the case if connection is new)
|
||||
if(connectionData.id > 0){
|
||||
@@ -3389,10 +3328,14 @@ define([
|
||||
let mapElement = mapTabContentElement.find('.' + config.mapClass);
|
||||
let mapId = mapElement.data('id');
|
||||
|
||||
|
||||
scrollableElement.initCustomScrollbar({
|
||||
callbacks: {
|
||||
onScroll: function(){
|
||||
// scroll complete
|
||||
// update scroll position for drag-frame-selection
|
||||
mapElement.attr('data-scroll-left', this.mcs.left);
|
||||
mapElement.attr('data-scroll-top', this.mcs.top);
|
||||
|
||||
// store new map scrollOffset -> localDB
|
||||
MapUtil.storeLocalData('map', mapId, 'offsetX', Math.abs(this.mcs.left) );
|
||||
},
|
||||
@@ -3402,11 +3345,6 @@ define([
|
||||
|
||||
// hide all system head tooltips
|
||||
$(this).find('.' + config.systemHeadClass + ' .fa').tooltip('hide');
|
||||
},
|
||||
whileScrolling:function(){
|
||||
// update scroll position for drag-frame-selection
|
||||
mapElement.data('scrollLeft', this.mcs.left);
|
||||
mapElement.data('scrollTop', this.mcs.top);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -3422,7 +3360,6 @@ define([
|
||||
return {
|
||||
getMapInstance: getMapInstance,
|
||||
clearMapInstance: clearMapInstance,
|
||||
getDataByConnection: getDataByConnection,
|
||||
showNewSystemDialog: showNewSystemDialog
|
||||
};
|
||||
|
||||
|
||||
@@ -5,8 +5,9 @@
|
||||
define([
|
||||
'jquery',
|
||||
'app/init',
|
||||
'app/util'
|
||||
], function($, Init, Util) {
|
||||
'app/util',
|
||||
'app/map/util'
|
||||
], function($, Init, Util, MapUtil) {
|
||||
'use strict';
|
||||
|
||||
let config = {
|
||||
@@ -72,34 +73,15 @@ define([
|
||||
* @param label
|
||||
*/
|
||||
let addEndpointOverlay = (endpoint, label) => {
|
||||
let newLabel = '';
|
||||
let colorClass = 'txt-color-grayLighter';
|
||||
|
||||
if(label.length > 0){
|
||||
newLabel = label;
|
||||
|
||||
// check if multiple labels found => conflict
|
||||
if( label.includes(', ') ){
|
||||
colorClass = 'txt-color-orangeLight';
|
||||
}else if( !label.includes('K162') ){
|
||||
colorClass = 'txt-color-yellow';
|
||||
}
|
||||
}else{
|
||||
// endpoint not connected with a signature
|
||||
newLabel = '<i class="fa fa-question-circle"></i>';
|
||||
colorClass = 'txt-color-red';
|
||||
}
|
||||
|
||||
endpoint.addOverlay([
|
||||
'Label',
|
||||
{
|
||||
label: '<span class="txt-color ' + colorClass + '">' + newLabel + '</span>',
|
||||
label: MapUtil.getEndpointOverlayContent(label),
|
||||
id: config.connectionOverlaySmallId,
|
||||
cssClass: config.connectionOverlaySmallClass,
|
||||
location: [ 0.5, 0.5 ]
|
||||
location: [ 0.9, 0.9 ]
|
||||
}
|
||||
]);
|
||||
|
||||
};
|
||||
|
||||
// loop through all map connections (get from DOM)
|
||||
@@ -119,53 +101,15 @@ define([
|
||||
|
||||
// ... find matching connectionData (from Ajax)
|
||||
for(let connectionData of connectionsData){
|
||||
if(
|
||||
connectionData.id === connectionId &&
|
||||
connectionData.signatures // signature data is required...
|
||||
){
|
||||
|
||||
// ... collect overlay/label data from signatures
|
||||
for(let signatureData of connectionData.signatures){
|
||||
// ... typeId is required to get a valid name
|
||||
if(signatureData.typeId > 0){
|
||||
|
||||
// whether "source" or "target" system is relevant for current connection and current signature...
|
||||
let tmpSystem = null;
|
||||
let tmpSystemType = null;
|
||||
|
||||
if(signatureData.system.id === sourceId){
|
||||
// relates to "source" endpoint
|
||||
tmpSystemType = 'sourceLabels';
|
||||
tmpSystem = sourceSystem;
|
||||
}else if(signatureData.system.id === targetId){
|
||||
// relates to "target" endpoint
|
||||
tmpSystemType = 'targetLabels';
|
||||
tmpSystem = targetSystem;
|
||||
}
|
||||
|
||||
// ... get endpoint label for source || target system
|
||||
if(tmpSystem && tmpSystem){
|
||||
// ... get all available signature type (wormholes) names
|
||||
let availableSigTypeNames = SystemSignatures.getAllSignatureNamesBySystem(tmpSystem, 5);
|
||||
let flattenSigTypeNames = Util.flattenXEditableSelectArray(availableSigTypeNames);
|
||||
|
||||
if( flattenSigTypeNames.hasOwnProperty(signatureData.typeId) ){
|
||||
let label = flattenSigTypeNames[signatureData.typeId];
|
||||
// shorten label, just take the in game name
|
||||
label = label.substr(0, label.indexOf(' '));
|
||||
signatureTypeNames[tmpSystemType].push(label);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(connectionData.id === connectionId){
|
||||
signatureTypeNames = MapUtil.getConnectionDataFromSignatures(connection, connectionData);
|
||||
// ... connection matched -> continue with next one
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
let sourceLabel = signatureTypeNames.sourceLabels.join(', ');
|
||||
let targetLabel = signatureTypeNames.targetLabels.join(', ');
|
||||
let sourceLabel = signatureTypeNames.sourceLabels;
|
||||
let targetLabel = signatureTypeNames.targetLabels;
|
||||
|
||||
// add endpoint overlays ------------------------------------------------------
|
||||
addEndpointOverlay(sourceEndpoint, sourceLabel);
|
||||
@@ -176,19 +120,19 @@ define([
|
||||
let arrowDirection = 1;
|
||||
|
||||
if(
|
||||
(sourceLabel.includes('K162') && targetLabel.includes('K162')) ||
|
||||
(sourceLabel.indexOf('K162') !== -1 && targetLabel.indexOf('K162') !== -1) ||
|
||||
(sourceLabel.length === 0 && targetLabel.length === 0) ||
|
||||
(
|
||||
sourceLabel.length > 0 && targetLabel.length > 0 &&
|
||||
!sourceLabel.includes('K162') && !targetLabel.includes('K162')
|
||||
sourceLabel.indexOf('K162') === -1 && targetLabel.indexOf('K162') === -1
|
||||
)
|
||||
){
|
||||
// unknown direction
|
||||
overlayType = 'Diamond'; // not specified
|
||||
arrowDirection = 1;
|
||||
}else if(
|
||||
(sourceLabel.includes('K162')) ||
|
||||
(sourceLabel.length === 0 && !targetLabel.includes('K162'))
|
||||
(sourceLabel.indexOf('K162') !== -1) ||
|
||||
(sourceLabel.length === 0 && targetLabel.indexOf('K162') === -1)
|
||||
){
|
||||
// convert default arrow direction
|
||||
overlayType = 'Arrow';
|
||||
@@ -283,7 +227,9 @@ define([
|
||||
showLoading(overlayConnectionIcon);
|
||||
|
||||
let requestData = {
|
||||
mapId: mapElement.data('id')
|
||||
mapId: mapElement.data('id'),
|
||||
addData : ['signatures'],
|
||||
filterData : ['signatures']
|
||||
};
|
||||
|
||||
$.ajax({
|
||||
|
||||
@@ -18,7 +18,7 @@ define([
|
||||
y: 0
|
||||
},
|
||||
|
||||
systemActiveClass: 'pf-system-active', // class for an active system in a map
|
||||
systemActiveClass: 'pf-system-active', // class for an active system on a map
|
||||
|
||||
dialogRallyId: 'pf-rally-dialog', // id for "Rally point" dialog
|
||||
|
||||
|
||||
@@ -24,7 +24,8 @@ define([
|
||||
|
||||
systemIdPrefix: 'pf-system-', // id prefix for a system
|
||||
systemClass: 'pf-system', // class for all systems
|
||||
systemSelectedClass: 'pf-system-selected', // class for selected systems in a map
|
||||
systemActiveClass: 'pf-system-active', // class for an active system on a map
|
||||
systemSelectedClass: 'pf-system-selected', // class for selected systems on on map
|
||||
|
||||
// dataTable
|
||||
tableCellEllipsisClass: 'pf-table-cell-ellipsis',
|
||||
@@ -60,7 +61,7 @@ define([
|
||||
* @param {bool} filterByUser
|
||||
* @returns {Array}
|
||||
*/
|
||||
let getMapTypes = function(filterByUser){
|
||||
let getMapTypes = (filterByUser) => {
|
||||
let mapTypes = [];
|
||||
|
||||
$.each(Init.mapTypes, function(prop, data){
|
||||
@@ -109,7 +110,7 @@ define([
|
||||
* get all available scopes for a map
|
||||
* @returns {Array}
|
||||
*/
|
||||
let getMapScopes = function(){
|
||||
let getMapScopes = () => {
|
||||
let scopes = [];
|
||||
$.each(Init.mapScopes, function(prop, data){
|
||||
let tempData = data;
|
||||
@@ -126,7 +127,7 @@ define([
|
||||
* @param {string} option
|
||||
* @returns {string}
|
||||
*/
|
||||
let getScopeInfoForMap = function(info, option){
|
||||
let getScopeInfoForMap = (info, option) => {
|
||||
let scopeInfo = '';
|
||||
if(Init.mapScopes.hasOwnProperty(info)){
|
||||
scopeInfo = Init.mapScopes[info][option];
|
||||
@@ -138,7 +139,7 @@ define([
|
||||
* get all available map icons
|
||||
* @returns {Object[]}
|
||||
*/
|
||||
let getMapIcons = function(){
|
||||
let getMapIcons = () => {
|
||||
return Init.mapIcons;
|
||||
};
|
||||
|
||||
@@ -148,7 +149,7 @@ define([
|
||||
* @param {string} option
|
||||
* @returns {string}
|
||||
*/
|
||||
let getInfoForMap = function(mapType, option){
|
||||
let getInfoForMap = (mapType, option) => {
|
||||
let mapInfo = '';
|
||||
if(Init.mapTypes.hasOwnProperty(mapType)){
|
||||
mapInfo = Init.mapTypes[mapType][option];
|
||||
@@ -162,7 +163,7 @@ define([
|
||||
* @param {string} option
|
||||
* @returns {string}
|
||||
*/
|
||||
let getInfoForSystem = function(info, option){
|
||||
let getInfoForSystem = (info, option) => {
|
||||
let systemInfo = '';
|
||||
if(Init.classes.systemInfo.hasOwnProperty(info)){
|
||||
systemInfo = Init.classes.systemInfo[info][option];
|
||||
@@ -176,7 +177,7 @@ define([
|
||||
* @param {string} option
|
||||
* @returns {string}
|
||||
*/
|
||||
let getSystemTypeInfo = function(systemTypeId, option){
|
||||
let getSystemTypeInfo = (systemTypeId, option) => {
|
||||
let systemTypeInfo = '';
|
||||
$.each(Init.systemType, function(prop, data){
|
||||
if(systemTypeId === data.id){
|
||||
@@ -193,7 +194,7 @@ define([
|
||||
* @param option
|
||||
* @returns {string}
|
||||
*/
|
||||
let getEffectInfoForSystem = function(effect, option){
|
||||
let getEffectInfoForSystem = (effect, option) => {
|
||||
let effectInfo = '';
|
||||
if( Init.classes.systemEffects.hasOwnProperty(effect) ){
|
||||
effectInfo = Init.classes.systemEffects[effect][option];
|
||||
@@ -210,7 +211,7 @@ define([
|
||||
};
|
||||
|
||||
/**
|
||||
* get all selected (NOT active) systems in a map
|
||||
* get all selected (NOT active) systems on a map
|
||||
* @returns {*}
|
||||
*/
|
||||
$.fn.getSelectedSystems = function(){
|
||||
@@ -219,21 +220,327 @@ define([
|
||||
};
|
||||
|
||||
/**
|
||||
* search connections by systems
|
||||
* @param {Object} map - jsPlumb
|
||||
* @param {JQuery[]} systems - system DOM elements
|
||||
* @returns {Array} connections - found connection, DOM elements
|
||||
* filter connections by type
|
||||
* @param map
|
||||
* @param type
|
||||
* @returns {Array}
|
||||
*/
|
||||
let searchConnectionsBySystems = function(map, systems){
|
||||
let getConnectionsByType = (map, type) => {
|
||||
let connections = [];
|
||||
// iterate through ALL connections and filter...
|
||||
// -> there is no "filterByScope()" method in jsPlumb
|
||||
for(let connection of map.getAllConnections()){
|
||||
if(connection.getType().indexOf(type) !== -1){
|
||||
connections.push(connection);
|
||||
}
|
||||
}
|
||||
return connections;
|
||||
};
|
||||
|
||||
/**
|
||||
* get all relevant data for a connection object
|
||||
* @param connection
|
||||
* @returns {{id: Number, source: Number, sourceName: (*|T|JQuery|{}), target: Number, targetName: (*|T|JQuery), scope: *, type: *, updated: Number}}
|
||||
*/
|
||||
let getDataByConnection = (connection) => {
|
||||
let source = $(connection.source);
|
||||
let target = $(connection.target);
|
||||
|
||||
let id = connection.getParameter('connectionId');
|
||||
let updated = connection.getParameter('updated');
|
||||
|
||||
let connectionTypes = connection.getType();
|
||||
|
||||
// normalize connection array
|
||||
connectionTypes = $.grep(connectionTypes, function(n){
|
||||
// 'default' is added by jsPlumb by default -_-
|
||||
return ( n.length > 0 && n !== 'default' && n !== 'active');
|
||||
});
|
||||
|
||||
let data = {
|
||||
id: id ? id : 0,
|
||||
source: parseInt( source.data('id') ),
|
||||
sourceName: source.data('name'),
|
||||
sourceAlias: source.getSystemInfo(['alias']) || source.data('name'),
|
||||
target: parseInt( target.data('id') ),
|
||||
targetName: target.data('name'),
|
||||
targetAlias: target.getSystemInfo(['alias']) || target.data('name'),
|
||||
scope: connection.scope,
|
||||
type: connectionTypes,
|
||||
updated: updated ? updated : 0
|
||||
};
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
/**
|
||||
* @see getDataByConnection
|
||||
* @param connections
|
||||
* @returns {Array}
|
||||
*/
|
||||
let getDataByConnections = (connections) => {
|
||||
let data = [];
|
||||
for(let connection of connections){
|
||||
data.push(getDataByConnection(connection));
|
||||
}
|
||||
return data;
|
||||
};
|
||||
|
||||
/**
|
||||
* get connection related data from a connection
|
||||
* -> data requires a signature bind to that connection
|
||||
* @param connection
|
||||
* @param connectionData
|
||||
* @returns {{sourceLabels: Array, targetLabels: Array}}
|
||||
*/
|
||||
let getConnectionDataFromSignatures = (connection, connectionData) => {
|
||||
let signatureTypeNames = {
|
||||
sourceLabels: [],
|
||||
targetLabels: []
|
||||
};
|
||||
|
||||
if(
|
||||
connection &&
|
||||
connectionData.signatures // signature data is required...
|
||||
){
|
||||
let SystemSignatures = require('app/ui/system_signature');
|
||||
|
||||
let connectionId = connection.getParameter('connectionId');
|
||||
let sourceEndpoint = connection.endpoints[0];
|
||||
let targetEndpoint = connection.endpoints[1];
|
||||
let sourceSystem = $(sourceEndpoint.element);
|
||||
let targetSystem = $(targetEndpoint.element);
|
||||
let sourceId = sourceSystem.data('id');
|
||||
let targetId = targetSystem.data('id');
|
||||
|
||||
// ... collect overlay/label data from signatures
|
||||
for(let signatureData of connectionData.signatures){
|
||||
// ... typeId is required to get a valid name
|
||||
if(signatureData.typeId > 0){
|
||||
|
||||
// whether "source" or "target" system is relevant for current connection and current signature...
|
||||
let tmpSystem = null;
|
||||
let tmpSystemType = null;
|
||||
|
||||
if(signatureData.system.id === sourceId){
|
||||
// relates to "source" endpoint
|
||||
tmpSystemType = 'sourceLabels';
|
||||
tmpSystem = sourceSystem;
|
||||
}else if(signatureData.system.id === targetId){
|
||||
// relates to "target" endpoint
|
||||
tmpSystemType = 'targetLabels';
|
||||
tmpSystem = targetSystem;
|
||||
}
|
||||
|
||||
// ... get endpoint label for source || target system
|
||||
if(tmpSystem && tmpSystem){
|
||||
// ... get all available signature type (wormholes) names
|
||||
let availableSigTypeNames = SystemSignatures.getAllSignatureNamesBySystem(tmpSystem, 5);
|
||||
let flattenSigTypeNames = Util.flattenXEditableSelectArray(availableSigTypeNames);
|
||||
|
||||
if( flattenSigTypeNames.hasOwnProperty(signatureData.typeId) ){
|
||||
let label = flattenSigTypeNames[signatureData.typeId];
|
||||
// shorten label, just take the in game name
|
||||
label = label.substr(0, label.indexOf(' '));
|
||||
signatureTypeNames[tmpSystemType].push(label);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return signatureTypeNames;
|
||||
};
|
||||
|
||||
/**
|
||||
* get overlay HTML for connection endpoints by Label array
|
||||
* @param label
|
||||
* @returns {string}
|
||||
*/
|
||||
let getEndpointOverlayContent = (label) => {
|
||||
let newLabel = '';
|
||||
let colorClass = 'txt-color-grayLighter';
|
||||
|
||||
if(label.length > 0){
|
||||
newLabel = label.join(', ');
|
||||
|
||||
// check if multiple labels found => conflict
|
||||
if( newLabel.includes(', ') ){
|
||||
colorClass = 'txt-color-orangeLight';
|
||||
}else if( !newLabel.includes('K162') ){
|
||||
colorClass = 'txt-color-yellow';
|
||||
}
|
||||
}else{
|
||||
// endpoint not connected with a signature
|
||||
newLabel = '<i class="fa fa-question-circle"></i>';
|
||||
colorClass = 'txt-color-red';
|
||||
}
|
||||
return '<span class="txt-color ' + colorClass + '">' + newLabel + '</span>';
|
||||
};
|
||||
|
||||
/**
|
||||
* get TabContentElement by any element on a map e.g. system
|
||||
* @param element
|
||||
* @returns {*}
|
||||
*/
|
||||
let getTabContentElementByMapElement = (element) => {
|
||||
let tabContentElement = $(element).parents('.' + config.mapTabContentClass);
|
||||
return tabContentElement;
|
||||
};
|
||||
|
||||
/**
|
||||
* checks if there is an "active" connection on a map
|
||||
* @param map
|
||||
* @returns {boolean}
|
||||
*/
|
||||
let hasActiveConnection = (map) => {
|
||||
let activeConnections = getConnectionsByType(map, 'active');
|
||||
return activeConnections.length > 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* mark a system as "active"
|
||||
* @param map
|
||||
* @param system
|
||||
*/
|
||||
let setSystemActive = (map, system) => {
|
||||
// deselect all selected systems on map
|
||||
let mapContainer = $( map.getContainer() );
|
||||
mapContainer.find('.' + config.systemClass).removeClass(config.systemActiveClass);
|
||||
|
||||
// set current system active
|
||||
system.addClass(config.systemActiveClass);
|
||||
};
|
||||
|
||||
/**
|
||||
* mark a connection as "active"
|
||||
* @param connections
|
||||
*/
|
||||
let setConnectionsActive = (map, connections) => {
|
||||
// set all inactive
|
||||
for(let connection of getConnectionsByType(map, 'active')){
|
||||
connection.removeType('active');
|
||||
}
|
||||
|
||||
for(let connection of connections){
|
||||
connection.addType('active');
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* toggle "selected" status of system
|
||||
* @param map
|
||||
* @param systems
|
||||
*/
|
||||
let toggleSelectSystem = (map, systems) => {
|
||||
for(let system of systems){
|
||||
system = $(system);
|
||||
if( system.data('locked') !== true ){
|
||||
if( system.hasClass( config.systemSelectedClass ) ){
|
||||
system.removeClass( config.systemSelectedClass );
|
||||
|
||||
map.removeFromDragSelection(system);
|
||||
}else{
|
||||
system.addClass( config.systemSelectedClass );
|
||||
map.addToDragSelection(system);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* toggle "selected" status of connections
|
||||
* @param map
|
||||
* @param connections
|
||||
*/
|
||||
let toggleConnectionActive = (map, connections) => {
|
||||
let selectedConnections = [];
|
||||
let deselectedConnections = [];
|
||||
for(let connection of connections){
|
||||
if(connection.hasType('active')){
|
||||
connection.removeType('active');
|
||||
deselectedConnections.push(connection);
|
||||
}else{
|
||||
connection.addType('active');
|
||||
selectedConnections.push(connection);
|
||||
}
|
||||
}
|
||||
updateConnectionInfo(map, selectedConnections, deselectedConnections);
|
||||
};
|
||||
|
||||
/**
|
||||
* show system info panels
|
||||
* @param map
|
||||
* @param system
|
||||
*/
|
||||
let showSystemInfo = (map, system) => {
|
||||
setSystemActive(map, system);
|
||||
|
||||
// get parent Tab Content and fire update event
|
||||
let tabContentElement = getTabContentElementByMapElement( system );
|
||||
|
||||
// collect all required data from map module to update the info element
|
||||
// store them global and assessable for each module
|
||||
Util.setCurrentSystemData({
|
||||
systemData: system.getSystemData(),
|
||||
mapId: parseInt( system.attr('data-mapid') )
|
||||
});
|
||||
|
||||
$(tabContentElement).trigger('pf:drawSystemModules');
|
||||
};
|
||||
|
||||
/**
|
||||
* show connection info panels
|
||||
* @param map
|
||||
* @param connections
|
||||
*/
|
||||
let showConnectionInfo = (map, connections) => {
|
||||
setConnectionsActive(map, connections);
|
||||
|
||||
// get parent Tab Content and fire update event
|
||||
let mapContainer = $(map.getContainer());
|
||||
let tabContentElement = getTabContentElementByMapElement(mapContainer);
|
||||
|
||||
$(tabContentElement).trigger('pf:drawConnectionModules', {
|
||||
connections: connections,
|
||||
mapId: parseInt(mapContainer.data('id'))
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* update connection info panels
|
||||
* @param map
|
||||
* @param selectedConnections
|
||||
* @param deselectedConnections
|
||||
*/
|
||||
let updateConnectionInfo = (map, selectedConnections, deselectedConnections) => {
|
||||
// get parent Tab Content and fire update event
|
||||
let mapContainer = $(map.getContainer());
|
||||
|
||||
$(document).trigger('pf:updateConnectionInfoModule', {
|
||||
connectionsUpdate: selectedConnections,
|
||||
connectionsRemove: deselectedConnections,
|
||||
mapId: parseInt(mapContainer.data('id'))
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* search connections by systems
|
||||
* @param map
|
||||
* @param systems
|
||||
* @param scope
|
||||
* @returns {Array}
|
||||
*/
|
||||
let searchConnectionsBySystems = (map, systems, scope) => {
|
||||
let connections = [];
|
||||
let withBackConnection = true;
|
||||
|
||||
$.each(systems, function(i, system){
|
||||
// get connections where system is source
|
||||
connections = connections.concat( map.getConnections({source: system}) );
|
||||
connections = connections.concat( map.getConnections({scope: scope, source: system}) );
|
||||
if(withBackConnection === true){
|
||||
// get connections where system is target
|
||||
connections = connections.concat( map.getConnections({target: system}) );
|
||||
connections = connections.concat( map.getConnections({scope: scope, target: system}) );
|
||||
}
|
||||
});
|
||||
return connections;
|
||||
@@ -247,7 +554,7 @@ define([
|
||||
* @param {string|string[]} type
|
||||
* @returns {Array}
|
||||
*/
|
||||
let searchConnectionsByScopeAndType = function(map, scope, type){
|
||||
let searchConnectionsByScopeAndType = (map, scope, type) => {
|
||||
let connections = [];
|
||||
let scopeArray = (scope === undefined) ? ['*'] : ((Array.isArray(scope)) ? scope : [scope]);
|
||||
let typeArray = (type === undefined) ? [] : ((Array.isArray(type)) ? type : [type]);
|
||||
@@ -276,7 +583,7 @@ define([
|
||||
* @param {string} option
|
||||
* @returns {string}
|
||||
*/
|
||||
let getConnectionInfo = function(connectionTyp, option){
|
||||
let getConnectionInfo = (connectionTyp, option) => {
|
||||
let connectionInfo = '';
|
||||
if(Init.connectionTypes.hasOwnProperty(connectionTyp)){
|
||||
connectionInfo = Init.connectionTypes[connectionTyp][option];
|
||||
@@ -291,7 +598,7 @@ define([
|
||||
* @param {JQuery} systemB
|
||||
* @returns {Array}
|
||||
*/
|
||||
let checkForConnection = function(map, systemA, systemB){
|
||||
let checkForConnection = (map, systemA, systemB) => {
|
||||
let connections = [];
|
||||
connections = connections.concat( map.getConnections({scope: '*', source: systemA, target: systemB}) );
|
||||
// get connections where system is target
|
||||
@@ -305,7 +612,7 @@ define([
|
||||
* @param {string} scope
|
||||
* @returns {string}
|
||||
*/
|
||||
let getDefaultConnectionTypeByScope = function(scope){
|
||||
let getDefaultConnectionTypeByScope = (scope) => {
|
||||
let type = '';
|
||||
switch(scope){
|
||||
case 'wh':
|
||||
@@ -329,7 +636,7 @@ define([
|
||||
* @param {Object} connection - jsPlumb object
|
||||
* @param {string} status
|
||||
*/
|
||||
let setConnectionWHStatus = function(connection, status){
|
||||
let setConnectionWHStatus = (connection, status) => {
|
||||
if(
|
||||
status === 'wh_fresh' &&
|
||||
connection.hasType('wh_fresh') !== true
|
||||
@@ -370,7 +677,7 @@ define([
|
||||
* @param {string} option
|
||||
* @returns {string}
|
||||
*/
|
||||
let getScopeInfoForConnection = function(info, option){
|
||||
let getScopeInfoForConnection = (info, option) => {
|
||||
let scopeInfo = '';
|
||||
if(Init.connectionScopes.hasOwnProperty(info)){
|
||||
switch(option){
|
||||
@@ -388,21 +695,11 @@ define([
|
||||
return scopeInfo;
|
||||
};
|
||||
|
||||
/**
|
||||
* get TabContentElement by any element on a map e.g. system
|
||||
* @param element
|
||||
* @returns {*}
|
||||
*/
|
||||
let getTabContentElementByMapElement = function(element){
|
||||
let tabContentElement = $(element).parents('.' + config.mapTabContentClass);
|
||||
return tabContentElement;
|
||||
};
|
||||
|
||||
/**
|
||||
* store mapId for current user (IndexedDB)
|
||||
* @param mapId
|
||||
*/
|
||||
let storeDefaultMapId = function(mapId){
|
||||
let storeDefaultMapId = (mapId) => {
|
||||
if(mapId > 0){
|
||||
let userData = Util.getCurrentUserData();
|
||||
if(
|
||||
@@ -419,7 +716,7 @@ define([
|
||||
* @param type
|
||||
* @returns {boolean}
|
||||
*/
|
||||
let getLocalStoragePrefixByType = function(type){
|
||||
let getLocalStoragePrefixByType = (type) => {
|
||||
let prefix = false;
|
||||
switch(type){
|
||||
case 'character': prefix = config.characterLocalStoragePrefix; break;
|
||||
@@ -435,7 +732,7 @@ define([
|
||||
* @param objectId
|
||||
* @returns {*}
|
||||
*/
|
||||
let getLocaleData = function(type, objectId){
|
||||
let getLocaleData = (type, objectId) => {
|
||||
if(objectId > 0){
|
||||
let storageKey = getLocalStoragePrefixByType(type) + objectId;
|
||||
return Util.getLocalStorage().getItem(storageKey);
|
||||
@@ -451,7 +748,7 @@ define([
|
||||
* @param key
|
||||
* @param value
|
||||
*/
|
||||
let storeLocalData = function(type, objectId, key, value){
|
||||
let storeLocalData = (type, objectId, key, value) => {
|
||||
if(objectId > 0){
|
||||
// get current map config
|
||||
let storageKey = getLocalStoragePrefixByType(type) + objectId;
|
||||
@@ -481,7 +778,7 @@ define([
|
||||
* @param objectId
|
||||
* @param key
|
||||
*/
|
||||
let deleteLocalData = function(type, objectId, key){
|
||||
let deleteLocalData = (type, objectId, key) => {
|
||||
if(objectId > 0){
|
||||
// get current map config
|
||||
let storageKey = getLocalStoragePrefixByType(type) + objectId;
|
||||
@@ -625,6 +922,56 @@ define([
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* add a wormhole tooltip with wh specific data to elements
|
||||
* @param tooltipData
|
||||
* @returns {*}
|
||||
*/
|
||||
$.fn.addWormholeInfoTooltip = function(tooltipData){
|
||||
return this.each(function() {
|
||||
let element = $(this);
|
||||
|
||||
requirejs(['text!templates/tooltip/wormhole_info.html', 'mustache'], function (template, Mustache) {
|
||||
// format tooltip data
|
||||
let data = {};
|
||||
if(tooltipData.massTotal){
|
||||
data.massTotal = Util.formatMassValue(tooltipData.massTotal);
|
||||
}
|
||||
if(tooltipData.massIndividual){
|
||||
data.massIndividual = Util.formatMassValue(tooltipData.massIndividual);
|
||||
}
|
||||
if(tooltipData.massRegeneration){
|
||||
data.massRegeneration = Util.formatMassValue(tooltipData.massRegeneration);
|
||||
}
|
||||
if(tooltipData.maxStableTime){
|
||||
data.maxStableTime = tooltipData.maxStableTime + ' h';
|
||||
}
|
||||
|
||||
let title = tooltipData.name +
|
||||
'<span class="pull-right ' + tooltipData.class +'">' + tooltipData.security + '</span>';
|
||||
let content = Mustache.render(template, data);
|
||||
|
||||
element.popover({
|
||||
placement: 'top',
|
||||
html: true,
|
||||
trigger: 'hover',
|
||||
content: '',
|
||||
container: 'body',
|
||||
title: title,
|
||||
delay: {
|
||||
show: 150,
|
||||
hide: 0
|
||||
}
|
||||
});
|
||||
|
||||
// set new popover content
|
||||
let popover = element.data('bs.popover');
|
||||
popover.options.title = title;
|
||||
popover.options.content = content;
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
$.fn.findMapElement = function(){
|
||||
return $(this).find('.' + config.mapClass);
|
||||
};
|
||||
@@ -650,6 +997,12 @@ define([
|
||||
getInfoForSystem: getInfoForSystem,
|
||||
getSystemTypeInfo: getSystemTypeInfo,
|
||||
getEffectInfoForSystem: getEffectInfoForSystem,
|
||||
toggleSelectSystem: toggleSelectSystem,
|
||||
toggleConnectionActive: toggleConnectionActive,
|
||||
showSystemInfo: showSystemInfo,
|
||||
showConnectionInfo: showConnectionInfo,
|
||||
getConnectionsByType: getConnectionsByType,
|
||||
getDataByConnection: getDataByConnection,
|
||||
searchConnectionsBySystems: searchConnectionsBySystems,
|
||||
searchConnectionsByScopeAndType: searchConnectionsByScopeAndType,
|
||||
getConnectionInfo: getConnectionInfo,
|
||||
@@ -657,7 +1010,11 @@ define([
|
||||
getDefaultConnectionTypeByScope: getDefaultConnectionTypeByScope,
|
||||
setConnectionWHStatus: setConnectionWHStatus,
|
||||
getScopeInfoForConnection: getScopeInfoForConnection,
|
||||
getDataByConnections: getDataByConnections,
|
||||
getConnectionDataFromSignatures: getConnectionDataFromSignatures,
|
||||
getEndpointOverlayContent: getEndpointOverlayContent,
|
||||
getTabContentElementByMapElement: getTabContentElementByMapElement,
|
||||
hasActiveConnection: hasActiveConnection,
|
||||
storeDefaultMapId: storeDefaultMapId,
|
||||
getLocaleData: getLocaleData,
|
||||
storeLocalData: storeLocalData,
|
||||
|
||||
@@ -64,6 +64,7 @@ define([
|
||||
Init.connectionScopes = initData.connectionScopes;
|
||||
Init.systemStatus = initData.systemStatus;
|
||||
Init.systemType = initData.systemType;
|
||||
Init.wormholes = initData.wormholes;
|
||||
Init.characterStatus = initData.characterStatus;
|
||||
Init.routes = initData.routes;
|
||||
Init.url = initData.url;
|
||||
@@ -382,7 +383,18 @@ define([
|
||||
// Send map update request on tab close/reload, in order to save map changes that
|
||||
// haven´t been saved through default update trigger
|
||||
window.addEventListener('beforeunload', function(e) {
|
||||
// save unsaved map changes ...
|
||||
triggerMapUpdatePing();
|
||||
|
||||
// check if character should be switched on reload or current character should be loaded afterwards
|
||||
let characterSwitch = Boolean( $('body').data('characterSwitch') );
|
||||
if(!characterSwitch){
|
||||
let characterId = Util.getCurrentCharacterId();
|
||||
if(characterId){
|
||||
Util.setCookie('old_char_id', characterId, 3, 's');
|
||||
}
|
||||
}
|
||||
|
||||
// IMPORTANT, return false in order to not "abort" ajax request in background!
|
||||
return false;
|
||||
});
|
||||
|
||||
@@ -4,14 +4,28 @@ define([
|
||||
'app/util',
|
||||
'app/map/map',
|
||||
'app/map/util',
|
||||
'app/counter',
|
||||
'sortable',
|
||||
'app/ui/system_info',
|
||||
'app/ui/system_graph',
|
||||
'app/ui/system_signature',
|
||||
'app/ui/system_route',
|
||||
'app/ui/system_killboard'
|
||||
], function($, Init, Util, Map, MapUtil) {
|
||||
|
||||
'app/ui/system_killboard',
|
||||
'app/ui/connection_info',
|
||||
'app/counter'
|
||||
], function(
|
||||
$,
|
||||
Init,
|
||||
Util,
|
||||
Map,
|
||||
MapUtil,
|
||||
Sortable,
|
||||
SystemInfoModule,
|
||||
SystemGraphModule,
|
||||
SystemSignatureModule,
|
||||
SystemRouteModule,
|
||||
SystemKillboardModule,
|
||||
ConnectionInfoModule
|
||||
){
|
||||
'use strict';
|
||||
|
||||
let config = {
|
||||
@@ -67,118 +81,245 @@ define([
|
||||
*/
|
||||
$.fn.setTabContentObserver = function(){
|
||||
return this.each(function(){
|
||||
let tabContentElement = $(this);
|
||||
// update Tab Content with system data information
|
||||
$(this).on('pf:drawSystemModules', function(e){
|
||||
drawSystemModules($( e.target ));
|
||||
tabContentElement.on('pf:drawSystemModules', function(e){
|
||||
drawSystemModules($(e.target));
|
||||
});
|
||||
|
||||
$(this).on('pf:removeSystemModules', function(e){
|
||||
removeSystemModules($( e.target ));
|
||||
tabContentElement.on('pf:removeSystemModules', function(e){
|
||||
removeSystemModules($(e.target));
|
||||
});
|
||||
|
||||
tabContentElement.on('pf:drawConnectionModules', function(e, data){
|
||||
drawConnectionModules($(e.target), data);
|
||||
});
|
||||
|
||||
tabContentElement.on('pf:removeConnectionModules', function(e){
|
||||
removeConnectionModules($(e.target));
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* clear all system info modules and remove them
|
||||
* remove multiple modules
|
||||
* @param tabContentElement
|
||||
* @param modules
|
||||
*/
|
||||
let removeModules = (tabContentElement, modules) => {
|
||||
for(let Module of modules){
|
||||
let moduleElement = tabContentElement.find('.' + Module.config.moduleTypeClass);
|
||||
removeModule(moduleElement, Module);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* clear all system modules and remove them
|
||||
* @param tabContentElement
|
||||
*/
|
||||
let removeSystemModules = (tabContentElement) => {
|
||||
let systemModules = [SystemInfoModule, SystemGraphModule, SystemSignatureModule, SystemRouteModule, SystemKillboardModule];
|
||||
removeModules(tabContentElement, systemModules);
|
||||
};
|
||||
|
||||
/**
|
||||
* clear all connection modules and remove them
|
||||
* @param tabContentElement
|
||||
*/
|
||||
let removeConnectionModules = (tabContentElement) => {
|
||||
let connectionModules = [ConnectionInfoModule];
|
||||
removeModules(tabContentElement, connectionModules);
|
||||
};
|
||||
|
||||
/**
|
||||
* remove a single module
|
||||
* @param moduleElement
|
||||
* @param Module
|
||||
* @param callback
|
||||
*/
|
||||
let removeSystemModules = function(tabContentElement, callback){
|
||||
tabContentElement.find('.' + config.moduleClass).velocity('transition.slideDownOut', {
|
||||
duration: Init.animationSpeed.mapModule,
|
||||
complete: function(tempElement){
|
||||
$(tempElement).remove();
|
||||
|
||||
if(callback){
|
||||
callback();
|
||||
}
|
||||
let removeModule = (moduleElement, Module, callback) => {
|
||||
if(moduleElement.length > 0){
|
||||
if(typeof Module.beforeReDraw === 'function'){
|
||||
Module.beforeReDraw();
|
||||
}
|
||||
});
|
||||
|
||||
moduleElement.velocity('reverse',{
|
||||
complete: function(moduleElement){
|
||||
moduleElement = $(moduleElement);
|
||||
if(typeof Module.beforeDestroy === 'function'){
|
||||
Module.beforeDestroy(moduleElement);
|
||||
}
|
||||
moduleElement.remove();
|
||||
|
||||
if(typeof callback === 'function'){
|
||||
callback();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* generic function that draws a modulePanel for a given Module object
|
||||
* @param parentElement
|
||||
* @param Module
|
||||
* @param mapId
|
||||
* @param data
|
||||
*/
|
||||
let drawModule = (parentElement, Module, mapId, data) => {
|
||||
/**
|
||||
* get module position within its parentElement
|
||||
* @param parentElement
|
||||
* @param Module
|
||||
* @param defaultPosition
|
||||
* @returns {number}
|
||||
*/
|
||||
let getModulePosition = (parentElement, Module, defaultPosition) => {
|
||||
let position = 0;
|
||||
if(defaultPosition > 0){
|
||||
parentElement.children().each((i, moduleElement) => {
|
||||
position = i + 1;
|
||||
let tempPosition = parseInt(moduleElement.getAttribute('data-position')) || 0;
|
||||
if(tempPosition >= defaultPosition){
|
||||
position--;
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
return position;
|
||||
};
|
||||
|
||||
/**
|
||||
* show/render a Module
|
||||
* @param parentElement
|
||||
* @param Module
|
||||
* @param mapId
|
||||
* @param data
|
||||
*/
|
||||
let showPanel = (parentElement, Module, mapId, data) => {
|
||||
let moduleElement = Module.getModule(parentElement, mapId, data);
|
||||
if (moduleElement) {
|
||||
// store Module object to DOM element for further access
|
||||
moduleElement.data('module', Module);
|
||||
moduleElement.data('data', data);
|
||||
moduleElement.addClass([config.moduleClass, Module.config.moduleTypeClass].join(' '));
|
||||
moduleElement.css({opacity: 0}); // will be animated
|
||||
|
||||
// check module position from local storage
|
||||
let promiseStore = MapUtil.getLocaleData('map', mapId);
|
||||
promiseStore.then(function (dataStore) {
|
||||
let Module = this.moduleElement.data('module');
|
||||
let defaultPosition = Module.config.modulePosition || 0;
|
||||
|
||||
// check for stored module order in indexDB (client) ----------------------------------------------
|
||||
let key = 'modules_cell_' + this.parentElement.attr('data-position');
|
||||
if (
|
||||
dataStore &&
|
||||
dataStore[key]
|
||||
) {
|
||||
let positionIndex = dataStore[key].indexOf(Module.config.moduleName);
|
||||
if (positionIndex !== -1) {
|
||||
// first index (0) => is position 1
|
||||
defaultPosition = positionIndex + 1;
|
||||
}
|
||||
}
|
||||
|
||||
// find correct position for new moduleElement ----------------------------------------------------
|
||||
let position = getModulePosition(this.parentElement, Module, defaultPosition);
|
||||
|
||||
this.moduleElement.attr('data-position', defaultPosition);
|
||||
this.moduleElement.attr('data-module', Module.config.moduleName);
|
||||
|
||||
// insert at correct position ---------------------------------------------------------------------
|
||||
let prevModuleElement = this.parentElement.find('.' + config.moduleClass + ':nth-child(' + position + ')');
|
||||
if (prevModuleElement.length) {
|
||||
this.moduleElement.insertAfter(prevModuleElement);
|
||||
} else {
|
||||
this.parentElement.prepend(this.moduleElement);
|
||||
}
|
||||
|
||||
if(typeof Module.beforeShow === 'function'){
|
||||
Module.beforeShow(this.moduleElement, moduleElement.data('data'));
|
||||
}
|
||||
|
||||
// show animation ---------------------------------------------------------------------------------
|
||||
this.moduleElement.velocity({
|
||||
opacity: [1, 0],
|
||||
translateY: [0, +20]
|
||||
}, {
|
||||
duration: Init.animationSpeed.mapModule,
|
||||
easing: 'easeOutSine',
|
||||
complete: function (moduleElement) {
|
||||
moduleElement = $(moduleElement);
|
||||
let Module = $(moduleElement).data('module');
|
||||
if (typeof Module.initModule === 'function') {
|
||||
Module.initModule(moduleElement, mapId, moduleElement.data('data'));
|
||||
}
|
||||
}
|
||||
});
|
||||
}.bind({
|
||||
parentElement: parentElement,
|
||||
moduleElement: moduleElement
|
||||
}));
|
||||
}
|
||||
};
|
||||
|
||||
// check if module already exists
|
||||
let moduleElement = parentElement.find('.' + Module.config.moduleTypeClass);
|
||||
if(moduleElement.length > 0){
|
||||
removeModule(moduleElement, Module, () => {
|
||||
showPanel(parentElement, Module, mapId, data);
|
||||
});
|
||||
}else{
|
||||
showPanel(parentElement, Module, mapId, data);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* clears and updates the system info element (signature table, system info,...)
|
||||
* @param tabContentElement
|
||||
*/
|
||||
let drawSystemModules = function(tabContentElement){
|
||||
require(['datatables.loader'], () => {
|
||||
let drawSystemModules = (tabContentElement) => {
|
||||
require(['datatables.loader'], function(){
|
||||
let currentSystemData = Util.getCurrentSystemData();
|
||||
|
||||
// get Table cell for system Info
|
||||
let firstCell = $(tabContentElement).find('.' + config.mapTabContentCellFirst);
|
||||
let secondCell = $(tabContentElement).find('.' + config.mapTabContentCellSecond);
|
||||
// get grid cells
|
||||
let firstCell = tabContentElement.find('.' + config.mapTabContentCellFirst);
|
||||
let secondCell = tabContentElement.find('.' + config.mapTabContentCellSecond);
|
||||
|
||||
// draw system info module
|
||||
firstCell.drawSystemInfoModule(currentSystemData.mapId, currentSystemData.systemData);
|
||||
drawModule(firstCell, SystemInfoModule, currentSystemData.mapId, currentSystemData.systemData);
|
||||
|
||||
// draw system graph module
|
||||
firstCell.drawSystemGraphModule(currentSystemData.systemData);
|
||||
drawModule(firstCell, SystemGraphModule, currentSystemData.mapId, currentSystemData.systemData);
|
||||
|
||||
// draw signature table module
|
||||
firstCell.drawSignatureTableModule(currentSystemData.mapId, currentSystemData.systemData);
|
||||
drawModule(firstCell, SystemSignatureModule, currentSystemData.mapId, currentSystemData.systemData);
|
||||
|
||||
// draw system routes module
|
||||
secondCell.drawSystemRouteModule(currentSystemData.mapId, currentSystemData.systemData);
|
||||
drawModule(secondCell, SystemRouteModule, currentSystemData.mapId, currentSystemData.systemData);
|
||||
|
||||
// draw system killboard module
|
||||
secondCell.drawSystemKillboardModule(currentSystemData.systemData);
|
||||
|
||||
// set Module Observer
|
||||
setModuleObserver();
|
||||
drawModule(secondCell, SystemKillboardModule, currentSystemData.mapId, currentSystemData.systemData);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* set observer for each module
|
||||
* clears and updates the connection info element (mass log)
|
||||
* @param tabContentElement
|
||||
* @param data
|
||||
*/
|
||||
let setModuleObserver = function(){
|
||||
let drawConnectionModules = (tabContentElement, data) => {
|
||||
require(['datatables.loader'], function(){
|
||||
|
||||
// toggle height for a module
|
||||
$(document).off('click.toggleModuleHeight').on('click.toggleModuleHeight', '.' + config.moduleClass, function(e){
|
||||
let moduleElement = $(this);
|
||||
// get click position
|
||||
let posX = moduleElement.offset().left;
|
||||
let posY = moduleElement.offset().top;
|
||||
let clickX = e.pageX - posX;
|
||||
let clickY = e.pageY - posY;
|
||||
// get grid cells
|
||||
let firstCell = $(tabContentElement).find('.' + config.mapTabContentCellFirst);
|
||||
|
||||
// check for top-left click
|
||||
if(clickX <= 8 && clickY <= 8){
|
||||
|
||||
// remember height
|
||||
if(! moduleElement.data('origHeight')){
|
||||
|
||||
moduleElement.data('origHeight', moduleElement.outerHeight());
|
||||
}
|
||||
|
||||
if(moduleElement.hasClass( config.moduleClosedClass )){
|
||||
let moduleHeight = moduleElement.data('origHeight');
|
||||
moduleElement.velocity('finish').velocity({
|
||||
height: [ moduleHeight + 'px', [ 400, 15 ] ]
|
||||
},{
|
||||
duration: 400,
|
||||
easing: 'easeOutSine',
|
||||
complete: function(){
|
||||
moduleElement.removeClass( config.moduleClosedClass );
|
||||
moduleElement.removeData();
|
||||
}
|
||||
});
|
||||
}else{
|
||||
moduleElement.velocity('finish').velocity({
|
||||
height: [ '35px', [ 400, 15 ] ]
|
||||
},{
|
||||
duration: 400,
|
||||
easing: 'easeOutSine',
|
||||
complete: function(){
|
||||
moduleElement.addClass( config.moduleClosedClass );
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
// draw connection info module
|
||||
drawModule(firstCell, ConnectionInfoModule, this.mapId, this.connections);
|
||||
}.bind(data));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* updates only visible/active map module
|
||||
* @returns {boolean}
|
||||
@@ -236,26 +377,115 @@ define([
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* set observer for tab content (area where modules will be shown)
|
||||
* @param contentStructure
|
||||
* @param mapId
|
||||
*/
|
||||
let setContentStructureObserver = (contentStructure, mapId) => {
|
||||
contentStructure.find('.' + config.mapTabContentCell).each((index, cellElement) => {
|
||||
let sortable = Sortable.create(cellElement, {
|
||||
group: {
|
||||
name: 'cell_' + cellElement.getAttribute('data-position')
|
||||
},
|
||||
animation: Init.animationSpeed.mapModule,
|
||||
handle: '.pf-module-handler-drag',
|
||||
draggable: '.' + config.moduleClass,
|
||||
ghostClass: 'pf-sortable-ghost',
|
||||
scroll: true,
|
||||
scrollSensitivity: 50,
|
||||
scrollSpeed: 20,
|
||||
dataIdAttr: 'data-module',
|
||||
sort: true,
|
||||
store: {
|
||||
get: function (sortable) {
|
||||
return [];
|
||||
},
|
||||
set: function (sortable) {
|
||||
let key = 'modules_' + sortable.options.group.name;
|
||||
MapUtil.storeLocalData('map', mapId, key, sortable.toArray());
|
||||
}
|
||||
},
|
||||
onStart: function (e) {
|
||||
// Element dragging started
|
||||
// -> save initial sort state -> see store.set()
|
||||
this.save();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// toggle height for a module
|
||||
contentStructure.on('click.toggleModuleHeight', '.' + config.moduleClass, function(e){
|
||||
let moduleElement = $(this);
|
||||
// get click position
|
||||
let posX = moduleElement.offset().left;
|
||||
let posY = moduleElement.offset().top;
|
||||
let clickX = e.pageX - posX;
|
||||
let clickY = e.pageY - posY;
|
||||
|
||||
// check for top-left click
|
||||
if(clickX <= 8 && clickY <= 8){
|
||||
|
||||
// remember height
|
||||
if(! moduleElement.data('origHeight')){
|
||||
|
||||
moduleElement.data('origHeight', moduleElement.outerHeight());
|
||||
}
|
||||
|
||||
if(moduleElement.hasClass( config.moduleClosedClass )){
|
||||
let moduleHeight = moduleElement.data('origHeight');
|
||||
moduleElement.velocity('finish').velocity({
|
||||
height: [ moduleHeight + 'px', [ 400, 15 ] ]
|
||||
},{
|
||||
duration: 400,
|
||||
easing: 'easeOutSine',
|
||||
complete: function(){
|
||||
moduleElement.removeClass( config.moduleClosedClass );
|
||||
moduleElement.removeData('origHeight');
|
||||
}
|
||||
});
|
||||
}else{
|
||||
moduleElement.velocity('finish').velocity({
|
||||
height: [ '35px', [ 400, 15 ] ]
|
||||
},{
|
||||
duration: 400,
|
||||
easing: 'easeOutSine',
|
||||
complete: function(){
|
||||
moduleElement.addClass( config.moduleClosedClass );
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* load all structure elements into a TabsContent div (tab body)
|
||||
*/
|
||||
$.fn.initContentStructure = function(){
|
||||
return this.each(function(){
|
||||
// init bootstrap Grid
|
||||
let contentStructure = $('<div>', {
|
||||
class: ['row', config.mapTabContentRow].join(' ')
|
||||
}).append(
|
||||
let initContentStructure = (tabContentElements) => {
|
||||
tabContentElements.each(function(){
|
||||
let tabContentElement = $(this);
|
||||
let mapId = parseInt( tabContentElement.attr('data-mapid') );
|
||||
|
||||
// "add" tab does not need a structure and obervers...
|
||||
if(mapId > 0){
|
||||
let contentStructure = $('<div>', {
|
||||
class: ['row', config.mapTabContentRow].join(' ')
|
||||
}).append(
|
||||
$('<div>', {
|
||||
class: ['col-xs-12', 'col-md-8', config.mapTabContentCellFirst, config.mapTabContentCell].join(' ')
|
||||
})
|
||||
}).attr('data-position', 1)
|
||||
).append(
|
||||
$('<div>', {
|
||||
class: ['col-xs-12', 'col-md-4', config.mapTabContentCellSecond, config.mapTabContentCell].join(' ')
|
||||
})
|
||||
}).attr('data-position', 2)
|
||||
);
|
||||
|
||||
// append grid structure
|
||||
$(this).append(contentStructure);
|
||||
// append grid structure
|
||||
tabContentElement.append(contentStructure);
|
||||
|
||||
setContentStructureObserver(contentStructure, mapId);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
@@ -264,7 +494,7 @@ define([
|
||||
* @param options
|
||||
* @returns {*|jQuery|HTMLElement}
|
||||
*/
|
||||
let getTabElement = function(options){
|
||||
let getTabElement = (options) => {
|
||||
let tabElement = $('<div>', {
|
||||
id: config.mapTabElementId
|
||||
});
|
||||
@@ -401,17 +631,17 @@ define([
|
||||
// update Tab element -> set data
|
||||
linkElement.updateTabData(options);
|
||||
|
||||
// tabs content =======================================================
|
||||
// tabs content -----------------------------------------------------------------------------------------------
|
||||
let contentElement = $('<div>', {
|
||||
id: config.mapTabIdPrefix + parseInt( options.id ),
|
||||
class: [config.mapTabContentClass].join(' ')
|
||||
});
|
||||
}).attr('data-mapid', parseInt( options.id ));
|
||||
|
||||
contentElement.addClass('tab-pane');
|
||||
|
||||
tabContent.append(contentElement);
|
||||
|
||||
// init tab ===========================================================
|
||||
// init tab ---------------------------------------------------------------------------------------------------
|
||||
linkElement.on('click', function(e){
|
||||
e.preventDefault();
|
||||
|
||||
@@ -603,7 +833,7 @@ define([
|
||||
newTabElements.contentElement.setTabContentObserver();
|
||||
|
||||
// load all the structure elements for the new tab
|
||||
newTabElements.contentElement.initContentStructure();
|
||||
initContentStructure(newTabElements.contentElement);
|
||||
|
||||
tabsChanged = true;
|
||||
|
||||
@@ -671,7 +901,7 @@ define([
|
||||
mapKeyTabSelector = 'nth-child(' + ( mapDataIndex + 1 ) + ')';
|
||||
}
|
||||
|
||||
// ==============================================================
|
||||
// ----------------------------------------------------------------------------------------------------
|
||||
|
||||
// this new created module
|
||||
let tabContentElements = tabMapElement.find('.' + config.mapTabContentClass);
|
||||
@@ -680,7 +910,7 @@ define([
|
||||
tabContentElements.setTabContentObserver();
|
||||
|
||||
// load all the structure elements for ALL Tab Content Body
|
||||
tabContentElements.initContentStructure();
|
||||
initContentStructure(tabContentElements);
|
||||
|
||||
// set first Tab active
|
||||
tabMapElement.find('.' + config.mapTabClass + ':' + mapKeyTabSelector + ' a').tab('show');
|
||||
|
||||
124
js/app/page.js
124
js/app/page.js
@@ -120,8 +120,8 @@ define([
|
||||
// load right menu
|
||||
$('.' + config.pageSlidebarRightClass).loadRightMenu();
|
||||
|
||||
// set document observer for global events
|
||||
setDocumentObserver();
|
||||
// set page observer for global events
|
||||
setPageObserver();
|
||||
});
|
||||
};
|
||||
|
||||
@@ -568,7 +568,7 @@ define([
|
||||
/**
|
||||
* catch all global document events
|
||||
*/
|
||||
let setDocumentObserver = function(){
|
||||
let setPageObserver = function(){
|
||||
|
||||
// on "full-screen" change event
|
||||
$(document).on('fscreenchange', function(e, state, elem){
|
||||
@@ -696,6 +696,10 @@ define([
|
||||
|
||||
// END menu events =============================================================================
|
||||
|
||||
// global "modal" callback (for all modals)
|
||||
$('body').on('hide.bs.modal', '> .modal', function(a,b) {
|
||||
$(this).destroyTimestampCounter();
|
||||
});
|
||||
|
||||
// update header links with current map data
|
||||
$(document).on('pf:updateHeaderMapData', function(e, data){
|
||||
@@ -783,45 +787,70 @@ define([
|
||||
$.fn.updateHeaderUserData = function(){
|
||||
let userData = Util.getCurrentUserData();
|
||||
|
||||
let userInfoElement = $('.' + config.headUserCharacterClass);
|
||||
let currentCharacterId = userInfoElement.data('characterId');
|
||||
let currentCharactersOptionIds = userInfoElement.data('characterOptionIds') ? userInfoElement.data('characterOptionIds') : [];
|
||||
let newCharacterId = 0;
|
||||
let newCharacterName = '';
|
||||
let userInfoElement = $('.' + config.headUserCharacterClass);
|
||||
let currentCharacterId = userInfoElement.data('characterId');
|
||||
let currentCharactersOptionIds = userInfoElement.data('characterOptionIds') ? userInfoElement.data('characterOptionIds') : [];
|
||||
let newCharacterId = 0;
|
||||
let newCharacterName = '';
|
||||
|
||||
let userShipElement = $('.' + config.headUserShipClass);
|
||||
let currentShipId = userShipElement.data('shipId');
|
||||
let newShipId = 0;
|
||||
let newShipName = '';
|
||||
let userShipElement = $('.' + config.headUserShipClass);
|
||||
let currentShipData = userShipElement.data('shipData');
|
||||
let currentShipId = Util.getObjVal(currentShipData, 'typeId') || 0;
|
||||
let newShipData = {
|
||||
typeId: 0,
|
||||
typeName: ''
|
||||
};
|
||||
|
||||
// function for header element toggle animation
|
||||
let animateHeaderElement = function(element, callback, triggerShow){
|
||||
let animateHeaderElement = (element, callback, triggerShow) => {
|
||||
let currentOpacity = parseInt(element.css('opacity'));
|
||||
|
||||
element.show().velocity('stop').velocity({
|
||||
opacity: 0
|
||||
},{
|
||||
visibility : 'hidden',
|
||||
duration: 500,
|
||||
complete: function(){
|
||||
// callback
|
||||
callback();
|
||||
let showHeaderElement = (element) => {
|
||||
element.show().velocity({
|
||||
opacity: [ 1, 0 ]
|
||||
},{
|
||||
// display: 'block',
|
||||
visibility : 'visible',
|
||||
duration: 1000
|
||||
});
|
||||
};
|
||||
|
||||
// show element
|
||||
if(triggerShow === true){
|
||||
element.velocity({
|
||||
opacity: 1
|
||||
}, {
|
||||
visibility : 'visible',
|
||||
duration: 500
|
||||
});
|
||||
}else{
|
||||
// hide element
|
||||
let hideHeaderElement = (element, callback) => {
|
||||
element.velocity('stop').velocity({
|
||||
opacity: [ 0, 1 ]
|
||||
},{
|
||||
// display: 'none',
|
||||
visibility : 'hidden',
|
||||
duration: 1000,
|
||||
complete: function(){
|
||||
element.hide();
|
||||
// callback
|
||||
callback($(this));
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
// run show/hide toggle in the correct order
|
||||
if(currentOpacity > 0 && triggerShow){
|
||||
// hide then show animation
|
||||
hideHeaderElement(element, (element) => {
|
||||
callback(element);
|
||||
showHeaderElement(element);
|
||||
});
|
||||
}else if(currentOpacity > 0 && !triggerShow){
|
||||
// hide animation
|
||||
hideHeaderElement(element, (element) => {
|
||||
element.hide();
|
||||
callback(element);
|
||||
});
|
||||
}else if(currentOpacity === 0 && triggerShow){
|
||||
// show animation
|
||||
callback(element);
|
||||
showHeaderElement(element);
|
||||
}else{
|
||||
// no animation
|
||||
callback(element);
|
||||
}
|
||||
};
|
||||
|
||||
// check for character/ship changes ---------------------------------------------
|
||||
@@ -833,8 +862,7 @@ define([
|
||||
newCharacterName = userData.character.name;
|
||||
|
||||
if(userData.character.log){
|
||||
newShipId = userData.character.log.ship.typeId;
|
||||
newShipName = userData.character.log.ship.typeName;
|
||||
newShipData = userData.character.log.ship;
|
||||
}
|
||||
|
||||
// en/disable "map tracking" toggle
|
||||
@@ -854,7 +882,7 @@ define([
|
||||
}
|
||||
|
||||
// toggle element
|
||||
animateHeaderElement(userInfoElement, function(){
|
||||
animateHeaderElement(userInfoElement, (userInfoElement) => {
|
||||
if(currentCharacterChanged){
|
||||
userInfoElement.find('span').text( newCharacterName );
|
||||
userInfoElement.find('img').attr('src', Init.url.ccpImageServer + '/Character/' + newCharacterId + '_32.jpg' );
|
||||
@@ -869,21 +897,21 @@ define([
|
||||
}
|
||||
|
||||
// update user ship data --------------------------------------------------------
|
||||
if(currentShipId !== newShipId){
|
||||
if(currentShipId !== newShipData.typeId){
|
||||
// set new data for next check
|
||||
userShipElement.data('shipData', newShipData);
|
||||
|
||||
let showShipElement = true;
|
||||
if(newShipId === 0){
|
||||
showShipElement = false;
|
||||
}
|
||||
let showShipElement = newShipData.typeId > 0;
|
||||
|
||||
// toggle element
|
||||
animateHeaderElement(userShipElement, function(){
|
||||
userShipElement.find('span').text( newShipName );
|
||||
userShipElement.find('img').attr('src', Init.url.ccpImageServer + '/Render/' + newShipId + '_32.png' );
|
||||
animateHeaderElement(userShipElement, (userShipElement) => {
|
||||
userShipElement.find('span').text( newShipData.typeName );
|
||||
userShipElement.find('img').attr('src', Init.url.ccpImageServer + '/Render/' + newShipData.typeId + '_32.png' );
|
||||
// trigger ship change event
|
||||
$(document).trigger('pf:activeShip', {
|
||||
shipData: newShipData
|
||||
});
|
||||
}, showShipElement);
|
||||
|
||||
// set new id for next check
|
||||
userShipElement.data('shipId', newShipId);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ define(['jquery', 'mustache'], function($, Mustache) {
|
||||
typeof config.functions === 'object' &&
|
||||
typeof config.functions[functionName] === 'function'
|
||||
){
|
||||
config.functions[functionName]();
|
||||
config.functions[functionName](config);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -27,16 +27,13 @@ define(['jquery', 'mustache'], function($, Mustache) {
|
||||
* @param data
|
||||
*/
|
||||
let showModule = function(config, data){
|
||||
|
||||
// require module template
|
||||
requirejs(['text!templates/' + config.name + '.html'], function(template) {
|
||||
|
||||
// check for an id, if module already exists, do not insert again
|
||||
if(
|
||||
data.id === 'undefined' ||
|
||||
$('#' + data.id).length === 0
|
||||
){
|
||||
|
||||
let content = Mustache.render(template, data);
|
||||
|
||||
// display module
|
||||
@@ -57,8 +54,6 @@ define(['jquery', 'mustache'], function($, Mustache) {
|
||||
|
||||
// init module function after render
|
||||
initModule('after', config);
|
||||
|
||||
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
971
js/app/ui/connection_info.js
Normal file
971
js/app/ui/connection_info.js
Normal file
@@ -0,0 +1,971 @@
|
||||
/**
|
||||
* connection info module
|
||||
*/
|
||||
|
||||
define([
|
||||
'jquery',
|
||||
'app/init',
|
||||
'app/util',
|
||||
'app/map/util'
|
||||
], ($, Init, Util, MapUtil) => {
|
||||
'use strict';
|
||||
|
||||
let config = {
|
||||
// module info
|
||||
modulePosition: 1,
|
||||
moduleName: 'connectionInfo',
|
||||
moduleHeadClass: 'pf-module-head', // class for module header
|
||||
moduleHandlerClass: 'pf-module-handler-drag', // class for "drag" handler
|
||||
|
||||
headUserShipClass: 'pf-head-user-ship', // class for "user settings" link
|
||||
|
||||
// connection info module
|
||||
moduleTypeClass: 'pf-connection-info-module', // class for this module
|
||||
|
||||
// headline toolbar
|
||||
moduleHeadlineIconClass: 'pf-module-icon-button', // class for toolbar icons in the head
|
||||
moduleHeadlineIconRefreshClass: 'pf-module-icon-button-refresh', // class for "refresh" icon
|
||||
moduleHeadlineIconCurrentMassClass: 'pf-module-icon-button-mass', // class for "current ship mass" toggle icon
|
||||
|
||||
connectionInfoPanelClass: 'pf-connection-info-panel', // class for connection info panels
|
||||
connectionInfoPanelId: 'pf-connection-info-panel-', // id prefix for connection info panels
|
||||
|
||||
// info table
|
||||
moduleTableClass: 'pf-module-table', // class for module tables
|
||||
connectionInfoTableLabelSourceClass: 'pf-connection-info-label-source', // class for source label
|
||||
connectionInfoTableLabelTargetClass: 'pf-connection-info-label-target', // class for target label
|
||||
connectionInfoTableRowMassShipClass: 'pf-connection-info-row-mass-ship', // class for "current ship mass" table row
|
||||
connectionInfoTableCellMassTotalTooltipClass: 'pf-connection-info-mass-total-tooltip', // class for "mass total tooltip" table cell
|
||||
connectionInfoTableCellMassTotalClass: 'pf-connection-info-mass-total', // class for "mass total" table cell
|
||||
connectionInfoTableCellMassLogClass: 'pf-connection-info-mass-log', // class for "mass log" table cell
|
||||
connectionInfoTableCellMassShipClass: 'pf-connection-info-mass-ship', // class for "current ship mass" table cell
|
||||
connectionInfoTableCellMassLeftClass: 'pf-connection-info-mass-left', // class for "mass left" table cell
|
||||
|
||||
connectionInfoTableTooltipIconClass: 'pf-connection-info-tooltip-icon', // class for "tooltip" icon
|
||||
connectionInfoTableWarningIconClass: 'pf-connection-info-warning-icon', // class for "warning" icon
|
||||
|
||||
// dataTable
|
||||
connectionInfoTableClass: 'pf-connection-info-table', // class for connection tables
|
||||
tableCellImageClass: 'pf-table-image-cell', // class for table "image" cells
|
||||
tableCellCounterClass: 'pf-table-counter-cell', // class for table "counter" cells
|
||||
|
||||
// config
|
||||
showShip: true // default for "show current ship mass" toggle
|
||||
};
|
||||
|
||||
/**
|
||||
* get module toolbar element
|
||||
* @returns {*|jQuery|HTMLElement|void}
|
||||
*/
|
||||
let getHeadlineToolbar = () => {
|
||||
let headlineToolbar = $('<h5>', {
|
||||
class: 'pull-right'
|
||||
}).append(
|
||||
$('<i>', {
|
||||
class: ['fa', 'fa-fw', 'fa-male',
|
||||
config.showShip ? 'active' : '' ,
|
||||
config.moduleHeadlineIconClass,
|
||||
config.moduleHeadlineIconCurrentMassClass].join(' '),
|
||||
title: 'toggle current ship mass'
|
||||
}).attr('data-html', 'true').attr('data-toggle', 'tooltip'),
|
||||
$('<i>', {
|
||||
class: ['fa', 'fa-fw', 'fa-refresh',
|
||||
config.moduleHeadlineIconClass,
|
||||
config.moduleHeadlineIconRefreshClass].join(' '),
|
||||
title: 'refresh all'
|
||||
}).attr('data-html', 'true').attr('data-toggle', 'tooltip')
|
||||
);
|
||||
|
||||
headlineToolbar.find('[data-toggle="tooltip"]').tooltip({
|
||||
container: 'body'
|
||||
});
|
||||
|
||||
return headlineToolbar;
|
||||
};
|
||||
|
||||
/**
|
||||
* get new connection element
|
||||
* @param mapId
|
||||
* @param connectionId
|
||||
* @returns {jQuery}
|
||||
*/
|
||||
let getConnectionElement = (mapId, connectionId) => {
|
||||
let connectionElement = $('<div>', {
|
||||
id: getConnectionElementId(connectionId),
|
||||
class: ['col-xs-12', 'col-sm-4', 'col-lg-3' , config.connectionInfoPanelClass].join(' ')
|
||||
}).data({
|
||||
mapId: mapId,
|
||||
connectionId: connectionId
|
||||
});
|
||||
|
||||
return connectionElement;
|
||||
};
|
||||
|
||||
/**
|
||||
* get info control panel element
|
||||
* @param mapId
|
||||
* @returns {void|jQuery|*}
|
||||
*/
|
||||
let getInfoPanelControl = (mapId) => {
|
||||
let connectionElement = getConnectionElement(mapId, 0).append($('<div>', {
|
||||
class: 'pf-dynamic-area',
|
||||
html: '<i class="fa fa-fw fa-plus"></i> add connection <kbd>ctrl</kbd> + <kbd>click</kbd>'
|
||||
}));
|
||||
|
||||
return connectionElement;
|
||||
};
|
||||
|
||||
/**
|
||||
* get connection information element
|
||||
* @param connectionData
|
||||
* @returns {void|*|jQuery|HTMLElement}
|
||||
*/
|
||||
let getInformationElement = (connectionData) => {
|
||||
|
||||
// connection scope -----------------------------------------------------------------------
|
||||
let scopeLabel = MapUtil.getScopeInfoForConnection(connectionData.scope, 'label');
|
||||
|
||||
// connection type (dummy) classes --------------------------------------------------------
|
||||
let connectionClasses = ['pf-fake-connection'];
|
||||
for(let i = 0; i < connectionData.type.length; i++){
|
||||
connectionClasses.push( MapUtil.getConnectionInfo( connectionData.type[i], 'cssClass') );
|
||||
}
|
||||
|
||||
let massLog = 0;
|
||||
|
||||
let element = $('<div>', {
|
||||
class: 'pf-dynamic-area'
|
||||
}).append(
|
||||
$('<table>', {
|
||||
class: ['table', 'table-condensed', 'pf-table-fixed', config.moduleTableClass].join(' ')
|
||||
}).data('showShip', config.showShip).append(
|
||||
$('<thead>').append(
|
||||
$('<tr>').append(
|
||||
$('<th>', {
|
||||
class: ['pf-table-cell-20', 'text-right', 'pf-help', 'pf-pie-chart'].join(' ')
|
||||
}).attr('data-toggle', 'tooltip').attr('data-percent', '-100').easyPieChart({
|
||||
barColor: (percent) => {
|
||||
let color = '#e28a0d';
|
||||
if((percent * -1) >= 100){
|
||||
color = '#a52521';
|
||||
}
|
||||
return color;
|
||||
},
|
||||
overrideOptions: 'signed',
|
||||
trackColor: '#5cb85c',
|
||||
size: 14,
|
||||
scaleColor: false,
|
||||
lineWidth: 2,
|
||||
lineCap: 'butt',
|
||||
animate: false
|
||||
}),
|
||||
$('<th>', {
|
||||
class: ['text-right'].join(' ')
|
||||
}).attr('colspan', 2).append(
|
||||
$('<span>', {
|
||||
class: 'pf-link',
|
||||
html: connectionData.sourceAlias + ' '
|
||||
}).on('click', function(){
|
||||
Util.getMapModule().getActiveMap().triggerMenuEvent('SelectSystem', {systemId: connectionData.source });
|
||||
}),
|
||||
$('<span>', {
|
||||
class: [config.connectionInfoTableLabelSourceClass].join(' ')
|
||||
}),
|
||||
$('<i>', {
|
||||
class: 'fa fa-fw fa-angle-double-right'
|
||||
}),
|
||||
$('<span>', {
|
||||
class: [config.connectionInfoTableLabelTargetClass].join(' ')
|
||||
}),
|
||||
$('<span>', {
|
||||
class: 'pf-link',
|
||||
html: ' ' + connectionData.targetAlias
|
||||
}).on('click', function(){
|
||||
Util.getMapModule().getActiveMap().triggerMenuEvent('SelectSystem', {systemId: connectionData.target });
|
||||
})
|
||||
)
|
||||
)
|
||||
),
|
||||
$('<tbody>').append(
|
||||
$('<tr>').append(
|
||||
$('<td>', {
|
||||
class: ['text-right', 'pf-help', config.connectionInfoTableCellMassTotalTooltipClass].join(' '),
|
||||
html: '<i class="fa fa-fw fa-question-circle"></i>'
|
||||
}),
|
||||
$('<td>', {
|
||||
text: scopeLabel.charAt(0).toUpperCase() + scopeLabel.slice(1)
|
||||
}),
|
||||
$('<td>', {
|
||||
class: ['text-right'].join(' ')
|
||||
}).append(
|
||||
$('<div>', {
|
||||
class: connectionClasses.join(' ')
|
||||
})
|
||||
)
|
||||
),
|
||||
$('<tr>').append(
|
||||
$('<td>', {
|
||||
class: ['text-right', 'pf-help'].join(' '),
|
||||
html: '<i class="fa fa-fw fa-question-circle"></i>',
|
||||
title: 'initial mass. From signature table'
|
||||
}).attr('data-toggle', 'tooltip'),
|
||||
$('<td>', {
|
||||
text: 'Total mass'
|
||||
}),
|
||||
$('<td>', {
|
||||
class: ['text-right', 'txt-color', config.connectionInfoTableCellMassTotalClass].join(' ')
|
||||
})
|
||||
),
|
||||
$('<tr>').append(
|
||||
$('<td>', {
|
||||
class: ['text-right', 'pf-help'].join(' '),
|
||||
html: '<i class="fa fa-fw fa-question-circle"></i>',
|
||||
title: 'recorded total jump mass'
|
||||
}).attr('data-toggle', 'tooltip'),
|
||||
$('<td>', {
|
||||
text: 'Logged mass'
|
||||
}),
|
||||
$('<td>', {
|
||||
class: ['text-right', config.connectionInfoTableCellMassLogClass].join(' ')
|
||||
})
|
||||
),
|
||||
$('<tr>', {
|
||||
class: config.connectionInfoTableRowMassShipClass
|
||||
}).append(
|
||||
$('<td>', {
|
||||
class: ['text-right', 'pf-help'].join(' '),
|
||||
title: 'current ship mass'
|
||||
}).attr('data-toggle', 'tooltip').append(
|
||||
$('<i>', {
|
||||
class: [
|
||||
'fa', 'fa-fw', 'fa-question-circle',
|
||||
config.connectionInfoTableTooltipIconClass
|
||||
].join(' ')
|
||||
}),
|
||||
$('<i>', {
|
||||
class: [
|
||||
'fa', 'fa-fw', 'fa-exclamation-triangle',
|
||||
'txt-color', 'txt-color-danger',
|
||||
'hidden', config.connectionInfoTableWarningIconClass
|
||||
].join(' ')
|
||||
})
|
||||
),
|
||||
$('<td>', {
|
||||
class: ['pf-table-cell-ellipses-auto'].join(' '),
|
||||
text: 'Ship mass'
|
||||
}),
|
||||
$('<td>', {
|
||||
class: ['text-right', 'txt-color', config.connectionInfoTableCellMassShipClass].join(' ')
|
||||
})
|
||||
),
|
||||
$('<tr>').append(
|
||||
$('<td>', {
|
||||
class: ['text-right', 'pf-help'].join(' '),
|
||||
html: '<i class="fa fa-fw fa-question-circle"></i>',
|
||||
title: 'max. mass left'
|
||||
}).attr('data-toggle', 'tooltip'),
|
||||
$('<td>', {
|
||||
text: 'Mass left'
|
||||
}),
|
||||
$('<td>', {
|
||||
class: ['text-right', 'txt-color', config.connectionInfoTableCellMassLeftClass].join(' ')
|
||||
})
|
||||
)
|
||||
)
|
||||
).on('pf:updateInfoTable', function(e, data){
|
||||
// update information table -------------------------------------------------------
|
||||
let tableElement = $(this);
|
||||
let connectionData = tableElement.data('connectionData');
|
||||
if(connectionData){
|
||||
if(connectionData.scope === 'wh'){
|
||||
// update signature information -------------------------------------------
|
||||
let sourceLabelElement = tableElement.find('.' + config.connectionInfoTableLabelSourceClass);
|
||||
let targetLabelElement = tableElement.find('.' + config.connectionInfoTableLabelTargetClass);
|
||||
|
||||
// get related jsPlumb connection
|
||||
let connection = $().getConnectionById(data.mapId, data.connectionId);
|
||||
let signatureTypeNames = MapUtil.getConnectionDataFromSignatures(connection, connectionData);
|
||||
|
||||
let sourceLabel = signatureTypeNames.sourceLabels;
|
||||
let targetLabel = signatureTypeNames.targetLabels;
|
||||
sourceLabelElement.html(MapUtil.getEndpointOverlayContent(sourceLabel));
|
||||
targetLabelElement.html(MapUtil.getEndpointOverlayContent(targetLabel));
|
||||
|
||||
// remove K162
|
||||
sourceLabel.diff(['K162']);
|
||||
targetLabel.diff(['K162']);
|
||||
|
||||
// get static wormhole data by endpoint Labels
|
||||
let wormholeName = '';
|
||||
let wormholeData = null;
|
||||
if(sourceLabel.length === 1 && targetLabel.length === 0){
|
||||
wormholeName = sourceLabel[0];
|
||||
}else if(sourceLabel.length === 0 && targetLabel.length === 1){
|
||||
wormholeName = targetLabel[0];
|
||||
}
|
||||
|
||||
if(
|
||||
wormholeName &&
|
||||
Init.wormholes.hasOwnProperty(wormholeName)
|
||||
){
|
||||
wormholeData = Object.assign({}, Init.wormholes[wormholeName]);
|
||||
wormholeData.class = Util.getSecurityClassForSystem(wormholeData.security);
|
||||
|
||||
// init wormhole tooltip ----------------------------------------------
|
||||
let massTotalTooltipCell = tableElement.find('.' + config.connectionInfoTableCellMassTotalTooltipClass);
|
||||
massTotalTooltipCell.addWormholeInfoTooltip(wormholeData);
|
||||
}
|
||||
|
||||
// all required data is set -> re-calculate rows
|
||||
tableElement.data('wormholeData', wormholeData);
|
||||
tableElement.trigger('pf:calcInfoTable');
|
||||
}
|
||||
|
||||
}
|
||||
}).on('pf:calcInfoTable', function(e){
|
||||
// re-calculate information table from .data() cell values ------------------------
|
||||
let tableElement = $(this);
|
||||
let massChartCell = tableElement.find('[data-percent]');
|
||||
|
||||
let wormholeData = tableElement.data('wormholeData');
|
||||
let shipData = null;
|
||||
let shipName = '';
|
||||
let showShip = Boolean(tableElement.data('showShip'));
|
||||
let massShipRow = tableElement.find('.' + config.connectionInfoTableRowMassShipClass);
|
||||
|
||||
// icons
|
||||
let massShipTooltipIcon = massShipRow.find('.' + config.connectionInfoTableTooltipIconClass);
|
||||
let massShipWarningIcon = massShipRow.find('.' + config.connectionInfoTableWarningIconClass);
|
||||
|
||||
// table cells
|
||||
let massTotalCell = tableElement.find('.' + config.connectionInfoTableCellMassTotalClass);
|
||||
let massLogCell = tableElement.find('.' + config.connectionInfoTableCellMassLogClass);
|
||||
let massShipCell = tableElement.find('.' + config.connectionInfoTableCellMassShipClass);
|
||||
let massLeftCell = tableElement.find('.' + config.connectionInfoTableCellMassLeftClass);
|
||||
let massTotal = null; // initial connection mass
|
||||
let massLog = massLogCell.data('mass'); // recorded mass
|
||||
let massLogTotal = massLog; // recorded mass + current ship
|
||||
let massIndividual = null; // mass mass per jump
|
||||
let massShip = 0; // current ship
|
||||
let massIndividualError = false;
|
||||
|
||||
// get wormhole data from signature binding ---------------------------------------
|
||||
if(wormholeData){
|
||||
massTotal = parseInt(wormholeData.massTotal);
|
||||
massIndividual = parseInt(wormholeData.massIndividual);
|
||||
}
|
||||
|
||||
// get current ship data ----------------------------------------------------------
|
||||
massShipCell.parent().toggle(showShip);
|
||||
if(showShip){
|
||||
shipData = $('.' + config.headUserShipClass).data('shipData');
|
||||
if(shipData){
|
||||
if(shipData.mass){
|
||||
massShip = parseInt(shipData.mass);
|
||||
|
||||
// check individual mass jump
|
||||
if(massIndividual){
|
||||
massIndividualError = massShip > massIndividual;
|
||||
}
|
||||
}
|
||||
if(shipData.typeId && shipData.typeName){
|
||||
shipName = shipData.typeName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// update ship mass and "individual mass" cells ----------------------------------
|
||||
massShipTooltipIcon.toggleClass('hidden', massIndividualError);
|
||||
massShipWarningIcon.toggleClass('hidden', !massIndividualError);
|
||||
let shipMassTooltip = 'current ship mass ' + (shipName ? '"' + shipName + '"' : '');
|
||||
if(massIndividualError){
|
||||
shipMassTooltip = '"' + shipName + '" exceeds max jump mass for this connection: ' + Util.formatMassValue(massIndividual);
|
||||
}else{
|
||||
// current ship mass check is OK -> add to massLogTotal
|
||||
massLogTotal += massShip;
|
||||
}
|
||||
massShipTooltipIcon.parent().attr('title', shipMassTooltip).tooltip('fixTitle');
|
||||
|
||||
// current ship mass --------------------------------------------------------------
|
||||
massShipCell.html( function(){
|
||||
let cell = $(this);
|
||||
let value = ' ';
|
||||
let error = false;
|
||||
let textLineThrough = false;
|
||||
if(massShip > 0){
|
||||
value += Util.formatMassValue(massShip);
|
||||
if(massIndividualError){
|
||||
error = textLineThrough = true;
|
||||
value = ' ' + value;
|
||||
}else{
|
||||
value = '-' + value;
|
||||
}
|
||||
}else{
|
||||
error = true;
|
||||
value = 'undefined';
|
||||
}
|
||||
|
||||
// change cell style
|
||||
cell.toggleClass('txt-color-red', error)
|
||||
.toggleClass('txt-color-warning', !error)
|
||||
.toggleClass('pf-font-line-through', textLineThrough);
|
||||
|
||||
return value;
|
||||
});
|
||||
|
||||
// calculate mass left ------------------------------------------------------------
|
||||
let massLeft = massTotal - massLogTotal;
|
||||
massLeft = (massLeft < 0) ? 0 : massLeft;
|
||||
let massPercentLog = (massTotal > 0) ? Math.floor((100 / massTotal) * massLogTotal) : 0;
|
||||
|
||||
// update easyPieChart and tooltip ------------------------------------------------
|
||||
let massPercentLeft = (100 - massPercentLog <= 0) ? 0 : '< ' + (100 - massPercentLog);
|
||||
massChartCell.data('easyPieChart').enableAnimation().update(massPercentLog * -1);
|
||||
massChartCell.attr('title', massPercentLeft + '% mass left').tooltip('fixTitle');
|
||||
|
||||
// update mass cells --------------------------------------------------------------
|
||||
massTotalCell.html(massTotal > 0 ? Util.formatMassValue(massTotal) : 'undefined')
|
||||
.toggleClass('txt-color-red', massTotal <= 0);
|
||||
massLogCell.html('- ' + Util.formatMassValue(massLog));
|
||||
massLeftCell.html(
|
||||
massLeft > 0 ?
|
||||
'~ ' + Util.formatMassValue(massLeft) :
|
||||
(massLeft === 0 && massTotal) ?
|
||||
'will collapse' : 'undefined')
|
||||
.toggleClass('txt-color-red', massLeft <= 0)
|
||||
.toggleClass('txt-color-success', massLeft > 0);
|
||||
})
|
||||
);
|
||||
|
||||
element.find('[data-toggle="tooltip"]').tooltip({
|
||||
container: 'body'
|
||||
});
|
||||
|
||||
return element;
|
||||
};
|
||||
|
||||
/**
|
||||
* get HTML id by connectionId
|
||||
* @param connectionId
|
||||
* @returns {string}
|
||||
*/
|
||||
let getConnectionElementId = (connectionId) => {
|
||||
return config.connectionInfoPanelId + connectionId;
|
||||
};
|
||||
|
||||
/**
|
||||
* get all visible connection panel elements
|
||||
* @param moduleElement
|
||||
* @returns {*|T|{}}
|
||||
*/
|
||||
let getConnectionElements = (moduleElement) => {
|
||||
return moduleElement.find('.' + config.connectionInfoPanelClass).not('#' + getConnectionElementId(0));
|
||||
};
|
||||
|
||||
/**
|
||||
* request connection log data
|
||||
* @param requestData
|
||||
* @param context
|
||||
* @param callback
|
||||
*/
|
||||
let requestConnectionLogData = (requestData, context, callback) => {
|
||||
// show loading animation
|
||||
for(let connectionId of requestData.connectionIds){
|
||||
context.moduleElement.find('#' + getConnectionElementId(connectionId) + ' table').showLoadingAnimation();
|
||||
}
|
||||
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: Init.path.getMapConnectionData,
|
||||
data: requestData,
|
||||
dataType: 'json',
|
||||
context: context
|
||||
}).done(function(connectionsData){
|
||||
// enrich connectionData with "logs" data (if available) and other "missing" data
|
||||
for(let i = 0; i < this.connectionsData.length; i++){
|
||||
for(let connectionData of connectionsData) {
|
||||
if(this.connectionsData[i].id === connectionData.id){
|
||||
// copy some missing data
|
||||
this.connectionsData[i].created = connectionData.created;
|
||||
// check for mass logs and copy data
|
||||
if(connectionData.logs && connectionData.logs.length){
|
||||
this.connectionsData[i].logs = connectionData.logs;
|
||||
}
|
||||
// check for signatures and copy data
|
||||
if(connectionData.signatures && connectionData.signatures.length){
|
||||
this.connectionsData[i].signatures = connectionData.signatures;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
callback(this.moduleElement, this.connectionsData);
|
||||
}).always(function(){
|
||||
// hide loading animation
|
||||
for(let contextData of this.connectionsData){
|
||||
context.moduleElement.find('#' + getConnectionElementId(contextData.id) + ' table').hideLoadingAnimation();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* @see requestConnectionLogData
|
||||
* @param moduleElement
|
||||
* @param mapId
|
||||
* @param connectionsData
|
||||
*/
|
||||
let getConnectionsLogData = (moduleElement, mapId, connectionsData) => {
|
||||
let connectionIds = [];
|
||||
for(let connectionData of connectionsData) {
|
||||
connectionIds.push(connectionData.id);
|
||||
}
|
||||
|
||||
let requestData = {
|
||||
mapId: mapId,
|
||||
connectionIds: connectionIds,
|
||||
addData : ['signatures', 'logs'],
|
||||
// filterData : ['logs'] // do not exclude connections with NO "logs" -> sig data will be used as well
|
||||
};
|
||||
|
||||
let contextData = {
|
||||
moduleElement: moduleElement,
|
||||
connectionsData: connectionsData
|
||||
};
|
||||
|
||||
requestConnectionLogData(requestData, contextData, addConnectionsData);
|
||||
};
|
||||
|
||||
/**
|
||||
* replace/insert dataTables log data
|
||||
* @param moduleElement
|
||||
* @param connectionsData
|
||||
*/
|
||||
let addConnectionsData = (moduleElement, connectionsData) => {
|
||||
|
||||
let getRowIndexesByData = (dataTable, colName, value) => {
|
||||
return dataTable.rows().eq(0).filter((rowIdx) => {
|
||||
return (dataTable.cell(rowIdx, colName + ':name' ).data() === value);
|
||||
});
|
||||
};
|
||||
|
||||
for(let connectionData of connectionsData) {
|
||||
// find related dom element for current connection
|
||||
let connectionElement = moduleElement.find('#' + getConnectionElementId(connectionData.id));
|
||||
if(connectionElement.length){
|
||||
// attach connectionData to connection information for later use ------------------
|
||||
let connectionInfoElement = connectionElement.find('.' + config.moduleTableClass);
|
||||
connectionInfoElement.data('connectionData', connectionData);
|
||||
|
||||
// update dataTable ---------------------------------------------------------------
|
||||
let dataTable = connectionElement.find('.dataTable').dataTable().api();
|
||||
|
||||
if(connectionData.logs && connectionData.logs.length > 0){
|
||||
for(let i = 0; i < connectionData.logs.length; i++){
|
||||
let rowData = connectionData.logs[i];
|
||||
let row = null;
|
||||
let animationStatus = null;
|
||||
let indexes = getRowIndexesByData(dataTable, 'index', rowData.id);
|
||||
if(indexes.length === 0){
|
||||
// row not found -> add new row
|
||||
row = dataTable.row.add( rowData );
|
||||
animationStatus = 'added';
|
||||
}
|
||||
/* else{
|
||||
// we DON´t expect changes -> no row update)
|
||||
// update row with FIRST index
|
||||
//row = dataTable.row( parseInt(indexes[0]) );
|
||||
// update row data
|
||||
//row.data(connectionData.logs[i]);
|
||||
//animationStatus = 'changed';
|
||||
} */
|
||||
|
||||
if(
|
||||
animationStatus !== null &&
|
||||
row.length > 0
|
||||
){
|
||||
row.nodes().to$().data('animationStatus', animationStatus);
|
||||
}
|
||||
}
|
||||
}else{
|
||||
// clear table or leave empty
|
||||
dataTable.clear();
|
||||
}
|
||||
|
||||
// redraw dataTable
|
||||
dataTable.draw(false);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param moduleElement
|
||||
* @param mapId
|
||||
* @param connectionData
|
||||
*/
|
||||
let updateConnectionPanel = (moduleElement, mapId, connectionData) => {
|
||||
let rowElement = moduleElement.find('.row');
|
||||
let connectionElement = rowElement.find('#' + getConnectionElementId(connectionData.id));
|
||||
|
||||
if( !connectionElement.length ){
|
||||
connectionElement = getConnectionElement(mapId, connectionData.id);
|
||||
connectionElement.append(getInformationElement(connectionData));
|
||||
|
||||
let table = $('<table>', {
|
||||
class: ['compact', 'stripe', 'order-column', 'row-border', 'nowrap', config.connectionInfoTableClass].join(' ')
|
||||
}).append('<tfoot><tr><th></th><th></th><th></th><th></th><th></th></tr></tfoot>');
|
||||
connectionElement.append(table);
|
||||
|
||||
// init empty table
|
||||
let logTable = table.DataTable({
|
||||
pageLength: 8,
|
||||
paging: true,
|
||||
pagingType: 'simple',
|
||||
lengthChange: false,
|
||||
ordering: true,
|
||||
order: [[ 4, 'desc' ]],
|
||||
info: true,
|
||||
searching: false,
|
||||
hover: false,
|
||||
autoWidth: false,
|
||||
// rowId: 'systemTo',
|
||||
language: {
|
||||
emptyTable: 'No jumps recorded',
|
||||
info: '_START_ to _END_ of _MAX_',
|
||||
infoEmpty: ''
|
||||
},
|
||||
columnDefs: [
|
||||
{
|
||||
targets: 0,
|
||||
name: 'index',
|
||||
title: '<i class="fa fa-hashtag"></i>',
|
||||
orderable: false,
|
||||
searchable: false,
|
||||
width: 20,
|
||||
class: 'text-center',
|
||||
data: 'id'
|
||||
},{
|
||||
targets: 1,
|
||||
title: '',
|
||||
width: 26,
|
||||
orderable: false,
|
||||
className: ['pf-help-default', 'text-center', config.tableCellImageClass].join(' '),
|
||||
data: 'ship',
|
||||
render: {
|
||||
_: function(data, type, row){
|
||||
let value = data.typeId;
|
||||
if(type === 'display'){
|
||||
value = '<img src="' + Init.url.ccpImageServer + '/Render/' + value + '_32.png" title="' + data.typeName + '" data-toggle="tooltip" />';
|
||||
}
|
||||
return value;
|
||||
}
|
||||
},
|
||||
createdCell: function(cell, cellData, rowData, rowIndex, colIndex){
|
||||
$(cell).find('img').tooltip();
|
||||
}
|
||||
},{
|
||||
targets: 2,
|
||||
title: '',
|
||||
width: 26,
|
||||
orderable: false,
|
||||
className: ['pf-help-default', 'text-center', config.tableCellImageClass].join(' '),
|
||||
data: 'created.character',
|
||||
render: {
|
||||
_: function(data, type, row){
|
||||
let value = data.name;
|
||||
if(type === 'display'){
|
||||
value = '<img src="' + Init.url.ccpImageServer + '/Character/' + data.id + '_32.jpg" title="' + value + '" data-toggle="tooltip" />';
|
||||
}
|
||||
return value;
|
||||
}
|
||||
},
|
||||
createdCell: function(cell, cellData, rowData, rowIndex, colIndex){
|
||||
$(cell).find('img').tooltip();
|
||||
}
|
||||
},{
|
||||
targets: 3,
|
||||
title: 'mass',
|
||||
className: ['text-right'].join(' ') ,
|
||||
data: 'ship.mass',
|
||||
render: {
|
||||
_: function(data, type, row){
|
||||
let value = data;
|
||||
if(type === 'display'){
|
||||
value = Util.formatMassValue(value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
},{
|
||||
targets: 4,
|
||||
title: 'log',
|
||||
width: 55,
|
||||
className: ['text-right', config.tableCellCounterClass].join(' '),
|
||||
data: 'created.created',
|
||||
createdCell: function(cell, cellData, rowData, rowIndex, colIndex){
|
||||
$(cell).initTimestampCounter('d');
|
||||
}
|
||||
}
|
||||
],
|
||||
drawCallback: function(settings){
|
||||
let animationRows = this.api().rows().nodes().to$().filter(function(a,b ) {
|
||||
return (
|
||||
$(this).data('animationStatus') ||
|
||||
$(this).data('animationTimer')
|
||||
);
|
||||
});
|
||||
|
||||
for(let i = 0; i < animationRows.length; i++){
|
||||
$(animationRows[i]).pulseTableRow($(animationRows[i]).data('animationStatus'));
|
||||
$(animationRows[i]).removeData('animationStatus');
|
||||
}
|
||||
|
||||
},
|
||||
footerCallback: function ( row, data, start, end, display ) {
|
||||
|
||||
let api = this.api();
|
||||
let sumColumnIndexes = [3];
|
||||
|
||||
// column data for "sum" columns over this page
|
||||
let pageTotalColumns = api
|
||||
.columns( sumColumnIndexes, { page: 'all'} )
|
||||
.data();
|
||||
|
||||
// sum columns for "total" sum
|
||||
pageTotalColumns.each((colData, index) => {
|
||||
pageTotalColumns[index] = colData.reduce((a, b) => {
|
||||
return parseInt(a) + parseInt(b);
|
||||
}, 0);
|
||||
});
|
||||
|
||||
$(sumColumnIndexes).each((index, value) => {
|
||||
$( api.column( value ).footer() ).text( Util.formatMassValue(pageTotalColumns[index]) );
|
||||
|
||||
// save mass for further reCalculation of "info" table
|
||||
connectionElement.find('.' + config.connectionInfoTableCellMassLogClass).data('mass', pageTotalColumns[index]);
|
||||
});
|
||||
|
||||
// calculate "info" table -----------------------------------------------------
|
||||
connectionElement.find('.' + config.moduleTableClass).trigger('pf:updateInfoTable', connectionElement.data());
|
||||
}
|
||||
});
|
||||
|
||||
// find position to insert
|
||||
connectionElement.insertBefore(rowElement.find('#' + getConnectionElementId(0)));
|
||||
|
||||
logTable.on('order.dt search.dt', function(){
|
||||
let pageInfo = logTable.page.info();
|
||||
logTable.column(0, {search:'applied', order:'applied'}).nodes().each((cell, i) => {
|
||||
let content = (pageInfo.recordsTotal - i) + '. ';
|
||||
$(cell).html(content);
|
||||
});
|
||||
});
|
||||
|
||||
logTable.on('destroy.dt', function(){
|
||||
$(this).destroyTimestampCounter();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* remove connection Panel from moduleElement
|
||||
* @param connectionElement
|
||||
*/
|
||||
let removeConnectionPanel = (connectionElement) => {
|
||||
connectionElement = $(connectionElement);
|
||||
if(connectionElement.length){
|
||||
// destroy dataTable (and remove table from DOM)
|
||||
let logTable = connectionElement.find('.' + config.connectionInfoTableClass);
|
||||
logTable.dataTable().api().destroy(true);
|
||||
// remove belonging connectionElement
|
||||
connectionElement.remove();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* get connections from ModuleElement
|
||||
* -> validate with current map data
|
||||
* @param moduleElement
|
||||
* @param mapId
|
||||
* @returns {{connectionsDataUpdate: Array, connectionsDataRemove: Array}}
|
||||
*/
|
||||
let getConnectionsDataFromModule = (moduleElement, mapId) => {
|
||||
let activeMap = Util.getMapModule().getActiveMap();
|
||||
let mapData = activeMap.getMapDataFromClient({forceData: true});
|
||||
let connectionsData = {
|
||||
connectionsDataUpdate: [],
|
||||
connectionsDataRemove: [],
|
||||
};
|
||||
|
||||
if(mapData !== false){
|
||||
getConnectionElements(moduleElement).each((i, connectionElement) => {
|
||||
let removeConnectionPanel = true;
|
||||
let connectionData = {id: $(connectionElement).data('connectionId') };
|
||||
|
||||
let connection = $().getConnectionById(mapId, connectionData.id);
|
||||
if(connection){
|
||||
let connectionDataTemp = MapUtil.getDataByConnection(connection);
|
||||
if(connectionDataTemp.id > 0){
|
||||
// connection still on map - OK
|
||||
removeConnectionPanel = false;
|
||||
connectionData = connectionDataTemp;
|
||||
}
|
||||
}
|
||||
|
||||
if(removeConnectionPanel){
|
||||
connectionsData.connectionsDataRemove.push(connectionData);
|
||||
}else{
|
||||
connectionsData.connectionsDataUpdate.push(connectionData);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return connectionsData;
|
||||
};
|
||||
|
||||
/**
|
||||
* update/init multiple connection panels at once
|
||||
* @param moduleElement
|
||||
* @param mapId
|
||||
* @param connectionsDataUpdate
|
||||
* @param connectionsDataRemove
|
||||
*/
|
||||
let updateConnectionPanels = (moduleElement, mapId, connectionsDataUpdate, connectionsDataRemove) => {
|
||||
for(let connectionData of connectionsDataRemove){
|
||||
let connectionElement = moduleElement.find('#' + getConnectionElementId(connectionData.id));
|
||||
removeConnectionPanel(connectionElement);
|
||||
}
|
||||
|
||||
for(let connectionData of connectionsDataUpdate){
|
||||
updateConnectionPanel(moduleElement, mapId, connectionData);
|
||||
}
|
||||
|
||||
// request connectionsLogData for each updated connection
|
||||
if(connectionsDataUpdate.length){
|
||||
getConnectionsLogData(moduleElement, mapId, connectionsDataUpdate);
|
||||
}
|
||||
|
||||
// remove module if no connection panel left
|
||||
// --> all connection deselected on map
|
||||
let connectionElements = getConnectionElements(moduleElement);
|
||||
if(connectionElements.length === 0){
|
||||
MapUtil.getTabContentElementByMapElement(moduleElement).trigger('pf:removeConnectionModules');
|
||||
}
|
||||
|
||||
// hide "control" panel when multiple connection
|
||||
moduleElement.find('#' + getConnectionElementId(0)).toggle(connectionElements.length < 2);
|
||||
};
|
||||
|
||||
/**
|
||||
* set module observer
|
||||
* @param moduleElement
|
||||
* @param mapId
|
||||
*/
|
||||
let setModuleObserver = (moduleElement, mapId) => {
|
||||
$(document).off('pf:updateConnectionInfoModule').on('pf:updateConnectionInfoModule', function(e, data){
|
||||
updateConnectionPanels(
|
||||
moduleElement,
|
||||
data.mapId,
|
||||
MapUtil.getDataByConnections(data.connectionsUpdate),
|
||||
MapUtil.getDataByConnections(data.connectionsRemove)
|
||||
);
|
||||
});
|
||||
|
||||
$(document).off('pf:activeShip').on('pf:activeShip', function(e){
|
||||
moduleElement.find('.' + config.connectionInfoPanelClass).each((i, connectionElement) => {
|
||||
$(connectionElement).find('.' + config.moduleTableClass).each((i, tableElement) => {
|
||||
$(tableElement).trigger('pf:calcInfoTable');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// init toggle active ship ----------------------------------------------------------------
|
||||
moduleElement.find('.' + config.moduleHeadlineIconCurrentMassClass).on('click', function(e){
|
||||
let currentMassIcon = $(this).toggleClass('active');
|
||||
moduleElement.find('.' + config.connectionInfoPanelClass).each((i, connectionElement) => {
|
||||
$(connectionElement).find('.' + config.moduleTableClass).each((i, tableElement) => {
|
||||
$(tableElement).data('showShip', currentMassIcon.hasClass('active')).trigger('pf:calcInfoTable');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// init refresh connections ---------------------------------------------------------------
|
||||
moduleElement.find('.' + config.moduleHeadlineIconRefreshClass).on('click', function(e){
|
||||
refreshConnectionPanels(moduleElement, mapId);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* refresh all connection panels in a module
|
||||
* @param moduleElement
|
||||
* @param mapId
|
||||
*/
|
||||
let refreshConnectionPanels = (moduleElement, mapId) => {
|
||||
let connectionsData = getConnectionsDataFromModule(moduleElement, mapId);
|
||||
updateConnectionPanels(moduleElement, mapId, connectionsData.connectionsDataUpdate, connectionsData.connectionsDataRemove);
|
||||
};
|
||||
|
||||
/**
|
||||
* before module destroy callback
|
||||
* @param moduleElement
|
||||
*/
|
||||
let beforeDestroy = (moduleElement) => {
|
||||
getConnectionElements(moduleElement).each((i, connectionElement) => {
|
||||
removeConnectionPanel(connectionElement);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* init callback
|
||||
* @param moduleElement
|
||||
* @param mapId
|
||||
* @param connectionData
|
||||
*/
|
||||
let initModule = (moduleElement, mapId, connectionData) => {
|
||||
setModuleObserver(moduleElement, mapId);
|
||||
};
|
||||
|
||||
/**
|
||||
* get module element
|
||||
* @param parentElement
|
||||
* @param mapId
|
||||
* @param connections
|
||||
* @returns {*|jQuery|HTMLElement}
|
||||
*/
|
||||
let getModule = (parentElement, mapId, connections) => {
|
||||
// create new module container
|
||||
let moduleElement = $('<div>').append(
|
||||
$('<div>', {
|
||||
class: config.moduleHeadClass
|
||||
}).append(
|
||||
$('<h5>', {
|
||||
class: config.moduleHandlerClass
|
||||
}),
|
||||
$('<h5>', {
|
||||
text: 'Connection'
|
||||
}),
|
||||
getHeadlineToolbar()
|
||||
)
|
||||
);
|
||||
|
||||
let rowElement = $('<div>', {
|
||||
class: 'row'
|
||||
});
|
||||
|
||||
moduleElement.append(rowElement);
|
||||
|
||||
rowElement.append(getInfoPanelControl(mapId));
|
||||
|
||||
updateConnectionPanels(moduleElement, mapId, MapUtil.getDataByConnections(connections), []);
|
||||
|
||||
return moduleElement;
|
||||
};
|
||||
|
||||
return {
|
||||
config: config,
|
||||
getModule: getModule,
|
||||
initModule: initModule,
|
||||
beforeDestroy: beforeDestroy
|
||||
};
|
||||
});
|
||||
@@ -9,7 +9,7 @@ define([
|
||||
|
||||
'use strict';
|
||||
|
||||
var config = {
|
||||
let config = {
|
||||
headerSystemsContainerId: 'pf-header-systems', // id for systems layer
|
||||
headerSystemConnectorsId: 'pf-header-connectors', // id for connectors layer
|
||||
headerConnectionsContainerId: 'pf-header-connections', // id for connections layer
|
||||
@@ -26,9 +26,9 @@ define([
|
||||
* draw systems layer
|
||||
* @param callback
|
||||
*/
|
||||
var drawSystems = function(callback){
|
||||
let drawSystems = function(callback){
|
||||
|
||||
var pathObj = {
|
||||
let pathObj = {
|
||||
systems: {
|
||||
strokepath: [
|
||||
// systems =======================================================================
|
||||
@@ -98,11 +98,11 @@ define([
|
||||
* draw connectors layer
|
||||
* @param callback
|
||||
*/
|
||||
var drawConnectors = function(callback){
|
||||
let drawConnectors = function(callback){
|
||||
|
||||
var connectorDuration = 150;
|
||||
let connectorDuration = 150;
|
||||
|
||||
var pathObj = {
|
||||
let pathObj = {
|
||||
connectors: {
|
||||
strokepath: [
|
||||
// connectors ====================================================================
|
||||
@@ -184,14 +184,14 @@ define([
|
||||
* draw connections layer
|
||||
* @param callback
|
||||
*/
|
||||
var drawConnections = function(callback){
|
||||
let drawConnections = function(callback){
|
||||
|
||||
var connectionDuration = 250;
|
||||
var connectionWidth = 8;
|
||||
var connectionInnerWidth = 4;
|
||||
var connectionBorderColor = '#63676A'; //gray
|
||||
let connectionDuration = 250;
|
||||
let connectionWidth = 8;
|
||||
let connectionInnerWidth = 4;
|
||||
let connectionBorderColor = '#63676A'; //gray
|
||||
|
||||
var pathObj = {
|
||||
let pathObj = {
|
||||
connections: {
|
||||
strokepath: [
|
||||
// connections ====================================================================
|
||||
@@ -288,7 +288,7 @@ define([
|
||||
* draw background layer
|
||||
* @param callback
|
||||
*/
|
||||
var drawBackground = function(callback){
|
||||
let drawBackground = function(callback){
|
||||
$('#' + config.headerBackgroundContainerId + ' .' + config.headerSystemClass).velocity('transition.bounceUpIn', {
|
||||
stagger: 150,
|
||||
complete: function(){
|
||||
@@ -304,7 +304,7 @@ define([
|
||||
* @param callback
|
||||
*/
|
||||
$.fn.drawDemoMap = function(callback){
|
||||
var canvasElement = $(this);
|
||||
let canvasElement = $(this);
|
||||
|
||||
|
||||
// draw systems
|
||||
|
||||
@@ -11,7 +11,7 @@ define([
|
||||
], function($, Init, Util, Render, bootbox) {
|
||||
'use strict';
|
||||
|
||||
var config = {
|
||||
let config = {
|
||||
// select character dialog
|
||||
settingsDialogId: 'pf-settings-dialog', // id for "settings" dialog
|
||||
settingsAccountContainerId: 'pf-settings-dialog-account', // id for the "account" container
|
||||
@@ -37,14 +37,14 @@ define([
|
||||
$.fn.showSettingsDialog = function(){
|
||||
|
||||
// check if there are other dialogs open
|
||||
var openDialogs = Util.getOpenDialogs();
|
||||
let openDialogs = Util.getOpenDialogs();
|
||||
if(openDialogs.length > 0){
|
||||
return false;
|
||||
}
|
||||
|
||||
requirejs(['text!templates/dialog/settings.html', 'mustache'], function(template, Mustache) {
|
||||
|
||||
var data = {
|
||||
let data = {
|
||||
id: config.settingsDialogId,
|
||||
settingsAccountContainerId: config.settingsAccountContainerId,
|
||||
settingsShareContainerId: config.settingsShareContainerId,
|
||||
@@ -56,9 +56,9 @@ define([
|
||||
ccpImageServer: Init.url.ccpImageServer
|
||||
};
|
||||
|
||||
var content = Mustache.render(template, data);
|
||||
let content = Mustache.render(template, data);
|
||||
|
||||
var accountSettingsDialog = bootbox.dialog({
|
||||
let accountSettingsDialog = bootbox.dialog({
|
||||
title: 'Account settings',
|
||||
message: content,
|
||||
buttons: {
|
||||
@@ -72,19 +72,19 @@ define([
|
||||
callback: function() {
|
||||
|
||||
// get the current active form
|
||||
var form = $('#' + config.settingsDialogId).find('form').filter(':visible');
|
||||
let form = $('#' + config.settingsDialogId).find('form').filter(':visible');
|
||||
|
||||
// validate form
|
||||
form.validator('validate');
|
||||
|
||||
// check whether the form is valid
|
||||
var formValid = form.isValidForm();
|
||||
let formValid = form.isValidForm();
|
||||
|
||||
if(formValid === true){
|
||||
var tabFormValues = form.getFormValues();
|
||||
let tabFormValues = form.getFormValues();
|
||||
|
||||
// send Tab data and store values
|
||||
var requestData = {
|
||||
let requestData = {
|
||||
formData: tabFormValues
|
||||
};
|
||||
|
||||
@@ -134,7 +134,7 @@ define([
|
||||
}).fail(function( jqXHR, status, error) {
|
||||
accountSettingsDialog.find('.modal-content').hideLoadingAnimation();
|
||||
|
||||
var reason = status + ' ' + error;
|
||||
let reason = status + ' ' + error;
|
||||
Util.showNotify({title: jqXHR.status + ': saveAccountSettings', text: reason, type: 'error'});
|
||||
|
||||
// set new captcha for any request
|
||||
@@ -147,7 +147,7 @@ define([
|
||||
if(jqXHR.status === 500){
|
||||
|
||||
if(jqXHR.responseText){
|
||||
var errorObj = $.parseJSON(jqXHR.responseText);
|
||||
let errorObj = $.parseJSON(jqXHR.responseText);
|
||||
|
||||
if(
|
||||
errorObj.error &&
|
||||
@@ -172,11 +172,11 @@ define([
|
||||
// after modal is shown =======================================================================
|
||||
accountSettingsDialog.on('shown.bs.modal', function(e) {
|
||||
|
||||
var dialogElement = $(this);
|
||||
var form = dialogElement.find('form');
|
||||
let dialogElement = $(this);
|
||||
let form = dialogElement.find('form');
|
||||
|
||||
// request captcha image and show
|
||||
var captchaImageWrapperContainer = $('#' + config.captchaImageWrapperId);
|
||||
let captchaImageWrapperContainer = $('#' + config.captchaImageWrapperId);
|
||||
captchaImageWrapperContainer.showCaptchaImage(config.captchaKeyUpdateAccount);
|
||||
|
||||
// init captcha refresh button
|
||||
@@ -200,7 +200,7 @@ define([
|
||||
off: 'Disable <i class="fa fa-fw fa-ban"></i>',
|
||||
onstyle: 'success',
|
||||
offstyle: 'warning',
|
||||
width: 90,
|
||||
width: 100,
|
||||
height: 30
|
||||
});
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ define([
|
||||
], function($, Init, Util, Render, bootbox) {
|
||||
'use strict';
|
||||
|
||||
var config = {
|
||||
let config = {
|
||||
// jump info dialog
|
||||
creditsDialogClass: 'pf-credits-dialog', // class for credits dialog
|
||||
creditsDialogLogoContainerId: 'pf-logo-container' // id for logo element
|
||||
@@ -25,14 +25,14 @@ define([
|
||||
|
||||
requirejs(['text!templates/dialog/credit.html', 'mustache'], function(template, Mustache) {
|
||||
|
||||
var data = {
|
||||
let data = {
|
||||
logoContainerId: config.creditsDialogLogoContainerId,
|
||||
version: Util.getVersion()
|
||||
};
|
||||
|
||||
var content = Mustache.render(template, data);
|
||||
let content = Mustache.render(template, data);
|
||||
|
||||
var creditDialog = bootbox.dialog({
|
||||
let creditDialog = bootbox.dialog({
|
||||
className: config.creditsDialogClass,
|
||||
title: 'Licence',
|
||||
message: content
|
||||
|
||||
@@ -10,7 +10,7 @@ define([
|
||||
], function($, Init, Util, bootbox) {
|
||||
'use strict';
|
||||
|
||||
var config = {
|
||||
let config = {
|
||||
// global dialog
|
||||
deleteAccountId: 'pf-dialog-delete-account', // dialog id
|
||||
|
||||
@@ -27,16 +27,16 @@ define([
|
||||
|
||||
requirejs(['text!templates/dialog/delete_account.html', 'mustache'], function(template, Mustache) {
|
||||
|
||||
var data = {
|
||||
let data = {
|
||||
deleteAccountId: config.deleteAccountId,
|
||||
userData: Util.getCurrentUserData(),
|
||||
captchaImageWrapperId: config.captchaImageWrapperId,
|
||||
formErrorContainerClass: Util.config.formErrorContainerClass
|
||||
};
|
||||
|
||||
var content = Mustache.render(template, data);
|
||||
let content = Mustache.render(template, data);
|
||||
|
||||
var deleteAccountDialog = bootbox.dialog({
|
||||
let deleteAccountDialog = bootbox.dialog({
|
||||
title: 'Delete account',
|
||||
message: content,
|
||||
buttons: {
|
||||
@@ -48,20 +48,20 @@ define([
|
||||
label: '<i class="fa fa-user-times fa-fw"></i> delete account',
|
||||
className: 'btn-danger',
|
||||
callback: function() {
|
||||
var dialogElement = $(this);
|
||||
var form = dialogElement.find('form');
|
||||
let dialogElement = $(this);
|
||||
let form = dialogElement.find('form');
|
||||
|
||||
// validate form
|
||||
form.validator('validate');
|
||||
var formValid = form.isValidForm();
|
||||
let formValid = form.isValidForm();
|
||||
|
||||
if(formValid){
|
||||
|
||||
var formValues = form.getFormValues();
|
||||
let formValues = form.getFormValues();
|
||||
|
||||
if(! $.isEmptyObject(formValues) ){
|
||||
// send Tab data and store values
|
||||
var requestData = {
|
||||
let requestData = {
|
||||
formData: formValues
|
||||
};
|
||||
|
||||
@@ -91,7 +91,7 @@ define([
|
||||
}).fail(function( jqXHR, status, error) {
|
||||
dialogElement.find('.modal-content').hideLoadingAnimation();
|
||||
|
||||
var reason = status + ' ' + error;
|
||||
let reason = status + ' ' + error;
|
||||
Util.showNotify({title: jqXHR.status + ': deleteAccount', text: reason, type: 'error'});
|
||||
|
||||
});
|
||||
|
||||
@@ -8,31 +8,85 @@ define([
|
||||
'app/util',
|
||||
'app/render',
|
||||
'bootbox',
|
||||
], function($, Init, Util, Render, bootbox) {
|
||||
|
||||
], ($, Init, Util, Render, bootbox) => {
|
||||
'use strict';
|
||||
|
||||
let config = {
|
||||
// jump info dialog
|
||||
jumpInfoDialogClass: 'pf-jump-info-dialog' // class for jump info dialog
|
||||
jumpInfoDialogClass: 'pf-jump-info-dialog', // class for jump info dialog
|
||||
wormholeInfoMassTableClass: 'pf-wormhole-info-mass-table', // class for "wormhole mass" table
|
||||
wormholeInfoJumpTableClass: 'pf-wormhole-info-jump-table' // class for "wormhole jump" table
|
||||
};
|
||||
|
||||
/**
|
||||
* show jump info dialog
|
||||
*/
|
||||
$.fn.showJumpInfoDialog = function(){
|
||||
|
||||
requirejs(['text!templates/dialog/jump_info.html', 'mustache'], function(template, Mustache) {
|
||||
let data = {};
|
||||
requirejs(['text!templates/dialog/jump_info.html', 'mustache'], (template, Mustache) => {
|
||||
let data = {
|
||||
config: config,
|
||||
wormholes: Object.keys(Init.wormholes).map(function(k) { return Init.wormholes[k]; }), // convert Json to array
|
||||
securityClass: function(){
|
||||
return function(value, render){
|
||||
return this.Util.getSecurityClassForSystem( render(value) );
|
||||
}.bind(this);
|
||||
}.bind({
|
||||
Util: Util
|
||||
}),
|
||||
massValue: function(){
|
||||
return function(value, render){
|
||||
let mass = render(value);
|
||||
switch(mass.length){
|
||||
case 0: return '';
|
||||
case 1: return 'Yes';
|
||||
default: return this.Util.formatMassValue(mass);
|
||||
}
|
||||
}.bind(this);
|
||||
}.bind({
|
||||
Util: Util
|
||||
})
|
||||
};
|
||||
let content = Mustache.render(template, data);
|
||||
|
||||
let signatureReaderDialog = bootbox.dialog({
|
||||
let jumpDialog = bootbox.dialog({
|
||||
className: config.jumpInfoDialogClass,
|
||||
title: 'Wormhole jump information',
|
||||
message: content
|
||||
message: content,
|
||||
show: false
|
||||
});
|
||||
|
||||
});
|
||||
jumpDialog.on('show.bs.modal', function(e) {
|
||||
// init dataTable
|
||||
$(this).find('.' + config.wormholeInfoMassTableClass).DataTable({
|
||||
pageLength: 25,
|
||||
lengthMenu: [[10, 20, 25, 30, 40, -1], [10, 20, 25, 30, 40, 'All']],
|
||||
autoWidth: false,
|
||||
language: {
|
||||
emptyTable: 'No wormholes',
|
||||
zeroRecords: 'No wormholes found',
|
||||
lengthMenu: 'Show _MENU_ wormholes',
|
||||
info: 'Showing _START_ to _END_ of _TOTAL_ wormholes'
|
||||
},
|
||||
});
|
||||
|
||||
$(this).find('.' + config.wormholeInfoJumpTableClass).DataTable({
|
||||
pageLength: -1,
|
||||
paging: false,
|
||||
lengthChange: false,
|
||||
ordering: false,
|
||||
searching: false,
|
||||
info: false,
|
||||
autoWidth: false,
|
||||
language: {
|
||||
emptyTable: 'No wormholes',
|
||||
zeroRecords: 'No wormholes found',
|
||||
lengthMenu: 'Show _MENU_ wormholes',
|
||||
info: 'Showing _START_ to _END_ of _TOTAL_ wormholes'
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
jumpDialog.modal('show');
|
||||
});
|
||||
};
|
||||
});
|
||||
@@ -184,7 +184,6 @@ define([
|
||||
|
||||
systemsElement.showLoadingAnimation(config.loadingOptions);
|
||||
|
||||
// table init complete
|
||||
systemTable.on( 'init.dt', function () {
|
||||
systemsElement.hideLoadingAnimation();
|
||||
|
||||
@@ -193,6 +192,10 @@ define([
|
||||
tooltipElements.tooltip();
|
||||
});
|
||||
|
||||
systemTable.on('destroy.dt', function(){
|
||||
$(this).destroyTimestampCounter();
|
||||
});
|
||||
|
||||
// prepare data for dataTables
|
||||
let systemsData = [];
|
||||
for(let i = 0; i < mapData.data.systems.length; i++){
|
||||
@@ -438,13 +441,6 @@ define([
|
||||
data: 'updated',
|
||||
createdCell: function(cell, cellData, rowData, rowIndex, colIndex){
|
||||
$(cell).initTimestampCounter();
|
||||
|
||||
// highlight cell
|
||||
let diff = new Date().getTime() - cellData * 1000;
|
||||
let dateDiff = new Date(diff);
|
||||
if(dateDiff.getUTCDate() > 1){
|
||||
$(cell).addClass('txt-color txt-color-warning');
|
||||
}
|
||||
}
|
||||
},{
|
||||
title: '',
|
||||
@@ -545,7 +541,6 @@ define([
|
||||
let connectionClasses = [];
|
||||
for(let k = 0; k < tempConnectionData.type.length; k++){
|
||||
connectionClasses.push( MapUtil.getConnectionInfo( tempConnectionData.type[k], 'cssClass') );
|
||||
|
||||
}
|
||||
|
||||
connectionClasses = connectionClasses.join(' ');
|
||||
@@ -626,11 +621,13 @@ define([
|
||||
createdCell: function(cell, cellData, rowData, rowIndex, colIndex){
|
||||
$(cell).initTimestampCounter();
|
||||
|
||||
// highlight cell
|
||||
let diff = new Date().getTime() - cellData * 1000;
|
||||
let dateDiff = new Date(diff);
|
||||
if(dateDiff.getUTCDate() > 1){
|
||||
$(cell).addClass('txt-color txt-color-warning');
|
||||
if(rowData.scope.scope_sort === 'wh'){
|
||||
// highlight cell
|
||||
let diff = new Date().getTime() - cellData * 1000;
|
||||
let dateDiff = new Date(diff);
|
||||
if(dateDiff.getUTCDate() > 1){
|
||||
$(cell).addClass('txt-color txt-color-warning');
|
||||
}
|
||||
}
|
||||
}
|
||||
},{
|
||||
@@ -1269,7 +1266,6 @@ define([
|
||||
|
||||
// load users table
|
||||
usersElement.initUsersInfoTable(mapData);
|
||||
|
||||
});
|
||||
|
||||
// events for tab change
|
||||
|
||||
@@ -11,7 +11,7 @@ define([
|
||||
], function($, Init, Util, Render, bootbox) {
|
||||
'use strict';
|
||||
|
||||
var config = {
|
||||
let config = {
|
||||
releasesDialogClass: 'pf-releases-dialog' // class for "Releases" dialog
|
||||
};
|
||||
|
||||
@@ -19,10 +19,10 @@ define([
|
||||
* load release information in dialog
|
||||
* @param releasesDialog
|
||||
*/
|
||||
var loadDialogData = function(releasesDialog){
|
||||
let loadDialogData = function(releasesDialog){
|
||||
|
||||
// lock dialog
|
||||
var dialogContent = releasesDialog.find('.modal-content');
|
||||
let dialogContent = releasesDialog.find('.modal-content');
|
||||
dialogContent.showLoadingAnimation();
|
||||
|
||||
$.ajax({
|
||||
@@ -32,18 +32,18 @@ define([
|
||||
dataType: 'json'
|
||||
}).done(function(releasesData){
|
||||
requirejs(['text!templates/ui/timeline_element.html', 'mustache'], function(template, Mustache) {
|
||||
for(var i = 0; i < releasesData.length; i++){
|
||||
var releaseData = releasesData[i];
|
||||
for(let i = 0; i < releasesData.length; i++){
|
||||
let releaseData = releasesData[i];
|
||||
|
||||
// template vars
|
||||
var data = {
|
||||
let data = {
|
||||
isFirst: (i === 0),
|
||||
isOdd: (i % 2 !== 0),
|
||||
releaseDate: releaseData.published_at.substr(0, 10),
|
||||
releaseData: releaseData
|
||||
};
|
||||
|
||||
var content = Mustache.render(template, data);
|
||||
let content = Mustache.render(template, data);
|
||||
releasesDialog.find('ul.timeline').append(content);
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ define([
|
||||
});
|
||||
});
|
||||
}).fail(function( jqXHR, status, error) {
|
||||
var reason = status + ' ' + jqXHR.status + ': ' + error;
|
||||
let reason = status + ' ' + jqXHR.status + ': ' + error;
|
||||
Util.showNotify({title: jqXHR.status + ': login', text: reason, type: 'error'});
|
||||
}).always(function() {
|
||||
dialogContent.hideLoadingAnimation();
|
||||
@@ -66,9 +66,9 @@ define([
|
||||
* show releases dialog
|
||||
*/
|
||||
$.fn.releasesDialog = function(){
|
||||
var content = '<ul class="timeline"></ul>';
|
||||
let content = '<ul class="timeline"></ul>';
|
||||
|
||||
var releasesDialog = bootbox.dialog({
|
||||
let releasesDialog = bootbox.dialog({
|
||||
className: config.releasesDialogClass,
|
||||
title: 'Releases',
|
||||
size: 'large',
|
||||
|
||||
@@ -12,14 +12,17 @@ define([
|
||||
|
||||
let config = {
|
||||
// module info
|
||||
moduleClass: 'pf-module', // class for each module
|
||||
modulePosition: 3,
|
||||
moduleName: 'systemGraph',
|
||||
moduleHeadClass: 'pf-module-head', // class for module header
|
||||
moduleHandlerClass: 'pf-module-handler-drag', // class for "drag" handler
|
||||
|
||||
// system graph module
|
||||
systemGraphModuleClass: 'pf-system-graph-module', // class for this module
|
||||
moduleTypeClass: 'pf-system-graph-module', // class for this module
|
||||
systemGraphClass: 'pf-system-graph', // class for each graph
|
||||
|
||||
// system graph labels
|
||||
systemGraphLabels: {
|
||||
systemGraphs: {
|
||||
jumps: {
|
||||
headline: 'Jumps',
|
||||
units: 'jumps',
|
||||
@@ -55,9 +58,8 @@ define([
|
||||
*/
|
||||
let getInfoForGraph = function(graphKey, option){
|
||||
let info = '';
|
||||
|
||||
if(config.systemGraphLabels.hasOwnProperty(graphKey)){
|
||||
info = config.systemGraphLabels[graphKey][option];
|
||||
if(config.systemGraphs.hasOwnProperty(graphKey)){
|
||||
info = config.systemGraphs[graphKey][option];
|
||||
}
|
||||
|
||||
return info;
|
||||
@@ -68,9 +70,9 @@ define([
|
||||
* @param graphElement
|
||||
* @param graphKey
|
||||
* @param graphData
|
||||
* @param eventLine
|
||||
*/
|
||||
let initGraph = function(graphElement, graphKey, graphData, eventLine){
|
||||
|
||||
if(graphData.length > 0){
|
||||
let labelYFormat = function(y){
|
||||
return Math.round(y);
|
||||
@@ -117,125 +119,130 @@ define([
|
||||
};
|
||||
|
||||
/**
|
||||
* draw graph module
|
||||
* @param parentElement
|
||||
* @param systemData
|
||||
* request graphs data
|
||||
* @param requestData
|
||||
* @param context
|
||||
* @param callback
|
||||
*/
|
||||
let drawModule = function(parentElement, systemData){
|
||||
|
||||
// graph data is available for k-space systems
|
||||
if(systemData.type.id === 2){
|
||||
let requestData = {
|
||||
systemIds: [systemData.systemId]
|
||||
};
|
||||
|
||||
// calculate time offset until system created
|
||||
let serverData = Util.getServerTime();
|
||||
|
||||
let timestampNow = Math.floor(serverData.getTime() / 1000);
|
||||
let timeSinceUpdate = timestampNow - systemData.updated;
|
||||
|
||||
let timeInHours = Math.floor(timeSinceUpdate / 3600);
|
||||
let timeInMinutes = Math.floor((timeSinceUpdate % 3600) / 60);
|
||||
let timeInMinutesPercent = ( timeInMinutes / 60 ).toFixed(2);
|
||||
let eventLine = timeInHours + timeInMinutesPercent;
|
||||
|
||||
// graph is from right to left -> convert event line
|
||||
eventLine = 23 - eventLine;
|
||||
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: Init.path.getSystemGraphData,
|
||||
data: requestData,
|
||||
dataType: 'json'
|
||||
}).done(function(systemGraphsData){
|
||||
|
||||
if( Object.keys(systemGraphsData).length > 0 ){
|
||||
// create new (hidden) module container
|
||||
let moduleElement = $('<div>', {
|
||||
class: [config.moduleClass, config.systemGraphModuleClass].join(' '),
|
||||
css: {opacity: 0}
|
||||
});
|
||||
|
||||
// insert at the correct position
|
||||
if($(parentElement).children().length === 1){
|
||||
$(parentElement).append(moduleElement);
|
||||
}else{
|
||||
$(parentElement).find('>:first-child').after(moduleElement);
|
||||
}
|
||||
|
||||
// row element
|
||||
let rowElement = $('<div>', {
|
||||
class: 'row'
|
||||
});
|
||||
moduleElement.append(rowElement);
|
||||
|
||||
$.each(systemGraphsData, function(systemId, graphsData){
|
||||
$.each(graphsData, function(graphKey, graphData){
|
||||
|
||||
let colElement = $('<div>', {
|
||||
class: ['col-xs-12', 'col-sm-6', 'col-md-4'].join(' ')
|
||||
});
|
||||
|
||||
let headlineElement = $('<h5>').text( getInfoForGraph(graphKey, 'headline') );
|
||||
|
||||
colElement.append(headlineElement);
|
||||
|
||||
let graphElement = $('<div>', {
|
||||
class: config.systemGraphClass
|
||||
});
|
||||
|
||||
colElement.append(graphElement);
|
||||
|
||||
rowElement.append(colElement);
|
||||
initGraph(graphElement, graphKey, graphData, eventLine);
|
||||
});
|
||||
});
|
||||
|
||||
moduleElement.append($('<div>', {
|
||||
css: {'clear': 'both'}
|
||||
}));
|
||||
|
||||
// show module
|
||||
moduleElement.velocity('transition.slideDownIn', {
|
||||
duration: Init.animationSpeed.mapModule,
|
||||
delay: Init.animationSpeed.mapModule
|
||||
});
|
||||
}
|
||||
}).fail(function( jqXHR, status, error) {
|
||||
let reason = status + ' ' + error;
|
||||
Util.showNotify({title: jqXHR.status + ': System graph data', text: reason, type: 'warning'});
|
||||
$(document).setProgramStatus('problem');
|
||||
});
|
||||
}
|
||||
let requestGraphData = (requestData, context, callback) => {
|
||||
// show loading animation
|
||||
context.moduleElement.find('.' + config.systemGraphClass).showLoadingAnimation();
|
||||
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: Init.path.getSystemGraphData,
|
||||
data: requestData,
|
||||
dataType: 'json',
|
||||
context: context
|
||||
}).done(function(systemGraphsData){
|
||||
callback(this, systemGraphsData);
|
||||
}).fail(function( jqXHR, status, error) {
|
||||
let reason = status + ' ' + error;
|
||||
Util.showNotify({title: jqXHR.status + ': System graph data', text: reason, type: 'warning'});
|
||||
$(document).setProgramStatus('problem');
|
||||
this.moduleElement.hide();
|
||||
}).always(function(){
|
||||
// hide loading animation
|
||||
context.moduleElement.find('.' + config.systemGraphClass).hideLoadingAnimation();
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* main module load function
|
||||
* @param systemData
|
||||
* update graph elements with data
|
||||
* @param context
|
||||
* @param systemGraphsData
|
||||
*/
|
||||
$.fn.drawSystemGraphModule = function(systemData){
|
||||
let addGraphData = (context, systemGraphsData) => {
|
||||
|
||||
let parentElement = $(this);
|
||||
// calculate time offset until system created -----------------------------------------------------------------
|
||||
let serverData = Util.getServerTime();
|
||||
let timestampNow = Math.floor(serverData.getTime() / 1000);
|
||||
let timeSinceUpdate = timestampNow - context.systemData.updated.updated;
|
||||
|
||||
// check if module already exists
|
||||
let moduleElement = parentElement.find('.' + config.systemGraphModuleClass);
|
||||
let timeInHours = Math.floor(timeSinceUpdate / 3600);
|
||||
let timeInMinutes = Math.floor((timeSinceUpdate % 3600) / 60);
|
||||
let timeInMinutesPercent = ( timeInMinutes / 60 ).toFixed(2);
|
||||
let eventLine = timeInHours + timeInMinutesPercent;
|
||||
|
||||
if(moduleElement.length > 0){
|
||||
moduleElement.velocity('transition.slideDownOut', {
|
||||
duration: Init.animationSpeed.mapModule,
|
||||
complete: function(tempElement){
|
||||
$(tempElement).remove();
|
||||
drawModule(parentElement, systemData);
|
||||
}
|
||||
});
|
||||
}else{
|
||||
drawModule(parentElement, systemData);
|
||||
// graph is from right to left -> convert event line
|
||||
eventLine = 23 - eventLine;
|
||||
|
||||
// update graph data ------------------------------------------------------------------------------------------
|
||||
for (let [systemId, graphsData] of Object.entries(systemGraphsData)){
|
||||
for (let [graphKey, graphData] of Object.entries(graphsData)){
|
||||
let graphElement = context.moduleElement.find('[data-graph="' + graphKey + '"]');
|
||||
initGraph(graphElement, graphKey, graphData, eventLine);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @see requestGraphData
|
||||
* @param moduleElement
|
||||
* @param mapId
|
||||
* @param systemData
|
||||
*/
|
||||
let updateGraphPanel = (moduleElement, mapId, systemData) => {
|
||||
let requestData = {
|
||||
systemIds: [systemData.systemId]
|
||||
};
|
||||
|
||||
let contextData = {
|
||||
moduleElement: moduleElement,
|
||||
systemData: systemData
|
||||
};
|
||||
|
||||
requestGraphData(requestData, contextData, addGraphData);
|
||||
};
|
||||
|
||||
/**
|
||||
* get module element
|
||||
* @param parentElement
|
||||
* @param mapId
|
||||
* @param systemData
|
||||
* @returns {*}
|
||||
*/
|
||||
let getModule = (parentElement, mapId, systemData) => {
|
||||
// graph data is available for k-space systems
|
||||
let moduleElement = null;
|
||||
if(systemData.type.id === 2){
|
||||
moduleElement = $('<div>');
|
||||
let rowElement = $('<div>', {
|
||||
class: 'row'
|
||||
});
|
||||
|
||||
for (let [graphKey, graphConfig] of Object.entries(config.systemGraphs)){
|
||||
rowElement.append(
|
||||
$('<div>', {
|
||||
class: ['col-xs-12', 'col-sm-6', 'col-md-4'].join(' ')
|
||||
}).append(
|
||||
$('<div>', {
|
||||
class: config.moduleHeadClass
|
||||
}).append(
|
||||
$('<h5>', {
|
||||
class: config.moduleHandlerClass
|
||||
}),
|
||||
$('<h5>', {
|
||||
text: getInfoForGraph(graphKey, 'headline')
|
||||
})
|
||||
),
|
||||
$('<div>', {
|
||||
class: config.systemGraphClass
|
||||
}).attr('data-graph', graphKey)
|
||||
)
|
||||
);
|
||||
}
|
||||
moduleElement.append(rowElement);
|
||||
|
||||
updateGraphPanel(moduleElement, mapId, systemData);
|
||||
}
|
||||
|
||||
return moduleElement;
|
||||
};
|
||||
|
||||
return {
|
||||
config: config,
|
||||
getModule: getModule
|
||||
};
|
||||
|
||||
});
|
||||
|
||||
@@ -13,10 +13,11 @@ define([
|
||||
|
||||
let config = {
|
||||
// module info
|
||||
moduleClass: 'pf-module', // class for each module
|
||||
modulePosition: 2,
|
||||
moduleName: 'systemInfo',
|
||||
|
||||
// system info module
|
||||
systemInfoModuleClass: 'pf-system-info-module', // module wrapper
|
||||
moduleTypeClass: 'pf-system-info-module', // class for this module
|
||||
|
||||
// breadcrumb
|
||||
constellationLinkClass: 'pf-system-info-constellation', // class for "constellation" name
|
||||
@@ -24,7 +25,7 @@ define([
|
||||
typeLinkClass: 'pf-system-info-type', // class for "type" name
|
||||
|
||||
// info table
|
||||
systemInfoTableClass: 'pf-system-info-table', // class for system info table
|
||||
systemInfoTableClass: 'pf-module-table', // class for system info table
|
||||
systemInfoNameInfoClass: 'pf-system-info-name', // class for "name" information element
|
||||
systemInfoEffectInfoClass: 'pf-system-info-effect', // class for "effect" information element
|
||||
systemInfoStatusLabelClass: 'pf-system-info-status-label', // class for "status" information element
|
||||
@@ -54,7 +55,6 @@ define([
|
||||
* set module observer and look for relevant system data to update
|
||||
*/
|
||||
let setModuleObserver = function(moduleElement){
|
||||
|
||||
$(document).off('pf:updateSystemInfoModule').on('pf:updateSystemInfoModule', function(e, data){
|
||||
if(data){
|
||||
moduleElement.updateSystemInfoModule(data);
|
||||
@@ -197,24 +197,19 @@ define([
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* get module element
|
||||
* @param parentElement
|
||||
* @param mapId
|
||||
* @param systemData
|
||||
*/
|
||||
let drawModule = function(parentElement, mapId, systemData){
|
||||
let getModule = function(parentElement, mapId, systemData){
|
||||
|
||||
// create new module container
|
||||
let moduleElement = $('<div>', {
|
||||
class: [config.moduleClass, config.systemInfoModuleClass].join(' '),
|
||||
css: {opacity: 0}
|
||||
});
|
||||
let moduleElement = $('<div>');
|
||||
|
||||
// store systemId -> module can be updated with the correct data
|
||||
moduleElement.data('id', systemData.id);
|
||||
|
||||
parentElement.prepend(moduleElement);
|
||||
|
||||
// shattered wormhole info data
|
||||
let shatteredWormholeInfo = false;
|
||||
|
||||
@@ -240,8 +235,8 @@ define([
|
||||
position: moduleElement,
|
||||
link: 'append',
|
||||
functions: {
|
||||
after: function(){
|
||||
let tempModuleElement = parentElement.find('.' + config.systemInfoModuleClass);
|
||||
after: function(conf){
|
||||
let tempModuleElement = conf.position;
|
||||
|
||||
// lock "description" field until first update
|
||||
tempModuleElement.find('.' + config.descriptionArea).showLoadingAnimation();
|
||||
@@ -426,7 +421,6 @@ define([
|
||||
return 'Loading...';
|
||||
}
|
||||
|
||||
showModule(moduleElement);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -464,52 +458,40 @@ define([
|
||||
};
|
||||
|
||||
Render.showModule(moduleConfig, moduleData);
|
||||
|
||||
return moduleElement;
|
||||
};
|
||||
|
||||
/**
|
||||
* show system info module with animation
|
||||
* init callback
|
||||
* @param moduleElement
|
||||
*/
|
||||
let showModule = function(moduleElement){
|
||||
moduleElement.velocity('transition.slideDownIn', {
|
||||
duration: Init.animationSpeed.mapModule,
|
||||
delay: Init.animationSpeed.mapModule,
|
||||
complete: function(){
|
||||
// set module observer
|
||||
setModuleObserver(moduleElement);
|
||||
|
||||
// enable auto update
|
||||
disableModuleUpdate = false;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* update system info module
|
||||
* @param mapId
|
||||
* @param systemData
|
||||
*/
|
||||
$.fn.drawSystemInfoModule = function(mapId, systemData){
|
||||
let initModule = function(moduleElement, mapId, systemData){
|
||||
// set module observer
|
||||
setModuleObserver(moduleElement);
|
||||
|
||||
let parentElement = $(this);
|
||||
|
||||
// check if module already exists
|
||||
let moduleElement = parentElement.find('.' + config.systemInfoModuleClass);
|
||||
|
||||
if(moduleElement.length > 0){
|
||||
moduleElement.velocity('transition.slideDownOut', {
|
||||
duration: Init.animationSpeed.mapModule,
|
||||
complete: function(tempElement){
|
||||
$(tempElement).remove();
|
||||
|
||||
drawModule(parentElement, mapId, systemData);
|
||||
}
|
||||
});
|
||||
}else{
|
||||
drawModule(parentElement, mapId, systemData);
|
||||
}
|
||||
// enable auto update
|
||||
disableModuleUpdate = false;
|
||||
};
|
||||
|
||||
/**
|
||||
* efore module destroy callback
|
||||
* @param moduleElement
|
||||
*/
|
||||
let beforeDestroy = (moduleElement) => {
|
||||
// remove xEditable description textarea
|
||||
let descriptionTextareaElement = moduleElement.find('.' + config.descriptionTextareaElementClass);
|
||||
descriptionTextareaElement.editable('destroy');
|
||||
};
|
||||
|
||||
return {
|
||||
config: config,
|
||||
getModule: getModule,
|
||||
initModule: initModule,
|
||||
beforeDestroy: beforeDestroy
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
|
||||
@@ -8,13 +8,16 @@ define([
|
||||
|
||||
let config = {
|
||||
// module info
|
||||
moduleClass: 'pf-module', // class for each module
|
||||
modulePosition: 2,
|
||||
moduleName: 'systemKillboard',
|
||||
moduleHeadClass: 'pf-module-head', // class for module header
|
||||
moduleHandlerClass: 'pf-module-handler-drag', // class for "drag" handler
|
||||
|
||||
// headline toolbar
|
||||
systemModuleHeadlineIcon: 'pf-module-icon-button', // class for toolbar icons in the head
|
||||
moduleHeadlineIconClass: 'pf-module-icon-button', // class for toolbar icons in the head
|
||||
|
||||
// system killboard module
|
||||
systemKillboardModuleClass: 'pf-system-killboard-module', // module wrapper
|
||||
moduleTypeClass: 'pf-system-killboard-module', // class for this module
|
||||
systemKillboardGraphKillsClass: 'pf-system-killboard-graph-kills', // class for system kill graph
|
||||
|
||||
// system killboard list
|
||||
@@ -178,34 +181,8 @@ define([
|
||||
* @param systemData
|
||||
*/
|
||||
$.fn.updateSystemInfoGraphs = function(systemData){
|
||||
|
||||
let moduleElement = $(this);
|
||||
|
||||
|
||||
// headline toolbar icons
|
||||
let headlineToolbar = $('<h5>', {
|
||||
class: 'pull-right'
|
||||
}).append(
|
||||
$('<i>', {
|
||||
class: ['fa', 'fa-fw', 'fa-external-link ', config.systemModuleHeadlineIcon].join(' '),
|
||||
title: 'zkillboard.com'
|
||||
}).on('click', function(e){
|
||||
window.open(
|
||||
'//zkillboard.com/system/' + systemData.systemId,
|
||||
'_blank'
|
||||
);
|
||||
}).attr('data-toggle', 'tooltip')
|
||||
);
|
||||
|
||||
moduleElement.append(headlineToolbar);
|
||||
|
||||
// headline
|
||||
let headline = $('<h5>', {
|
||||
text: 'Killboard'
|
||||
});
|
||||
|
||||
moduleElement.append(headline);
|
||||
|
||||
let killboardGraphElement = $('<div>', {
|
||||
class: config.systemKillboardGraphKillsClass
|
||||
});
|
||||
@@ -222,14 +199,11 @@ define([
|
||||
|
||||
// private function draws a "system kills" graph
|
||||
let drawGraph = function(data){
|
||||
|
||||
let tableData = data.tableData;
|
||||
|
||||
// change order (show right to left)
|
||||
tableData.reverse();
|
||||
|
||||
|
||||
|
||||
if(data.count === 0){
|
||||
labelOptions.type = 'label-success';
|
||||
label = getLabel( 'No kills found within the last 24h', labelOptions );
|
||||
@@ -247,6 +221,7 @@ define([
|
||||
Morris.Bar({
|
||||
element: killboardGraphElement,
|
||||
resize: true,
|
||||
redraw: true,
|
||||
grid: true,
|
||||
gridStrokeWidth: 0.3,
|
||||
gridTextSize: 9,
|
||||
@@ -418,64 +393,71 @@ define([
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* get module toolbar element
|
||||
* @param systemData
|
||||
* @returns {*|jQuery|HTMLElement|void}
|
||||
*/
|
||||
let getHeadlineToolbar = (systemData) => {
|
||||
let headlineToolbar = $('<h5>', {
|
||||
class: 'pull-right'
|
||||
}).append(
|
||||
$('<i>', {
|
||||
class: ['fa', 'fa-fw', 'fa-external-link ', config.moduleHeadlineIconClass].join(' '),
|
||||
title: 'zkillboard.com'
|
||||
}).on('click', function(e){
|
||||
window.open(
|
||||
'//zkillboard.com/system/' + systemData.systemId,
|
||||
'_blank'
|
||||
);
|
||||
}).attr('data-toggle', 'tooltip')
|
||||
);
|
||||
|
||||
headlineToolbar.find('[data-toggle="tooltip"]').tooltip({
|
||||
container: 'body'
|
||||
});
|
||||
|
||||
return headlineToolbar;
|
||||
};
|
||||
|
||||
/**
|
||||
* before module "show" callback
|
||||
* @param moduleElement
|
||||
* @param systemData
|
||||
*/
|
||||
let beforeShow = (moduleElement, systemData) => {
|
||||
// update graph
|
||||
moduleElement.updateSystemInfoGraphs(systemData);
|
||||
};
|
||||
|
||||
/**
|
||||
* get module element
|
||||
* @param parentElement
|
||||
* @param systemData
|
||||
* @returns {*|jQuery|HTMLElement}
|
||||
*/
|
||||
let getModule = function(parentElement, systemData){
|
||||
|
||||
let getModule = (parentElement, mapId, systemData) => {
|
||||
// create new module container
|
||||
let moduleElement = $('<div>', {
|
||||
class: [config.moduleClass, config.systemKillboardModuleClass].join(' '),
|
||||
css: {opacity: 0}
|
||||
});
|
||||
|
||||
parentElement.append(moduleElement);
|
||||
|
||||
// update graph
|
||||
moduleElement.updateSystemInfoGraphs(systemData);
|
||||
let moduleElement = $('<div>').append(
|
||||
$('<div>', {
|
||||
class: config.moduleHeadClass
|
||||
}).append(
|
||||
$('<h5>', {
|
||||
class: config.moduleHandlerClass
|
||||
}),
|
||||
$('<h5>', {
|
||||
text: 'Killboard'
|
||||
}),
|
||||
getHeadlineToolbar(systemData)
|
||||
)
|
||||
);
|
||||
|
||||
return moduleElement;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* main module load function
|
||||
* @param systemData
|
||||
*/
|
||||
$.fn.drawSystemKillboardModule = function(systemData){
|
||||
|
||||
let parentElement = $(this);
|
||||
|
||||
// show route module
|
||||
let showModule = function(moduleElement){
|
||||
if(moduleElement){
|
||||
moduleElement.velocity('transition.slideDownIn', {
|
||||
duration: Init.animationSpeed.mapModule,
|
||||
delay: Init.animationSpeed.mapModule
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// check if module already exists
|
||||
let moduleElement = parentElement.find('.' + config.systemKillboardModuleClass);
|
||||
|
||||
if(moduleElement.length > 0){
|
||||
moduleElement.velocity('transition.slideDownOut', {
|
||||
duration: Init.animationSpeed.mapModule,
|
||||
complete: function(tempElement){
|
||||
$(tempElement).remove();
|
||||
|
||||
moduleElement = getModule(parentElement, systemData);
|
||||
showModule(moduleElement);
|
||||
}
|
||||
});
|
||||
}else{
|
||||
moduleElement = getModule(parentElement, systemData);
|
||||
showModule(moduleElement);
|
||||
}
|
||||
|
||||
return {
|
||||
config: config,
|
||||
getModule: getModule,
|
||||
beforeShow: beforeShow
|
||||
};
|
||||
});
|
||||
@@ -13,18 +13,21 @@ define([
|
||||
|
||||
let config = {
|
||||
// module info
|
||||
moduleClass: 'pf-module', // class for each module
|
||||
modulePosition: 1,
|
||||
moduleName: 'systemRoute',
|
||||
moduleHeadClass: 'pf-module-head', // class for module header
|
||||
moduleHandlerClass: 'pf-module-handler-drag', // class for "drag" handler
|
||||
|
||||
routeCacheTTL: 10, // route cache timer (client) in seconds
|
||||
|
||||
// system route module
|
||||
systemRouteModuleClass: 'pf-system-route-module', // class for this module
|
||||
moduleTypeClass: 'pf-system-route-module', // class for this module
|
||||
|
||||
// headline toolbar
|
||||
systemModuleHeadlineIcon: 'pf-module-icon-button', // class for toolbar icons in the head
|
||||
systemModuleHeadlineIconSearch: 'pf-module-icon-button-search', // class for "search" icon
|
||||
systemModuleHeadlineIconSettings: 'pf-module-icon-button-settings', // class for "settings" icon
|
||||
systemModuleHeadlineIconRefresh: 'pf-module-icon-button-refresh', // class for "refresh" icon
|
||||
moduleHeadlineIconClass: 'pf-module-icon-button', // class for toolbar icons in the head
|
||||
moduleHeadlineIconSearchClass: 'pf-module-icon-button-search', // class for "search" icon
|
||||
moduleHeadlineIconSettingsClass: 'pf-module-icon-button-settings', // class for "settings" icon
|
||||
moduleHeadlineIconRefreshClass: 'pf-module-icon-button-refresh', // class for "refresh" icon
|
||||
|
||||
systemSecurityClassPrefix: 'pf-system-security-', // prefix class for system security level (color)
|
||||
|
||||
@@ -35,7 +38,7 @@ define([
|
||||
systemInfoRoutesTableClass: 'pf-system-route-table', // class for route tables
|
||||
mapSelectId: 'pf-route-dialog-map-select', // id for "map" select
|
||||
|
||||
dataTableActionCellClass: 'pf-table-action-cell' // class for "action" cells
|
||||
dataTableActionCellClass: 'pf-table-action-cell' // class for "action" cells
|
||||
};
|
||||
|
||||
// cache for system routes
|
||||
@@ -48,7 +51,7 @@ define([
|
||||
* @param context
|
||||
* @param routesData
|
||||
*/
|
||||
let callbackAddRouteRow = function(context, routesData){
|
||||
let callbackAddRouteRow = (context, routesData) => {
|
||||
|
||||
if(routesData.length > 0){
|
||||
for(let i = 0; i < routesData.length; i++){
|
||||
@@ -86,7 +89,7 @@ define([
|
||||
* @param rowData
|
||||
* @returns {*}
|
||||
*/
|
||||
let addRow = function(context, rowData){
|
||||
let addRow = (context, rowData) => {
|
||||
let dataTable = context.dataTable;
|
||||
let rowElement = null;
|
||||
let row = null;
|
||||
@@ -94,7 +97,7 @@ define([
|
||||
|
||||
// search for an existing row (e.g. on mass "table refresh" [all routes])
|
||||
// get rowIndex where column 1 (equals to "systemToData.name") matches rowData.systemToData.name
|
||||
let indexes = dataTable.rows().eq(0).filter( function (rowIdx) {
|
||||
let indexes = dataTable.rows().eq(0).filter((rowIdx) => {
|
||||
return (dataTable.cell(rowIdx, 1 ).data().name === rowData.systemToData.name);
|
||||
});
|
||||
|
||||
@@ -129,8 +132,7 @@ define([
|
||||
* @param context
|
||||
* @param callback
|
||||
*/
|
||||
let getRouteData = function(requestData, context, callback){
|
||||
|
||||
let getRouteData = (requestData, context, callback) => {
|
||||
context.moduleElement.showLoadingAnimation();
|
||||
|
||||
$.ajax({
|
||||
@@ -145,7 +147,6 @@ define([
|
||||
// execute callback
|
||||
callback(this, routesData.routesData);
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -153,7 +154,7 @@ define([
|
||||
* @param moduleElement
|
||||
* @param dataTable
|
||||
*/
|
||||
let updateRoutesTable = function(moduleElement, dataTable){
|
||||
let updateRoutesTable = (moduleElement, dataTable) => {
|
||||
let context = {
|
||||
moduleElement: moduleElement,
|
||||
dataTable: dataTable
|
||||
@@ -172,7 +173,7 @@ define([
|
||||
* @param {Object} rowData
|
||||
* @returns {Object}
|
||||
*/
|
||||
let getRouteRequestDataFromRowData = function(rowData){
|
||||
let getRouteRequestDataFromRowData = (rowData) => {
|
||||
return {
|
||||
mapIds: (rowData.hasOwnProperty('mapIds')) ? rowData.mapIds : [],
|
||||
systemFromData: (rowData.hasOwnProperty('systemFromData')) ? rowData.systemFromData : {},
|
||||
@@ -193,7 +194,7 @@ define([
|
||||
* show route dialog. User can search for systems and jump-info for each system is added to a data table
|
||||
* @param dialogData
|
||||
*/
|
||||
let showFindRouteDialog = function(dialogData){
|
||||
let showFindRouteDialog = (dialogData) => {
|
||||
|
||||
let mapSelectOptions = [];
|
||||
let currentMapData = Util.getCurrentMapData();
|
||||
@@ -678,50 +679,45 @@ define([
|
||||
};
|
||||
|
||||
/**
|
||||
* get the route finder moduleElement
|
||||
* get module element
|
||||
* @returns {*}
|
||||
*/
|
||||
let getModule = function(){
|
||||
|
||||
// create new module container
|
||||
let moduleElement = $('<div>', {
|
||||
class: [config.moduleClass, config.systemRouteModuleClass].join(' ')
|
||||
});
|
||||
|
||||
// headline toolbar icons
|
||||
let headlineToolbar = $('<h5>', {
|
||||
class: 'pull-right'
|
||||
}).append(
|
||||
$('<i>', {
|
||||
class: ['fa', 'fa-fw', 'fa-search', config.systemModuleHeadlineIcon, config.systemModuleHeadlineIconSearch].join(' '),
|
||||
title: 'find route'
|
||||
}).attr('data-html', 'true').attr('data-toggle', 'tooltip'),
|
||||
$('<i>', {
|
||||
class: ['fa', 'fa-fw', 'fa-sliders', config.systemModuleHeadlineIcon, config.systemModuleHeadlineIconSettings].join(' '),
|
||||
title: 'settings'
|
||||
}).attr('data-html', 'true').attr('data-toggle', 'tooltip'),
|
||||
$('<i>', {
|
||||
class: ['fa', 'fa-fw', 'fa-refresh', config.systemModuleHeadlineIcon, config.systemModuleHeadlineIconRefresh].join(' '),
|
||||
title: 'refresh all'
|
||||
}).attr('data-html', 'true').attr('data-toggle', 'tooltip')
|
||||
let moduleElement = $('<div>').append(
|
||||
$('<div>', {
|
||||
class: config.moduleHeadClass
|
||||
}).append(
|
||||
$('<h5>', {
|
||||
class: config.moduleHandlerClass
|
||||
}),
|
||||
$('<h5>', {
|
||||
class: 'pull-right'
|
||||
}).append(
|
||||
$('<i>', {
|
||||
class: ['fa', 'fa-fw', 'fa-search', config.moduleHeadlineIconClass, config.moduleHeadlineIconSearchClass].join(' '),
|
||||
title: 'find route'
|
||||
}).attr('data-html', 'true').attr('data-toggle', 'tooltip'),
|
||||
$('<i>', {
|
||||
class: ['fa', 'fa-fw', 'fa-sliders', config.moduleHeadlineIconClass, config.moduleHeadlineIconSettingsClass].join(' '),
|
||||
title: 'settings'
|
||||
}).attr('data-html', 'true').attr('data-toggle', 'tooltip'),
|
||||
$('<i>', {
|
||||
class: ['fa', 'fa-fw', 'fa-refresh', config.moduleHeadlineIconClass, config.moduleHeadlineIconRefreshClass].join(' '),
|
||||
title: 'refresh all'
|
||||
}).attr('data-html', 'true').attr('data-toggle', 'tooltip')
|
||||
),
|
||||
$('<h5>', {
|
||||
text: 'Routes'
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
moduleElement.append(headlineToolbar);
|
||||
|
||||
// headline
|
||||
let headline = $('<h5>', {
|
||||
class: 'pull-left',
|
||||
text: 'Routes'
|
||||
});
|
||||
|
||||
moduleElement.append(headline);
|
||||
|
||||
// crate new route table
|
||||
let table = $('<table>', {
|
||||
class: ['compact', 'stripe', 'order-column', 'row-border', config.systemInfoRoutesTableClass].join(' ')
|
||||
});
|
||||
|
||||
moduleElement.append( $(table) );
|
||||
moduleElement.append(table);
|
||||
|
||||
// init empty table
|
||||
let routesTable = table.DataTable( {
|
||||
@@ -1006,12 +1002,12 @@ define([
|
||||
let routesTable = routesTableElement.DataTable();
|
||||
|
||||
// init refresh routes --------------------------------------------------------------------
|
||||
moduleElement.find('.' + config.systemModuleHeadlineIconRefresh).on('click', function(e){
|
||||
moduleElement.find('.' + config.moduleHeadlineIconRefreshClass).on('click', function(e){
|
||||
updateRoutesTable(moduleElement, routesTable);
|
||||
});
|
||||
|
||||
// init search routes dialog --------------------------------------------------------------
|
||||
moduleElement.find('.' + config.systemModuleHeadlineIconSearch).on('click', function(e){
|
||||
moduleElement.find('.' + config.moduleHeadlineIconSearchClass).on('click', function(e){
|
||||
let maxRouteSearchLimit = this.Init.routeSearch.limit;
|
||||
|
||||
if(routesTable.rows().count() >= maxRouteSearchLimit){
|
||||
@@ -1032,7 +1028,7 @@ define([
|
||||
}));
|
||||
|
||||
// init settings dialog -------------------------------------------------------------------
|
||||
moduleElement.find('.' + config.systemModuleHeadlineIconSettings).on('click', function(e){
|
||||
moduleElement.find('.' + config.moduleHeadlineIconSettingsClass).on('click', function(e){
|
||||
let dialogData = {
|
||||
mapId: mapId
|
||||
};
|
||||
@@ -1061,49 +1057,10 @@ define([
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* updates an dom element with the system route module
|
||||
* @param mapId
|
||||
* @param systemData
|
||||
*/
|
||||
$.fn.drawSystemRouteModule = function(mapId, systemData){
|
||||
|
||||
let parentElement = $(this);
|
||||
|
||||
// show route module
|
||||
let showModule = function(moduleElement){
|
||||
if(moduleElement){
|
||||
moduleElement.css({ opacity: 0 });
|
||||
parentElement.append(moduleElement);
|
||||
|
||||
moduleElement.velocity('transition.slideDownIn', {
|
||||
duration: Init.animationSpeed.mapModule,
|
||||
delay: Init.animationSpeed.mapModule,
|
||||
complete: function(){
|
||||
initModule(moduleElement, mapId, systemData);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// check if module already exists
|
||||
let moduleElement = parentElement.find('.' + config.systemRouteModuleClass);
|
||||
|
||||
if(moduleElement.length > 0){
|
||||
moduleElement.velocity('transition.slideDownOut', {
|
||||
duration: Init.animationSpeed.mapModule,
|
||||
complete: function(tempElement){
|
||||
$(tempElement).remove();
|
||||
|
||||
moduleElement = getModule();
|
||||
showModule(moduleElement);
|
||||
}
|
||||
});
|
||||
}else{
|
||||
moduleElement = getModule();
|
||||
showModule(moduleElement);
|
||||
}
|
||||
|
||||
return {
|
||||
config: config,
|
||||
getModule: getModule,
|
||||
initModule: initModule
|
||||
};
|
||||
|
||||
});
|
||||
@@ -15,10 +15,15 @@ define([
|
||||
|
||||
let config = {
|
||||
// module info
|
||||
modulePosition: 4,
|
||||
moduleName: 'systemSignature',
|
||||
moduleHeadClass: 'pf-module-head', // class for module header
|
||||
moduleHandlerClass: 'pf-module-handler-drag', // class for "drag" handler
|
||||
|
||||
moduleClass: 'pf-module', // class for each module
|
||||
|
||||
// system signature module
|
||||
systemSigModuleClass: 'pf-sig-table-module', // module wrapper
|
||||
moduleTypeClass: 'pf-sig-table-module', // module wrapper
|
||||
|
||||
// tables
|
||||
tableToolsClass: 'pf-table-tools', // class for table toolbar
|
||||
@@ -31,6 +36,7 @@ define([
|
||||
signatureScannedProgressBarClass: 'pf-system-progress-scanned', // class for signature progress bar
|
||||
|
||||
// toolbar
|
||||
sigTableLazyToggleButtonClass: 'pf-sig-table-lazy-button', // class for "lazy update" toggle button
|
||||
sigTableClearButtonClass: 'pf-sig-table-clear-button', // class for "clear" signatures button
|
||||
|
||||
// signature table
|
||||
@@ -965,19 +971,19 @@ define([
|
||||
|
||||
if( clearButton.is(':hidden') ){
|
||||
// show button
|
||||
clearButton.velocity('transition.bounceIn', {
|
||||
duration: 180
|
||||
clearButton.velocity('transition.expandIn', {
|
||||
duration: 100
|
||||
});
|
||||
}else{
|
||||
// highlight button
|
||||
clearButton.velocity('callout.pulse', {
|
||||
duration: 240
|
||||
duration: 200
|
||||
});
|
||||
}
|
||||
}else{
|
||||
// hide button
|
||||
clearButton.velocity('transition.bounceOut', {
|
||||
duration: 180
|
||||
clearButton.velocity('transition.expandOut', {
|
||||
duration: 100
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -1048,6 +1054,12 @@ define([
|
||||
checkDeleteSignaturesButton(moduleElement);
|
||||
}
|
||||
})
|
||||
).append(
|
||||
$('<input>', {
|
||||
type: 'checkbox',
|
||||
class: [config.sigTableLazyToggleButtonClass, 'btn-labeled'].join(' '),
|
||||
value: 1,
|
||||
}).attr('data-toggle', 'toggle')
|
||||
).append(
|
||||
getLabledButton({
|
||||
type: 'danger',
|
||||
@@ -1073,6 +1085,24 @@ define([
|
||||
|
||||
moduleElement.append(tableToolbar);
|
||||
|
||||
// "lazy update" toggle button --------------------------------------------------------------------------------
|
||||
let lazyToggleCheckbox = moduleElement.find('.' + config.sigTableLazyToggleButtonClass).bootstrapToggle({
|
||||
size: 'small' ,
|
||||
on: '<i class="fa fa-fw fa-exchange"></i> lazy delete',
|
||||
off: '<i class="fa fa-fw fa-clipboard"></i> lazy update',
|
||||
onstyle: 'warning' ,
|
||||
offstyle: 'default' ,
|
||||
width: 110
|
||||
});
|
||||
|
||||
let lazyToggleButton = lazyToggleCheckbox.parent();
|
||||
lazyToggleButton.find('.toggle-on').attr('title', 'lazy \'update\' and \'delete\' old<br>from clipboard |ctrl + v|');
|
||||
lazyToggleButton.find('.toggle-off').attr('title', 'lazy \'update\' signatures<br>from clipboard |ctrl + v|');
|
||||
lazyToggleButton.initTooltips({
|
||||
container: 'body',
|
||||
html: true
|
||||
});
|
||||
|
||||
// add toolbar action for table -------------------------------------------------------------------------------
|
||||
let tableToolbarAction = $('<div>', {
|
||||
class: config.tableToolsActionClass
|
||||
@@ -1469,11 +1499,11 @@ define([
|
||||
let getSignatureConnectionOptions = (mapId, systemData) => {
|
||||
let map = Map.getMapInstance( mapId );
|
||||
let systemId = MapUtil.getSystemId(mapId, systemData.id);
|
||||
let systemConnections = MapUtil.searchConnectionsBySystems(map, [systemId]);
|
||||
let systemConnections = MapUtil.searchConnectionsBySystems(map, [systemId], 'wh');
|
||||
let connectionOptions = [];
|
||||
|
||||
for(let i = 0; i < systemConnections.length; i++){
|
||||
let connectionData = Map.getDataByConnection(systemConnections[i]);
|
||||
let connectionData = MapUtil.getDataByConnection(systemConnections[i]);
|
||||
|
||||
// connectionId is required (must be stored)
|
||||
if(connectionData.id){
|
||||
@@ -1739,7 +1769,7 @@ define([
|
||||
let deleteSignatures = function(tableApi, rows){
|
||||
let deletedSignatures = 0;
|
||||
|
||||
let moduleElement = $('.' + config.systemSigModuleClass);
|
||||
let moduleElement = $('.' + config.moduleTypeClass);
|
||||
let data = rows.data();
|
||||
let rowElements = rows.nodes().to$();
|
||||
let signatureCount = data.length;
|
||||
@@ -2312,12 +2342,35 @@ define([
|
||||
checkDeleteSignaturesButton(e.data.moduleElement);
|
||||
});
|
||||
|
||||
// destroy dataTables event -----------------------------------------------------------------------------------
|
||||
tablePrimaryElement.on('destroy.dt', function(){
|
||||
$(this).destroyTimestampCounter();
|
||||
});
|
||||
signatureTableApi.on('destroy.dt', function(){
|
||||
$(this).destroyTimestampCounter();
|
||||
});
|
||||
|
||||
// event listener for global "paste" signatures into the page -------------------------------------------------
|
||||
moduleElement.on('pf:updateSystemSignatureModuleByClipboard', function(e, clipboard){
|
||||
$(this).updateSignatureTableByClipboard(systemData, clipboard, {});
|
||||
// check "lazy update" toggle button
|
||||
let signatureOptions = {
|
||||
deleteOld: moduleElement.find('.' + config.sigTableLazyToggleButtonClass).is(':checked') ? 1 : 0
|
||||
};
|
||||
|
||||
$(this).updateSignatureTableByClipboard(systemData, clipboard, signatureOptions);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* init callback
|
||||
* @param moduleElement
|
||||
* @param mapId
|
||||
* @param connectionData
|
||||
*/
|
||||
let initModule = (moduleElement, mapId, systemData) => {
|
||||
unlockSignatureTable(true);
|
||||
};
|
||||
|
||||
/**
|
||||
* get module element
|
||||
* @param parentElement
|
||||
@@ -2326,25 +2379,23 @@ define([
|
||||
* @returns {*|jQuery|HTMLElement}
|
||||
*/
|
||||
let getModule = function(parentElement, mapId, systemData){
|
||||
|
||||
// create new module container
|
||||
let moduleElement = $('<div>', {
|
||||
class: [config.moduleClass, config.systemSigModuleClass].join(' '),
|
||||
css: {opacity: 0}
|
||||
});
|
||||
let moduleElement = $('<div>').append(
|
||||
$('<div>', {
|
||||
class: config.moduleHeadClass
|
||||
}).append(
|
||||
$('<h5>', {
|
||||
class: config.moduleHandlerClass
|
||||
}),
|
||||
$('<h5>', {
|
||||
text: 'Signatures'
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
moduleElement.data('mapId', mapId);
|
||||
moduleElement.data('systemId', systemData.id);
|
||||
|
||||
// headline
|
||||
let headline = $('<h5>', {
|
||||
text: 'Signatures'
|
||||
});
|
||||
|
||||
moduleElement.append(headline);
|
||||
|
||||
$(parentElement).append(moduleElement);
|
||||
|
||||
// init dataTables
|
||||
initSignatureDataTable(systemData);
|
||||
|
||||
@@ -2385,76 +2436,31 @@ define([
|
||||
};
|
||||
|
||||
/**
|
||||
* main module load function
|
||||
* @param mapId
|
||||
* @param systemData
|
||||
* before module reDraw callback
|
||||
*/
|
||||
$.fn.drawSignatureTableModule = function(mapId, systemData){
|
||||
let parentElement = $(this);
|
||||
let beforeReDraw = () => {
|
||||
// disable update
|
||||
lockSignatureTable();
|
||||
};
|
||||
|
||||
// show module
|
||||
let showModule = function(moduleElement){
|
||||
if(moduleElement){
|
||||
moduleElement.velocity('transition.slideDownIn', {
|
||||
duration: Init.animationSpeed.mapModule,
|
||||
delay: Init.animationSpeed.mapModule,
|
||||
complete: function(){
|
||||
unlockSignatureTable(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// some custom array functions
|
||||
let initArrayFunctions = function(){
|
||||
/**
|
||||
* sort array of objects by property name
|
||||
* @param p
|
||||
* @returns {Array.<T>}
|
||||
*/
|
||||
Array.prototype.sortBy = function(p) {
|
||||
return this.slice(0).sort(function(a,b) {
|
||||
return (a[p] > b[p]) ? 1 : (a[p] < b[p]) ? -1 : 0;
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
// check if module already exists
|
||||
let moduleElement = parentElement.find('.' + config.systemSigModuleClass);
|
||||
|
||||
if(moduleElement.length > 0){
|
||||
// disable update
|
||||
lockSignatureTable();
|
||||
|
||||
moduleElement.velocity('transition.slideDownOut', {
|
||||
duration: Init.animationSpeed.mapModule,
|
||||
complete: function(tempElement){
|
||||
tempElement = $(tempElement);
|
||||
// Destroying the data tables throws
|
||||
// save remove of all dataTables
|
||||
let mapId = tempElement.data('mapId');
|
||||
let systemId = tempElement.data('systemId');
|
||||
deleteDataTableInstance(mapId, systemId, 'primary');
|
||||
deleteDataTableInstance(mapId, systemId, 'secondary');
|
||||
|
||||
tempElement.remove();
|
||||
|
||||
moduleElement = getModule(parentElement, mapId, systemData);
|
||||
// make modules appear "nice"
|
||||
moduleElement.delay(150);
|
||||
showModule(moduleElement);
|
||||
}
|
||||
});
|
||||
}else{
|
||||
// init array prototype functions
|
||||
initArrayFunctions();
|
||||
|
||||
moduleElement = getModule(parentElement, mapId, systemData);
|
||||
showModule(moduleElement);
|
||||
}
|
||||
/**
|
||||
* before module destroy callback
|
||||
*/
|
||||
let beforeDestroy = (moduleElement) => {
|
||||
// Destroying the data tables throws
|
||||
// -> safety remove all dataTables
|
||||
let mapId = moduleElement.data('mapId');
|
||||
let systemId = moduleElement.data('systemId');
|
||||
deleteDataTableInstance(mapId, systemId, 'primary');
|
||||
deleteDataTableInstance(mapId, systemId, 'secondary');
|
||||
};
|
||||
|
||||
return {
|
||||
config: config,
|
||||
getModule: getModule,
|
||||
initModule: initModule,
|
||||
beforeReDraw: beforeReDraw,
|
||||
beforeDestroy: beforeDestroy,
|
||||
getAllSignatureNamesBySystem: getAllSignatureNamesBySystem
|
||||
};
|
||||
|
||||
|
||||
184
js/app/util.js
184
js/app/util.js
@@ -546,6 +546,8 @@ define([
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return element;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -618,6 +620,17 @@ define([
|
||||
popoverElement = button.data('bs.popover').tip();
|
||||
popoverElement.velocity('transition.' + easeEffect, velocityOptions);
|
||||
popoverElement.initTooltips();
|
||||
|
||||
// set click events. This is required to pass data to "beforeunload" events
|
||||
// -> there is no way to identify the target within that event
|
||||
popoverElement.on('click', '.btn', function(){
|
||||
// character switch detected
|
||||
$('body').data('characterSwitch', true);
|
||||
// ... and remove "characterSwitch" data again! after "unload"
|
||||
setTimeout(function() {
|
||||
$('body').removeData('characterSwitch');
|
||||
}, 500);
|
||||
});
|
||||
}else{
|
||||
popoverElement = button.data('bs.popover').tip();
|
||||
if(popoverElement.is(':visible')){
|
||||
@@ -668,39 +681,6 @@ define([
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* add a wormhole tooltip with wh specific data to elements
|
||||
* @param tooltipData
|
||||
* @returns {*}
|
||||
*/
|
||||
$.fn.addWormholeInfoTooltip = function(tooltipData){
|
||||
return this.each(function() {
|
||||
let element = $(this);
|
||||
|
||||
requirejs(['text!templates/tooltip/wormhole_info.html', 'mustache'], function (template, Mustache) {
|
||||
let content = Mustache.render(template, tooltipData);
|
||||
|
||||
element.popover({
|
||||
placement: 'top',
|
||||
html: true,
|
||||
trigger: 'hover',
|
||||
content: '',
|
||||
container: 'body',
|
||||
title: tooltipData.name +
|
||||
'<span class="pull-right ' + tooltipData.class +'">' + tooltipData.security + '</span>',
|
||||
delay: {
|
||||
show: 250,
|
||||
hide: 0
|
||||
}
|
||||
});
|
||||
|
||||
// set new popover content
|
||||
let popover = element.data('bs.popover');
|
||||
popover.options.content = content;
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* display a custom message (info/warning/error) to a container element
|
||||
* check: $.fn.showFormMessage() for an other way of showing messages
|
||||
@@ -862,6 +842,17 @@ define([
|
||||
Array.prototype.diff = function(a) {
|
||||
return this.filter(function(i) {return a.indexOf(i) < 0;});
|
||||
};
|
||||
|
||||
/**
|
||||
* sort array of objects by property name
|
||||
* @param p
|
||||
* @returns {Array.<T>}
|
||||
*/
|
||||
Array.prototype.sortBy = function(p) {
|
||||
return this.slice(0).sort((a,b) => {
|
||||
return (a[p] > b[p]) ? 1 : (a[p] < b[p]) ? -1 : 0;
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -883,7 +874,7 @@ define([
|
||||
}
|
||||
|
||||
return flatten;
|
||||
} ;
|
||||
};
|
||||
|
||||
/**
|
||||
* set default configuration for "Bootbox" dialogs
|
||||
@@ -1081,6 +1072,28 @@ define([
|
||||
return Init.currentUserData;
|
||||
};
|
||||
|
||||
/**
|
||||
* get either active characterID or characterId from initial page load
|
||||
* @returns {number}
|
||||
*/
|
||||
let getCurrentCharacterId = () => {
|
||||
let userData = getCurrentUserData();
|
||||
let currentCharacterId = 0;
|
||||
if(
|
||||
userData &&
|
||||
userData.character
|
||||
){
|
||||
currentCharacterId = parseInt( userData.character.id );
|
||||
}
|
||||
|
||||
if(!currentCharacterId){
|
||||
// no active character... -> get default characterId from initial page load
|
||||
currentCharacterId = parseInt(document.body.getAttribute('data-character-id'));
|
||||
}
|
||||
|
||||
return currentCharacterId;
|
||||
};
|
||||
|
||||
/**
|
||||
* get a unique ID for each tab
|
||||
* -> store ID in session storage
|
||||
@@ -1104,21 +1117,9 @@ define([
|
||||
// Add custom application headers on "same origin" requests only!
|
||||
// -> Otherwise a "preflight" request is made, which will "probably" fail
|
||||
if(settings.crossDomain === false){
|
||||
// Add browser tab information
|
||||
xhr.setRequestHeader('Pf-Tab-Id', getBrowserTabId()) ;
|
||||
|
||||
// add current character data to ANY XHR request (HTTP HEADER)
|
||||
// -> This helps to identify multiple characters on multiple browser tabs
|
||||
let userData = getCurrentUserData();
|
||||
let currentCharacterId = 0;
|
||||
if(
|
||||
userData &&
|
||||
userData.character
|
||||
){
|
||||
currentCharacterId = parseInt( userData.character.id );
|
||||
}
|
||||
|
||||
xhr.setRequestHeader('Pf-Character', currentCharacterId);
|
||||
xhr.setRequestHeader('Pf-Character', getCurrentCharacterId());
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -1278,7 +1279,6 @@ define([
|
||||
* @returns {*|HTMLElement}
|
||||
*/
|
||||
let getMapModule = function(){
|
||||
|
||||
let mapModule = $('#' + config.mapModuleId);
|
||||
if(mapModule.length === 0){
|
||||
mapModule = $('<div>', {
|
||||
@@ -1470,13 +1470,11 @@ define([
|
||||
* @param sec
|
||||
* @returns {string}
|
||||
*/
|
||||
let getSecurityClassForSystem = function(sec){
|
||||
let getSecurityClassForSystem = (sec) => {
|
||||
let secClass = '';
|
||||
|
||||
if( Init.classes.systemSecurity.hasOwnProperty(sec) ){
|
||||
secClass = Init.classes.systemSecurity[sec]['class'];
|
||||
}
|
||||
|
||||
return secClass;
|
||||
};
|
||||
|
||||
@@ -1994,7 +1992,7 @@ define([
|
||||
* set currentSystemData as "global" variable
|
||||
* @param systemData
|
||||
*/
|
||||
let setCurrentSystemData = function(systemData){
|
||||
let setCurrentSystemData = (systemData) => {
|
||||
Init.currentSystemData = systemData;
|
||||
};
|
||||
|
||||
@@ -2002,7 +2000,7 @@ define([
|
||||
* get currentSystemData from "global" variables
|
||||
* @returns {*}
|
||||
*/
|
||||
let getCurrentSystemData = function(){
|
||||
let getCurrentSystemData = () => {
|
||||
return Init.currentSystemData;
|
||||
};
|
||||
|
||||
@@ -2060,7 +2058,7 @@ define([
|
||||
* @param price
|
||||
* @returns {string}
|
||||
*/
|
||||
let formatPrice = function(price){
|
||||
let formatPrice = (price) => {
|
||||
price = Number( price ).toFixed(2);
|
||||
|
||||
let parts = price.toString().split('.');
|
||||
@@ -2069,6 +2067,15 @@ define([
|
||||
return price + ' ISK';
|
||||
};
|
||||
|
||||
/**
|
||||
* format mass value
|
||||
* @param value
|
||||
* @returns {string}
|
||||
*/
|
||||
let formatMassValue = (value) => {
|
||||
return (parseInt(value) / 1000).toLocaleString() + ' t';
|
||||
};
|
||||
|
||||
/**
|
||||
* get localForage instance (singleton) for offline client site storage
|
||||
* @returns {localforage}
|
||||
@@ -2098,7 +2105,7 @@ define([
|
||||
* @param date
|
||||
* @returns {Date}
|
||||
*/
|
||||
let createDateAsUTC = function(date){
|
||||
let createDateAsUTC = (date) => {
|
||||
return new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds()));
|
||||
};
|
||||
|
||||
@@ -2107,7 +2114,7 @@ define([
|
||||
* @param date
|
||||
* @returns {Date}
|
||||
*/
|
||||
let convertDateToUTC = function(date){
|
||||
let convertDateToUTC = (date) => {
|
||||
return new Date(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds());
|
||||
};
|
||||
|
||||
@@ -2117,7 +2124,7 @@ define([
|
||||
* @param showSeconds
|
||||
* @returns {string}
|
||||
*/
|
||||
let convertDateToString = function(date, showSeconds){
|
||||
let convertDateToString = (date, showSeconds) => {
|
||||
let dateString = ('0'+ (date.getMonth() + 1 )).slice(-2) + '/' + ('0'+date.getDate()).slice(-2) + '/' + date.getFullYear();
|
||||
let timeString = ('0' + date.getHours()).slice(-2) + ':' + ('0'+date.getMinutes()).slice(-2);
|
||||
timeString += (showSeconds) ? ':' + ('0'+date.getSeconds()).slice(-2) : '';
|
||||
@@ -2142,7 +2149,7 @@ define([
|
||||
* -> www.pathfinder.com/pathfinder/ -> /pathfinder
|
||||
* @returns {string|string}
|
||||
*/
|
||||
let getDocumentPath = function(){
|
||||
let getDocumentPath = () => {
|
||||
let pathname = window.location.pathname;
|
||||
// replace file endings
|
||||
let r = /[^\/]*$/;
|
||||
@@ -2155,7 +2162,7 @@ define([
|
||||
* @param url
|
||||
* @param params
|
||||
*/
|
||||
let redirect = function(url, params){
|
||||
let redirect = (url, params) => {
|
||||
let currentUrl = document.URL;
|
||||
|
||||
if(url !== currentUrl){
|
||||
@@ -2173,7 +2180,7 @@ define([
|
||||
* send logout request
|
||||
* @param params
|
||||
*/
|
||||
let logout = function(params){
|
||||
let logout = (params) => {
|
||||
let data = {};
|
||||
if(
|
||||
params &&
|
||||
@@ -2197,6 +2204,56 @@ define([
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* set a cookie
|
||||
* @param name
|
||||
* @param value
|
||||
* @param expire
|
||||
* @param format
|
||||
*/
|
||||
let setCookie = (name, value, expire, format) => {
|
||||
let d = new Date();
|
||||
let time = d.getTime();
|
||||
let timeExpire = time * -1;
|
||||
|
||||
if(expire > 0){
|
||||
switch(format){
|
||||
case 'd': // days
|
||||
timeExpire = expire * 24 * 60 * 60 * 1000; break;
|
||||
case 's': // seconds
|
||||
timeExpire = expire * 1000; break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
d.setTime(time + timeExpire);
|
||||
let expires = 'expires=' + d.toUTCString();
|
||||
let path = 'path=' + getDocumentPath();
|
||||
document.cookie = name + '=' + value + '; ' + expires + '; ' + path;
|
||||
};
|
||||
|
||||
/**
|
||||
* get cookie value by name
|
||||
* @param cname
|
||||
* @returns {string}
|
||||
*/
|
||||
let getCookie = (cname) => {
|
||||
let name = cname + '=';
|
||||
let ca = document.cookie.split(';');
|
||||
|
||||
for(let i = 0; i <ca.length; i++) {
|
||||
let c = ca[i];
|
||||
while (c.charAt(0) === ' ') {
|
||||
c = c.substring(1);
|
||||
}
|
||||
|
||||
if (c.indexOf(name) === 0) {
|
||||
return c.substring(name.length,c.length);
|
||||
}
|
||||
}
|
||||
return '';
|
||||
};
|
||||
|
||||
return {
|
||||
config: config,
|
||||
getVersion: getVersion,
|
||||
@@ -2239,6 +2296,7 @@ define([
|
||||
deleteCurrentMapData: deleteCurrentMapData,
|
||||
setCurrentUserData: setCurrentUserData,
|
||||
getCurrentUserData: getCurrentUserData,
|
||||
getCurrentCharacterId: getCurrentCharacterId,
|
||||
setCurrentSystemData: setCurrentSystemData,
|
||||
getCurrentSystemData: getCurrentSystemData,
|
||||
getCurrentLocationData: getCurrentLocationData,
|
||||
@@ -2253,12 +2311,14 @@ define([
|
||||
getOpenDialogs: getOpenDialogs,
|
||||
openIngameWindow: openIngameWindow,
|
||||
formatPrice: formatPrice,
|
||||
formatMassValue: formatMassValue,
|
||||
getLocalStorage: getLocalStorage,
|
||||
clearSessionStorage: clearSessionStorage,
|
||||
getBrowserTabId: getBrowserTabId,
|
||||
getObjVal: getObjVal,
|
||||
getDocumentPath: getDocumentPath,
|
||||
redirect: redirect,
|
||||
logout: logout
|
||||
logout: logout,
|
||||
setCookie: setCookie,
|
||||
getCookie: getCookie
|
||||
};
|
||||
});
|
||||
8
js/lib/bootstrap-toggle.min.js
vendored
Normal file
8
js/lib/bootstrap-toggle.min.js
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
/*! ========================================================================
|
||||
* Bootstrap Toggle: bootstrap-toggle.js v2.2.0
|
||||
* http://www.bootstraptoggle.com
|
||||
* ========================================================================
|
||||
* Copyright 2014 Min Hur, The New York Times Company
|
||||
* Licensed under MIT
|
||||
* ======================================================================== */
|
||||
+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.toggle"),f="object"==typeof b&&b;e||d.data("bs.toggle",e=new c(this,f)),"string"==typeof b&&e[b]&&e[b]()})}var c=function(b,c){this.$element=a(b),this.options=a.extend({},this.defaults(),c),this.render()};c.VERSION="2.2.0",c.DEFAULTS={on:"On",off:"Off",onstyle:"primary",offstyle:"default",size:"normal",style:"",width:null,height:null},c.prototype.defaults=function(){return{on:this.$element.attr("data-on")||c.DEFAULTS.on,off:this.$element.attr("data-off")||c.DEFAULTS.off,onstyle:this.$element.attr("data-onstyle")||c.DEFAULTS.onstyle,offstyle:this.$element.attr("data-offstyle")||c.DEFAULTS.offstyle,size:this.$element.attr("data-size")||c.DEFAULTS.size,style:this.$element.attr("data-style")||c.DEFAULTS.style,width:this.$element.attr("data-width")||c.DEFAULTS.width,height:this.$element.attr("data-height")||c.DEFAULTS.height}},c.prototype.render=function(){this._onstyle="btn-"+this.options.onstyle,this._offstyle="btn-"+this.options.offstyle;var b="large"===this.options.size?"btn-lg":"small"===this.options.size?"btn-sm":"mini"===this.options.size?"btn-xs":"",c=a('<label class="btn">').html(this.options.on).addClass(this._onstyle+" "+b),d=a('<label class="btn">').html(this.options.off).addClass(this._offstyle+" "+b+" active"),e=a('<span class="toggle-handle btn btn-default">').addClass(b),f=a('<div class="toggle-group">').append(c,d,e),g=a('<div class="toggle btn" data-toggle="toggle">').addClass(this.$element.prop("checked")?this._onstyle:this._offstyle+" off").addClass(b).addClass(this.options.style);this.$element.wrap(g),a.extend(this,{$toggle:this.$element.parent(),$toggleOn:c,$toggleOff:d,$toggleGroup:f}),this.$toggle.append(f);var h=this.options.width||Math.max(c.outerWidth(),d.outerWidth())+e.outerWidth()/2,i=this.options.height||Math.max(c.outerHeight(),d.outerHeight());c.addClass("toggle-on"),d.addClass("toggle-off"),this.$toggle.css({width:h,height:i}),this.options.height&&(c.css("line-height",c.height()+"px"),d.css("line-height",d.height()+"px")),this.update(!0),this.trigger(!0)},c.prototype.toggle=function(){this.$element.prop("checked")?this.off():this.on()},c.prototype.on=function(a){return this.$element.prop("disabled")?!1:(this.$toggle.removeClass(this._offstyle+" off").addClass(this._onstyle),this.$element.prop("checked",!0),void(a||this.trigger()))},c.prototype.off=function(a){return this.$element.prop("disabled")?!1:(this.$toggle.removeClass(this._onstyle).addClass(this._offstyle+" off"),this.$element.prop("checked",!1),void(a||this.trigger()))},c.prototype.enable=function(){this.$toggle.removeAttr("disabled"),this.$element.prop("disabled",!1)},c.prototype.disable=function(){this.$toggle.attr("disabled","disabled"),this.$element.prop("disabled",!0)},c.prototype.update=function(a){this.$element.prop("disabled")?this.disable():this.enable(),this.$element.prop("checked")?this.on(a):this.off(a)},c.prototype.trigger=function(b){this.$element.off("change.bs.toggle"),b||this.$element.change(),this.$element.on("change.bs.toggle",a.proxy(function(){this.update()},this))},c.prototype.destroy=function(){this.$element.off("change.bs.toggle"),this.$toggleGroup.remove(),this.$element.removeData("bs.toggle"),this.$element.unwrap()};var d=a.fn.bootstrapToggle;a.fn.bootstrapToggle=b,a.fn.bootstrapToggle.Constructor=c,a.fn.toggle.noConflict=function(){return a.fn.bootstrapToggle=d,this},a(function(){a("input[type=checkbox][data-toggle^=toggle]").bootstrapToggle()}),a(document).on("click.bs.toggle","div[data-toggle^=toggle]",function(b){var c=a(this).find("input[type=checkbox]");c.bootstrapToggle("toggle"),b.preventDefault()})}(jQuery);
|
||||
8
js/lib/bootstrap2-toggle.min.js
vendored
8
js/lib/bootstrap2-toggle.min.js
vendored
@@ -1,8 +0,0 @@
|
||||
/*! ========================================================================
|
||||
* Bootstrap Toggle: bootstrap2-toggle.js v2.2.0
|
||||
* http://www.bootstraptoggle.com
|
||||
* ========================================================================
|
||||
* Copyright 2014 Min Hur, The New York Times Company
|
||||
* Licensed under MIT
|
||||
* ======================================================================== */
|
||||
+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.toggle"),f="object"==typeof b&&b;e||d.data("bs.toggle",e=new c(this,f)),"string"==typeof b&&e[b]&&e[b]()})}var c=function(b,c){this.$element=a(b),this.options=a.extend({},this.defaults(),c),this.render()};c.VERSION="2.2.0",c.DEFAULTS={on:"On",off:"Off",onstyle:"primary",offstyle:"default",size:"normal",style:"",width:null,height:null},c.prototype.defaults=function(){return{on:this.$element.attr("data-on")||c.DEFAULTS.on,off:this.$element.attr("data-off")||c.DEFAULTS.off,onstyle:this.$element.attr("data-onstyle")||c.DEFAULTS.onstyle,offstyle:this.$element.attr("data-offstyle")||c.DEFAULTS.offstyle,size:this.$element.attr("data-size")||c.DEFAULTS.size,style:this.$element.attr("data-style")||c.DEFAULTS.style,width:this.$element.attr("data-width")||c.DEFAULTS.width,height:this.$element.attr("data-height")||c.DEFAULTS.height}},c.prototype.render=function(){this._onstyle="btn-"+this.options.onstyle,this._offstyle="btn-"+this.options.offstyle;var b="large"===this.options.size?"btn-large":"small"===this.options.size?"btn-small":"mini"===this.options.size?"btn-mini":"",c=a('<label class="btn">').html(this.options.on).addClass(this._onstyle+" "+b),d=a('<label class="btn">').html(this.options.off).addClass(this._offstyle+" "+b+" active"),e=a('<span class="toggle-handle btn btn-default">').addClass(b),f=a('<div class="toggle-group">').append(c,d,e),g=a('<div class="toggle btn" data-toggle="toggle">').addClass(this.$element.prop("checked")?this._onstyle:this._offstyle+" off").addClass(b).addClass(this.options.style);this.$element.wrap(g),a.extend(this,{$toggle:this.$element.parent(),$toggleOn:c,$toggleOff:d,$toggleGroup:f}),this.$toggle.append(f);var h=this.options.width||Math.max(c.width(),d.width())+e.outerWidth()/2,i=this.options.height||Math.max(c.height(),d.height());c.addClass("toggle-on"),d.addClass("toggle-off"),this.$toggle.css({width:h,height:i}),this.options.height&&(c.css("line-height",c.height()+"px"),d.css("line-height",d.height()+"px")),this.update(!0),this.trigger(!0)},c.prototype.toggle=function(){this.$element.prop("checked")?this.off():this.on()},c.prototype.on=function(a){return this.$element.prop("disabled")?!1:(this.$toggle.removeClass(this._offstyle+" off").addClass(this._onstyle),this.$element.prop("checked",!0),void(a||this.trigger()))},c.prototype.off=function(a){return this.$element.prop("disabled")?!1:(this.$toggle.removeClass(this._onstyle).addClass(this._offstyle+" off"),this.$element.prop("checked",!1),void(a||this.trigger()))},c.prototype.enable=function(){this.$toggle.removeAttr("disabled"),this.$element.prop("disabled",!1)},c.prototype.disable=function(){this.$toggle.attr("disabled","disabled"),this.$element.prop("disabled",!0)},c.prototype.update=function(a){this.$element.prop("disabled")?this.disable():this.enable(),this.$element.prop("checked")?this.on(a):this.off(a)},c.prototype.trigger=function(b){this.$element.off("change.bs.toggle"),b||this.$element.change(),this.$element.on("change.bs.toggle",a.proxy(function(){this.update()},this))},c.prototype.destroy=function(){this.$element.off("change.bs.toggle"),this.$toggleGroup.remove(),this.$element.removeData("bs.toggle"),this.$element.unwrap()};var d=a.fn.bootstrapToggle;a.fn.bootstrapToggle=b,a.fn.bootstrapToggle.Constructor=c,a.fn.toggle.noConflict=function(){return a.fn.bootstrapToggle=d,this},a(function(){a("input[type=checkbox][data-toggle^=toggle]").bootstrapToggle()}),a(document).on("click.bs.toggle","div[data-toggle^=toggle]",function(b){var c=a(this).find("input[type=checkbox]");c.bootstrapToggle("toggle"),b.preventDefault()})}(jQuery);
|
||||
@@ -10388,12 +10388,13 @@
|
||||
|
||||
// in IE the top left corner is what it placed at the desired location. This will not
|
||||
// be fixed. IE8 is not going to be supported for much longer.
|
||||
var ts = "translate(-50%, -50%)";
|
||||
var ts = "translate(-50%, calc(-50% - .5px))";
|
||||
div.style.webkitTransform = ts;
|
||||
div.style.mozTransform = ts;
|
||||
div.style.msTransform = ts;
|
||||
div.style.oTransform = ts;
|
||||
div.style.transform = ts;
|
||||
div.style.WebkitFontSmoothing = 'antialiased';
|
||||
|
||||
// write the related component into the created element
|
||||
div._jsPlumb = this;
|
||||
|
||||
@@ -46,11 +46,11 @@ $('#jquery-drag-to-select-example').dragToSelect({
|
||||
}
|
||||
});
|
||||
*/
|
||||
jQuery.fn.dragToSelect = function (conf) {
|
||||
$.fn.dragToSelect = function (conf) {
|
||||
var c = typeof(conf) == 'object' ? conf : {};
|
||||
|
||||
// Config
|
||||
var config = jQuery.extend({
|
||||
var config = $.extend({
|
||||
className: 'pf-map-drag-to-select',
|
||||
activeClass: 'active',
|
||||
disabledClass: 'disabled',
|
||||
@@ -66,7 +66,7 @@ jQuery.fn.dragToSelect = function (conf) {
|
||||
onRefresh: function () {return true;}
|
||||
}, c);
|
||||
|
||||
var realParent = jQuery(this);
|
||||
var realParent = $(this);
|
||||
var parent = realParent;
|
||||
|
||||
var animationFrameId;
|
||||
@@ -156,14 +156,14 @@ jQuery.fn.dragToSelect = function (conf) {
|
||||
|
||||
// get scroll position
|
||||
var leftScroll = 0;
|
||||
var rightScroll = 0;
|
||||
var topScroll = 0;
|
||||
|
||||
if(realParent.data('scrollLeft')){
|
||||
leftScroll = realParent.data('scrollLeft');
|
||||
if(realParent.attr('data-scroll-left')){
|
||||
leftScroll = parseInt(realParent.attr('data-scroll-left'));
|
||||
}
|
||||
|
||||
if(realParent.data('scrollRight')){
|
||||
rightScroll = realParent.data('scrollRight');
|
||||
if(realParent.attr('data-scroll-top')){
|
||||
topScroll = parseInt(realParent.attr('data-scroll-top'));
|
||||
}
|
||||
|
||||
var left = lastMousePosition.x - parentDim.left + parent[0].scrollLeft;
|
||||
@@ -175,13 +175,11 @@ jQuery.fn.dragToSelect = function (conf) {
|
||||
newLeft = selectBoxOrigin.left - leftScroll;
|
||||
var newWidth = left - selectBoxOrigin.left;
|
||||
|
||||
|
||||
if(newWidth < 0){
|
||||
newLeft = newLeft - tempWidth ;
|
||||
newWidth = newWidth * -1;
|
||||
}
|
||||
|
||||
|
||||
if (top > selectBoxOrigin.top) {
|
||||
newTop = selectBoxOrigin.top;
|
||||
newHeight = top - selectBoxOrigin.top;
|
||||
@@ -368,7 +366,7 @@ jQuery.fn.dragToSelect = function (conf) {
|
||||
e.target === realParent[0] // prevent while dragging a system :)
|
||||
) {
|
||||
// Make sure user isn't clicking scrollbar (or disallow clicks far to the right actually)
|
||||
if ((e.pageX + 20) > jQuery(document.body).width()) {
|
||||
if ((e.pageX + 20) > $(document.body).width()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
14
js/lib/jquery.peity.min.js
vendored
14
js/lib/jquery.peity.min.js
vendored
@@ -1,13 +1,13 @@
|
||||
// Peity jQuery plugin version 3.2.0
|
||||
// (c) 2015 Ben Pickles
|
||||
// Peity jQuery plugin version 3.2.1
|
||||
// (c) 2016 Ben Pickles
|
||||
//
|
||||
// http://benpickles.github.io/peity
|
||||
//
|
||||
// Released under MIT license.
|
||||
(function(k,w,h,v){var d=k.fn.peity=function(a,b){y&&this.each(function(){var e=k(this),c=e.data("_peity");c?(a&&(c.type=a),k.extend(c.opts,b)):(c=new x(e,a,k.extend({},d.defaults[a],e.data("peity"),b)),e.change(function(){c.draw()}).data("_peity",c));c.draw()});return this},x=function(a,b,e){this.$el=a;this.type=b;this.opts=e},o=x.prototype,q=o.svgElement=function(a,b){return k(w.createElementNS("http://www.w3.org/2000/svg",a)).attr(b)},y="createElementNS"in w&&q("svg",{})[0].createSVGRect;o.draw=
|
||||
function(){var a=this.opts;d.graphers[this.type].call(this,a);a.after&&a.after.call(this,a)};o.fill=function(){var a=this.opts.fill;return k.isFunction(a)?a:function(b,e){return a[e%a.length]}};o.prepare=function(a,b){this.$svg||this.$el.hide().after(this.$svg=q("svg",{"class":"peity"}));return this.$svg.empty().data("peity",this).attr({height:b,width:a})};o.values=function(){return k.map(this.$el.text().split(this.opts.delimiter),function(a){return parseFloat(a)})};d.defaults={};d.graphers={};d.register=
|
||||
function(a,b,e){this.defaults[a]=b;this.graphers[a]=e};d.register("pie",{fill:["#ff9900","#fff4dd","#ffc66e"],radius:8},function(a){if(!a.delimiter){var b=this.$el.text().match(/[^0-9\.]/);a.delimiter=b?b[0]:","}b=k.map(this.values(),function(a){return 0<a?a:0});if("/"==a.delimiter)var e=b[0],b=[e,h.max(0,b[1]-e)];for(var c=0,e=b.length,t=0;c<e;c++)t+=b[c];t||(e=2,t=1,b=[0,1]);var l=2*a.radius,l=this.prepare(a.width||l,a.height||l),c=l.width(),f=l.height(),j=c/2,d=f/2,f=h.min(j,d),a=a.innerRadius;
|
||||
"donut"==this.type&&!a&&(a=0.5*f);for(var r=h.PI,s=this.fill(),g=this.scale=function(a,b){var c=a/t*r*2-r/2;return[b*h.cos(c)+j,b*h.sin(c)+d]},m=0,c=0;c<e;c++){var u=b[c],i=u/t;if(0!=i){if(1==i)if(a)var i=j-0.01,p=d-f,n=d-a,i=q("path",{d:["M",j,p,"A",f,f,0,1,1,i,p,"L",i,n,"A",a,a,0,1,0,j,n].join(" ")});else i=q("circle",{cx:j,cy:d,r:f});else p=m+u,n=["M"].concat(g(m,f),"A",f,f,0,0.5<i?1:0,1,g(p,f),"L"),a?n=n.concat(g(p,a),"A",a,a,0,0.5<i?1:0,0,g(m,a)):n.push(j,d),m+=u,i=q("path",{d:n.join(" ")});
|
||||
i.attr("fill",s.call(this,u,c,b));l.append(i)}}});d.register("donut",k.extend(!0,{},d.defaults.pie),function(a){d.graphers.pie.call(this,a)});d.register("line",{delimiter:",",fill:"#c6d9fd",height:16,min:0,stroke:"#4d89f9",strokeWidth:1,width:32},function(a){var b=this.values();1==b.length&&b.push(b[0]);for(var e=h.max.apply(h,a.max==v?b:b.concat(a.max)),c=h.min.apply(h,a.min==v?b:b.concat(a.min)),d=this.prepare(a.width,a.height),l=a.strokeWidth,f=d.width(),j=d.height()-l,k=e-c,e=this.x=function(a){return a*
|
||||
(f/(b.length-1))},r=this.y=function(a){var b=j;k&&(b-=(a-c)/k*j);return b+l/2},s=r(h.max(c,0)),g=[0,s],m=0;m<b.length;m++)g.push(e(m),r(b[m]));g.push(f,s);a.fill&&d.append(q("polygon",{fill:a.fill,points:g.join(" ")}));l&&d.append(q("polyline",{fill:"none",points:g.slice(2,g.length-2).join(" "),stroke:a.stroke,"stroke-width":l,"stroke-linecap":"square"}))});d.register("bar",{delimiter:",",fill:["#4D89F9"],height:16,min:0,padding:0.1,width:32},function(a){for(var b=this.values(),e=h.max.apply(h,a.max==
|
||||
function(){var a=this.opts;d.graphers[this.type].call(this,a);a.after&&a.after.call(this,a)};o.fill=function(){var a=this.opts.fill;return k.isFunction(a)?a:function(b,e){return a[e%a.length]}};o.prepare=function(a,b){this.$svg||this.$el.hide().after(this.$svg=q("svg",{"class":"peity"}));return this.$svg.empty().data("peity",this).attr({height:b,width:a})};o.values=function(){return k.map(this.$el.text().split(this.opts.delimiter),function(a){return parseFloat(a)})};d.defaults={};d.graphers={};d.register=
|
||||
function(a,b,e){this.defaults[a]=b;this.graphers[a]=e};d.register("pie",{fill:["#ff9900","#fff4dd","#ffc66e"],radius:8},function(a){if(!a.delimiter){var b=this.$el.text().match(/[^0-9\.]/);a.delimiter=b?b[0]:","}b=k.map(this.values(),function(a){return 0<a?a:0});if("/"==a.delimiter)var e=b[0],b=[e,h.max(0,b[1]-e)];for(var c=0,e=b.length,t=0;c<e;c++)t+=b[c];t||(e=2,t=1,b=[0,1]);var l=2*a.radius,l=this.prepare(a.width||l,a.height||l),c=l.width(),f=l.height(),j=c/2,d=f/2,f=h.min(j,d),a=a.innerRadius;
|
||||
"donut"==this.type&&!a&&(a=0.5*f);for(var r=h.PI,s=this.fill(),g=this.scale=function(a,b){var c=a/t*r*2-r/2;return[b*h.cos(c)+j,b*h.sin(c)+d]},m=0,c=0;c<e;c++){var u=b[c],i=u/t;if(0!=i){if(1==i)if(a)var i=j-0.01,p=d-f,n=d-a,i=q("path",{d:["M",j,p,"A",f,f,0,1,1,i,p,"L",i,n,"A",a,a,0,1,0,j,n].join(" ")});else i=q("circle",{cx:j,cy:d,r:f});else p=m+u,n=["M"].concat(g(m,f),"A",f,f,0,0.5<i?1:0,1,g(p,f),"L"),a?n=n.concat(g(p,a),"A",a,a,0,0.5<i?1:0,0,g(m,a)):n.push(j,d),m+=u,i=q("path",{d:n.join(" ")});
|
||||
i.attr("fill",s.call(this,u,c,b));l.append(i)}}});d.register("donut",k.extend(!0,{},d.defaults.pie),function(a){d.graphers.pie.call(this,a)});d.register("line",{delimiter:",",fill:"#c6d9fd",height:16,min:0,stroke:"#4d89f9",strokeWidth:1,width:32},function(a){var b=this.values();1==b.length&&b.push(b[0]);for(var e=h.max.apply(h,a.max==v?b:b.concat(a.max)),c=h.min.apply(h,a.min==v?b:b.concat(a.min)),d=this.prepare(a.width,a.height),l=a.strokeWidth,f=d.width(),j=d.height()-l,k=e-c,e=this.x=function(a){return a*
|
||||
(f/(b.length-1))},r=this.y=function(a){var b=j;k&&(b-=(a-c)/k*j);return b+l/2},s=r(h.max(c,0)),g=[0,s],m=0;m<b.length;m++)g.push(e(m),r(b[m]));g.push(f,s);a.fill&&d.append(q("polygon",{fill:a.fill,points:g.join(" ")}));l&&d.append(q("polyline",{fill:"none",points:g.slice(2,g.length-2).join(" "),stroke:a.stroke,"stroke-width":l,"stroke-linecap":"square"}))});d.register("bar",{delimiter:",",fill:["#4D89F9"],height:16,min:0,padding:0.1,width:32},function(a){for(var b=this.values(),e=h.max.apply(h,a.max==
|
||||
v?b:b.concat(a.max)),c=h.min.apply(h,a.min==v?b:b.concat(a.min)),d=this.prepare(a.width,a.height),l=d.width(),f=d.height(),j=e-c,a=a.padding,k=this.fill(),r=this.x=function(a){return a*l/b.length},s=this.y=function(a){return f-(j?(a-c)/j*f:1)},g=0;g<b.length;g++){var m=r(g+a),u=r(g+1-a)-m,i=b[g],p=s(i),n=p,o;j?0>i?n=s(h.min(e,0)):p=s(h.max(c,0)):o=1;o=p-n;0==o&&(o=1,0<e&&j&&n--);d.append(q("rect",{fill:k.call(this,i,g,b),x:m,y:n,width:u,height:o}))}})})(jQuery,document,Math);
|
||||
|
||||
2
js/lib/morris.min.js
vendored
2
js/lib/morris.min.js
vendored
File diff suppressed because one or more lines are too long
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user