15
app/cron.ini
15
app/cron.ini
@@ -17,15 +17,18 @@ sixthHour = */10 * * * *
|
||||
halfHour = */30 * * * *
|
||||
|
||||
[CRON.jobs]
|
||||
; delete character log data
|
||||
deleteLogData = Cron\CharacterUpdate->deleteLogData, @sixthHour
|
||||
|
||||
; delete expired signatures
|
||||
deleteSignatures = Cron\MapUpdate->deleteSignatures, @halfHour
|
||||
|
||||
; import system data (jump, kill,..) from CCP API
|
||||
importSystemData = Cron\CcpSystemsUpdate->importSystemData, @hourly
|
||||
|
||||
; disable outdated maps
|
||||
deactivateMapData = Cron\MapUpdate->deactivateMapData, @hourly
|
||||
|
||||
; delete character log data
|
||||
deleteLogData = Cron\CharacterUpdate->deleteLogData, @sixthHour
|
||||
|
||||
; delete disabled maps
|
||||
deleteMapData = Cron\MapUpdate->deleteMapData, @downtime
|
||||
|
||||
@@ -33,7 +36,7 @@ deleteMapData = Cron\MapUpdate->deleteMapData, @downtime
|
||||
deleteAuthenticationData = Cron\CharacterUpdate->deleteAuthenticationData, @downtime
|
||||
|
||||
; delete expired cache files
|
||||
deleteExpiredCacheData = Cron\Cache->deleteExpiredData, @weekly
|
||||
deleteExpiredCacheData = Cron\Cache->deleteExpiredData, @downtime
|
||||
|
||||
; delete expired signatures
|
||||
deleteSignatures = Cron\MapUpdate->deleteSignatures, @halfHour
|
||||
; delete old statistics (activity log) data
|
||||
deleteStatisticsData = Cron\StatisticsUpdate->deleteStatisticsData, @weekly
|
||||
@@ -10,7 +10,7 @@ namespace Controller\Api;
|
||||
use Controller;
|
||||
use Model;
|
||||
|
||||
class Connection extends Controller\AccessController{
|
||||
class Connection extends Controller\AccessController {
|
||||
|
||||
/**
|
||||
* @param \Base $f3
|
||||
|
||||
@@ -174,6 +174,14 @@ class Map extends Controller\AccessController {
|
||||
];
|
||||
$return->maxSharedCount = $maxSharedCount;
|
||||
|
||||
// get activity log options per map ---------------------------------------------------------------------------
|
||||
$activityLogging = [
|
||||
'character' => $f3->get('PATHFINDER.MAP.PRIVATE.ACTIVITY_LOGGING'),
|
||||
'corporation' => $f3->get('PATHFINDER.MAP.CORPORATION.ACTIVITY_LOGGING'),
|
||||
'alliance' => $f3->get('PATHFINDER.MAP.ALLIANCE.ACTIVITY_LOGGING'),
|
||||
];
|
||||
$return->activityLogging = $activityLogging;
|
||||
|
||||
// get program routes -----------------------------------------------------------------------------------------
|
||||
$return->routes = [
|
||||
'ssoLogin' => $this->getF3()->alias( 'sso', ['action' => 'requestAuthorization'] )
|
||||
@@ -223,11 +231,13 @@ class Map extends Controller\AccessController {
|
||||
* @var $system Model\SystemModel
|
||||
*/
|
||||
$system = Model\BasicModel::getNew('SystemModel');
|
||||
$system->setActivityLogging(false);
|
||||
|
||||
/**
|
||||
* @var $connection Model\ConnectionModel
|
||||
*/
|
||||
$connection = Model\BasicModel::getNew('ConnectionModel');
|
||||
$connection->setActivityLogging(false);
|
||||
|
||||
foreach($importData['mapData'] as $mapData){
|
||||
if(
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
*/
|
||||
|
||||
namespace Controller\Api;
|
||||
use Controller;
|
||||
use Model;
|
||||
|
||||
|
||||
@@ -15,7 +16,7 @@ use Model;
|
||||
* Class Route
|
||||
* @package Controller\Api
|
||||
*/
|
||||
class Route extends \Controller\AccessController {
|
||||
class Route extends Controller\AccessController {
|
||||
|
||||
/**
|
||||
* cache time for static jump data (e.g. K-Space stargates)
|
||||
|
||||
@@ -11,7 +11,7 @@ use Controller;
|
||||
use Model;
|
||||
|
||||
|
||||
class Signature extends Controller\AccessController{
|
||||
class Signature extends Controller\AccessController {
|
||||
|
||||
/**
|
||||
* event handler
|
||||
|
||||
291
app/main/controller/api/statistic.php
Normal file
291
app/main/controller/api/statistic.php
Normal file
@@ -0,0 +1,291 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: Exodus
|
||||
* Date: 03.10.2016
|
||||
* Time: 00:29
|
||||
*/
|
||||
|
||||
namespace controller\api;
|
||||
|
||||
use Controller;
|
||||
use Model\CharacterModel;
|
||||
|
||||
class Statistic extends Controller\AccessController {
|
||||
|
||||
/**
|
||||
* concat a year and calendar week number
|
||||
* week numbers > 10 will get prefixed with "0"
|
||||
* -> e.g. year 2016, week 2 => "201602"
|
||||
* @param int $year
|
||||
* @param int $week
|
||||
* @return string
|
||||
*/
|
||||
protected function concatYearWeek($year, $week){
|
||||
return strval($year) . str_pad($week, 2, 0, STR_PAD_LEFT);
|
||||
}
|
||||
|
||||
/**
|
||||
* get max count of weeks in a year
|
||||
* @param $year
|
||||
* @return int
|
||||
*/
|
||||
protected function getIsoWeeksInYear($year) {
|
||||
$date = new \DateTime;
|
||||
$date->setISODate($year, 53);
|
||||
return ($date->format('W') === '53' ? 53 : 52);
|
||||
}
|
||||
|
||||
/**
|
||||
* get number of weeks for a given period
|
||||
* @param string $period
|
||||
* @param int $year
|
||||
* @return int
|
||||
*/
|
||||
protected function getWeekCount($period, $year){
|
||||
$weeksInYear = $this->getIsoWeeksInYear($year);
|
||||
|
||||
switch($period){
|
||||
case 'yearly':
|
||||
$weekCount = $weeksInYear;
|
||||
break;
|
||||
case 'monthly':
|
||||
$weekCount = 4;
|
||||
break;
|
||||
case 'weekly':
|
||||
default:
|
||||
$weekCount = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
return $weekCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* calculate calendar week and year for a given offset (weekCount)
|
||||
* -> count forward OR backward
|
||||
* @param int $year
|
||||
* @param int $week
|
||||
* @param int $weekCount
|
||||
* @param bool $backwards
|
||||
* @return array
|
||||
*/
|
||||
protected function calculateYearWeekOffset($year, $week, $weekCount, $backwards = false){
|
||||
$offset = [
|
||||
'year' => (int)$year,
|
||||
'week' => (int)$week
|
||||
];
|
||||
|
||||
$weeksInYear = $this->getIsoWeeksInYear($year);
|
||||
|
||||
// just for security...
|
||||
if($offset['week'] > $weeksInYear){
|
||||
$offset['week'] = $weeksInYear;
|
||||
}elseif($offset['week'] <= 0){
|
||||
$offset['week'] = 1;
|
||||
}
|
||||
|
||||
for($i = 1; $i < $weekCount; $i++){
|
||||
|
||||
if($backwards){
|
||||
// calculate backward
|
||||
$offset['week']--;
|
||||
|
||||
if($offset['week'] <= 0){
|
||||
// year change -> reset yearWeeks
|
||||
$offset['year']--;
|
||||
$offset['week'] = $this->getIsoWeeksInYear($offset['year']);
|
||||
}
|
||||
}else{
|
||||
// calculate forward
|
||||
$offset['week']++;
|
||||
|
||||
if($offset['week'] > $weeksInYear){
|
||||
// year change -> reset yearWeeks
|
||||
$offset['week'] = 1;
|
||||
$offset['year']++;
|
||||
$weeksInYear = $this->getIsoWeeksInYear($offset['year']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* query statistic data for "activity log"
|
||||
* -> group result by characterId
|
||||
* @param CharacterModel $character
|
||||
* @param int $typeId
|
||||
* @param int $yearStart
|
||||
* @param int $weekStart
|
||||
* @param int $yearEnd
|
||||
* @param int $weekEnd
|
||||
* @return array
|
||||
*/
|
||||
protected function queryStatistic( CharacterModel $character, $typeId, $yearStart, $weekStart, $yearEnd, $weekEnd){
|
||||
$data = [];
|
||||
|
||||
// can be either "characterId" || "corporationId" || "allianceId"
|
||||
// -> is required (>0) to limit the result to only accessible data for the given character!
|
||||
$objectId = 0;
|
||||
|
||||
// add map-"typeId" (private/corp/ally) condition -------------------------------------------------------------
|
||||
// check if "ACTIVITY_LOGGING" is active for a given "typeId"
|
||||
$sqlMapType = "";
|
||||
|
||||
switch($typeId){
|
||||
case 2:
|
||||
if( $this->getF3()->get('PATHFINDER.MAP.PRIVATE.ACTIVITY_LOGGING') ){
|
||||
$sqlMapType .= " AND `character`.`id` = :objectId ";
|
||||
$objectId = $character->_id;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
if(
|
||||
$this->getF3()->get('PATHFINDER.MAP.CORPORATION.ACTIVITY_LOGGING') &&
|
||||
$character->hasCorporation()
|
||||
){
|
||||
$sqlMapType .= " AND `character`.`corporationId` = :objectId ";
|
||||
$objectId = $character->get('corporationId', true);
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
if(
|
||||
$this->getF3()->get('PATHFINDER.MAP.ALLIANCE.ACTIVITY_LOGGING') &&
|
||||
$character->hasAlliance()
|
||||
){
|
||||
$sqlMapType .= " AND `character`.`allianceId` = :objectId ";
|
||||
$objectId = $character->get('allianceId', true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if($objectId > 0){
|
||||
|
||||
$queryData = [
|
||||
':active' => 1,
|
||||
':objectId' => $objectId
|
||||
];
|
||||
|
||||
// date offset condition ----------------------------------------------------------------------------------
|
||||
$sqlDateOffset = " AND CONCAT(`log`.`year`, `log`.`week`) BETWEEN :yearWeekStart AND :yearWeekEnd ";
|
||||
|
||||
$queryData[':yearWeekStart'] = $this->concatYearWeek($yearStart, $weekStart);
|
||||
$queryData[':yearWeekEnd'] = $this->concatYearWeek($yearEnd, $weekEnd);
|
||||
|
||||
// build query --------------------------------------------------------------------------------------------
|
||||
$sql = "SELECT
|
||||
`log`.`year`,
|
||||
`log`.`week`,
|
||||
`log`.`characterId`,
|
||||
`character`.`name`,
|
||||
`character`.`lastLogin`,
|
||||
SUM(`log`.`systemCreate`) `systemCreate`,
|
||||
SUM(`log`.`systemUpdate`) `systemUpdate`,
|
||||
SUM(`log`.`systemDelete`) `systemDelete`,
|
||||
SUM(`log`.`connectionCreate`) `connectionCreate`,
|
||||
SUM(`log`.`connectionUpdate`) `connectionUpdate`,
|
||||
SUM(`log`.`connectionDelete`) `connectionDelete`,
|
||||
SUM(`log`.`signatureCreate`) `signatureCreate`,
|
||||
SUM(`log`.`signatureUpdate`) `signatureUpdate`,
|
||||
SUM(`log`.`signatureDelete`) `signatureDelete`
|
||||
FROM
|
||||
`activity_log` `log` INNER JOIN
|
||||
`character` ON
|
||||
`character`.`id` = `log`.`characterId`
|
||||
WHERE
|
||||
`log`.`active` = :active
|
||||
" . $sqlMapType . "
|
||||
" . $sqlDateOffset . "
|
||||
GROUP BY
|
||||
`log`.`year`,
|
||||
`log`.`week`,
|
||||
`log`.`characterId`
|
||||
ORDER BY
|
||||
`log`.`year` DESC, `log`.`week` DESC";
|
||||
|
||||
$result = $this->getDB()->exec($sql, $queryData);
|
||||
|
||||
if( !empty($result) ){
|
||||
// group result by characterId
|
||||
foreach ($result as $key => &$entry) {
|
||||
$tmp = $entry;
|
||||
unset($tmp['characterId']);
|
||||
unset($tmp['name']);
|
||||
unset($tmp['lastLogin']);
|
||||
$data[$entry['characterId']]['name'] = $entry['name'];
|
||||
$data[$entry['characterId']]['lastLogin'] = strtotime($entry['lastLogin']);
|
||||
$data[$entry['characterId']]['weeks'][ $entry['year'] . $entry['week'] ] = $tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* get statistics data
|
||||
* @param \Base $f3
|
||||
*/
|
||||
public function getData(\Base $f3){
|
||||
$postData = (array)$f3->get('POST');
|
||||
$return = (object) [];
|
||||
|
||||
$period = $postData['period'];
|
||||
$typeId = (int)$postData['typeId'];
|
||||
$yearStart = (int)$postData['year'];
|
||||
$weekStart = (int)$postData['week'];
|
||||
|
||||
$currentYear = (int)date('o');
|
||||
$currentWeek = (int)date('W');
|
||||
|
||||
if(
|
||||
$yearStart &&
|
||||
$weekStart
|
||||
){
|
||||
$weekCount = $this->getWeekCount($period, $yearStart);
|
||||
}else{
|
||||
// if start date is not set -> calculate it from current data
|
||||
$tmpYear = $currentYear;
|
||||
if($period == 'yearly'){
|
||||
$tmpYear--;
|
||||
}
|
||||
$weekCount = $this->getWeekCount($period, $tmpYear);
|
||||
$offsetStart = $this->calculateYearWeekOffset($currentYear, $currentWeek, $weekCount, true);
|
||||
$yearStart = $offsetStart['year'];
|
||||
$weekStart = $offsetStart['week'];
|
||||
}
|
||||
|
||||
// date offset for statistics query
|
||||
$offset = $this->calculateYearWeekOffset($yearStart, $weekStart, $weekCount);
|
||||
|
||||
$activeCharacter = $this->getCharacter();
|
||||
|
||||
$return->statistics = $this->queryStatistic($activeCharacter, $typeId, $yearStart, $weekStart, $offset['year'], $offset['week']);
|
||||
$return->period = $period;
|
||||
$return->typeId = $typeId;
|
||||
$return->weekCount = $weekCount;
|
||||
$return->yearWeeks = [
|
||||
$yearStart => $this->getIsoWeeksInYear($yearStart),
|
||||
($yearStart + 1) => $this->getIsoWeeksInYear($yearStart + 1)
|
||||
];
|
||||
|
||||
// pagination offset
|
||||
$offsetNext = $this->calculateYearWeekOffset($yearStart, $weekStart, $weekCount + 1);
|
||||
$offsetPrev = $this->calculateYearWeekOffset($yearStart, $weekStart, $weekCount + 1, true);
|
||||
|
||||
// check if "next" button is available (not in future)
|
||||
$currentCurrentDataConcat = intval( $this->concatYearWeek($currentYear, $currentWeek) );
|
||||
$offsetNextDateConcat = intval( $this->concatYearWeek($offsetNext['year'], $offsetNext['week']) );
|
||||
if( $offsetNextDateConcat <= $currentCurrentDataConcat){
|
||||
$return->next = $offsetNext;
|
||||
}
|
||||
|
||||
$return->prev = $offsetPrev;
|
||||
$return->start = ['year' => $yearStart, 'week' => $weekStart];
|
||||
$return->offset = $offset;
|
||||
|
||||
echo json_encode($return);
|
||||
}
|
||||
}
|
||||
@@ -7,11 +7,12 @@
|
||||
*/
|
||||
|
||||
namespace Controller\Api;
|
||||
use Controller;
|
||||
use Controller\Ccp\Sso;
|
||||
use Data\Mapper as Mapper;
|
||||
use Model;
|
||||
|
||||
class System extends \Controller\AccessController {
|
||||
class System extends Controller\AccessController {
|
||||
|
||||
private $mainQuery = "SELECT
|
||||
map_sys.constellationID `connstallation_id`,
|
||||
@@ -68,7 +69,6 @@ class System extends \Controller\AccessController {
|
||||
* @param \Base $f3
|
||||
*/
|
||||
function beforeroute(\Base $f3) {
|
||||
|
||||
parent::beforeroute($f3);
|
||||
|
||||
// set header for all routes
|
||||
@@ -80,7 +80,6 @@ class System extends \Controller\AccessController {
|
||||
* @return string
|
||||
*/
|
||||
private function _getQuery(){
|
||||
|
||||
$query = $this->mainQuery;
|
||||
$query .= ' ' . $this->whereQuery;
|
||||
$query .= ' ' . $this->havingQuery;
|
||||
@@ -419,8 +418,17 @@ class System extends \Controller\AccessController {
|
||||
foreach($systemIds as $systemId){
|
||||
$system->getById($systemId);
|
||||
if( $system->hasAccess($activeCharacter) ){
|
||||
$system->setActive(false);
|
||||
$system->save();
|
||||
// check whether system should be deleted OR set "inactive"
|
||||
if(
|
||||
empty($system->alias) &&
|
||||
empty($system->description)
|
||||
){
|
||||
$system->erase();
|
||||
}else{
|
||||
// keep data -> set "inactive"
|
||||
$system->setActive(false);
|
||||
$system->save();
|
||||
}
|
||||
$system->reset();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,6 +95,9 @@ class Controller {
|
||||
* @param \Base $f3
|
||||
*/
|
||||
public function afterroute(\Base $f3){
|
||||
// store all user activities that are buffered for logging in this request
|
||||
self::storeActivities();
|
||||
|
||||
if($this->getTemplate()){
|
||||
// Ajax calls don´t need a page render..
|
||||
// this happens on client side
|
||||
@@ -779,6 +782,13 @@ class Controller {
|
||||
return LogController::getLogger($type);
|
||||
}
|
||||
|
||||
/**
|
||||
* store activity log data to DB
|
||||
*/
|
||||
static function storeActivities(){
|
||||
LogController::instance()->storeActivities();
|
||||
}
|
||||
|
||||
/**
|
||||
* removes illegal characters from a Hive-key that are not allowed
|
||||
* @param $key
|
||||
|
||||
@@ -7,10 +7,128 @@
|
||||
*/
|
||||
|
||||
namespace controller;
|
||||
use DB;
|
||||
|
||||
class LogController extends \Prefab {
|
||||
|
||||
class LogController extends Controller {
|
||||
/**
|
||||
* buffered activity log data for this singleton LogController() class
|
||||
* -> this buffered data can be stored somewhere (e.g. DB) before HTTP response
|
||||
* -> should be cleared afterwards!
|
||||
* @var array
|
||||
*/
|
||||
protected $activityLogBuffer = [];
|
||||
|
||||
/**
|
||||
* reserve a "new" character activity for logging
|
||||
* @param $characterId
|
||||
* @param $mapId
|
||||
* @param $action
|
||||
*/
|
||||
public function bufferActivity($characterId, $mapId, $action){
|
||||
$characterId = (int)$characterId;
|
||||
$mapId = (int)$mapId;
|
||||
|
||||
if(
|
||||
$characterId > 0 &&
|
||||
$mapId > 0
|
||||
){
|
||||
$key = $this->getBufferedActivityKey($characterId, $mapId);
|
||||
|
||||
if( is_null($key) ){
|
||||
$activity = [
|
||||
'characterId' => $characterId,
|
||||
'mapId' => $mapId,
|
||||
$action => 1
|
||||
];
|
||||
$this->activityLogBuffer[] = $activity;
|
||||
}else{
|
||||
$this->activityLogBuffer[$key][$action]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* store all buffered activity log data to DB
|
||||
*/
|
||||
public function storeActivities(){
|
||||
if( !empty($this->activityLogBuffer) ){
|
||||
$db = DB\Database::instance()->getDB('PF');
|
||||
|
||||
$quoteStr = function($str) use ($db) {
|
||||
return $db->quotekey($str);
|
||||
};
|
||||
|
||||
$placeholderStr = function($str){
|
||||
return ':' . $str;
|
||||
};
|
||||
|
||||
$updateRule = function($str){
|
||||
return $str . " = " . $str . " + VALUES(" . $str . ")";
|
||||
};
|
||||
|
||||
$year = (int)date('o');
|
||||
$yearWeek = (int)date('W');
|
||||
$db->begin();
|
||||
|
||||
foreach($this->activityLogBuffer as $activityData){
|
||||
$activityData['year'] = $year;
|
||||
$activityData['week'] = $yearWeek;
|
||||
|
||||
$columns = array_keys($activityData);
|
||||
$columnsQuoted = array_map($quoteStr, $columns);
|
||||
$placeholder = array_map($placeholderStr, $columns);
|
||||
$args = array_combine($placeholder, $activityData);
|
||||
|
||||
// "filter" columns that can be updated
|
||||
$columnsForUpdate = array_diff($columns, ['year', 'week', 'characterId', 'mapId']);
|
||||
$updateSql = array_map($updateRule, $columnsForUpdate);
|
||||
|
||||
$sql = "INSERT DELAYED INTO
|
||||
activity_log (" . implode(', ', $columnsQuoted) . ") values(
|
||||
" . implode(', ', $placeholder) . "
|
||||
)
|
||||
ON DUPLICATE KEY UPDATE
|
||||
updated = NOW(),
|
||||
" . implode(', ', $updateSql) . "
|
||||
";
|
||||
|
||||
$db->exec($sql, $args);
|
||||
}
|
||||
|
||||
$db->commit();
|
||||
|
||||
// clear activity data for this instance
|
||||
$this->activityLogBuffer = [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* get array key from "buffered activity log" array
|
||||
* @param int $characterId
|
||||
* @param int $mapId
|
||||
* @return int|null
|
||||
*/
|
||||
private function getBufferedActivityKey($characterId, $mapId){
|
||||
$activityKey = null;
|
||||
|
||||
if(
|
||||
$characterId > 0 &&
|
||||
$mapId > 0
|
||||
){
|
||||
foreach($this->activityLogBuffer as $key => $activityData){
|
||||
if(
|
||||
$activityData['characterId'] === $characterId &&
|
||||
$activityData['mapId'] === $mapId
|
||||
){
|
||||
$activityKey = $key;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $activityKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* get Logger instance
|
||||
|
||||
@@ -86,6 +86,8 @@ class Setup extends Controller {
|
||||
'Model\ConnectionModel',
|
||||
'Model\SystemSignatureModel',
|
||||
|
||||
'Model\ActivityLogModel',
|
||||
|
||||
'Model\SystemShipKillModel',
|
||||
'Model\SystemPodKillModel',
|
||||
'Model\SystemFactionKillModel',
|
||||
|
||||
@@ -47,7 +47,7 @@ class CharacterUpdate {
|
||||
* delete expired character authentication data
|
||||
* authentication data is used for cookie based login
|
||||
* >> php index.php "/cron/deleteAuthenticationData"
|
||||
* @param $f3
|
||||
* @param \Base $f3
|
||||
*/
|
||||
function deleteAuthenticationData($f3){
|
||||
DB\Database::instance()->getDB('PF');
|
||||
|
||||
@@ -35,11 +35,6 @@ class MapUpdate {
|
||||
TIMESTAMPDIFF(DAY, map.updated, NOW() ) > :lifetime";
|
||||
|
||||
$pfDB->exec($sqlDeactivateExpiredMaps, ['lifetime' => $privateMapLifetime]);
|
||||
$deactivatedMapsCount = $pfDB->count();
|
||||
|
||||
// Log ------------------------
|
||||
$log = new \Log('cron_' . __FUNCTION__ . '.log');
|
||||
$log->write( sprintf(self::LOG_TEXT_MAPS, __FUNCTION__, $deactivatedMapsCount) );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,13 +73,13 @@ class MapUpdate {
|
||||
if($signatureExpire > 0){
|
||||
$pfDB = DB\Database::instance()->getDB('PF');
|
||||
|
||||
$sqlDeleteExpiredSignatures = "DELETE `sys` FROM
|
||||
`system_signature` `sys` INNER JOIN
|
||||
$sqlDeleteExpiredSignatures = "DELETE `sigs` FROM
|
||||
`system_signature` `sigs` INNER JOIN
|
||||
`system` ON
|
||||
`system`.`id` = `sys`.`systemId`
|
||||
`system`.`id` = `sigs`.`systemId`
|
||||
WHERE
|
||||
`system`.`active` = 0 AND
|
||||
TIMESTAMPDIFF(SECOND, `sys`.`updated`, NOW() ) > :lifetime
|
||||
TIMESTAMPDIFF(SECOND, `sigs`.`updated`, NOW() ) > :lifetime
|
||||
";
|
||||
|
||||
$pfDB->exec($sqlDeleteExpiredSignatures, ['lifetime' => $signatureExpire]);
|
||||
|
||||
46
app/main/cron/statisticsupdate.php
Normal file
46
app/main/cron/statisticsupdate.php
Normal file
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: Exodus
|
||||
* Date: 16.10.2016
|
||||
* Time: 21:31
|
||||
*/
|
||||
|
||||
namespace cron;
|
||||
use DB;
|
||||
|
||||
class StatisticsUpdate {
|
||||
|
||||
const LOG_TEXT_STATISTICS = '%s (%d rows)';
|
||||
|
||||
/**
|
||||
* delete old statistics
|
||||
* -> older than 1 year
|
||||
* >> php index.php "/cron/deleteStatisticsData"
|
||||
* @param \Base $f3
|
||||
*/
|
||||
function deleteStatisticsData(\Base $f3){
|
||||
$currentYear = (int)date('o');
|
||||
$currentWeek = (int)date('W');
|
||||
$expiredYear = $currentYear - 1;
|
||||
|
||||
$pfDB = DB\Database::instance()->getDB('PF');
|
||||
|
||||
$queryData = [
|
||||
'yearWeekEnd' => strval($expiredYear) . str_pad($currentWeek, 2, 0, STR_PAD_LEFT)
|
||||
];
|
||||
|
||||
$sql = "DELETE FROM
|
||||
activity_log
|
||||
WHERE
|
||||
CONCAT(`year`, `week`) < :yearWeekEnd";
|
||||
|
||||
$pfDB->exec($sql, $queryData);
|
||||
|
||||
$deletedLogsCount = $pfDB->count();
|
||||
|
||||
// Log ------------------------
|
||||
$log = new \Log('cron_' . __FUNCTION__ . '.log');
|
||||
$log->write( sprintf(self::LOG_TEXT_STATISTICS, __FUNCTION__, $deletedLogsCount) );
|
||||
}
|
||||
}
|
||||
150
app/main/model/activitylogmodel.php
Normal file
150
app/main/model/activitylogmodel.php
Normal file
@@ -0,0 +1,150 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: Exodus
|
||||
* Date: 01.10.2016
|
||||
* Time: 15:11
|
||||
*/
|
||||
|
||||
namespace Model;
|
||||
|
||||
use DB\SQL\Schema;
|
||||
|
||||
class ActivityLogModel extends BasicModel {
|
||||
|
||||
protected $table = 'activity_log';
|
||||
|
||||
protected $fieldConf = [
|
||||
'active' => [
|
||||
'type' => Schema::DT_BOOL,
|
||||
'nullable' => false,
|
||||
'default' => 1,
|
||||
'index' => true
|
||||
],
|
||||
'characterId' => [
|
||||
'type' => Schema::DT_INT,
|
||||
'index' => true,
|
||||
'belongs-to-one' => 'Model\CharacterModel',
|
||||
'constraint' => [
|
||||
[
|
||||
'table' => 'character',
|
||||
'on-delete' => 'CASCADE'
|
||||
]
|
||||
]
|
||||
],
|
||||
'mapId' => [
|
||||
'type' => Schema::DT_INT,
|
||||
'index' => true,
|
||||
'belongs-to-one' => 'Model\MapModel',
|
||||
'constraint' => [
|
||||
[
|
||||
'table' => 'map',
|
||||
'on-delete' => 'SET NULL' // keep log data on map delete
|
||||
]
|
||||
]
|
||||
],
|
||||
|
||||
// system actions -----------------------------------------------------
|
||||
|
||||
'systemCreate' => [
|
||||
'type' => Schema::DT_SMALLINT,
|
||||
'nullable' => false,
|
||||
'default' => 0,
|
||||
],
|
||||
'systemUpdate' => [
|
||||
'type' => Schema::DT_SMALLINT,
|
||||
'nullable' => false,
|
||||
'default' => 0,
|
||||
],
|
||||
'systemDelete' => [
|
||||
'type' => Schema::DT_SMALLINT,
|
||||
'nullable' => false,
|
||||
'default' => 0,
|
||||
],
|
||||
|
||||
// connection actions -------------------------------------------------
|
||||
|
||||
'connectionCreate' => [
|
||||
'type' => Schema::DT_SMALLINT,
|
||||
'nullable' => false,
|
||||
'default' => 0,
|
||||
],
|
||||
'connectionUpdate' => [
|
||||
'type' => Schema::DT_SMALLINT,
|
||||
'nullable' => false,
|
||||
'default' => 0,
|
||||
],
|
||||
'connectionDelete' => [
|
||||
'type' => Schema::DT_SMALLINT,
|
||||
'nullable' => false,
|
||||
'default' => 0,
|
||||
],
|
||||
|
||||
// signature actions -------------------------------------------------
|
||||
|
||||
'signatureCreate' => [
|
||||
'type' => Schema::DT_SMALLINT,
|
||||
'nullable' => false,
|
||||
'default' => 0,
|
||||
],
|
||||
'signatureUpdate' => [
|
||||
'type' => Schema::DT_SMALLINT,
|
||||
'nullable' => false,
|
||||
'default' => 0,
|
||||
],
|
||||
'signatureDelete' => [
|
||||
'type' => Schema::DT_SMALLINT,
|
||||
'nullable' => false,
|
||||
'default' => 0,
|
||||
],
|
||||
];
|
||||
|
||||
public function __construct($db = NULL, $table = NULL, $fluid = NULL, $ttl = 0){
|
||||
$this->addStaticDateFieldConfig();
|
||||
|
||||
parent::__construct($db, $table, $fluid, $ttl);
|
||||
}
|
||||
|
||||
/**
|
||||
* extent the fieldConf Array with static fields for each table
|
||||
*/
|
||||
private function addStaticDateFieldConfig(){
|
||||
if(is_array($this->fieldConf)){
|
||||
$staticFieldConfig = [
|
||||
'year' => [
|
||||
'type' => Schema::DT_SMALLINT,
|
||||
'nullable' => false,
|
||||
'default' => date('o'), // 01.01 could be week 53 -> NOT "current" year!
|
||||
'index' => true
|
||||
],
|
||||
'week' => [ // week in year [1-53]
|
||||
'type' => Schema::DT_TINYINT,
|
||||
'nullable' => false,
|
||||
'default' => 1,
|
||||
'index' => true
|
||||
],
|
||||
];
|
||||
$this->fieldConf = array_merge($staticFieldConfig, $this->fieldConf);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* overwrites parent
|
||||
* @param null $db
|
||||
* @param null $table
|
||||
* @param null $fields
|
||||
* @return bool
|
||||
*/
|
||||
public static function setup($db=null, $table=null, $fields=null){
|
||||
$status = parent::setup($db,$table,$fields);
|
||||
|
||||
if($status === true){
|
||||
$status = parent::setMultiColumnIndex(['year', 'week', 'characterId', 'mapId'], true);
|
||||
if($status === true){
|
||||
$status = parent::setMultiColumnIndex(['year', 'week', 'characterId']);
|
||||
}
|
||||
}
|
||||
|
||||
return $status;
|
||||
}
|
||||
}
|
||||
@@ -56,6 +56,14 @@ abstract class BasicModel extends \DB\Cortex {
|
||||
*/
|
||||
protected $allowActiveChange = false;
|
||||
|
||||
/**
|
||||
* enables check for $fieldChanges on update/insert
|
||||
* -> fields that should be checked need an "activity-log" flag
|
||||
* in $fieldConf config
|
||||
* @var bool
|
||||
*/
|
||||
protected $enableActivityLogging = true;
|
||||
|
||||
/**
|
||||
* getData() cache key prefix
|
||||
* -> do not change, otherwise cached data is lost
|
||||
@@ -77,6 +85,12 @@ abstract class BasicModel extends \DB\Cortex {
|
||||
*/
|
||||
public static $enableDataImport = false;
|
||||
|
||||
/**
|
||||
* changed fields (columns) on update/insert
|
||||
* -> e.g. for character "activity logging"
|
||||
* @var array
|
||||
*/
|
||||
protected $fieldChanges = [];
|
||||
|
||||
public function __construct($db = NULL, $table = NULL, $fluid = NULL, $ttl = 0){
|
||||
|
||||
@@ -157,10 +171,54 @@ abstract class BasicModel extends \DB\Cortex {
|
||||
if(!$valid){
|
||||
$this->throwValidationError($key);
|
||||
}else{
|
||||
$this->checkFieldForActivityLogging($key, $val);
|
||||
|
||||
return parent::set($key, $val);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* change default "activity logging" status
|
||||
* -> enable/disable
|
||||
* @param $status
|
||||
*/
|
||||
public function setActivityLogging($status){
|
||||
$this->enableActivityLogging = (bool) $status;
|
||||
}
|
||||
|
||||
/**
|
||||
* check column for value changes,
|
||||
* --> if column is marked for "activity logging"
|
||||
* @param string $key
|
||||
* @param mixed $val
|
||||
*/
|
||||
protected function checkFieldForActivityLogging($key, $val){
|
||||
if( $this->enableActivityLogging ){
|
||||
$fieldConf = $this->fieldConf[$key];
|
||||
|
||||
// check for value changes if field has "activity logging" active
|
||||
if($fieldConf['activity-log'] === true){
|
||||
if(
|
||||
is_numeric($val) ||
|
||||
$fieldConf['type'] === Schema::DT_BOOL
|
||||
){
|
||||
$val = (int)$val;
|
||||
}
|
||||
|
||||
if( $fieldConf['type'] === self::DT_JSON){
|
||||
$currentValue = $this->get($key);
|
||||
}else{
|
||||
$currentValue = $this->get($key, true);
|
||||
}
|
||||
|
||||
if($currentValue !== $val){
|
||||
// field has changed
|
||||
in_array($key, $this->fieldChanges) ?: $this->fieldChanges[] = $key;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* setter for "active" status
|
||||
* -> default: keep current "active" status
|
||||
@@ -638,6 +696,18 @@ abstract class BasicModel extends \DB\Cortex {
|
||||
return ['added' => $addedCount, 'updated' => $updatedCount, 'deleted' => $deletedCount];
|
||||
}
|
||||
|
||||
/**
|
||||
* buffer a new activity (action) logging
|
||||
* -> increment buffered counter
|
||||
* -> log character activity create/update/delete events
|
||||
* @param int $characterId
|
||||
* @param int $mapId
|
||||
* @param string $action
|
||||
*/
|
||||
protected function bufferActivity($characterId, $mapId, $action){
|
||||
Controller\LogController::instance()->bufferActivity($characterId, $mapId, $action);
|
||||
}
|
||||
|
||||
/**
|
||||
* get the current class name
|
||||
* -> namespace not included
|
||||
|
||||
@@ -18,11 +18,11 @@ class CharacterLogModel extends BasicModel {
|
||||
|
||||
/**
|
||||
* caching for relational data
|
||||
* -> 10s matches REST API - Expire: Header-Data
|
||||
* -> 5s matches REST API - Expire: Header-Data
|
||||
* for "Location" calls
|
||||
* @var int
|
||||
*/
|
||||
protected $rel_ttl = 10;
|
||||
protected $rel_ttl = 5;
|
||||
|
||||
protected $fieldConf = [
|
||||
'active' => [
|
||||
|
||||
@@ -8,8 +8,9 @@
|
||||
|
||||
namespace Model;
|
||||
|
||||
use Controller\Api\Route;
|
||||
use DB\SQL\Schema;
|
||||
use Controller;
|
||||
use Controller\Api\Route;
|
||||
|
||||
class ConnectionModel extends BasicModel{
|
||||
|
||||
@@ -42,7 +43,8 @@ class ConnectionModel extends BasicModel{
|
||||
'table' => 'system',
|
||||
'on-delete' => 'CASCADE'
|
||||
]
|
||||
]
|
||||
],
|
||||
'activity-log' => true
|
||||
],
|
||||
'target' => [
|
||||
'type' => Schema::DT_INT,
|
||||
@@ -53,15 +55,18 @@ class ConnectionModel extends BasicModel{
|
||||
'table' => 'system',
|
||||
'on-delete' => 'CASCADE'
|
||||
]
|
||||
]
|
||||
],
|
||||
'activity-log' => true
|
||||
],
|
||||
'scope' => [
|
||||
'type' => Schema::DT_VARCHAR128,
|
||||
'nullable' => false,
|
||||
'default' => ''
|
||||
'default' => '',
|
||||
'activity-log' => true
|
||||
],
|
||||
'type' => [
|
||||
'type' => self::DT_JSON
|
||||
'type' => self::DT_JSON,
|
||||
'activity-log' => true
|
||||
],
|
||||
'eolUpdated' => [
|
||||
'type' => Schema::DT_TIMESTAMP,
|
||||
@@ -212,6 +217,66 @@ class ConnectionModel extends BasicModel{
|
||||
return parent::beforeInsertEvent($self, $pkeys);
|
||||
}
|
||||
|
||||
/**
|
||||
* Event "Hook" function
|
||||
* return false will stop any further action
|
||||
* @param self $self
|
||||
* @param $pkeys
|
||||
*/
|
||||
public function afterInsertEvent($self, $pkeys){
|
||||
parent::afterInsertEvent($self, $pkeys);
|
||||
|
||||
$self->logActivity('connectionCreate');
|
||||
}
|
||||
|
||||
/**
|
||||
* Event "Hook" function
|
||||
* return false will stop any further action
|
||||
* @param self $self
|
||||
* @param $pkeys
|
||||
*/
|
||||
public function afterUpdateEvent($self, $pkeys){
|
||||
parent::afterUpdateEvent($self, $pkeys);
|
||||
|
||||
$self->logActivity('connectionUpdate');
|
||||
}
|
||||
|
||||
/**
|
||||
* Event "Hook" function
|
||||
* can be overwritten
|
||||
* @param self $self
|
||||
* @param $pkeys
|
||||
*/
|
||||
public function afterEraseEvent($self, $pkeys){
|
||||
parent::afterUpdateEvent($self, $pkeys);
|
||||
|
||||
$self->logActivity('connectionDelete');
|
||||
}
|
||||
|
||||
/**
|
||||
* log character activity create/update/delete events
|
||||
* @param string $action
|
||||
*/
|
||||
protected function logActivity($action){
|
||||
|
||||
if(
|
||||
$this->enableActivityLogging &&
|
||||
(
|
||||
$action === 'connectionDelete' ||
|
||||
!empty($this->fieldChanges)
|
||||
) &&
|
||||
$this->get('mapId')->isActivityLogEnabled()
|
||||
){
|
||||
// TODO implement "dependency injection" for active character object...
|
||||
$controller = new Controller\Controller();
|
||||
$currentActiveCharacter = $controller->getCharacter();
|
||||
$characterId = is_null($currentActiveCharacter) ? 0 : $currentActiveCharacter->_id;
|
||||
$mapId = $this->get('mapId', true);
|
||||
|
||||
parent::bufferActivity($characterId, $mapId, $action);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* save connection and check if obj is valid
|
||||
* @return ConnectionModel|false
|
||||
|
||||
@@ -609,6 +609,31 @@ class MapModel extends BasicModel {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* check if "activity logging" is enabled for this map type
|
||||
* @return bool
|
||||
*/
|
||||
public function isActivityLogEnabled(){
|
||||
$f3 = self::getF3();
|
||||
$activityLogEnabled = false;
|
||||
|
||||
if( $this->isAlliance() ){
|
||||
if( $f3->get('PATHFINDER.MAP.ALLIANCE.ACTIVITY_LOGGING') ){
|
||||
$activityLogEnabled = true;
|
||||
}
|
||||
}elseif( $this->isCorporation() ){
|
||||
if( $f3->get('PATHFINDER.MAP.CORPORATION.ACTIVITY_LOGGING') ){
|
||||
$activityLogEnabled = true;
|
||||
}
|
||||
}elseif( $this->isPrivate() ){
|
||||
if( $f3->get('PATHFINDER.MAP.PRIVATE.ACTIVITY_LOGGING') ){
|
||||
$activityLogEnabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
return $activityLogEnabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* checks whether this map is private map
|
||||
* @return bool
|
||||
|
||||
@@ -24,7 +24,8 @@ class SystemModel extends BasicModel {
|
||||
'type' => Schema::DT_BOOL,
|
||||
'nullable' => false,
|
||||
'default' => 1,
|
||||
'index' => true
|
||||
'index' => true,
|
||||
'activity-log' => true
|
||||
],
|
||||
'mapId' => [
|
||||
'type' => Schema::DT_INT,
|
||||
@@ -49,7 +50,8 @@ class SystemModel extends BasicModel {
|
||||
'alias' => [
|
||||
'type' => Schema::DT_VARCHAR128,
|
||||
'nullable' => false,
|
||||
'default' => ''
|
||||
'default' => '',
|
||||
'activity-log' => true
|
||||
],
|
||||
'regionId' => [
|
||||
'type' => Schema::DT_INT,
|
||||
@@ -106,12 +108,14 @@ class SystemModel extends BasicModel {
|
||||
'table' => 'system_status',
|
||||
'on-delete' => 'CASCADE'
|
||||
]
|
||||
]
|
||||
],
|
||||
'activity-log' => true
|
||||
],
|
||||
'locked' => [
|
||||
'type' => Schema::DT_BOOL,
|
||||
'nullable' => false,
|
||||
'default' => 0
|
||||
'default' => 0,
|
||||
'activity-log' => true
|
||||
],
|
||||
'rallyUpdated' => [
|
||||
'type' => Schema::DT_TIMESTAMP,
|
||||
@@ -125,7 +129,8 @@ class SystemModel extends BasicModel {
|
||||
'description' => [
|
||||
'type' => Schema::DT_VARCHAR512,
|
||||
'nullable' => false,
|
||||
'default' => ''
|
||||
'default' => '',
|
||||
'activity-log' => true
|
||||
],
|
||||
'posX' => [
|
||||
'type' => Schema::DT_INT,
|
||||
@@ -351,6 +356,18 @@ class SystemModel extends BasicModel {
|
||||
return $rally;
|
||||
}
|
||||
|
||||
/**
|
||||
* Event "Hook" function
|
||||
* return false will stop any further action
|
||||
* @param self $self
|
||||
* @param $pkeys
|
||||
*/
|
||||
public function afterInsertEvent($self, $pkeys){
|
||||
parent::afterInsertEvent($self, $pkeys);
|
||||
|
||||
$self->logActivity('systemCreate');
|
||||
}
|
||||
|
||||
/**
|
||||
* Event "Hook" function
|
||||
* can be overwritten
|
||||
@@ -360,6 +377,8 @@ class SystemModel extends BasicModel {
|
||||
* @return bool
|
||||
*/
|
||||
public function beforeUpdateEvent($self, $pkeys){
|
||||
$status = parent::beforeUpdateEvent($self, $pkeys);
|
||||
|
||||
if( !$self->isActive()){
|
||||
// system becomes inactive
|
||||
// reset "rally point" fields
|
||||
@@ -372,7 +391,8 @@ class SystemModel extends BasicModel {
|
||||
$connection->erase();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
return $status;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -382,6 +402,8 @@ class SystemModel extends BasicModel {
|
||||
* @param $pkeys
|
||||
*/
|
||||
public function afterUpdateEvent($self, $pkeys){
|
||||
parent::afterUpdateEvent($self, $pkeys);
|
||||
|
||||
// check if rally point mail should be send
|
||||
if(
|
||||
$self->newRallyPointSet &&
|
||||
@@ -389,6 +411,41 @@ class SystemModel extends BasicModel {
|
||||
){
|
||||
$self->sendRallyPointMail();
|
||||
}
|
||||
|
||||
$activity = ($self->isActive()) ? 'systemUpdate' : 'systemDelete';
|
||||
$self->logActivity($activity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Event "Hook" function
|
||||
* can be overwritten
|
||||
* @param self $self
|
||||
* @param $pkeys
|
||||
*/
|
||||
public function afterEraseEvent($self, $pkeys){
|
||||
parent::afterUpdateEvent($self, $pkeys);
|
||||
|
||||
$self->logActivity('systemDelete');
|
||||
}
|
||||
|
||||
/**
|
||||
* log character activity create/update/delete events
|
||||
* @param string $action
|
||||
*/
|
||||
protected function logActivity($action){
|
||||
if(
|
||||
$this->enableActivityLogging &&
|
||||
(
|
||||
$action === 'systemDelete' ||
|
||||
!empty($this->fieldChanges)
|
||||
) &&
|
||||
$this->get('mapId')->isActivityLogEnabled()
|
||||
){
|
||||
$characterId = $this->get('updatedCharacterId', true);
|
||||
$mapId = $this->get('mapId', true);
|
||||
|
||||
parent::bufferActivity($characterId, $mapId, $action);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -37,22 +37,26 @@ class SystemSignatureModel extends BasicModel {
|
||||
'nullable' => false,
|
||||
'default' => 0,
|
||||
'index' => true,
|
||||
'activity-log' => true
|
||||
],
|
||||
'typeId' => [
|
||||
'type' => Schema::DT_INT,
|
||||
'nullable' => false,
|
||||
'default' => 0,
|
||||
'index' => true,
|
||||
'activity-log' => true
|
||||
],
|
||||
'name' => [
|
||||
'type' => Schema::DT_VARCHAR128,
|
||||
'nullable' => false,
|
||||
'default' => ''
|
||||
'default' => '',
|
||||
'activity-log' => true
|
||||
],
|
||||
'description' => [
|
||||
'type' => Schema::DT_VARCHAR512,
|
||||
'nullable' => false,
|
||||
'default' => ''
|
||||
'default' => '',
|
||||
'activity-log' => true
|
||||
],
|
||||
'createdCharacterId' => [
|
||||
'type' => Schema::DT_INT,
|
||||
@@ -172,6 +176,68 @@ class SystemSignatureModel extends BasicModel {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Event "Hook" function
|
||||
* return false will stop any further action
|
||||
* @param self $self
|
||||
* @param $pkeys
|
||||
*/
|
||||
public function afterInsertEvent($self, $pkeys){
|
||||
parent::afterInsertEvent($self, $pkeys);
|
||||
|
||||
$self->logActivity('signatureCreate');
|
||||
}
|
||||
|
||||
/**
|
||||
* Event "Hook" function
|
||||
* return false will stop any further action
|
||||
* @param self $self
|
||||
* @param $pkeys
|
||||
*/
|
||||
public function afterUpdateEvent($self, $pkeys){
|
||||
parent::afterUpdateEvent($self, $pkeys);
|
||||
|
||||
$self->logActivity('signatureUpdate');
|
||||
}
|
||||
|
||||
/**
|
||||
* Event "Hook" function
|
||||
* can be overwritten
|
||||
* @param self $self
|
||||
* @param $pkeys
|
||||
*/
|
||||
public function afterEraseEvent($self, $pkeys){
|
||||
parent::afterUpdateEvent($self, $pkeys);
|
||||
|
||||
$self->logActivity('signatureDelete');
|
||||
}
|
||||
|
||||
/**
|
||||
* log character activity create/update/delete events
|
||||
* @param string $action
|
||||
*/
|
||||
protected function logActivity($action){
|
||||
if($this->enableActivityLogging){
|
||||
/**
|
||||
* @var $map MapModel
|
||||
*/
|
||||
$map = $this->get('systemId')->get('mapId');
|
||||
|
||||
if(
|
||||
(
|
||||
$action === 'signatureDelete' ||
|
||||
!empty($this->fieldChanges)
|
||||
) &&
|
||||
$map->isActivityLogEnabled()
|
||||
){
|
||||
$characterId = $this->get('updatedCharacterId', true);
|
||||
$mapId = $map->_id;
|
||||
|
||||
parent::bufferActivity($characterId, $mapId, $action);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* overwrites parent
|
||||
* @param null $db
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
[PATHFINDER]
|
||||
NAME = Pathfinder
|
||||
; installed version (used for CSS/JS cache busting)
|
||||
VERSION = v1.1.5
|
||||
VERSION = v1.1.6
|
||||
; contact information [optional]
|
||||
CONTACT = https://github.com/exodus4d
|
||||
; public contact email [optional]
|
||||
@@ -45,23 +45,32 @@ LOGIN = templates/view/login.html
|
||||
|
||||
; MAP =============================================================================================
|
||||
; Map settings for "private", "corporation" and "alliance" maps
|
||||
; LIFETIME: Map will be deleted after "X" days, by cronjob
|
||||
; MAX_COUNT: Users can create/view up to "X" maps of a type
|
||||
; MAX_SHARED: Max number of shared entities per map
|
||||
; LIFETIME (days):
|
||||
; - Map will be deleted after "X" days, by cronjob
|
||||
; MAX_COUNT:
|
||||
; - Users can create/view up to "X" maps of a type
|
||||
; MAX_SHARED:
|
||||
; - Max number of shared entities per map
|
||||
; ACTIVITY_LOGGING (0: disable, 1: enable):
|
||||
; - Whether user activity should be logged for a map type
|
||||
; - E.g. create/update/delete of systems/connections/signatures
|
||||
[PATHFINDER.MAP.PRIVATE]
|
||||
LIFETIME = 14
|
||||
MAX_COUNT = 3
|
||||
MAX_SHARED = 10
|
||||
ACTIVITY_LOGGING = 1
|
||||
|
||||
[PATHFINDER.MAP.CORPORATION]
|
||||
LIFETIME = 99999
|
||||
MAX_COUNT = 3
|
||||
MAX_SHARED = 3
|
||||
ACTIVITY_LOGGING = 1
|
||||
|
||||
[PATHFINDER.MAP.ALLIANCE]
|
||||
LIFETIME = 99999
|
||||
MAX_COUNT = 3
|
||||
MAX_SHARED = 2
|
||||
ACTIVITY_LOGGING = 0
|
||||
|
||||
; Route search ====================================================================================
|
||||
[PATHFINDER.ROUTE]
|
||||
@@ -108,8 +117,8 @@ EXECUTION_LIMIT = 50
|
||||
CHARACTER_LOG = 300
|
||||
; expire time for static system data (seconds) (default: 20d)
|
||||
CONSTELLATION_SYSTEMS = 1728000
|
||||
; max expire time. Expired cache files will be deleted by cronjob (seconds) (default: 20d)
|
||||
EXPIRE_MAX = 1728000
|
||||
; max expire time. Expired cache files will be deleted by cronjob (seconds) (default: 10d)
|
||||
EXPIRE_MAX = 864000
|
||||
; expire time for signatures (inactive systems) (seconds) (default 3d)
|
||||
EXPIRE_SIGNATURES = 259200
|
||||
|
||||
|
||||
@@ -38,9 +38,10 @@ 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/
|
||||
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.5.0 Full screen mode - https://github.com/private-face/jquery.fullscreen
|
||||
fullScreen: 'lib/jquery.fullscreen.min', // v0.6.0 Full screen mode - https://github.com/private-face/jquery.fullscreen
|
||||
select2: 'lib/select2.min', // v4.0.3 Drop Down customization - https://select2.github.io
|
||||
validator: 'lib/validator.min', // v0.10.1 Validator for Bootstrap 3 - https://github.com/1000hz/bootstrap-validator
|
||||
lazylinepainter: 'lib/jquery.lazylinepainter-1.5.1.min', // v1.5.1 SVG line animation plugin - http://lazylinepainter.info
|
||||
@@ -123,6 +124,9 @@ requirejs.config({
|
||||
easyPieChart: {
|
||||
deps : ['jquery']
|
||||
},
|
||||
peityInlineChart: {
|
||||
deps : ['jquery']
|
||||
},
|
||||
dragToSelect: {
|
||||
deps : ['jquery']
|
||||
},
|
||||
|
||||
@@ -224,7 +224,8 @@ define(['jquery'], function($) {
|
||||
3: 'Minor Perimeter Reservoir', //*
|
||||
4: 'Sizeable Perimeter Reservoir', //*
|
||||
5: 'Ordinary Perimeter Reservoir', //*
|
||||
6: 'Vast Frontier Reservoir' //*
|
||||
6: 'Vast Frontier Reservoir', //*
|
||||
7: 'Bountiful Frontier Reservoir' //*
|
||||
},
|
||||
5: { // Wormhole
|
||||
// no *wandering* w-space -> k-space wormholes
|
||||
@@ -235,7 +236,8 @@ define(['jquery'], function($) {
|
||||
2: 'Common Perimeter Deposit', //*
|
||||
3: 'Unexceptional Frontier Deposit', //*
|
||||
4: 'Average Frontier Deposit', //*
|
||||
5: 'Unusual Core Deposit' //*
|
||||
5: 'Unusual Core Deposit', //*
|
||||
6: 'Infrequent Core Deposit' //*
|
||||
},
|
||||
7: { // Ghost
|
||||
|
||||
|
||||
@@ -35,7 +35,6 @@ define(['jquery'], function($) {
|
||||
getSystemGraphData: 'api/system/graphData', // ajax URL - get all system graph data
|
||||
getConstellationData: 'api/system/constellationData', // ajax URL - get system constellation data
|
||||
setDestination: 'api/system/setDestination', // ajax URL - set destination
|
||||
|
||||
// connection API
|
||||
saveConnection: 'api/connection/save', // ajax URL - save new connection to map
|
||||
deleteConnection: 'api/connection/delete', // ajax URL - delete connection from map
|
||||
@@ -45,6 +44,8 @@ define(['jquery'], function($) {
|
||||
deleteSignatureData: 'api/signature/delete', // ajax URL - delete signature data for system
|
||||
// route API
|
||||
searchRoute: 'api/route/search', // ajax URL - search system routes
|
||||
// stats API
|
||||
getStatisticsData: 'api/statistic/getData', // ajax URL - get statistics data (activity log)
|
||||
// GitHub API
|
||||
gitHubReleases: 'api/github/releases' // ajax URL - get release info from GitHub
|
||||
},
|
||||
@@ -52,6 +53,12 @@ define(['jquery'], function($) {
|
||||
ccpImageServer: 'https://image.eveonline.com/', // CCP image Server
|
||||
zKillboard: 'https://zkillboard.com/api/' // killboard api
|
||||
},
|
||||
breakpoints: [
|
||||
{ name: 'desktop', width: Infinity },
|
||||
{ name: 'tablet', width: 1200 },
|
||||
{ name: 'fablet', width: 780 },
|
||||
{ name: 'phone', width: 480 }
|
||||
],
|
||||
animationSpeed: {
|
||||
splashOverlay: 300, // "splash" loading overlay
|
||||
headerLink: 100, // links in head bar
|
||||
|
||||
168
js/app/login.js
168
js/app/login.js
@@ -59,6 +59,9 @@ define([
|
||||
galleryThumbContainerId: 'pf-landing-gallery-thumb-container', // id for gallery thumb images
|
||||
galleryCarouselId: 'pf-landing-gallery-carousel', // id for "carousel" element
|
||||
|
||||
// notification panel
|
||||
notificationPanelId: 'pf-notification-panel', // id for "notification panel" (e.g. last update information)
|
||||
|
||||
// server panel
|
||||
serverPanelId: 'pf-server-panel', // id for EVE Online server status panel
|
||||
|
||||
@@ -102,6 +105,14 @@ define([
|
||||
return '';
|
||||
};
|
||||
|
||||
/**
|
||||
* set link observer for "version info" dialog
|
||||
*/
|
||||
var setVersionLinkObserver = function(){
|
||||
$('.' + config.navigationVersionLinkClass).off('click').on('click', function(e){
|
||||
$.fn.releasesDialog();
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* set page observer
|
||||
@@ -118,11 +129,6 @@ define([
|
||||
setCookie('cookie', 1, 365);
|
||||
});
|
||||
|
||||
// releases -----------------------------------------------------------
|
||||
$('.' + config.navigationVersionLinkClass).on('click', function(e){
|
||||
$.fn.releasesDialog();
|
||||
});
|
||||
|
||||
// manual -------------------------------------------------------------
|
||||
$('.' + config.navigationLinkManualClass).on('click', function(e){
|
||||
e.preventDefault();
|
||||
@@ -135,6 +141,9 @@ define([
|
||||
$.fn.showCreditsDialog(false, true);
|
||||
});
|
||||
|
||||
// releases -----------------------------------------------------------
|
||||
setVersionLinkObserver();
|
||||
|
||||
// tooltips -----------------------------------------------------------
|
||||
var mapTooltipOptions = {
|
||||
toggle: 'tooltip',
|
||||
@@ -326,6 +335,9 @@ define([
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* init "YouTube" video preview
|
||||
*/
|
||||
var initYoutube = function(){
|
||||
|
||||
$('.youtube').each(function() {
|
||||
@@ -446,6 +458,50 @@ define([
|
||||
}).fail(handleAjaxErrorResponse);
|
||||
};
|
||||
|
||||
/**
|
||||
* show "notification panel" to user
|
||||
* -> checks if panel not already shown
|
||||
*/
|
||||
var initNotificationPanel = function(){
|
||||
var storageKey = 'notification_panel';
|
||||
var currentVersion = $('body').data('version');
|
||||
|
||||
var showNotificationPanel = function(){
|
||||
var data = {};
|
||||
|
||||
requirejs(['text!templates/ui/notice.html', 'mustache'], function(template, Mustache) {
|
||||
var content = Mustache.render(template, data);
|
||||
|
||||
var notificationPanel = $('#' + config.notificationPanelId);
|
||||
notificationPanel.html(content);
|
||||
notificationPanel.velocity('transition.slideUpIn', {
|
||||
duration: 300,
|
||||
complete: function(){
|
||||
setVersionLinkObserver();
|
||||
|
||||
// mark panel as "shown"
|
||||
Util.getLocalStorage().setItem(storageKey, currentVersion);
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
Util.getLocalStorage().getItem(storageKey).then(function(data){
|
||||
// check if panel was shown before
|
||||
if(data){
|
||||
if(data !== this.version){
|
||||
// show current panel
|
||||
showNotificationPanel();
|
||||
}
|
||||
}else{
|
||||
// show current panel
|
||||
showNotificationPanel();
|
||||
}
|
||||
}.bind({
|
||||
version: currentVersion
|
||||
}));
|
||||
};
|
||||
|
||||
/**
|
||||
* load character data from cookie information
|
||||
* -> all validation is done server side!
|
||||
@@ -520,75 +576,71 @@ define([
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
// request character data for each character panel
|
||||
$('.' + config.characterSelectionClass + ' .pf-dynamic-area').each(function(){
|
||||
var characterElement = $(this);
|
||||
requirejs(['text!templates/ui/character_panel.html', 'mustache'], function(template, Mustache){
|
||||
|
||||
characterElement.showLoadingAnimation();
|
||||
$('.' + config.characterSelectionClass + ' .pf-dynamic-area').each(function(){
|
||||
var characterElement = $(this);
|
||||
|
||||
var requestData = {
|
||||
cookie: characterElement.data('cookie')
|
||||
};
|
||||
characterElement.showLoadingAnimation();
|
||||
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: Init.path.getCookieCharacterData,
|
||||
data: requestData,
|
||||
dataType: 'json',
|
||||
context: {
|
||||
href: characterElement.data('href'),
|
||||
cookieName: requestData.cookie,
|
||||
characterElement: characterElement
|
||||
}
|
||||
}).done(function(responseData, textStatus, request){
|
||||
var characterElement = this.characterElement;
|
||||
characterElement.hideLoadingAnimation();
|
||||
var requestData = {
|
||||
cookie: characterElement.data('cookie')
|
||||
};
|
||||
|
||||
if(
|
||||
responseData.error &&
|
||||
responseData.error.length > 0
|
||||
){
|
||||
$('.' + config.dynamicMessageContainerClass).showMessage({
|
||||
type: responseData.error[0].type,
|
||||
title: 'Character verification failed',
|
||||
text: responseData.error[0].message
|
||||
});
|
||||
}
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: Init.path.getCookieCharacterData,
|
||||
data: requestData,
|
||||
dataType: 'json',
|
||||
context: {
|
||||
cookieName: requestData.cookie,
|
||||
characterElement: characterElement
|
||||
}
|
||||
}).done(function(responseData, textStatus, request){
|
||||
this.characterElement.hideLoadingAnimation();
|
||||
|
||||
if(responseData.hasOwnProperty('character')){
|
||||
if(
|
||||
responseData.error &&
|
||||
responseData.error.length > 0
|
||||
){
|
||||
$('.' + config.dynamicMessageContainerClass).showMessage({
|
||||
type: responseData.error[0].type,
|
||||
title: 'Character verification failed',
|
||||
text: responseData.error[0].message
|
||||
});
|
||||
}
|
||||
|
||||
var data = {
|
||||
link: this.href,
|
||||
cookieName: this.cookieName,
|
||||
character: responseData.character
|
||||
};
|
||||
if(responseData.hasOwnProperty('character')){
|
||||
|
||||
var data = {
|
||||
link: this.characterElement.data('href'),
|
||||
cookieName: this.cookieName,
|
||||
character: responseData.character
|
||||
};
|
||||
|
||||
requirejs(['text!templates/ui/character_panel.html', 'mustache'], function(template, Mustache) {
|
||||
var content = Mustache.render(template, data);
|
||||
characterElement.html(content);
|
||||
this.characterElement.html(content);
|
||||
|
||||
// show character panel (animation settings)
|
||||
initCharacterAnimation(characterElement.find('.' + config.characterImageWrapperClass));
|
||||
});
|
||||
}else{
|
||||
initCharacterAnimation(this.characterElement.find('.' + config.characterImageWrapperClass));
|
||||
}else{
|
||||
// character data not available -> remove panel
|
||||
removeCharacterPanel(this.characterElement);
|
||||
}
|
||||
}).fail(function( jqXHR, status, error) {
|
||||
var characterElement = this.characterElement;
|
||||
characterElement.hideLoadingAnimation();
|
||||
|
||||
// character data not available -> remove panel
|
||||
removeCharacterPanel(this.characterElement);
|
||||
}
|
||||
|
||||
}).fail(function( jqXHR, status, error) {
|
||||
var characterElement = this.characterElement;
|
||||
characterElement.hideLoadingAnimation();
|
||||
|
||||
// character data not available -> remove panel
|
||||
removeCharacterPanel(this.characterElement);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* default ajax error handler
|
||||
* -> show user notifications
|
||||
@@ -682,6 +734,10 @@ define([
|
||||
// init server status information
|
||||
initServerStatus();
|
||||
|
||||
// init notification panel
|
||||
initNotificationPanel();
|
||||
|
||||
// init character select
|
||||
initCharacterSelect();
|
||||
|
||||
// init page observer
|
||||
|
||||
@@ -1315,8 +1315,8 @@ define([
|
||||
setConnectionObserver(map, connection);
|
||||
}
|
||||
|
||||
var addType = $(newConnectionData.type).not(connectionData.type).get();
|
||||
var removeType = $(connectionData.type).not(newConnectionData.type).get();
|
||||
var addType = newConnectionData.type.diff( connectionData.type );
|
||||
var removeType = connectionData.type.diff( newConnectionData.type );
|
||||
|
||||
// check if source or target has changed
|
||||
if(connectionData.source !== newConnectionData.source ){
|
||||
@@ -1415,7 +1415,7 @@ define([
|
||||
{subIcon: '', subAction: 'filter_jumpbridge', subText: 'jumpbridge'}
|
||||
]},
|
||||
{divider: true, action: 'delete_systems'},
|
||||
{icon: 'fa-eraser', action: 'delete_systems', text: 'delete systems'}
|
||||
{icon: 'fa-trash', action: 'delete_systems', text: 'delete systems'}
|
||||
]
|
||||
};
|
||||
|
||||
@@ -1452,7 +1452,7 @@ define([
|
||||
|
||||
]},
|
||||
{divider: true, action: 'delete_connection'},
|
||||
{icon: 'fa-eraser', action: 'delete_connection', text: 'delete'}
|
||||
{icon: 'fa-trash', action: 'delete_connection', text: 'delete'}
|
||||
]
|
||||
};
|
||||
|
||||
@@ -1495,7 +1495,7 @@ define([
|
||||
{subIcon: 'fa-step-forward', subAction: 'add_last_waypoint', subText: 'add new [end]'}
|
||||
]},
|
||||
{divider: true, action: 'delete_system'},
|
||||
{icon: 'fa-eraser', action: 'delete_system', text: 'delete system(s)'}
|
||||
{icon: 'fa-trash', action: 'delete_system', text: 'delete system(s)'}
|
||||
]
|
||||
};
|
||||
|
||||
@@ -1624,6 +1624,9 @@ define([
|
||||
var hoverSystem = $(this).parents('.' + config.systemClass);
|
||||
var hoverSystemId = hoverSystem.attr('id');
|
||||
|
||||
// bring system in front (increase zIndex)
|
||||
hoverSystem.updateSystemZIndex();
|
||||
|
||||
// get ship counter and calculate expand height
|
||||
var userCount = parseInt( hoverSystem.data('userCount') );
|
||||
|
||||
|
||||
@@ -19,6 +19,8 @@ define([
|
||||
* main init "map" page
|
||||
*/
|
||||
$(function(){
|
||||
Util.initPrototypes();
|
||||
|
||||
// set default AJAX config
|
||||
Util.ajaxSetup();
|
||||
|
||||
@@ -60,6 +62,7 @@ define([
|
||||
Init.maxSharedCount = initData.maxSharedCount;
|
||||
Init.routes = initData.routes;
|
||||
Init.notificationStatus = initData.notificationStatus;
|
||||
Init.activityLogging = initData.activityLogging;
|
||||
|
||||
// init tab change observer, Once the timers are available
|
||||
Page.initTabChangeObserver();
|
||||
|
||||
121
js/app/page.js
121
js/app/page.js
@@ -12,6 +12,7 @@ define([
|
||||
'text!templates/modules/header.html',
|
||||
'text!templates/modules/footer.html',
|
||||
'dialog/notification',
|
||||
'dialog/stats',
|
||||
'dialog/map_info',
|
||||
'dialog/account_settings',
|
||||
'dialog/manual',
|
||||
@@ -115,6 +116,22 @@ define([
|
||||
setDocumentObserver();
|
||||
};
|
||||
|
||||
/**
|
||||
* get main menu title element
|
||||
* @param title
|
||||
* @returns {JQuery|*|jQuery}
|
||||
*/
|
||||
var getMenuHeadline = function(title){
|
||||
return $('<div>', {
|
||||
class: 'panel-heading'
|
||||
}).prepend(
|
||||
$('<h2>',{
|
||||
class: 'panel-title',
|
||||
text: title
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* load left menu content options
|
||||
*/
|
||||
@@ -132,20 +149,27 @@ define([
|
||||
class: 'fa fa-home fa-fw'
|
||||
})
|
||||
)
|
||||
).append(
|
||||
getMenuHeadline('Information')
|
||||
).append(
|
||||
$('<a>', {
|
||||
class: 'list-group-item',
|
||||
class: 'list-group-item list-group-item-info',
|
||||
href: '#'
|
||||
}).html(' Settings').prepend(
|
||||
}).html(' Statistics').prepend(
|
||||
$('<i>',{
|
||||
class: 'fa fa-sliders fa-fw'
|
||||
class: 'fa fa-line-chart fa-fw'
|
||||
})
|
||||
).append(
|
||||
$('<span>',{
|
||||
class: 'badge bg-color bg-color-gray txt-color txt-color-warning',
|
||||
text: 'beta'
|
||||
})
|
||||
).on('click', function(){
|
||||
$(document).triggerMenuEvent('ShowSettingsDialog');
|
||||
$(document).triggerMenuEvent('ShowStatsDialog');
|
||||
})
|
||||
).append(
|
||||
$('<a>', {
|
||||
class: 'list-group-item',
|
||||
class: 'list-group-item list-group-item-info',
|
||||
href: '#'
|
||||
}).html(' Effect info').prepend(
|
||||
$('<i>',{
|
||||
@@ -156,7 +180,7 @@ define([
|
||||
})
|
||||
).append(
|
||||
$('<a>', {
|
||||
class: 'list-group-item',
|
||||
class: 'list-group-item list-group-item-info',
|
||||
href: '#'
|
||||
}).html(' Jump info').prepend(
|
||||
$('<i>',{
|
||||
@@ -165,6 +189,19 @@ define([
|
||||
).on('click', function(){
|
||||
$(document).triggerMenuEvent('ShowJumpInfo');
|
||||
})
|
||||
).append(
|
||||
getMenuHeadline('Settings')
|
||||
).append(
|
||||
$('<a>', {
|
||||
class: 'list-group-item',
|
||||
href: '#'
|
||||
}).html(' Account').prepend(
|
||||
$('<i>',{
|
||||
class: 'fa fa-sliders fa-fw'
|
||||
})
|
||||
).on('click', function(){
|
||||
$(document).triggerMenuEvent('ShowSettingsDialog');
|
||||
})
|
||||
).append(
|
||||
$('<a>', {
|
||||
class: 'list-group-item hide', // trigger by js
|
||||
@@ -182,7 +219,7 @@ define([
|
||||
if($.fullscreen.isFullScreen()){
|
||||
$.fullscreen.exit();
|
||||
}else{
|
||||
fullScreenElement.fullscreen({overflow: 'overflow-y', toggleClass: config.fullScreenClass});
|
||||
fullScreenElement.fullscreen({overflow: 'scroll', toggleClass: config.fullScreenClass});
|
||||
}
|
||||
});
|
||||
})
|
||||
@@ -197,9 +234,11 @@ define([
|
||||
).on('click', function(){
|
||||
$(document).triggerMenuEvent('NotificationTest');
|
||||
})
|
||||
).append(
|
||||
getMenuHeadline('Danger zone')
|
||||
).append(
|
||||
$('<a>', {
|
||||
class: 'list-group-item',
|
||||
class: 'list-group-item list-group-item-danger',
|
||||
href: '#'
|
||||
}).html(' Delete account').prepend(
|
||||
$('<i>',{
|
||||
@@ -210,7 +249,7 @@ define([
|
||||
})
|
||||
).append(
|
||||
$('<a>', {
|
||||
class: 'list-group-item',
|
||||
class: 'list-group-item list-group-item-warning',
|
||||
href: '#'
|
||||
}).html(' Logout').prepend(
|
||||
$('<i>',{
|
||||
@@ -240,24 +279,26 @@ define([
|
||||
$('<a>', {
|
||||
class: 'list-group-item',
|
||||
href: '#'
|
||||
}).html(' Info').prepend(
|
||||
$('<i>',{
|
||||
class: 'fa fa-info fa-fw'
|
||||
})
|
||||
).on('click', function(){
|
||||
$(document).triggerMenuEvent('ShowMapInfo');
|
||||
}).html(' Status').prepend(
|
||||
$('<i>',{
|
||||
class: 'fa fa-info fa-fw'
|
||||
})
|
||||
).on('click', function(){
|
||||
$(document).triggerMenuEvent('ShowMapInfo');
|
||||
})
|
||||
).append(
|
||||
getMenuHeadline('Settings')
|
||||
).append(
|
||||
$('<a>', {
|
||||
class: 'list-group-item',
|
||||
href: '#'
|
||||
}).html(' Settings').prepend(
|
||||
}).html(' Map config').prepend(
|
||||
$('<i>',{
|
||||
class: 'fa fa-sliders fa-fw'
|
||||
class: 'fa fa-gears fa-fw'
|
||||
})
|
||||
).on('click', function(){
|
||||
$(document).triggerMenuEvent('ShowMapSettings', {tab: 'settings'});
|
||||
})
|
||||
$(document).triggerMenuEvent('ShowMapSettings', {tab: 'settings'});
|
||||
})
|
||||
).append(
|
||||
$('<a>', {
|
||||
class: 'list-group-item',
|
||||
@@ -289,34 +330,38 @@ define([
|
||||
});
|
||||
})
|
||||
).append(
|
||||
$('<a>', {
|
||||
class: 'list-group-item',
|
||||
href: '#'
|
||||
}).html(' Task-Manager').prepend(
|
||||
$('<i>',{
|
||||
class: 'fa fa-tasks fa-fw'
|
||||
})
|
||||
).on('click', function(){
|
||||
$(document).triggerMenuEvent('ShowTaskManager');
|
||||
})
|
||||
getMenuHeadline('Help')
|
||||
).append(
|
||||
$('<a>', {
|
||||
class: 'list-group-item',
|
||||
class: 'list-group-item list-group-item-info',
|
||||
href: '#'
|
||||
}).html(' Manual').prepend(
|
||||
$('<i>',{
|
||||
class: 'fa fa-info fa-fw'
|
||||
class: 'fa fa-book fa-fw'
|
||||
})
|
||||
).on('click', function(){
|
||||
$(document).triggerMenuEvent('Manual');
|
||||
})
|
||||
).append(
|
||||
$('<a>', {
|
||||
class: 'list-group-item',
|
||||
class: 'list-group-item list-group-item-info',
|
||||
href: '#'
|
||||
}).html(' Delete').prepend(
|
||||
}).html(' Task-Manager').prepend(
|
||||
$('<i>',{
|
||||
class: 'fa fa-eraser fa-fw'
|
||||
class: 'fa fa-tasks fa-fw'
|
||||
})
|
||||
).on('click', function(){
|
||||
$(document).triggerMenuEvent('ShowTaskManager');
|
||||
})
|
||||
).append(
|
||||
getMenuHeadline('Danger zone')
|
||||
).append(
|
||||
$('<a>', {
|
||||
class: 'list-group-item list-group-item-danger',
|
||||
href: '#'
|
||||
}).html(' Delete map').prepend(
|
||||
$('<i>',{
|
||||
class: 'fa fa-trash fa-fw'
|
||||
})
|
||||
).on('click', function(){
|
||||
$(document).triggerMenuEvent('DeleteMap');
|
||||
@@ -494,8 +539,14 @@ define([
|
||||
}
|
||||
});
|
||||
|
||||
$(document).on('pf:menuShowStatsDialog', function(e){
|
||||
// show user activity stats dialog
|
||||
$.fn.showStatsDialog();
|
||||
return false;
|
||||
});
|
||||
|
||||
$(document).on('pf:menuShowSystemEffectInfo', function(e){
|
||||
// show system effects info box
|
||||
// show system effects dialog
|
||||
$.fn.showSystemEffectInfoDialog();
|
||||
return false;
|
||||
});
|
||||
|
||||
@@ -295,12 +295,7 @@ define([
|
||||
order: [[ 9, 'desc' ], [ 3, 'asc' ]],
|
||||
autoWidth: false,
|
||||
responsive: {
|
||||
breakpoints: [
|
||||
{ name: 'desktop', width: Infinity },
|
||||
{ name: 'tablet', width: 1200 },
|
||||
{ name: 'fablet', width: 780 },
|
||||
{ name: 'phone', width: 480 }
|
||||
],
|
||||
breakpoints: Init.breakpoints,
|
||||
details: false
|
||||
},
|
||||
hover: false,
|
||||
|
||||
711
js/app/ui/dialog/stats.js
Normal file
711
js/app/ui/dialog/stats.js
Normal file
@@ -0,0 +1,711 @@
|
||||
/**
|
||||
* activity stats dialog
|
||||
*/
|
||||
|
||||
|
||||
define([
|
||||
'jquery',
|
||||
'app/init',
|
||||
'app/util',
|
||||
'app/render',
|
||||
'bootbox'
|
||||
], function($, Init, Util, Render, bootbox, MapUtil) {
|
||||
'use strict';
|
||||
|
||||
var config = {
|
||||
// dialog
|
||||
statsDialogId: 'pf-stats-dialog', // id for "stats" dialog
|
||||
dialogNavigationClass: 'pf-dialog-navigation-list', // class for dialog navigation bar
|
||||
dialogNavigationListItemClass: 'pf-dialog-navigation-list-item', // class for map manual li main navigation elements
|
||||
|
||||
dialogNavigationOffsetClass : 'pf-dialog-navigation-offset', // class for "current" offset filter
|
||||
dialogNavigationPrevClass : 'pf-dialog-navigation-prev', // class for "prev" period load
|
||||
dialogNavigationNextClass : 'pf-dialog-navigation-next', // class for "next" period load
|
||||
|
||||
// stats/dataTable
|
||||
statsContainerId: 'pf-stats-dialog-container', // class for statistics container (dynamic ajax content)
|
||||
statsTableId: 'pf-stats-table', // id for statistics table element
|
||||
tableImageCellClass: 'pf-table-image-cell', // class for table "image" cells
|
||||
|
||||
// charts
|
||||
statsLineChartClass: 'pf-line-chart' // class for inline chart elements
|
||||
};
|
||||
|
||||
/**
|
||||
* init blank statistics dataTable
|
||||
* @param dialogElement
|
||||
*/
|
||||
var initStatsTable = function(dialogElement){
|
||||
var columnNumberWidth = 35;
|
||||
var lineColor = '#477372';
|
||||
|
||||
// render function for inline-chart columns
|
||||
var renderInlineChartColumn = function(data, type, row, meta){
|
||||
/*
|
||||
switch(data.type){
|
||||
case 'C': lineColor = '#5cb85c'; break;
|
||||
case 'U': lineColor = '#e28a0d'; break;
|
||||
case 'D': lineColor = '#a52521'; break;
|
||||
}*/
|
||||
|
||||
if( /^\d+$/.test(data.data) ){
|
||||
// single digit (e.g. single week filter)
|
||||
return data.data;
|
||||
}else{
|
||||
// period -> prepare line chart
|
||||
return '<span class="' + config.statsLineChartClass + '" data-peity=\'{ "stroke": "' + lineColor + '" }\'>' + data.data + '</span>';
|
||||
}
|
||||
};
|
||||
|
||||
// render function for numeric columns
|
||||
var renderNumericColumn = function(data, type, row, meta){
|
||||
return data.toLocaleString();
|
||||
};
|
||||
|
||||
// get table element
|
||||
// Due to "complex" table headers, they are already rendered and part of the stats.html file
|
||||
var table = dialogElement.find('#' + config.statsTableId);
|
||||
|
||||
var statsTable = table.DataTable({
|
||||
pageLength: 30,
|
||||
lengthMenu: [[10, 20, 30, 50], [10, 20, 30, 50]],
|
||||
paging: true,
|
||||
ordering: true,
|
||||
order: [ 16, 'desc' ],
|
||||
info: true,
|
||||
searching: true,
|
||||
hover: false,
|
||||
autoWidth: false,
|
||||
language: {
|
||||
emptyTable: 'No statistics found',
|
||||
zeroRecords: 'No characters found',
|
||||
lengthMenu: 'Show _MENU_ characters',
|
||||
info: 'Showing _START_ to _END_ of _TOTAL_ characters'
|
||||
},
|
||||
columnDefs: [
|
||||
{
|
||||
targets: 0,
|
||||
title: '<i class="fa fa-hashtag"></i>',
|
||||
orderable: false,
|
||||
searchable: false,
|
||||
width: 10,
|
||||
class: 'text-right',
|
||||
data: 'character.id'
|
||||
},{
|
||||
targets: 1,
|
||||
title: '',
|
||||
orderable: false,
|
||||
searchable: false,
|
||||
width: 26,
|
||||
className: ['text-center', config.tableImageCellClass].join(' '),
|
||||
data: 'character',
|
||||
render: {
|
||||
_: function(data, type, row, meta){
|
||||
return '<img src="' + Init.url.ccpImageServer + 'Character/' + data.id + '_32.jpg" />';
|
||||
}
|
||||
}
|
||||
},{
|
||||
targets: 2,
|
||||
title: 'name',
|
||||
width: 200,
|
||||
data: 'character',
|
||||
render: {
|
||||
_: 'name',
|
||||
sort: 'name'
|
||||
}
|
||||
},{
|
||||
targets: 3,
|
||||
title: 'last login',
|
||||
searchable: false,
|
||||
width: 70,
|
||||
className: ['text-right', 'separator-right'].join(' '),
|
||||
data: 'character',
|
||||
render: {
|
||||
_: 'lastLogin',
|
||||
sort: 'lastLogin'
|
||||
},
|
||||
createdCell: function(cell, cellData, rowData, rowIndex, colIndex){
|
||||
$(cell).initTimestampCounter();
|
||||
}
|
||||
},{
|
||||
targets: 4,
|
||||
title: '<span title="created" data-toggle="tooltip">C </span>',
|
||||
orderable: false,
|
||||
searchable: false,
|
||||
width: columnNumberWidth,
|
||||
className: ['text-right', 'hidden-xs', 'hidden-sm'].join(' '),
|
||||
data: 'systemCreate',
|
||||
render: {
|
||||
_: renderInlineChartColumn
|
||||
}
|
||||
},{
|
||||
targets: 5,
|
||||
title: '<span title="updated" data-toggle="tooltip">U </span>',
|
||||
orderable: false,
|
||||
searchable: false,
|
||||
width: columnNumberWidth,
|
||||
className: ['text-right', 'hidden-xs', 'hidden-sm'].join(' '),
|
||||
data: 'systemUpdate',
|
||||
render: {
|
||||
_: renderInlineChartColumn
|
||||
}
|
||||
},{
|
||||
targets: 6,
|
||||
title: '<span title="deleted" data-toggle="tooltip">D </span>',
|
||||
orderable: false,
|
||||
searchable: false,
|
||||
width: columnNumberWidth,
|
||||
className: ['text-right', 'hidden-xs', 'hidden-sm'].join(' '),
|
||||
data: 'systemDelete',
|
||||
render: {
|
||||
_: renderInlineChartColumn
|
||||
}
|
||||
},{
|
||||
targets: 7,
|
||||
title: 'Σ ',
|
||||
searchable: false,
|
||||
width: 20,
|
||||
className: ['text-right', 'hidden-xs', 'hidden-sm', 'separator-right'].join(' '),
|
||||
data: 'systemSum',
|
||||
render: {
|
||||
_: renderNumericColumn
|
||||
}
|
||||
},{
|
||||
targets: 8,
|
||||
title: '<span title="created" data-toggle="tooltip">C </span>',
|
||||
orderable: false,
|
||||
searchable: false,
|
||||
width: columnNumberWidth,
|
||||
className: ['text-right', 'hidden-xs', 'hidden-sm'].join(' '),
|
||||
data: 'connectionCreate',
|
||||
render: {
|
||||
_: renderInlineChartColumn
|
||||
}
|
||||
},{
|
||||
targets: 9,
|
||||
title: '<span title="updated" data-toggle="tooltip">U </span>',
|
||||
orderable: false,
|
||||
searchable: false,
|
||||
width: columnNumberWidth,
|
||||
className: ['text-right', 'hidden-xs', 'hidden-sm'].join(' '),
|
||||
data: 'connectionUpdate',
|
||||
render: {
|
||||
_: renderInlineChartColumn
|
||||
}
|
||||
},{
|
||||
targets: 10,
|
||||
title: '<span title="deleted" data-toggle="tooltip">D </span>',
|
||||
orderable: false,
|
||||
searchable: false,
|
||||
width: columnNumberWidth,
|
||||
className: ['text-right', 'hidden-xs', 'hidden-sm'].join(' '),
|
||||
data: 'connectionDelete',
|
||||
render: {
|
||||
_: renderInlineChartColumn
|
||||
}
|
||||
},{
|
||||
targets: 11,
|
||||
title: 'Σ ',
|
||||
searchable: false,
|
||||
width: 20,
|
||||
className: ['text-right', 'hidden-xs', 'hidden-sm', 'separator-right'].join(' '),
|
||||
data: 'connectionSum',
|
||||
render: {
|
||||
_: renderNumericColumn
|
||||
}
|
||||
},{
|
||||
targets: 12,
|
||||
title: '<span title="created" data-toggle="tooltip">C </span>',
|
||||
orderable: false,
|
||||
searchable: false,
|
||||
width: columnNumberWidth,
|
||||
className: ['text-right', 'hidden-xs', 'hidden-sm'].join(' '),
|
||||
data: 'signatureCreate',
|
||||
render: {
|
||||
_: renderInlineChartColumn
|
||||
}
|
||||
},{
|
||||
targets: 13,
|
||||
title: '<span title="updated" data-toggle="tooltip">U </span>',
|
||||
orderable: false,
|
||||
searchable: false,
|
||||
width: columnNumberWidth,
|
||||
className: ['text-right', 'hidden-xs', 'hidden-sm'].join(' '),
|
||||
data: 'signatureUpdate',
|
||||
render: {
|
||||
_: renderInlineChartColumn
|
||||
}
|
||||
},{
|
||||
targets: 14,
|
||||
title: '<span title="deleted" data-toggle="tooltip">D </span>',
|
||||
orderable: false,
|
||||
searchable: false,
|
||||
width: columnNumberWidth,
|
||||
className: ['text-right', 'hidden-xs', 'hidden-sm'].join(' '),
|
||||
data: 'signatureDelete',
|
||||
render: {
|
||||
_: renderInlineChartColumn
|
||||
}
|
||||
},{
|
||||
targets: 15,
|
||||
title: 'Σ ',
|
||||
searchable: false,
|
||||
width: 20,
|
||||
className: ['text-right', 'hidden-xs', 'hidden-sm', 'separator-right'].join(' '),
|
||||
data: 'signatureSum',
|
||||
render: {
|
||||
_: renderNumericColumn
|
||||
}
|
||||
},{
|
||||
targets: 16,
|
||||
title: 'Σ ',
|
||||
searchable: false,
|
||||
width: 20,
|
||||
className: 'text-right',
|
||||
data: 'totalSum',
|
||||
render: {
|
||||
_: renderNumericColumn
|
||||
}
|
||||
}
|
||||
],
|
||||
initComplete: function(settings){
|
||||
var tableApi = this.api();
|
||||
|
||||
// initial statistics data request
|
||||
var requestData = getRequestDataFromTabPanels(dialogElement);
|
||||
getStatsData(requestData, {tableApi: tableApi, callback: drawStatsTable});
|
||||
},
|
||||
drawCallback: function(settings){
|
||||
this.api().rows().nodes().to$().each(function(i, row){
|
||||
$(row).find('.' + config.statsLineChartClass).peity('line', {
|
||||
fill: 'transparent',
|
||||
height: 18,
|
||||
min: 0,
|
||||
width: 50
|
||||
});
|
||||
});
|
||||
},
|
||||
footerCallback: function ( row, data, start, end, display ) {
|
||||
var api = this.api();
|
||||
var sumColumnIndexes = [7, 11, 15, 16];
|
||||
|
||||
// column data for "sum" columns over this page
|
||||
var pageTotalColumns = api
|
||||
.columns( sumColumnIndexes, { page: 'current'} )
|
||||
.data();
|
||||
|
||||
// sum columns for "total" sum
|
||||
pageTotalColumns.each(function(colData, index){
|
||||
pageTotalColumns[index] = colData.reduce(function(a, b){
|
||||
return a + b;
|
||||
}, 0);
|
||||
});
|
||||
|
||||
$(sumColumnIndexes).each(function(index, value){
|
||||
$( api.column( value ).footer() ).text( renderNumericColumn(pageTotalColumns[index]) );
|
||||
});
|
||||
},
|
||||
data: [] // will be added dynamic
|
||||
});
|
||||
|
||||
statsTable.on('order.dt search.dt', function(){
|
||||
statsTable.column(0, {search:'applied', order:'applied'}).nodes().each(function(cell, i){
|
||||
$(cell).html( (i + 1) + '. ');
|
||||
});
|
||||
}).draw();
|
||||
|
||||
var tooltipElements = dialogElement.find('[data-toggle="tooltip"]');
|
||||
tooltipElements.tooltip();
|
||||
};
|
||||
|
||||
/**
|
||||
* request raw statistics data and execute callback
|
||||
* @param requestData
|
||||
* @param context
|
||||
*/
|
||||
var getStatsData = function(requestData, context){
|
||||
|
||||
context.dynamicArea = $('#' + config.statsContainerId + ' .pf-dynamic-area');
|
||||
context.dynamicArea.showLoadingAnimation();
|
||||
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: Init.path.getStatisticsData,
|
||||
data: requestData,
|
||||
dataType: 'json',
|
||||
context: context
|
||||
}).done(function(data){
|
||||
this.dynamicArea.hideLoadingAnimation();
|
||||
|
||||
this.callback(data);
|
||||
}).fail(function( jqXHR, status, error) {
|
||||
var reason = status + ' ' + error;
|
||||
Util.showNotify({title: jqXHR.status + ': loadStatistics', text: reason, type: 'warning'});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* update dataTable with response data
|
||||
* update "header"/"filter" elements in dialog
|
||||
* @param responseData
|
||||
*/
|
||||
var drawStatsTable = function(responseData){
|
||||
var dialogElement = $('#' + config.statsDialogId);
|
||||
|
||||
// update filter/header -----------------------------------------------------------------------------
|
||||
var navigationListElements = $('.' + config.dialogNavigationClass);
|
||||
navigationListElements.find('a[data-type="typeId"][data-value="' + responseData.typeId + '"]').tab('show');
|
||||
navigationListElements.find('a[data-type="period"][data-value="' + responseData.period + '"]').tab('show');
|
||||
|
||||
// update period pagination -------------------------------------------------------------------------
|
||||
var prevButton = dialogElement.find('.' + config.dialogNavigationPrevClass);
|
||||
prevButton.data('newOffset', responseData.prev);
|
||||
prevButton.find('span').text('Week ' + responseData.prev.week + ', ' + responseData.prev.year);
|
||||
prevButton.css('visibility', 'visible');
|
||||
|
||||
var nextButton = dialogElement.find('.' + config.dialogNavigationNextClass);
|
||||
if(responseData.next){
|
||||
nextButton.data('newOffset', responseData.next);
|
||||
nextButton.find('span').text('Week ' + responseData.next.week + ', ' + responseData.next.year);
|
||||
nextButton.css('visibility', 'visible');
|
||||
}else{
|
||||
nextButton.css('visibility', 'hidden');
|
||||
}
|
||||
|
||||
// update current period information label ----------------------------------------------------------
|
||||
// if period == "weekly" there is no "offset" -> just a single week
|
||||
var offsetText = 'Week ' + responseData.start.week + ', ' + responseData.start.year;
|
||||
if(responseData.period !== 'weekly'){
|
||||
offsetText += ' <small><i class="fa fa-fw fa-minus"></i></small> ' +
|
||||
'Week ' + responseData.offset.week + ', ' + responseData.offset.year;
|
||||
}
|
||||
dialogElement.find('.' + config.dialogNavigationOffsetClass)
|
||||
.data('start', responseData.start)
|
||||
.data('period', responseData.period)
|
||||
.html(offsetText);
|
||||
|
||||
// clear and (re)-fill table ------------------------------------------------------------------------
|
||||
var formattedData = formatStatisticsData(responseData);
|
||||
this.tableApi.clear();
|
||||
this.tableApi.rows.add(formattedData).draw();
|
||||
};
|
||||
|
||||
/**
|
||||
* format statistics data for dataTable
|
||||
* -> e.g. format inline-chart data
|
||||
* @param statsData
|
||||
* @returns {Array}
|
||||
*/
|
||||
var formatStatisticsData = function(statsData){
|
||||
var formattedData = [];
|
||||
var yearStart = statsData.start.year;
|
||||
var weekStart = statsData.start.week;
|
||||
var weekCount = statsData.weekCount;
|
||||
var yearWeeks = statsData.yearWeeks;
|
||||
|
||||
var tempRand = function(min, max){
|
||||
return Math.random() * (max - min) + min;
|
||||
};
|
||||
|
||||
// format/sum week statistics data for inline charts
|
||||
var formatWeekData = function(weeksData){
|
||||
var currentYear = yearStart;
|
||||
var currentWeek = weekStart;
|
||||
|
||||
var formattedWeeksData = {
|
||||
systemCreate: [],
|
||||
systemUpdate: [],
|
||||
systemDelete: [],
|
||||
connectionCreate: [],
|
||||
connectionUpdate: [],
|
||||
connectionDelete: [],
|
||||
signatureCreate: [],
|
||||
signatureUpdate: [],
|
||||
signatureDelete: [],
|
||||
systemSum: 0,
|
||||
connectionSum: 0,
|
||||
signatureSum: 0
|
||||
};
|
||||
|
||||
for(let i = 0; i < weekCount; i++){
|
||||
let yearWeekProp = currentYear + '' + currentWeek;
|
||||
|
||||
if(weeksData.hasOwnProperty( yearWeekProp )){
|
||||
let weekData = weeksData[ yearWeekProp ];
|
||||
|
||||
// system -------------------------------------------------------------------------------
|
||||
formattedWeeksData.systemCreate.push( weekData.systemCreate );
|
||||
formattedWeeksData.systemSum += parseInt( weekData.systemCreate );
|
||||
|
||||
formattedWeeksData.systemUpdate.push( weekData.systemUpdate );
|
||||
formattedWeeksData.systemSum += parseInt( weekData.systemUpdate );
|
||||
|
||||
formattedWeeksData.systemDelete.push( weekData.systemDelete );
|
||||
formattedWeeksData.systemSum += parseInt( weekData.systemDelete );
|
||||
|
||||
// connection ---------------------------------------------------------------------------
|
||||
formattedWeeksData.connectionCreate.push( weekData.connectionCreate );
|
||||
formattedWeeksData.connectionSum += parseInt( weekData.connectionCreate );
|
||||
|
||||
formattedWeeksData.connectionUpdate.push( weekData.connectionUpdate );
|
||||
formattedWeeksData.connectionSum += parseInt( weekData.connectionUpdate );
|
||||
|
||||
formattedWeeksData.connectionDelete.push( weekData.connectionDelete );
|
||||
formattedWeeksData.connectionSum += parseInt( weekData.connectionDelete );
|
||||
|
||||
// signature ----------------------------------------------------------------------------
|
||||
formattedWeeksData.signatureCreate.push( weekData.signatureCreate );
|
||||
formattedWeeksData.signatureSum += parseInt( weekData.signatureCreate );
|
||||
|
||||
formattedWeeksData.signatureUpdate.push( weekData.signatureUpdate );
|
||||
formattedWeeksData.signatureSum += parseInt( weekData.signatureUpdate );
|
||||
|
||||
formattedWeeksData.signatureDelete.push( weekData.signatureDelete );
|
||||
formattedWeeksData.signatureSum += parseInt( weekData.signatureDelete );
|
||||
}else{
|
||||
// system -------------------------------------------------------------------------------
|
||||
formattedWeeksData.systemCreate.push(0);
|
||||
formattedWeeksData.systemUpdate.push(0);
|
||||
formattedWeeksData.systemDelete.push(0);
|
||||
|
||||
// connection ---------------------------------------------------------------------------
|
||||
formattedWeeksData.connectionCreate.push(0);
|
||||
formattedWeeksData.connectionUpdate.push(0);
|
||||
formattedWeeksData.connectionDelete.push(0);
|
||||
|
||||
// signature ----------------------------------------------------------------------------
|
||||
formattedWeeksData.signatureCreate.push(0);
|
||||
formattedWeeksData.signatureUpdate.push(0);
|
||||
formattedWeeksData.signatureDelete.push(0);
|
||||
}
|
||||
|
||||
currentWeek++;
|
||||
|
||||
if( currentWeek > yearWeeks[currentYear] ){
|
||||
currentWeek = 1;
|
||||
currentYear++;
|
||||
}
|
||||
}
|
||||
|
||||
// system ---------------------------------------------------------------------------------------
|
||||
formattedWeeksData.systemCreate = formattedWeeksData.systemCreate.join(',');
|
||||
formattedWeeksData.systemUpdate = formattedWeeksData.systemUpdate.join(',');
|
||||
formattedWeeksData.systemDelete = formattedWeeksData.systemDelete.join(',');
|
||||
|
||||
// connection -----------------------------------------------------------------------------------
|
||||
formattedWeeksData.connectionCreate = formattedWeeksData.connectionCreate.join(',');
|
||||
formattedWeeksData.connectionUpdate = formattedWeeksData.connectionUpdate.join(',');
|
||||
formattedWeeksData.connectionDelete = formattedWeeksData.connectionDelete.join(',');
|
||||
|
||||
// signature ------------------------------------------------------------------------------------
|
||||
formattedWeeksData.signatureCreate = formattedWeeksData.signatureCreate.join(',');
|
||||
formattedWeeksData.signatureUpdate = formattedWeeksData.signatureUpdate.join(',');
|
||||
formattedWeeksData.signatureDelete = formattedWeeksData.signatureDelete.join(',');
|
||||
|
||||
return formattedWeeksData;
|
||||
};
|
||||
|
||||
$.each(statsData.statistics, function(characterId, data){
|
||||
|
||||
var formattedWeeksData = formatWeekData(data.weeks);
|
||||
|
||||
var rowData = {
|
||||
character: {
|
||||
id: characterId,
|
||||
name: data.name,
|
||||
lastLogin: data.lastLogin
|
||||
},
|
||||
systemCreate: {
|
||||
type: 'C',
|
||||
data: formattedWeeksData.systemCreate
|
||||
},
|
||||
systemUpdate: {
|
||||
type: 'U',
|
||||
data: formattedWeeksData.systemUpdate
|
||||
},
|
||||
systemDelete: {
|
||||
type: 'D',
|
||||
data: formattedWeeksData.systemDelete
|
||||
},
|
||||
systemSum: formattedWeeksData.systemSum,
|
||||
connectionCreate: {
|
||||
type: 'C',
|
||||
data: formattedWeeksData.connectionCreate
|
||||
},
|
||||
connectionUpdate: {
|
||||
type: 'U',
|
||||
data: formattedWeeksData.connectionUpdate
|
||||
},
|
||||
connectionDelete: {
|
||||
type: 'D',
|
||||
data: formattedWeeksData.connectionDelete
|
||||
},
|
||||
connectionSum: formattedWeeksData.connectionSum,
|
||||
signatureCreate: {
|
||||
type: 'C',
|
||||
data: formattedWeeksData.signatureCreate
|
||||
},
|
||||
signatureUpdate: {
|
||||
type: 'U',
|
||||
data: formattedWeeksData.signatureUpdate
|
||||
},
|
||||
signatureDelete: {
|
||||
type: 'D',
|
||||
data: formattedWeeksData.signatureDelete
|
||||
},
|
||||
signatureSum: formattedWeeksData.signatureSum,
|
||||
totalSum: formattedWeeksData.systemSum + formattedWeeksData.connectionSum + formattedWeeksData.signatureSum
|
||||
};
|
||||
|
||||
formattedData.push(rowData);
|
||||
});
|
||||
|
||||
return formattedData;
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param dialogElement
|
||||
* @returns {{}}
|
||||
*/
|
||||
var getRequestDataFromTabPanels = function(dialogElement){
|
||||
var requestData = {};
|
||||
|
||||
// get data from "tab" panel links ------------------------------------------------------------------
|
||||
var navigationListElements = dialogElement.find('.' + config.dialogNavigationClass);
|
||||
navigationListElements.find('.' + config.dialogNavigationListItemClass + '.active a').each(function(){
|
||||
var linkElement = $(this);
|
||||
requestData[linkElement.data('type')]= linkElement.data('value');
|
||||
});
|
||||
|
||||
// get current period (no offset) data (if available) -----------------------------------------------
|
||||
var navigationOffsetElement = dialogElement.find('.' + config.dialogNavigationOffsetClass);
|
||||
var startData = navigationOffsetElement.data('start');
|
||||
var periodOld = navigationOffsetElement.data('period');
|
||||
|
||||
// if period switch was detected
|
||||
// -> "year" and "week" should not be send
|
||||
// -> start from "now"
|
||||
if(
|
||||
requestData.period === periodOld &&
|
||||
startData
|
||||
){
|
||||
requestData.year = startData.year;
|
||||
requestData.week = startData.week;
|
||||
}
|
||||
|
||||
return requestData;
|
||||
};
|
||||
|
||||
/**
|
||||
* check if "activity log" type is enabled for a group
|
||||
* @param type
|
||||
* @returns {boolean}
|
||||
*/
|
||||
var isTabTypeEnabled = function(type){
|
||||
var enabled = false;
|
||||
|
||||
switch(type){
|
||||
case 'private':
|
||||
if(Init.activityLogging.character){
|
||||
enabled = true;
|
||||
}
|
||||
break;
|
||||
case 'corporation':
|
||||
if(
|
||||
Init.activityLogging.corporation &&
|
||||
Util.getCurrentUserInfo('corporationId')
|
||||
){
|
||||
enabled = true;
|
||||
}
|
||||
break;
|
||||
case 'alliance':
|
||||
if(
|
||||
Init.activityLogging.alliance &&
|
||||
Util.getCurrentUserInfo('allianceId')
|
||||
){
|
||||
enabled = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return enabled;
|
||||
};
|
||||
|
||||
/**
|
||||
* show activity stats dialog
|
||||
*/
|
||||
$.fn.showStatsDialog = function(){
|
||||
requirejs(['text!templates/dialog/stats.html', 'mustache', 'peityInlineChart'], function(template, Mustache) {
|
||||
|
||||
var data = {
|
||||
id: config.statsDialogId,
|
||||
dialogNavigationClass: config.dialogNavigationClass,
|
||||
dialogNavLiClass: config.dialogNavigationListItemClass,
|
||||
enablePrivateTab: isTabTypeEnabled('private'),
|
||||
enableCorporationTab: isTabTypeEnabled('corporation'),
|
||||
enableAllianceTab: isTabTypeEnabled('alliance'),
|
||||
statsContainerId: config.statsContainerId,
|
||||
statsTableId: config.statsTableId,
|
||||
dialogNavigationOffsetClass: config.dialogNavigationOffsetClass,
|
||||
dialogNavigationPrevClass: config.dialogNavigationPrevClass,
|
||||
dialogNavigationNextClass: config.dialogNavigationNextClass
|
||||
};
|
||||
|
||||
var content = Mustache.render(template, data);
|
||||
|
||||
var statsDialog = bootbox.dialog({
|
||||
title: 'Statistics',
|
||||
message: content,
|
||||
size: 'large',
|
||||
show: false,
|
||||
buttons: {
|
||||
close: {
|
||||
label: 'close',
|
||||
className: 'btn-default'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// model events
|
||||
statsDialog.on('show.bs.modal', function(e) {
|
||||
var dialogElement = $(e.target);
|
||||
|
||||
initStatsTable(dialogElement);
|
||||
});
|
||||
|
||||
// Tab module events
|
||||
statsDialog.find('a[data-toggle="tab"]').on('show.bs.tab', function (e, b, c) {
|
||||
if( $(e.target).parent().hasClass('disabled') ){
|
||||
// no action on "disabled" tabs
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
statsDialog.find('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
|
||||
var requestData = getRequestDataFromTabPanels(statsDialog);
|
||||
var tableApi = statsDialog.find('#' + config.statsTableId).DataTable();
|
||||
|
||||
getStatsData(requestData, {tableApi: tableApi, callback: drawStatsTable});
|
||||
});
|
||||
|
||||
// offset change links
|
||||
statsDialog.find('.' + config.dialogNavigationPrevClass + ', .' + config.dialogNavigationNextClass).on('click', function(){
|
||||
var offsetData = $(this).data('newOffset');
|
||||
if(offsetData){
|
||||
// this should NEVER fail!
|
||||
// get "base" request data (e.g. typeId, period)
|
||||
// --> overwrite period data with new period data
|
||||
var tmpRequestData = getRequestDataFromTabPanels(statsDialog);
|
||||
var requestData = $.extend({}, tmpRequestData, offsetData);
|
||||
var tableApi = statsDialog.find('#' + config.statsTableId).DataTable();
|
||||
|
||||
getStatsData(requestData, {tableApi: tableApi, callback: drawStatsTable});
|
||||
}
|
||||
});
|
||||
|
||||
// show dialog
|
||||
statsDialog.modal('show');
|
||||
});
|
||||
};
|
||||
});
|
||||
@@ -316,7 +316,7 @@ define([
|
||||
var settingsDialog = bootbox.dialog({
|
||||
title: 'Route settings',
|
||||
message: content,
|
||||
show: false,
|
||||
show: false,
|
||||
buttons: {
|
||||
close: {
|
||||
label: 'cancel',
|
||||
@@ -444,7 +444,6 @@ define([
|
||||
data: requestData,
|
||||
context: context
|
||||
}).done(function(routesData){
|
||||
|
||||
this.moduleElement.hideLoadingAnimation();
|
||||
|
||||
// execute callback
|
||||
@@ -886,7 +885,14 @@ define([
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* draw route table
|
||||
* @param mapId
|
||||
* @param moduleElement
|
||||
* @param systemFromData
|
||||
* @param routesTable
|
||||
* @param systemsTo
|
||||
*/
|
||||
var drawRouteTable = function(mapId, moduleElement, systemFromData, routesTable, systemsTo){
|
||||
var requestRouteData = [];
|
||||
var currentTimestamp = Util.getServerTime().getTime();
|
||||
|
||||
@@ -48,7 +48,9 @@ define([
|
||||
sigTableActionCellClass: 'pf-table-action-cell', // class for "action" cells
|
||||
|
||||
// xEditable
|
||||
editableDiscriptionInputClass: 'pf-editable-description' // class for "description" textarea
|
||||
moduleIcon: 'pf-module-icon-button', // class for "filter" - icons
|
||||
editableDescriptionInputClass: 'pf-editable-description', // class for "description" textarea
|
||||
editableFilterInputClass: 'pf-editable-filter' // class for "filter" selects
|
||||
};
|
||||
|
||||
// lock Signature Table update temporary (until. some requests/animations) are finished
|
||||
@@ -95,6 +97,10 @@ define([
|
||||
'Источники сигналов' // == "Cosmic Signature"
|
||||
];
|
||||
|
||||
// some static signature data
|
||||
var signatureGroupsLabels = Util.getSignatureGroupInfo('label');
|
||||
var signatureGroupsNames = Util.getSignatureGroupInfo('name');
|
||||
|
||||
/**
|
||||
* collect all data of all editable fields in a signature table
|
||||
* @returns {Array}
|
||||
@@ -505,7 +511,7 @@ define([
|
||||
|
||||
if(clipboard.length){
|
||||
var signatureRows = clipboard.split(/\r\n|\r|\n/g);
|
||||
var signatureGroupOptions = Util.getSignatureGroupInfo('name');
|
||||
var signatureGroupOptions = signatureGroupsNames;
|
||||
var invalidSignatures = 0;
|
||||
|
||||
for(var i = 0; i < signatureRows.length; i++){
|
||||
@@ -892,8 +898,7 @@ define([
|
||||
var systemTypeId = parseInt( signatureGroupField.attr('data-systemTypeId') );
|
||||
|
||||
// get all available Signature Types
|
||||
// json object -> "translate" keys to names
|
||||
var availableTypes = Util.getSignatureGroupInfo('label');
|
||||
var availableTypes = signatureGroupsLabels;
|
||||
|
||||
// add empty option
|
||||
availableTypes[0] = '';
|
||||
@@ -943,7 +948,7 @@ define([
|
||||
}
|
||||
});
|
||||
|
||||
sigTypeFields.editable({ mode: 'popup',
|
||||
sigTypeFields.editable({
|
||||
type: 'select',
|
||||
title: 'type',
|
||||
name: 'typeId',
|
||||
@@ -982,7 +987,7 @@ define([
|
||||
onblur: 'submit',
|
||||
mode: 'inline',
|
||||
showbuttons: false,
|
||||
inputclass: config.editableDiscriptionInputClass,
|
||||
inputclass: config.editableDescriptionInputClass,
|
||||
params: modifyFieldParamsOnSend,
|
||||
success: function(response, newValue){
|
||||
if(response){
|
||||
@@ -1390,12 +1395,74 @@ define([
|
||||
class: ['display', 'compact', 'nowrap', config.sigTableClass, config.sigTablePrimaryClass].join(' ')
|
||||
});
|
||||
|
||||
// create table footer ----------------------------------------------------------------------------------------
|
||||
// get column count from default dataTable config
|
||||
var columnCount = $.fn.dataTable.defaults.columnDefs.length;
|
||||
var footerHtml = '<tfoot><tr>';
|
||||
for(let i = 0; i < columnCount; i++){
|
||||
footerHtml += '<td></td>';
|
||||
}
|
||||
footerHtml += '</tr></tfoot>';
|
||||
table.append(footerHtml);
|
||||
|
||||
moduleElement.append(table);
|
||||
|
||||
var dataTableOptions = {
|
||||
data: signatureData,
|
||||
initComplete: function (settings, json){
|
||||
// setup filter select in footer
|
||||
// column indexes that need a filter select
|
||||
var filterColumnIndexes = [2];
|
||||
|
||||
this.api().columns(filterColumnIndexes).every(function(){
|
||||
var column = this;
|
||||
var headerLabel = $(column.header()).text();
|
||||
var selectField = $('<a class="pf-editable ' +
|
||||
config.moduleIcon + ' ' +
|
||||
config.editableFilterInputClass +
|
||||
'" href="#" data-type="select" data-name="' + headerLabel + '"></a>');
|
||||
|
||||
// get all available options from column
|
||||
var source = {};
|
||||
column.data().unique().sort(function(a,b){
|
||||
// sort alphabetically
|
||||
var valA = a.filter.toLowerCase();
|
||||
var valB = b.filter.toLowerCase();
|
||||
|
||||
if(valA < valB) return -1;
|
||||
if(valA > valB) return 1;
|
||||
return 0;
|
||||
}).each(function(callData){
|
||||
if(callData.filter){
|
||||
source[callData.filter] = callData.filter;
|
||||
}
|
||||
});
|
||||
|
||||
// add empty option
|
||||
source[0] = '';
|
||||
|
||||
// add field to footer
|
||||
selectField.appendTo( $(column.footer()).empty() );
|
||||
|
||||
selectField.editable({
|
||||
emptytext: '<i class="fa fa-filter fa-fw"></i>',
|
||||
onblur: 'submit',
|
||||
title: 'filter',
|
||||
showbuttons: false,
|
||||
source: source,
|
||||
value: 0
|
||||
});
|
||||
|
||||
selectField.on('save', { column: column }, function(e, params) {
|
||||
var val = $.fn.dataTable.util.escapeRegex( params.newValue );
|
||||
e.data.column.search( val !== '0' ? '^' + val + '$' : '', true, false ).draw();
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// create signature table and store the jquery object global for this module
|
||||
signatureTable = table.dataTable( {
|
||||
data: signatureData
|
||||
} );
|
||||
signatureTable = table.dataTable(dataTableOptions);
|
||||
|
||||
// make Table editable
|
||||
signatureTable.makeEditable(systemData);
|
||||
@@ -1473,7 +1540,8 @@ define([
|
||||
|
||||
tempData.group = {
|
||||
group: sigGroup,
|
||||
group_sort: data.groupId
|
||||
sort: signatureGroupsLabels[data.groupId],
|
||||
filter: signatureGroupsLabels[data.groupId]
|
||||
};
|
||||
|
||||
// set type id ----------------------------------------------------------------------------------------
|
||||
@@ -1540,7 +1608,7 @@ define([
|
||||
*/
|
||||
var initSignatureDataTable = function(systemData){
|
||||
|
||||
$.extend( $.fn.dataTable.defaults, {
|
||||
$.extend( true, $.fn.dataTable.defaults, {
|
||||
pageLength: -1,
|
||||
lengthMenu: [[5, 10, 25, 50, -1], [5, 10, 25, 50, 'All']],
|
||||
order: [1, 'asc'],
|
||||
@@ -1579,14 +1647,15 @@ define([
|
||||
},{
|
||||
targets: 2,
|
||||
orderable: true,
|
||||
searchable: false,
|
||||
searchable: true,
|
||||
title: 'group',
|
||||
type: 'html',
|
||||
width: '50px',
|
||||
data: 'group',
|
||||
render: {
|
||||
_: 'group',
|
||||
sort: 'group_sort'
|
||||
sort: 'sort',
|
||||
filter: 'filter'
|
||||
}
|
||||
},{
|
||||
targets: 3,
|
||||
@@ -1755,14 +1824,7 @@ define([
|
||||
|
||||
}
|
||||
}
|
||||
],
|
||||
createdRow: function(row, data, dataIndex){
|
||||
|
||||
},
|
||||
initComplete: function(settings, json){
|
||||
// table init complete
|
||||
|
||||
}
|
||||
]
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
@@ -121,7 +121,9 @@ define([
|
||||
var loadingElement = $(this);
|
||||
var overlay = loadingElement.find('.' + config.ajaxOverlayClass );
|
||||
|
||||
$(overlay).velocity('reverse', {
|
||||
// important: "stop" is required to stop "show" animation
|
||||
// -> otherwise "complete" callback is not fired!
|
||||
$(overlay).velocity('stop').velocity('reverse', {
|
||||
complete: function(){
|
||||
$(this).remove();
|
||||
// enable all events
|
||||
@@ -847,6 +849,18 @@ define([
|
||||
console.info('PATHFINDER ' + versionNumber);
|
||||
};
|
||||
|
||||
/**
|
||||
* init utility prototype functions
|
||||
*/
|
||||
var initPrototypes = function(){
|
||||
// Array diff
|
||||
// [1,2,3,4,5,6].diff( [3,4,5] );
|
||||
// => [1, 2, 6]
|
||||
Array.prototype.diff = function(a) {
|
||||
return this.filter(function(i) {return a.indexOf(i) < 0;});
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* set default configuration for "Bootbox" dialogs
|
||||
*/
|
||||
@@ -1719,7 +1733,7 @@ define([
|
||||
var getLocalStorage = function(){
|
||||
if(localStorage === undefined){
|
||||
localStorage = localforage.createInstance({
|
||||
driver: localforage.INDEXEDDB,
|
||||
driver: [localforage.INDEXEDDB, localforage.WEBSQL, localforage.LOCALSTORAGE],
|
||||
name: 'Pathfinder local storage'
|
||||
});
|
||||
}
|
||||
@@ -1818,6 +1832,7 @@ define([
|
||||
return {
|
||||
config: config,
|
||||
showVersionInfo: showVersionInfo,
|
||||
initPrototypes: initPrototypes,
|
||||
initDefaultBootboxConfig: initDefaultBootboxConfig,
|
||||
getCurrentTriggerDelay: getCurrentTriggerDelay,
|
||||
getServerTime: getServerTime,
|
||||
|
||||
@@ -103,12 +103,12 @@ jQuery.fn.dragToSelect = function (conf) {
|
||||
|
||||
// Current origin of select box
|
||||
var selectBoxOrigin = {
|
||||
left: 0,
|
||||
left: 0,
|
||||
top: 0
|
||||
};
|
||||
|
||||
// Create select box
|
||||
var selectBox = jQuery('<div/>')
|
||||
var selectBox = $('<div>')
|
||||
.appendTo(parent)
|
||||
.attr('class', config.className)
|
||||
.css('position', 'absolute');
|
||||
@@ -119,8 +119,8 @@ jQuery.fn.dragToSelect = function (conf) {
|
||||
return;
|
||||
}
|
||||
|
||||
selectBoxOrigin.left = e.pageX - parentDim.left + parent[0].scrollLeft;
|
||||
selectBoxOrigin.top = e.pageY - parentDim.top + parent[0].scrollTop;
|
||||
selectBoxOrigin.left = e.pageX - parentDim.left + parent[0].scrollLeft - 5;
|
||||
selectBoxOrigin.top = e.pageY - parentDim.top + parent[0].scrollTop - 5;
|
||||
|
||||
var css = {
|
||||
left: selectBoxOrigin.left + 'px',
|
||||
|
||||
19
js/lib/jquery.fullscreen.min.js
vendored
19
js/lib/jquery.fullscreen.min.js
vendored
File diff suppressed because one or more lines are too long
13
js/lib/jquery.peity.min.js
vendored
Normal file
13
js/lib/jquery.peity.min.js
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
// Peity jQuery plugin version 3.2.0
|
||||
// (c) 2015 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==
|
||||
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);
|
||||
File diff suppressed because one or more lines are too long
BIN
public/img/landing/statistics_2.jpg
Normal file
BIN
public/img/landing/statistics_2.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 55 KiB |
BIN
public/img/landing/thumbs/statistics_2.jpg
Normal file
BIN
public/img/landing/thumbs/statistics_2.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 9.6 KiB |
@@ -1,2 +0,0 @@
|
||||
var mainScriptPath=document.body.getAttribute("data-script"),jsBaseUrl=document.body.getAttribute("data-js-path");requirejs.config({baseUrl:"js",paths:{layout:"layout",config:"app/config",dialog:"app/ui/dialog",templates:"../../templates",img:"../../img",login:"./app/login",mappage:"./app/mappage",setup:"./app/setup",jquery:"lib/jquery-3.0.0.min",bootstrap:"lib/bootstrap.min",text:"lib/requirejs/text",mustache:"lib/mustache.min",localForage:"lib/localforage.min",velocity:"lib/velocity.min",velocityUI:"lib/velocity.ui.min",slidebars:"lib/slidebars",jsPlumb:"lib/dom.jsPlumb-1.7.6",farahey:"lib/farahey-0.5",customScrollbar:"lib/jquery.mCustomScrollbar.min",mousewheel:"lib/jquery.mousewheel.min",xEditable:"lib/bootstrap-editable.min",morris:"lib/morris.min",raphael:"lib/raphael-min",bootbox:"lib/bootbox.min",easyPieChart:"lib/jquery.easypiechart.min",dragToSelect:"lib/jquery.dragToSelect",hoverIntent:"lib/jquery.hoverIntent.minified",fullScreen:"lib/jquery.fullscreen.min",select2:"lib/select2.min",validator:"lib/validator.min",lazylinepainter:"lib/jquery.lazylinepainter-1.5.1.min",blueImpGallery:"lib/blueimp-gallery",blueImpGalleryHelper:"lib/blueimp-helper",blueImpGalleryBootstrap:"lib/bootstrap-image-gallery",bootstrapConfirmation:"lib/bootstrap-confirmation",bootstrapToggle:"lib/bootstrap2-toggle.min",lazyload:"lib/jquery.lazyload.min",easePack:"lib/EasePack.min",tweenLite:"lib/TweenLite.min","datatables.net":"lib/datatables/DataTables-1.10.12/js/jquery.dataTables.min","datatables.net-buttons":"lib/datatables/Buttons-1.2.1/js/dataTables.buttons.min","datatables.net-buttons-html":"lib/datatables/Buttons-1.2.1/js/buttons.html5.min","datatables.net-responsive":"lib/datatables/Responsive-2.1.0/js/dataTables.responsive.min","datatables.net-select":"lib/datatables/Select-1.2.0/js/dataTables.select.min",pnotify:"lib/pnotify/pnotify","pnotify.buttons":"lib/pnotify/pnotify.buttons","pnotify.confirm":"lib/pnotify/pnotify.confirm","pnotify.nonblock":"lib/pnotify/pnotify.nonblock","pnotify.desktop":"lib/pnotify/pnotify.desktop","pnotify.history":"lib/pnotify/pnotify.history","pnotify.callbacks":"lib/pnotify/pnotify.callbacks","pnotify.reference":"lib/pnotify/pnotify.reference"},shim:{bootstrap:{deps:["jquery"]},farahey:{deps:["jsPlumb"]},velocity:{deps:["jquery"]},velocityUI:{deps:["velocity"]},slidebars:{deps:["jquery"]},customScrollbar:{deps:["jquery","mousewheel"]},"datatables.net":{deps:["jquery"]},"datatables.net-buttons":{deps:["datatables.net"]},"datatables.net-buttons-html":{deps:["datatables.net-buttons"]},"datatables.net-responsive":{deps:["datatables.net"]},"datatables.net-select":{deps:["datatables.net"]},xEditable:{deps:["bootstrap"]},bootbox:{deps:["jquery","bootstrap"],exports:"bootbox"},morris:{deps:["jquery","raphael"],exports:"Morris"},pnotify:{deps:["jquery"]},easyPieChart:{deps:["jquery"]},dragToSelect:{deps:["jquery"]},hoverIntent:{deps:["jquery"]},fullScreen:{deps:["jquery"]},select2:{deps:["jquery"],exports:"Select2"},validator:{deps:["jquery","bootstrap"]},lazylinepainter:{deps:["jquery","bootstrap"]},blueImpGallery:{deps:["jquery"]},bootstrapConfirmation:{deps:["bootstrap"]},bootstrapToggle:{deps:["jquery"]},lazyload:{deps:["jquery"]}}});require.config({baseUrl:jsBaseUrl});requirejs([mainScriptPath]);
|
||||
//# sourceMappingURL=app.js.map
|
||||
@@ -1 +0,0 @@
|
||||
{"version":3,"sources":["app.js.src.js"],"names":["mainScriptPath","document","body","getAttribute","jsBaseUrl","requirejs","config","baseUrl","paths","layout","dialog","templates","img","login","mappage","setup","jquery","bootstrap","text","mustache","localForage","velocity","velocityUI","slidebars","jsPlumb","farahey","customScrollbar","mousewheel","xEditable","morris","raphael","bootbox","easyPieChart","dragToSelect","hoverIntent","fullScreen","select2","validator","lazylinepainter","blueImpGallery","blueImpGalleryHelper","blueImpGalleryBootstrap","bootstrapConfirmation","bootstrapToggle","lazyload","easePack","tweenLite","datatables.net","datatables.net-buttons","datatables.net-buttons-html","datatables.net-responsive","datatables.net-select","pnotify","pnotify.buttons","pnotify.confirm","pnotify.nonblock","pnotify.desktop","pnotify.history","pnotify.callbacks","pnotify.reference","shim","deps","exports","require"],"mappings":"AACA,GAAIA,gBAAiBC,SAASC,KAAKC,aAAa,eAI5CC,UAAYH,SAASC,KAAKC,aAAa,eAG3CE,WAAUC,QACNC,QAAS,KAETC,OACIC,OAAQ,SACRH,OAAQ,aACRI,OAAQ,gBACRC,UAAW,kBACXC,IAAK,YAGLC,MAAO,cACPC,QAAS,gBACTC,MAAO,cAEPC,OAAQ,uBACRC,UAAW,oBACXC,KAAM,qBACNC,SAAU,mBACVC,YAAa,sBACbC,SAAU,mBACVC,WAAY,sBACZC,UAAW,gBACXC,QAAS,wBACTC,QAAS,kBACTC,gBAAiB,kCACjBC,WAAY,4BACZC,UAAW,6BACXC,OAAQ,iBACRC,QAAS,kBACTC,QAAS,kBACTC,aAAc,8BACdC,aAAc,0BACdC,YAAa,kCACbC,WAAY,4BACZC,QAAS,kBACTC,UAAW,oBACXC,gBAAiB,uCACjBC,eAAgB,sBAChBC,qBAAsB,qBACtBC,wBAAyB,8BACzBC,sBAAuB,6BACvBC,gBAAiB,4BACjBC,SAAU,0BAGVC,SAAU,mBACVC,UAAW,oBAGXC,iBAAkB,6DAClBC,yBAA0B,yDAC1BC,8BAA+B,oDAC/BC,4BAA6B,+DAC7BC,wBAAyB,uDAGzBC,QAAS,sBACTC,kBAAmB,8BACnBC,kBAAmB,8BACnBC,mBAAoB,+BACpBC,kBAAmB,8BACnBC,kBAAmB,8BACnBC,oBAAqB,gCACrBC,oBAAqB,iCAEzBC,MACI3C,WACI4C,MAAO,WAEXpC,SACIoC,MAAO,YAEXxC,UACIwC,MAAO,WAEXvC,YACIuC,MAAO,aAEXtC,WACIsC,MAAO,WAEXnC,iBACImC,MAAO,SAAU,eAErBd,kBACIc,MAAO,WAEXb,0BACIa,MAAO,mBAEXZ,+BACIY,MAAO,2BAEXX,6BACIW,MAAO,mBAEXV,yBACIU,MAAO,mBAEXjC,WACIiC,MAAO,cAEX9B,SACI8B,MAAO,SAAU,aACjBC,QAAS,WAEbjC,QACIgC,MAAO,SAAU,WACjBC,QAAS,UAEbV,SACIS,MAAQ,WAEZ7B,cACI6B,MAAQ,WAEZ5B,cACI4B,MAAQ,WAEZ3B,aACI2B,MAAQ,WAEZ1B,YACI0B,MAAQ,WAEZzB,SACIyB,MAAQ,UACRC,QAAS,WAEbzB,WACIwB,MAAQ,SAAU,cAEtBvB,iBACIuB,MAAQ,SAAU,cAEtBtB,gBACIsB,MAAQ,WAEZnB,uBACImB,MAAQ,cAEZlB,iBACIkB,MAAQ,WAEZjB,UACIiB,MAAQ,aAQpBE,SAAQzD,QACJC,QAASH,WAIbC,YAAYL","file":"app.js.map"}
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
2
public/js/v1.1.6/app.js
Normal file
2
public/js/v1.1.6/app.js
Normal file
@@ -0,0 +1,2 @@
|
||||
var mainScriptPath=document.body.getAttribute("data-script"),jsBaseUrl=document.body.getAttribute("data-js-path");requirejs.config({baseUrl:"js",paths:{layout:"layout",config:"app/config",dialog:"app/ui/dialog",templates:"../../templates",img:"../../img",login:"./app/login",mappage:"./app/mappage",setup:"./app/setup",jquery:"lib/jquery-3.0.0.min",bootstrap:"lib/bootstrap.min",text:"lib/requirejs/text",mustache:"lib/mustache.min",localForage:"lib/localforage.min",velocity:"lib/velocity.min",velocityUI:"lib/velocity.ui.min",slidebars:"lib/slidebars",jsPlumb:"lib/dom.jsPlumb-1.7.6",farahey:"lib/farahey-0.5",customScrollbar:"lib/jquery.mCustomScrollbar.min",mousewheel:"lib/jquery.mousewheel.min",xEditable:"lib/bootstrap-editable.min",morris:"lib/morris.min",raphael:"lib/raphael-min",bootbox:"lib/bootbox.min",easyPieChart:"lib/jquery.easypiechart.min",peityInlineChart:"lib/jquery.peity.min",dragToSelect:"lib/jquery.dragToSelect",hoverIntent:"lib/jquery.hoverIntent.minified",fullScreen:"lib/jquery.fullscreen.min",select2:"lib/select2.min",validator:"lib/validator.min",lazylinepainter:"lib/jquery.lazylinepainter-1.5.1.min",blueImpGallery:"lib/blueimp-gallery",blueImpGalleryHelper:"lib/blueimp-helper",blueImpGalleryBootstrap:"lib/bootstrap-image-gallery",bootstrapConfirmation:"lib/bootstrap-confirmation",bootstrapToggle:"lib/bootstrap2-toggle.min",lazyload:"lib/jquery.lazyload.min",easePack:"lib/EasePack.min",tweenLite:"lib/TweenLite.min","datatables.net":"lib/datatables/DataTables-1.10.12/js/jquery.dataTables.min","datatables.net-buttons":"lib/datatables/Buttons-1.2.1/js/dataTables.buttons.min","datatables.net-buttons-html":"lib/datatables/Buttons-1.2.1/js/buttons.html5.min","datatables.net-responsive":"lib/datatables/Responsive-2.1.0/js/dataTables.responsive.min","datatables.net-select":"lib/datatables/Select-1.2.0/js/dataTables.select.min",pnotify:"lib/pnotify/pnotify","pnotify.buttons":"lib/pnotify/pnotify.buttons","pnotify.confirm":"lib/pnotify/pnotify.confirm","pnotify.nonblock":"lib/pnotify/pnotify.nonblock","pnotify.desktop":"lib/pnotify/pnotify.desktop","pnotify.history":"lib/pnotify/pnotify.history","pnotify.callbacks":"lib/pnotify/pnotify.callbacks","pnotify.reference":"lib/pnotify/pnotify.reference"},shim:{bootstrap:{deps:["jquery"]},farahey:{deps:["jsPlumb"]},velocity:{deps:["jquery"]},velocityUI:{deps:["velocity"]},slidebars:{deps:["jquery"]},customScrollbar:{deps:["jquery","mousewheel"]},"datatables.net":{deps:["jquery"]},"datatables.net-buttons":{deps:["datatables.net"]},"datatables.net-buttons-html":{deps:["datatables.net-buttons"]},"datatables.net-responsive":{deps:["datatables.net"]},"datatables.net-select":{deps:["datatables.net"]},xEditable:{deps:["bootstrap"]},bootbox:{deps:["jquery","bootstrap"],exports:"bootbox"},morris:{deps:["jquery","raphael"],exports:"Morris"},pnotify:{deps:["jquery"]},easyPieChart:{deps:["jquery"]},peityInlineChart:{deps:["jquery"]},dragToSelect:{deps:["jquery"]},hoverIntent:{deps:["jquery"]},fullScreen:{deps:["jquery"]},select2:{deps:["jquery"],exports:"Select2"},validator:{deps:["jquery","bootstrap"]},lazylinepainter:{deps:["jquery","bootstrap"]},blueImpGallery:{deps:["jquery"]},bootstrapConfirmation:{deps:["bootstrap"]},bootstrapToggle:{deps:["jquery"]},lazyload:{deps:["jquery"]}}});require.config({baseUrl:jsBaseUrl});requirejs([mainScriptPath]);
|
||||
//# sourceMappingURL=app.js.map
|
||||
1
public/js/v1.1.6/app.js.map
Normal file
1
public/js/v1.1.6/app.js.map
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["app.js.src.js"],"names":["mainScriptPath","document","body","getAttribute","jsBaseUrl","requirejs","config","baseUrl","paths","layout","dialog","templates","img","login","mappage","setup","jquery","bootstrap","text","mustache","localForage","velocity","velocityUI","slidebars","jsPlumb","farahey","customScrollbar","mousewheel","xEditable","morris","raphael","bootbox","easyPieChart","peityInlineChart","dragToSelect","hoverIntent","fullScreen","select2","validator","lazylinepainter","blueImpGallery","blueImpGalleryHelper","blueImpGalleryBootstrap","bootstrapConfirmation","bootstrapToggle","lazyload","easePack","tweenLite","datatables.net","datatables.net-buttons","datatables.net-buttons-html","datatables.net-responsive","datatables.net-select","pnotify","pnotify.buttons","pnotify.confirm","pnotify.nonblock","pnotify.desktop","pnotify.history","pnotify.callbacks","pnotify.reference","shim","deps","exports","require"],"mappings":"AACA,GAAIA,gBAAiBC,SAASC,KAAKC,aAAa,eAI5CC,UAAYH,SAASC,KAAKC,aAAa,eAG3CE,WAAUC,QACNC,QAAS,KAETC,OACIC,OAAQ,SACRH,OAAQ,aACRI,OAAQ,gBACRC,UAAW,kBACXC,IAAK,YAGLC,MAAO,cACPC,QAAS,gBACTC,MAAO,cAEPC,OAAQ,uBACRC,UAAW,oBACXC,KAAM,qBACNC,SAAU,mBACVC,YAAa,sBACbC,SAAU,mBACVC,WAAY,sBACZC,UAAW,gBACXC,QAAS,wBACTC,QAAS,kBACTC,gBAAiB,kCACjBC,WAAY,4BACZC,UAAW,6BACXC,OAAQ,iBACRC,QAAS,kBACTC,QAAS,kBACTC,aAAc,8BACdC,iBAAkB,uBAClBC,aAAc,0BACdC,YAAa,kCACbC,WAAY,4BACZC,QAAS,kBACTC,UAAW,oBACXC,gBAAiB,uCACjBC,eAAgB,sBAChBC,qBAAsB,qBACtBC,wBAAyB,8BACzBC,sBAAuB,6BACvBC,gBAAiB,4BACjBC,SAAU,0BAGVC,SAAU,mBACVC,UAAW,oBAGXC,iBAAkB,6DAClBC,yBAA0B,yDAC1BC,8BAA+B,oDAC/BC,4BAA6B,+DAC7BC,wBAAyB,uDAGzBC,QAAS,sBACTC,kBAAmB,8BACnBC,kBAAmB,8BACnBC,mBAAoB,+BACpBC,kBAAmB,8BACnBC,kBAAmB,8BACnBC,oBAAqB,gCACrBC,oBAAqB,iCAEzBC,MACI5C,WACI6C,MAAO,WAEXrC,SACIqC,MAAO,YAEXzC,UACIyC,MAAO,WAEXxC,YACIwC,MAAO,aAEXvC,WACIuC,MAAO,WAEXpC,iBACIoC,MAAO,SAAU,eAErBd,kBACIc,MAAO,WAEXb,0BACIa,MAAO,mBAEXZ,+BACIY,MAAO,2BAEXX,6BACIW,MAAO,mBAEXV,yBACIU,MAAO,mBAEXlC,WACIkC,MAAO,cAEX/B,SACI+B,MAAO,SAAU,aACjBC,QAAS,WAEblC,QACIiC,MAAO,SAAU,WACjBC,QAAS,UAEbV,SACIS,MAAQ,WAEZ9B,cACI8B,MAAQ,WAEZ7B,kBACI6B,MAAQ,WAEZ5B,cACI4B,MAAQ,WAEZ3B,aACI2B,MAAQ,WAEZ1B,YACI0B,MAAQ,WAEZzB,SACIyB,MAAQ,UACRC,QAAS,WAEbzB,WACIwB,MAAQ,SAAU,cAEtBvB,iBACIuB,MAAQ,SAAU,cAEtBtB,gBACIsB,MAAQ,WAEZnB,uBACImB,MAAQ,cAEZlB,iBACIkB,MAAQ,WAEZjB,UACIiB,MAAQ,aAQpBE,SAAQ1D,QACJC,QAASH,WAIbC,YAAYL","file":"app.js.map"}
|
||||
@@ -38,9 +38,10 @@ 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/
|
||||
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.5.0 Full screen mode - https://github.com/private-face/jquery.fullscreen
|
||||
fullScreen: 'lib/jquery.fullscreen.min', // v0.6.0 Full screen mode - https://github.com/private-face/jquery.fullscreen
|
||||
select2: 'lib/select2.min', // v4.0.3 Drop Down customization - https://select2.github.io
|
||||
validator: 'lib/validator.min', // v0.10.1 Validator for Bootstrap 3 - https://github.com/1000hz/bootstrap-validator
|
||||
lazylinepainter: 'lib/jquery.lazylinepainter-1.5.1.min', // v1.5.1 SVG line animation plugin - http://lazylinepainter.info
|
||||
@@ -123,6 +124,9 @@ requirejs.config({
|
||||
easyPieChart: {
|
||||
deps : ['jquery']
|
||||
},
|
||||
peityInlineChart: {
|
||||
deps : ['jquery']
|
||||
},
|
||||
dragToSelect: {
|
||||
deps : ['jquery']
|
||||
},
|
||||
16
public/js/v1.1.6/app/login.js
Normal file
16
public/js/v1.1.6/app/login.js
Normal file
File diff suppressed because one or more lines are too long
1
public/js/v1.1.6/app/login.js.map
Normal file
1
public/js/v1.1.6/app/login.js.map
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
2
public/js/v1.1.6/app/notification.js
Normal file
2
public/js/v1.1.6/app/notification.js
Normal file
File diff suppressed because one or more lines are too long
1
public/js/v1.1.6/app/notification.js.map
Normal file
1
public/js/v1.1.6/app/notification.js.map
Normal file
File diff suppressed because one or more lines are too long
13
public/js/v1.1.6/app/setup.js
Normal file
13
public/js/v1.1.6/app/setup.js
Normal file
File diff suppressed because one or more lines are too long
1
public/js/v1.1.6/app/setup.js.map
Normal file
1
public/js/v1.1.6/app/setup.js.map
Normal file
File diff suppressed because one or more lines are too long
@@ -66,6 +66,7 @@ text!img/logo.svg!strip
|
||||
text!templates/modules/header.html
|
||||
text!templates/modules/footer.html
|
||||
app/ui/dialog/notification.js
|
||||
app/ui/dialog/stats.js
|
||||
app/map/util.js
|
||||
app/ui/dialog/map_info.js
|
||||
app/ui/dialog/account_settings.js
|
||||
2
public/js/v1.1.6/lib/jquery.fullscreen.min.js
vendored
Normal file
2
public/js/v1.1.6/lib/jquery.fullscreen.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
public/js/v1.1.6/lib/jquery.fullscreen.min.js.map
Normal file
1
public/js/v1.1.6/lib/jquery.fullscreen.min.js.map
Normal file
File diff suppressed because one or more lines are too long
28
public/js/v1.1.6/lib/jquery.fullscreen.min.js.src.js
Normal file
28
public/js/v1.1.6/lib/jquery.fullscreen.min.js.src.js
Normal file
File diff suppressed because one or more lines are too long
2
public/js/v1.1.6/lib/jquery.peity.min.js
vendored
Normal file
2
public/js/v1.1.6/lib/jquery.peity.min.js
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
!function(t,i,e,n){var r=t.fn.peity=function(i,e){l&&this.each(function(){var n=t(this),h=n.data("_peity");h?(i&&(h.type=i),t.extend(h.opts,e)):(h=new a(n,i,t.extend({},r.defaults[i],n.data("peity"),e)),n.change(function(){h.draw()}).data("_peity",h));h.draw()});return this},a=function(t,i,e){this.$el=t;this.type=i;this.opts=e},h=a.prototype,s=h.svgElement=function(e,n){return t(i.createElementNS("http://www.w3.org/2000/svg",e)).attr(n)},l="createElementNS"in i&&s("svg",{})[0].createSVGRect;h.draw=function(){var t=this.opts;r.graphers[this.type].call(this,t);t.after&&t.after.call(this,t)};h.fill=function(){var i=this.opts.fill;return t.isFunction(i)?i:function(t,e){return i[e%i.length]}};h.prepare=function(t,i){this.$svg||this.$el.hide().after(this.$svg=s("svg",{"class":"peity"}));return this.$svg.empty().data("peity",this).attr({height:i,width:t})};h.values=function(){return t.map(this.$el.text().split(this.opts.delimiter),function(t){return parseFloat(t)})};r.defaults={};r.graphers={};r.register=function(t,i,e){this.defaults[t]=i;this.graphers[t]=e};r.register("pie",{fill:["#ff9900","#fff4dd","#ffc66e"],radius:8},function(i){if(!i.delimiter){var n=this.$el.text().match(/[^0-9\.]/);i.delimiter=n?n[0]:","}n=t.map(this.values(),function(t){return t>0?t:0});if("/"==i.delimiter)var r=n[0],n=[r,e.max(0,n[1]-r)];for(var a=0,r=n.length,h=0;r>a;a++)h+=n[a];h||(r=2,h=1,n=[0,1]);var l=2*i.radius,l=this.prepare(i.width||l,i.height||l),a=l.width(),p=l.height(),o=a/2,f=p/2,p=e.min(o,f),i=i.innerRadius;"donut"==this.type&&!i&&(i=.5*p);for(var c=e.PI,u=this.fill(),d=this.scale=function(t,i){var n=t/h*c*2-c/2;return[i*e.cos(n)+o,i*e.sin(n)+f]},g=0,a=0;r>a;a++){var m=n[a],v=m/h;if(0!=v){if(1==v)if(i)var v=o-.01,y=f-p,w=f-i,v=s("path",{d:["M",o,y,"A",p,p,0,1,1,v,y,"L",v,w,"A",i,i,0,1,0,o,w].join(" ")});else v=s("circle",{cx:o,cy:f,r:p});else y=g+m,w=["M"].concat(d(g,p),"A",p,p,0,v>.5?1:0,1,d(y,p),"L"),i?w=w.concat(d(y,i),"A",i,i,0,v>.5?1:0,0,d(g,i)):w.push(o,f),g+=m,v=s("path",{d:w.join(" ")});v.attr("fill",u.call(this,m,a,n));l.append(v)}}});r.register("donut",t.extend(!0,{},r.defaults.pie),function(t){r.graphers.pie.call(this,t)});r.register("line",{delimiter:",",fill:"#c6d9fd",height:16,min:0,stroke:"#4d89f9",strokeWidth:1,width:32},function(t){var i=this.values();1==i.length&&i.push(i[0]);for(var r=e.max.apply(e,t.max==n?i:i.concat(t.max)),a=e.min.apply(e,t.min==n?i:i.concat(t.min)),h=this.prepare(t.width,t.height),l=t.strokeWidth,p=h.width(),o=h.height()-l,f=r-a,r=this.x=function(t){return t*(p/(i.length-1))},c=this.y=function(t){var i=o;f&&(i-=(t-a)/f*o);return i+l/2},u=c(e.max(a,0)),d=[0,u],g=0;g<i.length;g++)d.push(r(g),c(i[g]));d.push(p,u);t.fill&&h.append(s("polygon",{fill:t.fill,points:d.join(" ")}));l&&h.append(s("polyline",{fill:"none",points:d.slice(2,d.length-2).join(" "),stroke:t.stroke,"stroke-width":l,"stroke-linecap":"square"}))});r.register("bar",{delimiter:",",fill:["#4D89F9"],height:16,min:0,padding:.1,width:32},function(t){for(var i=this.values(),r=e.max.apply(e,t.max==n?i:i.concat(t.max)),a=e.min.apply(e,t.min==n?i:i.concat(t.min)),h=this.prepare(t.width,t.height),l=h.width(),p=h.height(),o=r-a,t=t.padding,f=this.fill(),c=this.x=function(t){return t*l/i.length},u=this.y=function(t){return p-(o?(t-a)/o*p:1)},d=0;d<i.length;d++){var g,m=c(d+t),v=c(d+1-t)-m,y=i[d],w=u(y),x=w;o?0>y?x=u(e.min(r,0)):w=u(e.max(a,0)):g=1;g=w-x;0==g&&(g=1,r>0&&o&&x--);h.append(s("rect",{fill:f.call(this,y,d,i),x:m,y:x,width:v,height:g}))}})}(jQuery,document,Math);
|
||||
//# sourceMappingURL=jquery.peity.min.js.map
|
||||
1
public/js/v1.1.6/lib/jquery.peity.min.js.map
Normal file
1
public/js/v1.1.6/lib/jquery.peity.min.js.map
Normal file
File diff suppressed because one or more lines are too long
13
public/js/v1.1.6/lib/jquery.peity.min.js.src.js
Normal file
13
public/js/v1.1.6/lib/jquery.peity.min.js.src.js
Normal file
@@ -0,0 +1,13 @@
|
||||
// Peity jQuery plugin version 3.2.0
|
||||
// (c) 2015 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==
|
||||
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);
|
||||
@@ -58,7 +58,7 @@
|
||||
<li><i class="fa fa-plus fa-fw"></i> Add a new system at the position, you clicked at</li>
|
||||
<li><i class="fa fa-object-ungroup fa-fw"></i> Select all (unlocked) systems on the map</li>
|
||||
<li><i class="fa fa-filter fa-fw"></i> Filter map connections by a scope <small><a href="#" data-target="#pf-manual-scrollspy-anchor-connection-scope">more</a></small></li>
|
||||
<li><i class="fa fa-eraser fa-fw"></i> Delete selected systems <small><a href="#" data-target="#pf-manual-scrollspy-anchor-system-delete">more</a></small></li>
|
||||
<li><i class="fa fa-trash fa-fw"></i> Delete selected systems <small><a href="#" data-target="#pf-manual-scrollspy-anchor-system-delete">more</a></small></li>
|
||||
</ul>
|
||||
<h4 id="pf-manual-scrollspy-anchor-map-select"><i class="fa fa-object-ungroup fa-fw"></i> Select methods</h4>
|
||||
<ul class="list-unstyled" style=" margin-left: 10px;">
|
||||
@@ -98,7 +98,7 @@
|
||||
|
||||
<p>
|
||||
Systems are represented by rectangle boxes on a map <small>(<i class="fa fa-code-fork fa-fw"></i><a href="#" data-target="#pf-manual-map">more</a>)</small>.
|
||||
Pilots can interact with systems like "delete systems" <small>(<i class="fa fa-eraser fa-fw"></i><a href="#" data-target="#pf-manual-scrollspy-anchor-system-delete">more</a>)</small> or
|
||||
Pilots can interact with systems like "delete systems" <small>(<i class="fa fa-trash fa-fw"></i><a href="#" data-target="#pf-manual-scrollspy-anchor-system-delete">more</a>)</small> or
|
||||
"move systems" <small>(<i class="fa fa-arrows-alt fa-fw"></i><a href="#" data-target="#pf-manual-scrollspy-anchor-system-move">more</a>)</small>.
|
||||
</p>
|
||||
<h4 id="pf-manual-scrollspy-anchor-system-active">Active system</h4>
|
||||
@@ -176,13 +176,13 @@
|
||||
<li><i class="fa fa-users fa-fw"></i> Set "Rally Point" for this system <small><a href="#" data-target="#pf-manual-scrollspy-anchor-system-rally">more</a></small></li>
|
||||
<li><i class="fa fa-tags fa-fw"></i> Changes the status of this system <small><a href="#" data-target="#pf-manual-scrollspy-anchor-system-status">more</a></small></li>
|
||||
<li><i class="fa fa-reply fa-rotate-180 fa-fw"></i> Waypoint options for this system <small><a href="#" data-target="#pf-manual-scrollspy-anchor-system-waypoint">more</a></small></li>
|
||||
<li><i class="fa fa-eraser fa-fw"></i> Delete this system and all connections <small><a href="#" data-target="#pf-manual-scrollspy-anchor-system-delete">more</a></small></li>
|
||||
<li><i class="fa fa-trash fa-fw"></i> Delete this system and all connections <small><a href="#" data-target="#pf-manual-scrollspy-anchor-system-delete">more</a></small></li>
|
||||
</ul>
|
||||
<h4 id="pf-manual-scrollspy-anchor-system-locked"><i class="fa fa-lock fa-fw"></i> Locked system</h4>
|
||||
<p>
|
||||
Locked systems can´t be selected <small>(<a href="#" data-target="#pf-manual-scrollspy-anchor-map-select">more</a>)</small>,
|
||||
moved <small>(<i class="fa fa-arrows-alt fa-fw"></i><a href="#" data-target="#pf-manual-scrollspy-anchor-system-move">more</a>)</small>
|
||||
or deleted <small>(<i class="fa fa-eraser fa-fw"></i><a href="#" data-target="#pf-manual-scrollspy-anchor-system-delete">more</a>)</small>.
|
||||
or deleted <small>(<i class="fa fa-trash fa-fw"></i><a href="#" data-target="#pf-manual-scrollspy-anchor-system-delete">more</a>)</small>.
|
||||
</p>
|
||||
<h4 id="pf-manual-scrollspy-anchor-system-rally"><i class="fa fa-users fa-fw"></i> Rally point</h4>
|
||||
<p>
|
||||
@@ -199,7 +199,7 @@
|
||||
<li>add new [start] -<small> (add new waypoint in front of your waypoint queue)</small></li>
|
||||
<li>add new [end] -<small> (add new waypoint to the end of your waypoint queue)</small></li>
|
||||
</ul>
|
||||
<h4 id="pf-manual-scrollspy-anchor-system-delete"><i class="fa fa-eraser fa-fw"></i> Delete system</h4>
|
||||
<h4 id="pf-manual-scrollspy-anchor-system-delete"><i class="fa fa-trash fa-fw"></i> Delete system</h4>
|
||||
<p>
|
||||
Any system that is not "Locked" <small>(<i class="fa fa-lock fa-fw"></i><a href="#" data-target="#pf-manual-scrollspy-anchor-system-locked">more</a>)</small> can be deleted from a map.
|
||||
</p>
|
||||
@@ -263,7 +263,7 @@
|
||||
<li><i class="fa fa-warning fa-fw"></i> Toggles this connection as <em>"Preserve Mass"</em> <small><a href="#" data-target="#pf-manual-scrollspy-anchor-connection-mass">more</a></small></li>
|
||||
<li><i class="fa fa-crosshairs fa-fw"></i> Changes the scope of this connection <small><a href="#" data-target="#pf-manual-scrollspy-anchor-connection-scope">more</a></small></li>
|
||||
<li><i class="fa fa-reply fa-rotate-180 fa-fw"></i> Changes the status of this connection <small><a href="#" data-target="#pf-manual-scrollspy-anchor-connection-status">more</a></small></li>
|
||||
<li><i class="fa fa-eraser fa-fw"></i> Delete this connection <small><a href="#" data-target="#pf-manual-scrollspy-anchor-connection-delete">more</a></small></li>
|
||||
<li><i class="fa fa-trash fa-fw"></i> Delete this connection <small><a href="#" data-target="#pf-manual-scrollspy-anchor-connection-delete">more</a></small></li>
|
||||
</ul>
|
||||
<h4 id="pf-manual-scrollspy-anchor-connection-frig"><i class="fa fa-plane fa-fw"></i> Frigate hole</h4>
|
||||
<p>
|
||||
@@ -276,7 +276,7 @@
|
||||
Let your mates know about critical connections that should be mass-saved
|
||||
(e.g. <span class="pf-system-sec-highSec">H</span> security exits) <small>(<a href="#" data-target="#pf-manual-scrollspy-anchor-system-security">more</a>)</small>.
|
||||
</p>
|
||||
<h4 id="pf-manual-scrollspy-anchor-connection-delete"><i class="fa fa-eraser fa-fw"></i> Delete connection</h4>
|
||||
<h4 id="pf-manual-scrollspy-anchor-connection-delete"><i class="fa fa-trash fa-fw"></i> Delete connection</h4>
|
||||
<p>
|
||||
Connections can be detached by several ways.
|
||||
</p>
|
||||
@@ -322,7 +322,7 @@
|
||||
<kbd>click</kbd> the browser tab were <em class="pf-brand">pathfinder</em> is open. Then press <kbd>ctrl</kbd> + <kbd>v</kbd>.<br>
|
||||
<em class="pf-brand">pathfinder</em> automatically detect the data format and updates the <em>"Signature table"</em>.
|
||||
</p>
|
||||
<h4><i class="fa fa-eraser fa-fw"></i> Delete signatures</h4>
|
||||
<h4><i class="fa fa-trash fa-fw"></i> Delete signatures</h4>
|
||||
<p>
|
||||
Signatures can be detached by several ways.
|
||||
</p>
|
||||
|
||||
@@ -88,7 +88,7 @@
|
||||
<div class="col-sm-offset-1 col-sm-11">
|
||||
<div class="col-sm-12 col-xs-6 checkbox checkbox-warning checkbox-circle" title="include reduced connections">
|
||||
<input id="form_wormholes_reduced" name="wormholesReduced" value="1" type="checkbox" checked>
|
||||
<label for="form_wormholes_reduced">Stage 1 (reduced)</label>
|
||||
<label for="form_wormholes_reduced">Stage 2 (reduced)</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -99,7 +99,7 @@
|
||||
<div class="col-sm-offset-1 col-sm-11">
|
||||
<div class="col-sm-12 col-xs-6 checkbox checkbox-danger checkbox-circle" title="include critical connections">
|
||||
<input id="form_wormholes_critical" name="wormholesCritical" value="1" type="checkbox" checked>
|
||||
<label for="form_wormholes_critical">Stage 2 (critical)</label>
|
||||
<label for="form_wormholes_critical">Stage 3 (critical)</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
117
public/templates/dialog/stats.html
Normal file
117
public/templates/dialog/stats.html
Normal file
@@ -0,0 +1,117 @@
|
||||
<div id="{{id}}">
|
||||
<nav class="navbar navbar-default" role="navigation">
|
||||
<div class="navbar-header pull-left">
|
||||
<ul class="nav navbar-nav {{dialogNavigationClass}}">
|
||||
<li class="{{dialogNavLiClass}} {{^enablePrivateTab}} disabled {{/enablePrivateTab}}">
|
||||
<a role="tab" data-toggle="tab" data-type="typeId" data-value="2" href="#{{statsContainerId}}">Private</a>
|
||||
</li>
|
||||
<li class="{{dialogNavLiClass}} active {{^enableCorporationTab}} disabled {{/enableCorporationTab}}">
|
||||
<a role="tab" data-toggle="tab" data-type="typeId" data-value="3" href="#{{statsContainerId}}">Corporation</a>
|
||||
</li>
|
||||
<li class="{{dialogNavLiClass}} {{^enableAllianceTab}} disabled {{/enableAllianceTab}}">
|
||||
<a role="tab" data-toggle="tab" data-type="typeId" data-value="4" href="#{{statsContainerId}}">Alliance</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="navbar-header pull-right">
|
||||
<p class="navbar-text">
|
||||
<i class="fa fa-filter fa-fw fa-lg"></i>
|
||||
</p>
|
||||
<ul class="nav navbar-nav {{dialogNavigationClass}}">
|
||||
<li class="{{dialogNavLiClass}}">
|
||||
<a role="tab" data-toggle="tab" data-type="period" data-value="weekly" href="#{{statsContainerId}}">Weekly</a>
|
||||
</li>
|
||||
<li class="{{dialogNavLiClass}} active">
|
||||
<a role="tab" data-toggle="tab" data-type="period" data-value="monthly" href="#{{statsContainerId}}">Monthly</a>
|
||||
</li>
|
||||
<li class="{{dialogNavLiClass}}">
|
||||
<a role="tab" data-toggle="tab" data-type="period" data-value="yearly" href="#{{statsContainerId}}">Yearly</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="alert alert-info fade in hidden-md hidden-lg">
|
||||
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><i class="fa fa-close"></i></button>
|
||||
<span class="txt-color txt-color-information">Info</span>
|
||||
<small> Your browser window is to small. Resize it to obtain more columns.</small>
|
||||
</div>
|
||||
|
||||
<div class="tab-content">
|
||||
<div role="tabpanel" class="tab-pane fade in active" id="{{statsContainerId}}">
|
||||
|
||||
<h5 class="text-center">
|
||||
{{! previous button }}
|
||||
<span class="pull-left pf-dialog-icon-button collapsed {{dialogNavigationPrevClass}}" style="visibility: hidden; min-width: 120px">
|
||||
<i class="fa fa-fw fa-arrow-left"></i>
|
||||
<span> </span>
|
||||
</span>
|
||||
|
||||
{{! offset label }}
|
||||
<span class="{{dialogNavigationOffsetClass}}"> </span>
|
||||
|
||||
{{! next button }}
|
||||
<span class="pull-right pf-dialog-icon-button collapsed {{dialogNavigationNextClass}}" style="visibility: hidden; min-width: 120px">
|
||||
<span> </span>
|
||||
<i class="fa fa-fw fa-arrow-right"></i>
|
||||
</span>
|
||||
</h5>
|
||||
|
||||
<div class="pf-dynamic-area">
|
||||
<table class="compact stripe order-column row-border nowrap" id="{{statsTableId}}">
|
||||
<thead>
|
||||
<tr>
|
||||
<th colspan="4" class="separator-right">character</th>
|
||||
<th colspan="4" class="separator-right hidden-xs hidden-sm">systems</th>
|
||||
<th colspan="4" class="separator-right hidden-xs hidden-sm">connection</th>
|
||||
<th colspan="4" class="separator-right hidden-xs hidden-sm">signatures</th>
|
||||
<th class="text-right">sum</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th></th>
|
||||
<th></th>
|
||||
<th></th>
|
||||
<th></th>
|
||||
<th></th>
|
||||
<th></th>
|
||||
<th></th>
|
||||
<th></th>
|
||||
<th></th>
|
||||
<th></th>
|
||||
<th></th>
|
||||
<th></th>
|
||||
<th></th>
|
||||
<th></th>
|
||||
<th></th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th></th>
|
||||
<th></th>
|
||||
<th></th>
|
||||
<th></th>
|
||||
<th></th>
|
||||
<th></th>
|
||||
<th class="bg-color bg-color-grayDarker"></th>
|
||||
<th></th>
|
||||
<th></th>
|
||||
<th></th>
|
||||
<th class="bg-color bg-color-grayDarker"></th>
|
||||
<th></th>
|
||||
<th></th>
|
||||
<th></th>
|
||||
<th class="bg-color bg-color-grayDarker"></th>
|
||||
<th class="bg-color bg-color-tealDarker txt-color txt-color-orange"></th>
|
||||
</tr>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,17 +1,24 @@
|
||||
{* Login notice information *}
|
||||
<div class="row text-center">
|
||||
<div class="col-xs-12 col-md-8 col-md-offset-2 pf-landing-pricing-panel">
|
||||
<div class="panel panel-primary pricing-big">
|
||||
<div class="panel-heading" >
|
||||
<h3 class="panel-title">Release v1.1.5</h3>
|
||||
<h3 class="panel-title">New release v1.1.6</h3>
|
||||
</div>
|
||||
<div class="panel-body no-padding text-align-center">
|
||||
<div class="price-features" style="min-height: inherit;">
|
||||
<ul class="list-unstyled text-left">
|
||||
<li><i class="fa fa-fw fa-angle-right"></i>New: Support for multiple active characters</li>
|
||||
<li><i class="fa fa-fw fa-angle-right"></i>New: Customizable default routes</li>
|
||||
<li><i class="fa fa-fw fa-angle-right"></i>New: Filter option for "<em>EOL</em>" connections added to route finder</li>
|
||||
|
||||
<li><i class="fa fa-fw fa-angle-right"></i>New: "<em><a target="_self" href="#pf-landing-feature-user-statistics">User Statistics</a></em>" module</li>
|
||||
<li>
|
||||
<ul class="list-unstyled text-left">
|
||||
<li><i class="fa fa-fw fa-angle-right"></i>'private', 'corporation', 'alliance' - statistics</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><i class="fa fa-fw fa-angle-right"></i>New: "<em>Activity Log</em>" history</li>
|
||||
<li>
|
||||
<ul class="list-unstyled text-left">
|
||||
<li><i class="fa fa-fw fa-angle-right"></i>'weekly', 'monthly', 'yearly' - filters</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><i class="fa fa-fw fa-angle-double-right"></i>Complete <a href="javascript:void(0)" class="pf-navbar-version-info">changelog</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@@ -137,8 +137,8 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{* splash page *}
|
||||
<include href="templates/ui/notice.html"/>
|
||||
{* splash page -> shown by Javascript *}
|
||||
<div id="pf-notification-panel"></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -186,7 +186,7 @@
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-9 col-lg-4">
|
||||
<h4><i class="fa fa-fw fa-angle-double-right"></i>Pathfinder</h4>
|
||||
<h4>Pathfinder</h4>
|
||||
<ul class="fa-ul pf-landing-list">
|
||||
<li><i></i><span class="txt-color txt-color-greenDark"><e class="fa fa-fw fa-lock"></e>SSL</span> encrypted connection</li>
|
||||
<li><i></i>User friendly <a class="pf-navbar-manual" href="#">manual</a></li>
|
||||
@@ -250,7 +250,7 @@
|
||||
</div>
|
||||
|
||||
<div class="col-xs-12 col-sm-9 col-lg-4">
|
||||
<h4><i class="fa fa-fw fa-angle-double-right"></i>Map module</h4>
|
||||
<h4>Map module</h4>
|
||||
<ul class="fa-ul pf-landing-list">
|
||||
<li><i></i>Live synchronisation between clients</li>
|
||||
<li><i></i>Multiple map support</li>
|
||||
@@ -329,7 +329,7 @@
|
||||
</div>
|
||||
|
||||
<div class="col-xs-12 col-sm-9 col-lg-4">
|
||||
<h4><i class="fa fa-fw fa-angle-double-right"></i>System module</h4>
|
||||
<h4>System module</h4>
|
||||
<ul class="fa-ul pf-landing-list">
|
||||
<li><i></i>Quick access to all relevant information</li>
|
||||
<li>
|
||||
@@ -368,7 +368,7 @@
|
||||
</div>
|
||||
|
||||
<div class="col-xs-12 col-sm-9 col-lg-4">
|
||||
<h4><i class="fa fa-fw fa-angle-double-right"></i>Signature module</h4>
|
||||
<h4>Signature module</h4>
|
||||
<ul class="fa-ul pf-landing-list">
|
||||
<li><i></i>Share system signature information</li>
|
||||
<li><i></i>Add/Update multiple signatures at once <kbd>ctrl</kbd> + <kbd>c</kbd></li>
|
||||
@@ -407,7 +407,7 @@
|
||||
</div>
|
||||
|
||||
<div class="col-xs-12 col-sm-9 col-lg-4">
|
||||
<h4><i class="fa fa-fw fa-angle-double-right"></i>Killboard module</h4>
|
||||
<h4>Killboard module</h4>
|
||||
<ul class="fa-ul pf-landing-list">
|
||||
<li><i></i><em><a target="_blank" href="https://github.com/zKillboard/zKillboard/wiki">zkillboard.com</a></em> API integration</li>
|
||||
<li><i></i>Detailed information about all recent activities in a system</li>
|
||||
@@ -440,7 +440,7 @@
|
||||
</div>
|
||||
|
||||
<div class="col-xs-12 col-sm-9 col-lg-4">
|
||||
<h4><i class="fa fa-fw fa-angle-double-right"></i>Route module</h4>
|
||||
<h4>Route module</h4>
|
||||
<ul class="fa-ul pf-landing-list">
|
||||
<li><i></i>Search for routes between systems</li>
|
||||
<li><i></i>Predefined trade hub routes</li>
|
||||
@@ -477,19 +477,20 @@
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
|
||||
<div class="col-xs-12 col-sm-3 col-lg-2">
|
||||
<a class="pf-animate-on-visible pf-animate" href="public/img/landing/statistics_1.jpg" data-description="Statistics" data-gallery="#pf-gallery">
|
||||
<img class="pf-landing-image-preview pf-landing-image-preview-small" data-original="public/img/landing/thumbs/statistics_1.jpg" width="160" height="160" alt="Statistics">
|
||||
<a class="pf-animate-on-visible pf-animate" href="public/img/landing/statistics_1.jpg" data-description="System statistics" data-gallery="#pf-gallery">
|
||||
<img class="pf-landing-image-preview pf-landing-image-preview-small" data-original="public/img/landing/thumbs/statistics_1.jpg" width="160" height="160" alt="System statistics">
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="col-xs-12 col-sm-9 col-lg-4">
|
||||
<h4><i class="fa fa-fw fa-angle-double-right"></i>Statistics module</h4>
|
||||
<h4>System statistics module</h4>
|
||||
<ul class="fa-ul pf-landing-list">
|
||||
<li><i></i>Integrated live data for all systems</li>
|
||||
<li><i></i>Live in-game system data</li>
|
||||
<li>
|
||||
<ul class="fa-ul">
|
||||
<li><i></i>System jumps</li>
|
||||
<li><i></i>System jump data</li>
|
||||
<li><i></i>Ship/POD kills</li>
|
||||
<li><i></i>NPC kills</li>
|
||||
</ul>
|
||||
@@ -497,9 +498,36 @@
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="clearfix visible-xs visible-sm visible-md"></div>
|
||||
|
||||
<div class="col-xs-12 col-sm-3 col-lg-2" id="pf-landing-feature-user-statistics">
|
||||
<a class="pf-animate-on-visible pf-animate" href="public/img/landing/statistics_2.jpg" data-description="User statistics" data-gallery="#pf-gallery">
|
||||
<img class="pf-landing-image-preview pf-landing-image-preview-small" data-original="public/img/landing/thumbs/statistics_2.jpg" width="160" height="160" alt="User statistics">
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="col-xs-12 col-sm-9 col-lg-4">
|
||||
<h4>User statistics <span class="label label-success">new</span> </h4>
|
||||
<ul class="fa-ul pf-landing-list">
|
||||
<li><i></i>User activity logging</li>
|
||||
<li>
|
||||
<ul class="fa-ul">
|
||||
<li><i></i>Private statistics</li>
|
||||
<li><i></i>Corporation statistics</li>
|
||||
<li><i></i>Alliance statistics</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><i></i>Log history</li>
|
||||
<li>
|
||||
<ul class="fa-ul">
|
||||
<li><i></i>Weekly</li>
|
||||
<li><i></i>Monthly</li>
|
||||
<li><i></i>Yearly</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="row text-center hidden-xs">
|
||||
@@ -634,7 +662,7 @@
|
||||
</div>
|
||||
|
||||
<div class="col-xs-12 col-sm-9 col-lg-4">
|
||||
<h4><i class="fa fa-fw fa-server"></i>Requirements check</h4>
|
||||
<h4><i class="fa fa-fw fa-server"></i> Requirements check</h4>
|
||||
<ul class="fa-ul pf-landing-list">
|
||||
<li><i></i>Checks your server type/status</li>
|
||||
<li><i></i>Checks your installed PHP version</li>
|
||||
@@ -656,7 +684,7 @@
|
||||
</div>
|
||||
|
||||
<div class="col-xs-12 col-sm-9 col-lg-4">
|
||||
<h4><i class="fa fa-fw fa-database"></i>Database setup</h4>
|
||||
<h4><i class="fa fa-fw fa-database"></i> Database setup</h4>
|
||||
<ul class="fa-ul pf-landing-list">
|
||||
<li><i></i>Check DB connections</li>
|
||||
<li><i></i>Check DB version</li>
|
||||
@@ -692,7 +720,7 @@
|
||||
|
||||
<div class="row">
|
||||
<div class="col-xs-12 col-sm-6 col-md-6 col-lg-6 col-sm-offset-1 col-md-offset-1 col-lg-offset-1">
|
||||
<h4><i class="fa fa-fw fa-angle-double-right"></i>About Me</h4>
|
||||
<h4>About Me</h4>
|
||||
<p>
|
||||
I am playing <em><a target="_blank" href="https://www.eveonline.com/">EVE Online</a></em> since almost 4 years.
|
||||
The majority of time (3+ years), my characters were a part of the <em><a target="_blank" href="https://www.themittani.com/news/j150020-three-alliances-enter-none-leave">"No Holes Barred"</a></em> alliance.
|
||||
@@ -728,7 +756,7 @@
|
||||
</div>
|
||||
|
||||
<div class="col-xs-12 col-sm-6 col-md-6 col-lg-6">
|
||||
<h4><i class="fa fa-fw fa-angle-double-right"></i>Technology stack</h4>
|
||||
<h4>Technology stack</h4>
|
||||
<p>
|
||||
If you are planning to get deeper into the project or even think about hosting it on your own webserver, you should be aware of some important key points.
|
||||
<em>Pathfinder</em> is not comparable with any "out of the box" web applications or common CMS systems that come along with an auto-install feature.
|
||||
|
||||
@@ -157,7 +157,7 @@
|
||||
<div class="panel-body no-padding text-align-center">
|
||||
|
||||
<table class="table">
|
||||
<tbody>
|
||||
<thead>
|
||||
<repeat group="{{ @serverInformation }}" value="{{ @information }}">
|
||||
<tr>
|
||||
<td>{{@information.label}}</td>
|
||||
@@ -165,7 +165,7 @@
|
||||
</tr>
|
||||
</repeat>
|
||||
|
||||
</tbody>
|
||||
</thead>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
@@ -235,7 +235,7 @@
|
||||
|
||||
<div class="panel-body no-padding text-align-center">
|
||||
<table class="table">
|
||||
<tbody>
|
||||
<thead>
|
||||
<repeat group="{{ @environmentInformation }}" value="{{ @environmentData }}">
|
||||
<tr>
|
||||
<td>{{@environmentData.label}}</td>
|
||||
@@ -251,7 +251,7 @@
|
||||
</td>
|
||||
</tr>
|
||||
</repeat>
|
||||
</tbody>
|
||||
</thead>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
@@ -264,11 +264,36 @@
|
||||
<div class="panel panel-default pricing-big">
|
||||
|
||||
<div class="panel-heading text-left">
|
||||
<h3 class="panel-title">Map restrictions</h3>
|
||||
<h3 class="panel-title">Registration</h3>
|
||||
</div>
|
||||
|
||||
<div class="panel-body no-padding text-align-center">
|
||||
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<td>Status</td>
|
||||
<td class="text-right col-md-2">
|
||||
<check if="{{ @PATHFINDER.REGISTRATION.STATUS }}">
|
||||
<true>
|
||||
<kbd class="txt-color txt-color-success">enabled</kbd>
|
||||
</true>
|
||||
<false>
|
||||
<kbd class="txt-color txt-color-warning">disabled</kbd>
|
||||
</false>
|
||||
</check>
|
||||
</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<div class="panel-footer text-left">
|
||||
<h3 class="panel-title">Map restrictions</h3>
|
||||
</div>
|
||||
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
@@ -295,17 +320,17 @@
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<td>Max. shared users (private map)</td>
|
||||
<td>Max. shared users (private maps)</td>
|
||||
<td class="text-right col-md-2"><kbd>{{ @PATHFINDER.MAP.PRIVATE.MAX_SHARED }}</kbd></td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Max. shared users (corporation map)</td>
|
||||
<td>Max. shared users (corporation maps)</td>
|
||||
<td class="text-right"><kbd>{{ @PATHFINDER.MAP.CORPORATION.MAX_SHARED }}</kbd></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Max. shared users (alliance map)</td>
|
||||
<td>Max. shared users (alliance maps)</td>
|
||||
<td class="text-right"><kbd>{{ @PATHFINDER.MAP.ALLIANCE.MAX_SHARED }}</kbd></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
@@ -318,32 +343,60 @@
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<td>Private map</td>
|
||||
<td>Private maps</td>
|
||||
<td class="text-right col-md-2"><kbd>{{ @PATHFINDER.MAP.PRIVATE.LIFETIME }}</kbd></td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Corporation map</td>
|
||||
<td>Corporation maps</td>
|
||||
<td class="text-right"><kbd>{{ @PATHFINDER.MAP.CORPORATION.LIFETIME }}</kbd></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Alliance map</td>
|
||||
<td>Alliance maps</td>
|
||||
<td class="text-right"><kbd>{{ @PATHFINDER.MAP.ALLIANCE.LIFETIME }}</kbd></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<div class="panel-footer text-left">
|
||||
<h3 class="panel-title">Registration</h3>
|
||||
<h3 class="panel-title">User activity logging</h3>
|
||||
</div>
|
||||
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<td>Status</td>
|
||||
<td>Private maps</td>
|
||||
<td class="text-right col-md-2">
|
||||
<check if="{{ @PATHFINDER.REGISTRATION.STATUS }}">
|
||||
<check if="{{ @PATHFINDER.MAP.PRIVATE.ACTIVITY_LOGGING }}">
|
||||
<true>
|
||||
<kbd class="txt-color txt-color-success">enabled</kbd>
|
||||
</true>
|
||||
<false>
|
||||
<kbd class="txt-color txt-color-warning">disabled</kbd>
|
||||
</false>
|
||||
</check>
|
||||
</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Corporation maps</td>
|
||||
<td class="text-right">
|
||||
<check if="{{ @PATHFINDER.MAP.CORPORATION.ACTIVITY_LOGGING }}">
|
||||
<true>
|
||||
<kbd class="txt-color txt-color-success">enabled</kbd>
|
||||
</true>
|
||||
<false>
|
||||
<kbd class="txt-color txt-color-warning">disabled</kbd>
|
||||
</false>
|
||||
</check>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Alliance maps</td>
|
||||
<td class="text-right">
|
||||
<check if="{{ @PATHFINDER.MAP.ALLIANCE.ACTIVITY_LOGGING }}">
|
||||
<true>
|
||||
<kbd class="txt-color txt-color-success">enabled</kbd>
|
||||
</true>
|
||||
@@ -353,13 +406,9 @@
|
||||
</check>
|
||||
</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
&.txt-color-redDarker { color: $red-darker !important; }
|
||||
&.txt-color-yellow { color: $yellow !important; }
|
||||
&.txt-color-orange { color: $orange !important; }
|
||||
&.txt-color-orangeDark { color: $orangeDark !important; }
|
||||
&.txt-color-orangeDark { color: $orange-dark !important; }
|
||||
&.txt-color-pink { color: $pink !important; }
|
||||
&.txt-color-pinkDark { color: $pinkDark !important; }
|
||||
&.txt-color-purple { color: $purple !important; }
|
||||
@@ -58,7 +58,9 @@
|
||||
&.bg-color-darken { background-color: $darken !important; }
|
||||
&.bg-color-lighten { background-color: $lighten !important; }
|
||||
&.bg-color-white { background-color: $white !important; }
|
||||
&.bg-color-gray { background-color: $gray !important; }
|
||||
&.bg-color-grayDark { background-color: $greyDark !important; }
|
||||
&.bg-color-grayDarker { background-color: $gray-darker !important; }
|
||||
&.bg-color-magenta { background-color: $magenta !important; }
|
||||
&.bg-color-tealLighter { background-color: $teal-lighter !important; }
|
||||
&.bg-color-tealDarker { background-color: $teal-darker !important; }
|
||||
|
||||
@@ -551,7 +551,7 @@ $modal-backdrop-opacity: .3;
|
||||
$modal-header-border-color: #e5e5e5;
|
||||
$modal-footer-border-color: $modal-header-border-color;
|
||||
|
||||
$modal-lg: 820px;
|
||||
$modal-lg: 1100px;
|
||||
$modal-md: 600px;
|
||||
$modal-sm: 300px;
|
||||
|
||||
|
||||
@@ -405,6 +405,10 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#pf-notification-panel{
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
// demo map -------------------------------------------------------------------
|
||||
|
||||
@@ -6,6 +6,7 @@ body{
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.pf-body{
|
||||
@@ -111,7 +112,7 @@ em{
|
||||
@include transition(color 0.15s ease-out);
|
||||
|
||||
&:hover{
|
||||
color: $orange;
|
||||
color: $orange !important;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -196,6 +197,7 @@ select:active, select:hover {
|
||||
|
||||
img{
|
||||
width: 26px; // smaller image (default 32)
|
||||
box-sizing: content-box;
|
||||
border-left: 1px solid $gray;
|
||||
border-right: 1px solid $gray;
|
||||
}
|
||||
@@ -227,6 +229,18 @@ select:active, select:hover {
|
||||
}
|
||||
}
|
||||
|
||||
// column separator
|
||||
td, th{
|
||||
&.separator-right{
|
||||
border-right: 1px solid $gray;
|
||||
}
|
||||
|
||||
svg.peity{
|
||||
// center vertical in column
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// table styles ===================================================================================
|
||||
@@ -293,7 +307,7 @@ table{
|
||||
|
||||
// navbar li =====================================================================================
|
||||
.navbar-nav {
|
||||
li{
|
||||
li:not(.disabled){
|
||||
&:hover, &.active{
|
||||
|
||||
&:before{
|
||||
|
||||
@@ -239,6 +239,8 @@ $mapWidth: 2500px ;
|
||||
.pf-system-body-item{
|
||||
color: lighten($gray-light, 10%);
|
||||
font-size: 10px;
|
||||
line-height: 16px;
|
||||
height: 16px;
|
||||
|
||||
.pf-system-body-right{
|
||||
text-overflow: ellipsis;
|
||||
@@ -250,13 +252,14 @@ $mapWidth: 2500px ;
|
||||
.pf-user-status{
|
||||
font-size: 7px;
|
||||
width: 10px;
|
||||
vertical-align: middle;
|
||||
height: 14px;
|
||||
}
|
||||
|
||||
.pf-system-body-item-name{
|
||||
display: inline-block;
|
||||
width: 65px;
|
||||
overflow: hidden;
|
||||
height: 10px;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
@@ -58,6 +58,14 @@
|
||||
.pf-sig-table-edit-name-input{
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
// table filter fields
|
||||
.pf-editable-filter{
|
||||
// overwrites default xEditable style
|
||||
color: $gray-light;
|
||||
border: none;
|
||||
font-style: normal;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -194,10 +194,7 @@ html.sb-static .sb-slidebar,
|
||||
*/
|
||||
|
||||
.sb-slide, #sb-site, .sb-site-container, .sb-slidebar {
|
||||
-webkit-transition: -webkit-transform 400ms ease;
|
||||
-moz-transition: -moz-transform 400ms ease;
|
||||
-o-transition: -o-transform 400ms ease;
|
||||
transition: transform 400ms ease;
|
||||
@include transition( transform 180ms ease-out );
|
||||
-webkit-transition-property: -webkit-transform, left, right; /* Add left/right for Android < 4.4. */
|
||||
-webkit-backface-visibility: hidden; /* Prevents flickering. This is non essential, and you may remove it if your having problems with fixed background images in Chrome. */
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user