- added custom/editable ship jump logs, #709
- fixed DB setup error: "`system`.`description` can´t have a default value", closed #701 - upgraded "lazyload" js lib `v1.9.5` → `v1.9.7` - upgraded multiple 3rd party NPM dependencies for Gulp build
This commit is contained in:
@@ -20,7 +20,6 @@ class AccessController extends Controller {
|
||||
* @param $params
|
||||
* @return bool
|
||||
* @throws \Exception
|
||||
* @throws \Exception\PathfinderException
|
||||
* @throws \ZMQSocketException
|
||||
*/
|
||||
function beforeroute(\Base $f3, $params): bool {
|
||||
@@ -29,15 +28,7 @@ class AccessController extends Controller {
|
||||
// requires a valid logged in user!
|
||||
if( !$this->isLoggedIn($f3) ){
|
||||
// no character found or login timer expired
|
||||
$this->logoutCharacter();
|
||||
|
||||
if($f3->get('AJAX')){
|
||||
// unauthorized request
|
||||
$f3->status(403);
|
||||
}else{
|
||||
// redirect to landing page
|
||||
$f3->reroute(['login']);
|
||||
}
|
||||
$this->logoutCharacter($f3);
|
||||
// skip route handler and afterroute()
|
||||
$return = false;
|
||||
}
|
||||
@@ -51,7 +42,6 @@ class AccessController extends Controller {
|
||||
* @param \Base $f3
|
||||
* @return bool
|
||||
* @throws \Exception
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
protected function isLoggedIn(\Base $f3): bool {
|
||||
$loginCheck = false;
|
||||
@@ -71,7 +61,6 @@ class AccessController extends Controller {
|
||||
* @param \Base $f3
|
||||
* @param Model\CharacterModel $character
|
||||
* @return bool
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
private function checkLogTimer(\Base $f3, Model\CharacterModel $character){
|
||||
$loginCheck = false;
|
||||
@@ -104,7 +93,6 @@ class AccessController extends Controller {
|
||||
* @param Model\MapModel $map
|
||||
* @return int (number of active connections for this map)
|
||||
* @throws \Exception
|
||||
* @throws \Exception\PathfinderException
|
||||
* @throws \ZMQSocketException
|
||||
*/
|
||||
protected function broadcastMapData(Model\MapModel $map){
|
||||
@@ -117,7 +105,6 @@ class AccessController extends Controller {
|
||||
* @param Model\MapModel $map
|
||||
* @return array
|
||||
* @throws \Exception
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
protected function getFormattedMapData(Model\MapModel $map){
|
||||
$mapData = $map->getData();
|
||||
|
||||
@@ -37,7 +37,6 @@ class Admin extends Controller{
|
||||
* @param $params
|
||||
* @return bool
|
||||
* @throws \Exception
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
function beforeroute(\Base $f3, $params): bool {
|
||||
$return = parent::beforeroute($f3, $params);
|
||||
@@ -67,7 +66,6 @@ class Admin extends Controller{
|
||||
/**
|
||||
* event handler after routing
|
||||
* @param \Base $f3
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
public function afterroute(\Base $f3) {
|
||||
// js view (file)
|
||||
@@ -123,7 +121,6 @@ class Admin extends Controller{
|
||||
* @param $params
|
||||
* @param null $character
|
||||
* @throws \Exception
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
public function dispatch(\Base $f3, $params, $character = null){
|
||||
if($character instanceof CharacterModel){
|
||||
@@ -232,7 +229,6 @@ class Admin extends Controller{
|
||||
* @param CharacterModel $character
|
||||
* @param int $kickCharacterId
|
||||
* @param int $minutes
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
protected function kickCharacter(CharacterModel $character, $kickCharacterId, $minutes){
|
||||
$kickOptions = self::KICK_OPTIONS;
|
||||
@@ -262,7 +258,6 @@ class Admin extends Controller{
|
||||
* @param CharacterModel $character
|
||||
* @param int $banCharacterId
|
||||
* @param int $value
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
protected function banCharacter(CharacterModel $character, $banCharacterId, $value){
|
||||
$banCharacters = $this->filterValidCharacters($character, $banCharacterId);
|
||||
@@ -309,7 +304,6 @@ class Admin extends Controller{
|
||||
* @param CharacterModel $character
|
||||
* @param int $mapId
|
||||
* @param int $value
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
protected function activateMap(CharacterModel $character, int $mapId, int $value){
|
||||
$maps = $this->filterValidMaps($character, $mapId);
|
||||
@@ -322,7 +316,6 @@ class Admin extends Controller{
|
||||
/**
|
||||
* @param CharacterModel $character
|
||||
* @param int $mapId
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
protected function deleteMap(CharacterModel $character, int $mapId){
|
||||
$maps = $this->filterValidMaps($character, $mapId);
|
||||
@@ -336,7 +329,6 @@ class Admin extends Controller{
|
||||
* @param CharacterModel $character
|
||||
* @param int $mapId
|
||||
* @return \DB\CortexCollection[]|MapModel[]
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
protected function filterValidMaps(CharacterModel $character, int $mapId) {
|
||||
$maps = [];
|
||||
@@ -355,7 +347,6 @@ class Admin extends Controller{
|
||||
* get log file for "admin" logs
|
||||
* @param string $type
|
||||
* @return \Log
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
static function getLogger($type = 'ADMIN'){
|
||||
return parent::getLogger('ADMIN');
|
||||
@@ -406,7 +397,6 @@ class Admin extends Controller{
|
||||
* init /maps page data
|
||||
* @param \Base $f3
|
||||
* @param CharacterModel $character
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
protected function initMaps(\Base $f3, CharacterModel $character){
|
||||
$data = (object) [];
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
*/
|
||||
|
||||
namespace Controller\Api;
|
||||
|
||||
use Controller;
|
||||
use Model;
|
||||
|
||||
@@ -97,7 +98,7 @@ class Connection extends Controller\AccessController {
|
||||
$map = Model\BasicModel::getNew('MapModel');
|
||||
$map->getById($mapId);
|
||||
|
||||
if( $map->hasAccess($activeCharacter) ){
|
||||
if($map->hasAccess($activeCharacter)){
|
||||
foreach($connectionIds as $connectionId){
|
||||
if( $connection = $map->getConnectionById($connectionId) ){
|
||||
$connection->delete( $activeCharacter );
|
||||
|
||||
@@ -29,7 +29,6 @@ class GitHub extends Controller\Controller {
|
||||
/**
|
||||
* get HTTP request options for API (curl) request
|
||||
* @return array
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
protected function getRequestReleaseOptions() : array {
|
||||
$options = $this->getBaseRequestOptions();
|
||||
@@ -41,7 +40,6 @@ class GitHub extends Controller\Controller {
|
||||
* get HTTP request options for API (curl) request
|
||||
* @param string $text
|
||||
* @return array
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
protected function getRequestMarkdownOptions(string $text) : array {
|
||||
$params = [
|
||||
@@ -59,7 +57,6 @@ class GitHub extends Controller\Controller {
|
||||
/**
|
||||
* get release information from GitHub
|
||||
* @param \Base $f3
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
public function releases(\Base $f3){
|
||||
$cacheKey = 'CACHE_GITHUB_RELEASES';
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
*/
|
||||
|
||||
namespace Controller\Api;
|
||||
|
||||
use Controller;
|
||||
use data\file\FileHandler;
|
||||
use lib\Config;
|
||||
@@ -50,7 +51,6 @@ class Map extends Controller\AccessController {
|
||||
* Get all required static config data for program initialization
|
||||
* @param \Base $f3
|
||||
* @throws Exception
|
||||
* @throws Exception\PathfinderException
|
||||
*/
|
||||
public function initData(\Base $f3){
|
||||
// expire time in seconds
|
||||
@@ -221,6 +221,7 @@ class Map extends Controller\AccessController {
|
||||
|
||||
// universe category data ---------------------------------------------------------------------------------
|
||||
$return->universeCategories = [
|
||||
6 => Model\Universe\BasicUniverseModel::getNew('CategoryModel')->getById(6)->getData(['mass']),
|
||||
65 => Model\Universe\BasicUniverseModel::getNew('CategoryModel')->getById(65)->getData()
|
||||
];
|
||||
|
||||
@@ -572,11 +573,7 @@ class Map extends Controller\AccessController {
|
||||
|
||||
$return->mapData = $map->getData();
|
||||
}catch(Exception\ValidationException $e){
|
||||
$validationError = (object) [];
|
||||
$validationError->type = 'error';
|
||||
$validationError->field = $e->getField();
|
||||
$validationError->message = $e->getMessage();
|
||||
$return->error[] = $validationError;
|
||||
$return->error[] = $e->getError();
|
||||
}
|
||||
}else{
|
||||
// map access denied
|
||||
@@ -634,7 +631,6 @@ class Map extends Controller\AccessController {
|
||||
* -> if characters with map access found -> broadcast mapData to them
|
||||
* @param Model\MapModel $map
|
||||
* @throws Exception
|
||||
* @throws Exception\PathfinderException
|
||||
* @throws \ZMQSocketException
|
||||
*/
|
||||
protected function broadcastMapAccess(Model\MapModel $map){
|
||||
@@ -708,7 +704,6 @@ class Map extends Controller\AccessController {
|
||||
* -> function is called continuously (trigger) by any active client
|
||||
* @param \Base $f3
|
||||
* @throws Exception
|
||||
* @throws Exception\PathfinderException
|
||||
*/
|
||||
public function updateData(\Base $f3){
|
||||
$postData = (array)$f3->get('POST');
|
||||
@@ -848,7 +843,6 @@ class Map extends Controller\AccessController {
|
||||
* @param Model\MapModel[] $mapModels
|
||||
* @return array
|
||||
* @throws Exception
|
||||
* @throws Exception\PathfinderException
|
||||
*/
|
||||
protected function getFormattedMapsData($mapModels){
|
||||
$mapData = [];
|
||||
@@ -864,7 +858,6 @@ class Map extends Controller\AccessController {
|
||||
* -> function is called continuously by any active client
|
||||
* @param \Base $f3
|
||||
* @throws Exception
|
||||
* @throws Exception\PathfinderException
|
||||
*/
|
||||
public function updateUserData(\Base $f3){
|
||||
$postData = (array)$f3->get('POST');
|
||||
@@ -1196,7 +1189,6 @@ class Map extends Controller\AccessController {
|
||||
* get map log data
|
||||
* @param \Base $f3
|
||||
* @throws Exception
|
||||
* @throws Exception\PathfinderException
|
||||
*/
|
||||
public function getLogData(\Base $f3){
|
||||
$postData = (array)$f3->get('POST');
|
||||
|
||||
45
app/main/controller/api/rest/abstractrestcontroller.php
Normal file
45
app/main/controller/api/rest/abstractrestcontroller.php
Normal file
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: exodu
|
||||
* Date: 13.10.2018
|
||||
* Time: 16:14
|
||||
*/
|
||||
|
||||
namespace Controller\Api\Rest;
|
||||
|
||||
use Controller;
|
||||
|
||||
abstract class AbstractRestController extends Controller\AccessController {
|
||||
|
||||
/**
|
||||
* get send data from request
|
||||
* API requests require "Content-Type: application/json"
|
||||
* -> $_POST does not include request data -> request BODY might contain JSON
|
||||
* @param \Base $f3
|
||||
* @return array
|
||||
*/
|
||||
protected function getRequestData(\Base $f3) : array {
|
||||
$data = [];
|
||||
if( !empty($body = $f3->get('BODY')) ){
|
||||
$bodyDecode = json_decode($body, true);
|
||||
if(($jsonError = json_last_error()) === JSON_ERROR_NONE){
|
||||
$data = $bodyDecode;
|
||||
}else{
|
||||
$f3->set('HALT', true);
|
||||
$f3->error(400, 'Request data: ' . json_last_error_msg());
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* render API response to client
|
||||
* @param $output
|
||||
*/
|
||||
protected function out($output){
|
||||
echo json_encode($output);
|
||||
}
|
||||
|
||||
}
|
||||
112
app/main/controller/api/rest/log.php
Normal file
112
app/main/controller/api/rest/log.php
Normal file
@@ -0,0 +1,112 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: exodu
|
||||
* Date: 13.10.2018
|
||||
* Time: 15:28
|
||||
*/
|
||||
|
||||
namespace Controller\Api\Rest;
|
||||
|
||||
use Model;
|
||||
|
||||
class Log extends AbstractRestController {
|
||||
|
||||
/**
|
||||
* put (insert) log data
|
||||
* @param \Base $f3
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function put(\Base $f3){
|
||||
$requestData = $this->getRequestData($f3);
|
||||
$connectionData = [];
|
||||
|
||||
if($connectionId = (int)$requestData['connectionId']){
|
||||
$activeCharacter = $this->getCharacter();
|
||||
|
||||
/**
|
||||
* @var Model\ConnectionModel $connection
|
||||
*/
|
||||
$connection = Model\BasicModel::getNew('ConnectionModel');
|
||||
$connection->getById($connectionId);
|
||||
|
||||
if($connection->hasAccess($activeCharacter)){
|
||||
$log = $connection->getNewLog();
|
||||
$log->setData($requestData);
|
||||
$log->record = false; // log not recorded by ESI
|
||||
$log->save();
|
||||
|
||||
$connectionData[] = $log->getConnection()->getData(true, true);
|
||||
}
|
||||
}
|
||||
|
||||
$this->out($connectionData);
|
||||
}
|
||||
|
||||
/**
|
||||
* delete (deactivate) log data
|
||||
* @param \Base $f3
|
||||
* @param $params
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function delete(\Base $f3, $params){
|
||||
$logId = (int)$params['id'];
|
||||
$connectionData = [];
|
||||
|
||||
if($log = $this->update($logId, ['active' => false])){
|
||||
$connectionData[] = $log->getConnection()->getData(true, true);
|
||||
}
|
||||
|
||||
$this->out($connectionData);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* update log data
|
||||
* @param \Base $f3
|
||||
* @param $params
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function patch(\Base $f3, $params){
|
||||
$logId = (int)$params['id'];
|
||||
$requestData = $this->getRequestData($f3);
|
||||
$connectionData = [];
|
||||
|
||||
if($log = $this->update($logId, $requestData)){
|
||||
$connectionData[] = $log->getConnection()->getData(true, true);
|
||||
}
|
||||
|
||||
$this->out($connectionData);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* update existing connectionLog with new data
|
||||
* @param int $logId
|
||||
* @param array $logData
|
||||
* @return bool|Model\ConnectionLogModel
|
||||
* @throws \Exception
|
||||
*/
|
||||
private function update(int $logId, array $logData){
|
||||
$log = false;
|
||||
if($logId){
|
||||
$activeCharacter = $this->getCharacter();
|
||||
/**
|
||||
* @var Model\ConnectionLogModel $log
|
||||
*/
|
||||
$log = Model\BasicModel::getNew('ConnectionLogModel');
|
||||
$log->getById($logId, 0, false);
|
||||
|
||||
if($log->hasAccess($activeCharacter)){
|
||||
$log->setData($logData);
|
||||
|
||||
if(isset($logData['active'])){
|
||||
$log->setActive((bool)$logData['active']);
|
||||
}
|
||||
$log->save();
|
||||
}
|
||||
}
|
||||
return $log;
|
||||
}
|
||||
}
|
||||
@@ -414,7 +414,7 @@ class Route extends Controller\AccessController {
|
||||
* @param array $mapIds
|
||||
* @param array $filterData
|
||||
* @return array
|
||||
* @throws \Exception\PathfinderException
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function searchRoute(int $systemFromId, int $systemToId, $searchDepth = 0, array $mapIds = [], array $filterData = []) : array {
|
||||
// search root by ESI API
|
||||
@@ -439,7 +439,6 @@ class Route extends Controller\AccessController {
|
||||
* @param array $filterData
|
||||
* @return array
|
||||
* @throws \Exception
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
private function searchRouteCustom(int $systemFromId, int $systemToId, $searchDepth = 0, array $mapIds = [], array $filterData = []) : array {
|
||||
// reset all previous set jump data
|
||||
@@ -519,7 +518,6 @@ class Route extends Controller\AccessController {
|
||||
* @param array $filterData
|
||||
* @return array
|
||||
* @throws \Exception
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
private function searchRouteESI(int $systemFromId, int $systemToId, int $searchDepth = 0, array $mapIds = [], array $filterData = []) : array {
|
||||
// reset all previous set jump data
|
||||
@@ -645,7 +643,6 @@ class Route extends Controller\AccessController {
|
||||
* search multiple route between two systems
|
||||
* @param \Base $f3
|
||||
* @throws \Exception
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
public function search($f3){
|
||||
$requestData = (array)$f3->get('POST');
|
||||
|
||||
@@ -123,7 +123,6 @@ class Statistic extends Controller\AccessController {
|
||||
* @param int $yearEnd
|
||||
* @param int $weekEnd
|
||||
* @return array
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
protected function queryStatistic( CharacterModel $character, $typeId, $yearStart, $weekStart, $yearEnd, $weekEnd){
|
||||
$data = [];
|
||||
|
||||
@@ -100,14 +100,8 @@ class System extends Controller\AccessController {
|
||||
$return->error = $systemModel->getErrors();
|
||||
}
|
||||
}catch(Exception\ValidationException $e){
|
||||
$validationError = (object) [];
|
||||
$validationError->type = 'error';
|
||||
$validationError->field = $e->getField();
|
||||
$validationError->message = $e->getMessage();
|
||||
$return->error[] = $validationError;
|
||||
$return->error[] = $e->getError();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -246,7 +240,6 @@ class System extends Controller\AccessController {
|
||||
* send Rally Point poke
|
||||
* @param \Base $f3
|
||||
* @throws \Exception
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
public function pokeRally(\Base $f3){
|
||||
$rallyData = (array)$f3->get('POST');
|
||||
|
||||
@@ -109,7 +109,6 @@ class User extends Controller\Controller{
|
||||
* -> return character data (if valid)
|
||||
* @param \Base $f3
|
||||
* @throws Exception
|
||||
* @throws Exception\PathfinderException
|
||||
*/
|
||||
public function getCookieCharacter(\Base $f3){
|
||||
$data = $f3->get('POST');
|
||||
@@ -201,15 +200,10 @@ class User extends Controller\Controller{
|
||||
/**
|
||||
* log the current user out + clear character system log data
|
||||
* @param \Base $f3
|
||||
* @throws Exception
|
||||
* @throws \ZMQSocketException
|
||||
*/
|
||||
public function logout(\Base $f3){
|
||||
$this->logoutCharacter(false, true, true, true);
|
||||
|
||||
$return = (object) [];
|
||||
$return->reroute = rtrim(self::getEnvironmentData('URL'), '/') . $f3->alias('login');
|
||||
echo json_encode($return);
|
||||
$this->logoutCharacter($f3, false, true, true, true);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -345,17 +339,9 @@ class User extends Controller\Controller{
|
||||
}
|
||||
|
||||
}catch(Exception\ValidationException $e){
|
||||
$validationError = (object) [];
|
||||
$validationError->type = 'error';
|
||||
$validationError->field = $e->getField();
|
||||
$validationError->message = $e->getMessage();
|
||||
$return->error[] = $validationError;
|
||||
$return->error[] = $e->getError();
|
||||
}catch(Exception\RegistrationException $e){
|
||||
$registrationError = (object) [];
|
||||
$registrationError->type = 'error';
|
||||
$registrationError->field = $e->getField();
|
||||
$registrationError->message = $e->getMessage();
|
||||
$return->error[] = $registrationError;
|
||||
$return->error[] = $e->getError();
|
||||
}
|
||||
|
||||
// return new/updated user data
|
||||
@@ -394,10 +380,8 @@ class User extends Controller\Controller{
|
||||
sprintf(self::LOG_DELETE_ACCOUNT, $user->id, $user->name)
|
||||
);
|
||||
|
||||
$this->logoutCharacter(true, true, true, true);
|
||||
$this->logoutCharacter($f3, true, true, true, true);
|
||||
$user->erase();
|
||||
|
||||
$return->reroute = rtrim(self::getEnvironmentData('URL'), '/') . $f3->alias('login');
|
||||
}
|
||||
}else{
|
||||
// captcha not valid -> return error
|
||||
|
||||
@@ -52,7 +52,6 @@ class Sso extends Api\User{
|
||||
* redirect user to CCP SSO page and request authorization
|
||||
* -> cf. Controller->getCookieCharacters() ( equivalent cookie based login)
|
||||
* @param \Base $f3
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
public function requestAdminAuthorization($f3){
|
||||
// store browser tabId to be "targeted" after login
|
||||
@@ -67,7 +66,6 @@ class Sso extends Api\User{
|
||||
* -> cf. Controller->getCookieCharacters() ( equivalent cookie based login)
|
||||
* @param \Base $f3
|
||||
* @throws \Exception
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
public function requestAuthorization($f3){
|
||||
$params = $f3->get('GET');
|
||||
@@ -133,7 +131,6 @@ class Sso extends Api\User{
|
||||
* @param \Base $f3
|
||||
* @param array $scopes
|
||||
* @param string $rootAlias
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
private function rerouteAuthorization(\Base $f3, $scopes = [], $rootAlias = 'login'){
|
||||
if( !empty( Controller\Controller::getEnvironmentData('CCP_SSO_CLIENT_ID') ) ){
|
||||
@@ -166,7 +163,6 @@ class Sso extends Api\User{
|
||||
* -> see requestAuthorization()
|
||||
* @param \Base $f3
|
||||
* @throws \Exception
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
public function callbackAuthorization($f3){
|
||||
$getParams = (array)$f3->get('GET');
|
||||
@@ -307,7 +303,6 @@ class Sso extends Api\User{
|
||||
* login by cookie name
|
||||
* @param \Base $f3
|
||||
* @throws \Exception
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
public function login(\Base $f3){
|
||||
$data = (array)$f3->get('GET');
|
||||
@@ -345,7 +340,6 @@ class Sso extends Api\User{
|
||||
* -> else try to refresh auth and get fresh "access_token"
|
||||
* @param bool $authCode
|
||||
* @return null|\stdClass
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
public function getSsoAccessData($authCode){
|
||||
$accessData = null;
|
||||
@@ -365,7 +359,6 @@ class Sso extends Api\User{
|
||||
* verify authorization code, and get an "access_token" data
|
||||
* @param $authCode
|
||||
* @return \stdClass
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
protected function verifyAuthorizationCode($authCode){
|
||||
$requestParams = [
|
||||
@@ -381,7 +374,6 @@ class Sso extends Api\User{
|
||||
* -> if "access_token" is expired, this function gets a fresh one
|
||||
* @param $refreshToken
|
||||
* @return \stdClass
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
public function refreshAccessToken($refreshToken){
|
||||
$requestParams = [
|
||||
@@ -398,7 +390,6 @@ class Sso extends Api\User{
|
||||
* OR by providing a valid "refresh_token"
|
||||
* @param $requestParams
|
||||
* @return \stdClass
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
protected function requestAccessData($requestParams){
|
||||
$verifyAuthCodeUrl = self::getVerifyAuthorizationCodeEndpoint();
|
||||
@@ -463,7 +454,6 @@ class Sso extends Api\User{
|
||||
* -> if more character information is required, use ESI "characters" endpoints request instead
|
||||
* @param $accessToken
|
||||
* @return mixed|null
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
public function verifyCharacterData($accessToken){
|
||||
$verifyUserUrl = self::getVerifyUserEndpoint();
|
||||
@@ -586,7 +576,6 @@ class Sso extends Api\User{
|
||||
* get CCP SSO url from configuration file
|
||||
* -> throw error if url is broken/missing
|
||||
* @return string
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
static function getSsoUrlRoot(){
|
||||
$url = '';
|
||||
@@ -616,7 +605,6 @@ class Sso extends Api\User{
|
||||
/**
|
||||
* get logger for SSO logging
|
||||
* @return \Log
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
static function getSSOLogger(){
|
||||
return parent::getLogger('SSO');
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
namespace Controller;
|
||||
|
||||
use Controller\Api as Api;
|
||||
use Exception\PathfinderException;
|
||||
use lib\Config;
|
||||
use lib\Resource;
|
||||
use lib\Monolog;
|
||||
@@ -66,7 +67,6 @@ class Controller {
|
||||
* @param \Base $f3
|
||||
* @param $params
|
||||
* @return bool
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
function beforeroute(\Base $f3, $params): bool {
|
||||
// initiate DB connection
|
||||
@@ -103,10 +103,10 @@ class Controller {
|
||||
header($resource->buildHeader(), false);
|
||||
}
|
||||
|
||||
if($this->getTemplate()){
|
||||
if($file = $this->getTemplate()){
|
||||
// Ajax calls don´t need a page render..
|
||||
// this happens on client side
|
||||
echo \Template::instance()->render( $this->getTemplate() );
|
||||
echo \Template::instance()->render($file);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -131,7 +131,6 @@ class Controller {
|
||||
* @param $session
|
||||
* @param $sid
|
||||
* @return bool
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
$onSuspect = function($session, $sid){
|
||||
self::getLogger('SESSION_SUSPECT')->write( sprintf(
|
||||
@@ -160,7 +159,6 @@ class Controller {
|
||||
/**
|
||||
* init new Resource handler
|
||||
* @param \Base $f3
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
protected function initResource(\Base $f3){
|
||||
$resource = Resource::instance();
|
||||
@@ -228,7 +226,6 @@ class Controller {
|
||||
* -> store validation data in DB
|
||||
* @param Model\CharacterModel $character
|
||||
* @throws \Exception
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
protected function setLoginCookie(Model\CharacterModel $character){
|
||||
if( $this->getCookieState() ){
|
||||
@@ -286,7 +283,6 @@ class Controller {
|
||||
* @param bool $checkAuthorization
|
||||
* @return Model\CharacterModel[]
|
||||
* @throws \Exception
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
protected function getCookieCharacters($cookieData = [], $checkAuthorization = true){
|
||||
$characters = [];
|
||||
@@ -489,15 +485,16 @@ class Controller {
|
||||
|
||||
/**
|
||||
* log out current character or all active characters (multiple browser tabs)
|
||||
* -> send response data to client
|
||||
* @param \Base $f3
|
||||
* @param bool $all
|
||||
* @param bool $deleteSession
|
||||
* @param bool $deleteLog
|
||||
* @param bool $deleteCookie
|
||||
* @throws \Exception
|
||||
* @throws \ZMQSocketException
|
||||
*/
|
||||
protected function logoutCharacter(bool $all = false, bool $deleteSession = true, bool $deleteLog = true, bool $deleteCookie = false){
|
||||
$sessionCharacterData = (array)$this->getF3()->get(Api\User::SESSION_KEY_CHARACTERS);
|
||||
protected function logoutCharacter(\Base $f3, bool $all = false, bool $deleteSession = true, bool $deleteLog = true, bool $deleteCookie = false){
|
||||
$sessionCharacterData = (array)$f3->get(Api\User::SESSION_KEY_CHARACTERS);
|
||||
|
||||
if($sessionCharacterData){
|
||||
$activeCharacterId = ($activeCharacter = $this->getCharacter()) ? $activeCharacter->_id : 0;
|
||||
@@ -523,6 +520,20 @@ class Controller {
|
||||
(new Socket( Config::getSocketUri() ))->sendData('characterLogout', $characterIds);
|
||||
}
|
||||
}
|
||||
|
||||
if($f3->get('AJAX')){
|
||||
$status = 403;
|
||||
$f3->status($status);
|
||||
|
||||
$return = (object) [];
|
||||
$return->reroute = rtrim(self::getEnvironmentData('URL'), '/') . $f3->alias('login');
|
||||
$return->error[] = $this->getErrorObject($status, Config::getMessageFromHTTPStatus($status));
|
||||
|
||||
echo json_encode($return);
|
||||
}else{
|
||||
// redirect to landing page
|
||||
$f3->reroute(['login']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -627,7 +638,6 @@ class Controller {
|
||||
/**
|
||||
* get a custom userAgent string for API calls
|
||||
* @return string
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
protected function getUserAgent(){
|
||||
$userAgent = '';
|
||||
@@ -663,18 +673,26 @@ class Controller {
|
||||
* -> on HTTP request -> render error page
|
||||
* @param \Base $f3
|
||||
* @return bool
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
public function showError(\Base $f3){
|
||||
|
||||
if(!headers_sent()){
|
||||
// collect error info -------------------------------------------------------------------------------------
|
||||
$error = $this->getErrorObject(
|
||||
$f3->get('ERROR.code'),
|
||||
$f3->get('ERROR.status'),
|
||||
$f3->get('ERROR.text'),
|
||||
$f3->get('DEBUG') === 3 ? $f3->get('ERROR.trace') : null
|
||||
);
|
||||
$errorData = $f3->get('ERROR');
|
||||
$exception = $f3->get('EXCEPTION');
|
||||
|
||||
if($exception instanceof PathfinderException){
|
||||
// ... handle Pathfinder exceptions (e.g. validation Exceptions,..)
|
||||
$error = $exception->getError();
|
||||
}else{
|
||||
// ... handle error $f3->error() calls
|
||||
$error = $this->getErrorObject(
|
||||
$errorData['code'],
|
||||
$errorData['status'],
|
||||
$errorData['text'],
|
||||
$f3->get('DEBUG') === 3 ? $errorData['trace'] : null
|
||||
);
|
||||
}
|
||||
|
||||
// check if error is a PDO Exception ----------------------------------------------------------------------
|
||||
if(strpos(strtolower( $f3->get('ERROR.text') ), 'duplicate') !== false){
|
||||
@@ -725,24 +743,6 @@ class Controller {
|
||||
* @return bool
|
||||
*/
|
||||
public function unload(\Base $f3){
|
||||
// track some 4xx Client side errors
|
||||
// 5xx errors are handled in "ONERROR" callback
|
||||
$status = http_response_code();
|
||||
if(!headers_sent() && $status >= 300){
|
||||
if($f3->get('AJAX')){
|
||||
$params = (array)$f3->get('POST');
|
||||
$return = (object) [];
|
||||
if((bool)$params['reroute']){
|
||||
$return->reroute = rtrim(self::getEnvironmentData('URL'), '/') . $f3->alias('login');
|
||||
}else{
|
||||
// no reroute -> errors can be shown
|
||||
$return->error[] = $this->getErrorObject($status, Config::getMessageFromHTTPStatus($status));
|
||||
}
|
||||
|
||||
echo json_encode($return);
|
||||
}
|
||||
}
|
||||
|
||||
// store all user activities that are buffered for logging in this request
|
||||
// this should work even on non HTTP200 responses
|
||||
$this->logActivities();
|
||||
@@ -887,7 +887,6 @@ class Controller {
|
||||
* get the current registration status
|
||||
* 0=registration stop |1=new registration allowed
|
||||
* @return int
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
static function getRegistrationStatus(){
|
||||
return (int)Config::getPathfinderData('registration.status');
|
||||
@@ -898,7 +897,6 @@ class Controller {
|
||||
* -> set in pathfinder.ini
|
||||
* @param string $type
|
||||
* @return \Log|null
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
static function getLogger($type){
|
||||
return LogController::getLogger($type);
|
||||
|
||||
@@ -163,7 +163,6 @@ class LogController extends \Prefab {
|
||||
* get Logger instance
|
||||
* @param string $type
|
||||
* @return \Log|null
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
public static function getLogger($type){
|
||||
$logFiles = Config::getPathfinderData('logfiles');
|
||||
|
||||
@@ -16,7 +16,6 @@ class MapController extends AccessController {
|
||||
/**
|
||||
* @param \Base $f3
|
||||
* @throws \Exception
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
public function init(\Base $f3) {
|
||||
$character = $this->getCharacter();
|
||||
|
||||
@@ -137,7 +137,6 @@ class Setup extends Controller {
|
||||
* @param \Base $f3
|
||||
* @param array $params
|
||||
* @return bool
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
function beforeroute(\Base $f3, $params): bool {
|
||||
$this->initResource($f3);
|
||||
@@ -162,7 +161,6 @@ class Setup extends Controller {
|
||||
|
||||
/**
|
||||
* @param \Base $f3
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
public function afterroute(\Base $f3) {
|
||||
// js view (file)
|
||||
@@ -789,7 +787,6 @@ class Setup extends Controller {
|
||||
* get default map config
|
||||
* @param \Base $f3
|
||||
* @return array
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
protected function getMapsDefaultConfig(\Base $f3): array {
|
||||
$matrix = \Matrix::instance();
|
||||
@@ -1517,8 +1514,8 @@ class Setup extends Controller {
|
||||
*/
|
||||
protected function invalidateCookies(\Base $f3){
|
||||
$this->getDB('PF');
|
||||
$authentidationModel = Model\BasicModel::getNew('CharacterAuthenticationModel');
|
||||
$results = $authentidationModel->find();
|
||||
$authenticationModel = Model\BasicModel::getNew('CharacterAuthenticationModel');
|
||||
$results = $authenticationModel->find();
|
||||
if($results){
|
||||
foreach($results as $result){
|
||||
$result->erase();
|
||||
@@ -1537,7 +1534,7 @@ class Setup extends Controller {
|
||||
if($bytes){
|
||||
$base = log($bytes, 1024);
|
||||
$suffixes = array('', 'KB', 'M', 'GB', 'TB');
|
||||
$result = round(pow(1024, $base - floor($base)), $precision) .''. $suffixes[floor($base)];
|
||||
$result = round(pow(1024, $base - floor($base)), $precision) .''. $suffixes[(int)floor($base)];
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
@@ -22,7 +22,6 @@ class MapUpdate extends AbstractCron {
|
||||
* deactivate all "private" maps whose lifetime is over
|
||||
* >> php index.php "/cron/deactivateMapData"
|
||||
* @param \Base $f3
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
function deactivateMapData(\Base $f3){
|
||||
$this->setMaxExecutionTime();
|
||||
|
||||
@@ -116,7 +116,6 @@ class Database extends \Prefab {
|
||||
* @param string $password
|
||||
* @param string $alias
|
||||
* @return SQL|null
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
protected function connect($dns, $name, $user, $password, $alias){
|
||||
$db = null;
|
||||
@@ -286,7 +285,6 @@ class Database extends \Prefab {
|
||||
/**
|
||||
* get logger for DB logging
|
||||
* @return \Log
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
static function getLogger(){
|
||||
return LogController::getLogger('ERROR');
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: exodus4d
|
||||
* Date: 21.02.15
|
||||
* Time: 00:41
|
||||
*/
|
||||
|
||||
namespace Exception;
|
||||
|
||||
|
||||
class BaseException extends \Exception {
|
||||
|
||||
const VALIDATION_EXCEPTION = 403;
|
||||
const REGISTRATION_EXCEPTION = 403;
|
||||
const CONFIG_VALUE_EXCEPTION = 500;
|
||||
const DB_EXCEPTION = 500;
|
||||
|
||||
public function __construct(string $message, int $code = 0){
|
||||
parent::__construct($message, $code);
|
||||
}
|
||||
|
||||
}
|
||||
18
app/main/exception/configexception.php
Normal file
18
app/main/exception/configexception.php
Normal file
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: exodu
|
||||
* Date: 20.10.2018
|
||||
* Time: 18:53
|
||||
*/
|
||||
|
||||
namespace Exception;
|
||||
|
||||
|
||||
class ConfigException extends PathfinderException {
|
||||
|
||||
protected $codes = [
|
||||
1000 => 500
|
||||
];
|
||||
|
||||
}
|
||||
@@ -8,9 +8,13 @@
|
||||
|
||||
namespace Exception;
|
||||
|
||||
class DatabaseException extends BaseException {
|
||||
class DatabaseException extends PathfinderException {
|
||||
|
||||
protected $codes = [
|
||||
1500 => 500
|
||||
];
|
||||
|
||||
public function __construct(string $message){
|
||||
parent::__construct($message, self::DB_EXCEPTION);
|
||||
parent::__construct($message, 1500);
|
||||
}
|
||||
}
|
||||
@@ -1,17 +1,59 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: exodu
|
||||
* Date: 05.06.2017
|
||||
* Time: 19:19
|
||||
* User: exodus4d
|
||||
* Date: 21.02.15
|
||||
* Time: 00:41
|
||||
*/
|
||||
|
||||
namespace Exception;
|
||||
|
||||
|
||||
class PathfinderException extends BaseException{
|
||||
class PathfinderException extends \Exception {
|
||||
|
||||
public function __construct($message){
|
||||
parent::__construct($message, self::CONFIG_VALUE_EXCEPTION);
|
||||
/**
|
||||
* default HTTP response code for PathfinderExceptions
|
||||
* -> can be specified by using custom Exception codes
|
||||
*/
|
||||
const DEFAULT_RESPONSECODE = 500;
|
||||
|
||||
/**
|
||||
* lists all exception codes
|
||||
* @var array
|
||||
*/
|
||||
protected $codes = [
|
||||
0 => self::DEFAULT_RESPONSECODE
|
||||
];
|
||||
|
||||
public function __construct(string $message, int $code = 0){
|
||||
if( !array_key_exists($code, $this->codes) ){
|
||||
// exception code not specified by child class
|
||||
$code = 0;
|
||||
}
|
||||
parent::__construct($message, $code);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* get error object
|
||||
* @return \stdClass
|
||||
*/
|
||||
public function getError() : \stdClass {
|
||||
$error = (object) [];
|
||||
$error->type = 'error';
|
||||
$error->code = $this->getResponseCode();
|
||||
$error->status = @constant('Base::HTTP_' . $this->getResponseCode());
|
||||
$error->message = $this->getMessage();
|
||||
//$error->trace = $this->getTraceAsString();
|
||||
$error->trace = $this->getTrace();
|
||||
return $error;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the HTTP response code for the client from exception
|
||||
* -> if Exception is not handled/catched 'somewhere' this code is used by the final onError handler
|
||||
* @return int
|
||||
*/
|
||||
public function getResponseCode() : int {
|
||||
return $this->codes[$this->getCode()];
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,11 @@
|
||||
namespace Exception;
|
||||
|
||||
|
||||
class RegistrationException extends BaseException{
|
||||
class RegistrationException extends PathfinderException{
|
||||
|
||||
protected $codes = [
|
||||
2000 => 403
|
||||
];
|
||||
|
||||
/**
|
||||
* form field name that causes this exception
|
||||
@@ -17,22 +21,18 @@ class RegistrationException extends BaseException{
|
||||
*/
|
||||
private $field;
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getField(){
|
||||
return $this->field;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $field
|
||||
*/
|
||||
public function setField($field){
|
||||
public function __construct(string $message, string $field = ''){
|
||||
parent::__construct($message, 2000);
|
||||
$this->field = $field;
|
||||
}
|
||||
|
||||
public function __construct($message, $field = ''){
|
||||
parent::__construct($message, self::REGISTRATION_EXCEPTION);
|
||||
$this->setField($field);
|
||||
/**
|
||||
* get error object
|
||||
* @return \stdClass
|
||||
*/
|
||||
public function getError() : \stdClass {
|
||||
$error = parent::getError();
|
||||
$error->field = $this->field;
|
||||
return $error;
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,11 @@
|
||||
namespace Exception;
|
||||
|
||||
|
||||
class ValidationException extends BaseException {
|
||||
class ValidationException extends PathfinderException {
|
||||
|
||||
protected $codes = [
|
||||
2000 => 593
|
||||
];
|
||||
|
||||
/**
|
||||
* table column that triggers the exception
|
||||
@@ -17,35 +21,18 @@ class ValidationException extends BaseException {
|
||||
*/
|
||||
private $field;
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getField(): string {
|
||||
return $this->field;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $field
|
||||
*/
|
||||
public function setField(string $field){
|
||||
$this->field = $field;
|
||||
}
|
||||
|
||||
|
||||
public function __construct(string $message, string $field = ''){
|
||||
parent::__construct($message, self::VALIDATION_EXCEPTION);
|
||||
$this->setField($field);
|
||||
parent::__construct($message, 2000);
|
||||
$this->field = $field;
|
||||
}
|
||||
|
||||
/**
|
||||
* get error object
|
||||
* @return \stdClass
|
||||
*/
|
||||
public function getError(){
|
||||
$error = (object) [];
|
||||
$error->type = 'error';
|
||||
$error->field = $this->getField();
|
||||
$error->message = $this->getMessage();
|
||||
public function getError() : \stdClass {
|
||||
$error = parent::getError();
|
||||
$error->field = $this->field;
|
||||
return $error;
|
||||
}
|
||||
}
|
||||
@@ -24,7 +24,6 @@ class CcpClient extends \Prefab {
|
||||
* get ApiClient instance
|
||||
* @param \Base $f3
|
||||
* @return ApiClient|null
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
protected function getClient(\Base $f3){
|
||||
$client = null;
|
||||
@@ -45,7 +44,6 @@ class CcpClient extends \Prefab {
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
protected function getUserAgent(){
|
||||
$userAgent = '';
|
||||
@@ -71,7 +69,6 @@ class CcpClient extends \Prefab {
|
||||
* @param $name
|
||||
* @param $arguments
|
||||
* @return array|mixed
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
public function __call($name, $arguments){
|
||||
$return = [];
|
||||
|
||||
@@ -208,7 +208,6 @@ class Config extends \Prefab {
|
||||
/**
|
||||
* get SMTP config values
|
||||
* @return \stdClass
|
||||
* @throws Exception\PathfinderException
|
||||
*/
|
||||
static function getSMTPConfig(): \stdClass{
|
||||
$config = new \stdClass();
|
||||
@@ -253,7 +252,6 @@ class Config extends \Prefab {
|
||||
* get email for notifications by hive key
|
||||
* @param $key
|
||||
* @return mixed
|
||||
* @throws Exception\PathfinderException
|
||||
*/
|
||||
static function getNotificationMail($key){
|
||||
return self::getPathfinderData('notification' . ($key ? '.' . $key : ''));
|
||||
@@ -264,7 +262,6 @@ class Config extends \Prefab {
|
||||
* -> read from pathfinder.ini
|
||||
* @param string $mapType
|
||||
* @return mixed
|
||||
* @throws Exception\PathfinderException
|
||||
*/
|
||||
static function getMapsDefaultConfig($mapType = ''){
|
||||
if( $mapConfig = self::getPathfinderData('map' . ($mapType ? '.' . $mapType : '')) ){
|
||||
@@ -380,16 +377,15 @@ class Config extends \Prefab {
|
||||
/**
|
||||
* @param string $key
|
||||
* @return null|mixed
|
||||
* @throws Exception\PathfinderException
|
||||
*/
|
||||
static function getPathfinderData($key = ''){
|
||||
$hiveKey = self::HIVE_KEY_PATHFINDER . ($key ? '.' . strtoupper($key) : '');
|
||||
$data = null; // make sure it is always defined
|
||||
try{
|
||||
if( !\Base::instance()->exists($hiveKey, $data) ){
|
||||
throw new Exception\PathfinderException(sprintf(self::ERROR_CONF_PATHFINDER, $hiveKey));
|
||||
throw new Exception\ConfigException(sprintf(self::ERROR_CONF_PATHFINDER, $hiveKey));
|
||||
}
|
||||
}catch (Exception\PathfinderException $e){
|
||||
}catch (Exception\ConfigException $e){
|
||||
LogController::getLogger('ERROR')->write($e->getMessage());
|
||||
}
|
||||
|
||||
|
||||
@@ -68,7 +68,6 @@ abstract class AbstractCharacterLog extends AbstractChannelLog{
|
||||
/**
|
||||
* get character thumbnailUrl
|
||||
* @return string
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
protected function getThumbUrl(): string {
|
||||
$url = '';
|
||||
|
||||
@@ -37,7 +37,6 @@ class RallyLog extends AbstractCharacterLog{
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
protected function getThumbUrl() : string{
|
||||
$url = '';
|
||||
|
||||
@@ -179,7 +179,6 @@ abstract class AbstractSlackWebhookHandler extends Handler\AbstractProcessingHan
|
||||
* @param array $attachment
|
||||
* @param array $characterData
|
||||
* @return array
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
protected function setAuthor(array $attachment, array $characterData): array {
|
||||
if( !empty($characterData['id']) && !empty($characterData['name'])){
|
||||
|
||||
@@ -15,7 +15,6 @@ class SlackMapWebhookHandler extends AbstractSlackWebhookHandler {
|
||||
/**
|
||||
* @param array $record
|
||||
* @return array
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
protected function getSlackData(array $record) : array{
|
||||
$postData = parent::getSlackData($record);
|
||||
|
||||
@@ -15,7 +15,6 @@ class SlackRallyWebhookHandler extends AbstractSlackWebhookHandler {
|
||||
/**
|
||||
* @param array $record
|
||||
* @return array
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
protected function getSlackData(array $record) : array{
|
||||
$postData = parent::getSlackData($record);
|
||||
|
||||
@@ -100,7 +100,6 @@ class Web extends \Web {
|
||||
* @param array $additionalOptions
|
||||
* @param int $retryCount request counter for failed call
|
||||
* @return array|FALSE|mixed
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
public function request($url,array $options = null, $additionalOptions = [], $retryCount = 0 ) {
|
||||
$f3 = \Base::instance();
|
||||
|
||||
@@ -23,7 +23,7 @@ abstract class AbstractMapTrackingModel extends BasicModel implements LogModelIn
|
||||
'on-delete' => 'CASCADE'
|
||||
]
|
||||
],
|
||||
'validate' => 'validate_notDry'
|
||||
'validate' => 'notDry'
|
||||
],
|
||||
'updatedCharacterId' => [
|
||||
'type' => Schema::DT_INT,
|
||||
@@ -35,7 +35,7 @@ abstract class AbstractMapTrackingModel extends BasicModel implements LogModelIn
|
||||
'on-delete' => 'CASCADE'
|
||||
]
|
||||
],
|
||||
'validate' => 'validate_notDry'
|
||||
'validate' => 'notDry'
|
||||
]
|
||||
];
|
||||
|
||||
|
||||
@@ -178,6 +178,7 @@ class ActivityLogModel extends BasicModel {
|
||||
* @param null $table
|
||||
* @param null $fields
|
||||
* @return bool
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function setup($db=null, $table=null, $fields=null){
|
||||
$status = parent::setup($db,$table,$fields);
|
||||
|
||||
@@ -77,7 +77,6 @@ class AllianceModel extends BasicModel {
|
||||
/**
|
||||
* get all maps for this alliance
|
||||
* @return array|mixed
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
public function getMaps(){
|
||||
$maps = [];
|
||||
|
||||
@@ -118,7 +118,7 @@ abstract class BasicModel extends \DB\Cortex {
|
||||
parent::__construct($db, $table, $fluid, $ttl);
|
||||
|
||||
// insert events ------------------------------------------------------------------------------------
|
||||
$this->beforeinsert( function($self, $pkeys){
|
||||
$this->beforeinsert(function($self, $pkeys){
|
||||
return $self->beforeInsertEvent($self, $pkeys);
|
||||
});
|
||||
|
||||
@@ -127,21 +127,21 @@ abstract class BasicModel extends \DB\Cortex {
|
||||
});
|
||||
|
||||
// update events ------------------------------------------------------------------------------------
|
||||
$this->beforeupdate( function($self, $pkeys){
|
||||
$this->beforeupdate(function($self, $pkeys){
|
||||
return $self->beforeUpdateEvent($self, $pkeys);
|
||||
});
|
||||
|
||||
$this->afterupdate( function($self, $pkeys){
|
||||
$this->afterupdate(function($self, $pkeys){
|
||||
$self->afterUpdateEvent($self, $pkeys);
|
||||
});
|
||||
|
||||
// erase events -------------------------------------------------------------------------------------
|
||||
|
||||
$this->beforeerase( function($self, $pkeys){
|
||||
$this->beforeerase(function($self, $pkeys){
|
||||
return $self->beforeEraseEvent($self, $pkeys);
|
||||
});
|
||||
|
||||
$this->aftererase( function($self, $pkeys){
|
||||
$this->aftererase(function($self, $pkeys){
|
||||
$self->afterEraseEvent($self, $pkeys);
|
||||
});
|
||||
}
|
||||
@@ -264,7 +264,7 @@ abstract class BasicModel extends \DB\Cortex {
|
||||
* get static fields for this model instance
|
||||
* @return array
|
||||
*/
|
||||
protected function getStaticFieldConf(): array {
|
||||
protected function getStaticFieldConf() : array {
|
||||
$staticFieldConfig = [];
|
||||
|
||||
// static tables (fixed data) do not require them...
|
||||
@@ -299,13 +299,14 @@ abstract class BasicModel extends \DB\Cortex {
|
||||
* @param $val
|
||||
* @return bool
|
||||
*/
|
||||
protected function validateField(string $key, $val): bool {
|
||||
protected function validateField(string $key, $val) : bool {
|
||||
$valid = true;
|
||||
if($fieldConf = $this->fieldConf[$key]){
|
||||
if($method = $this->fieldConf[$key]['validate']){
|
||||
if( !is_string($method)){
|
||||
$method = 'validate_' . $key;
|
||||
$method = $key;
|
||||
}
|
||||
$method = 'validate_' . $method;
|
||||
if(method_exists($this, $method)){
|
||||
// validate $key (column) with this method...
|
||||
$valid = $this->$method($key, $val);
|
||||
@@ -325,7 +326,7 @@ abstract class BasicModel extends \DB\Cortex {
|
||||
* @return bool
|
||||
* @throws \Exception\ValidationException
|
||||
*/
|
||||
protected function validate_notDry($key, $val): bool {
|
||||
protected function validate_notDry($key, $val) : bool {
|
||||
$valid = true;
|
||||
if($colConf = $this->fieldConf[$key]){
|
||||
if(isset($colConf['belongs-to-one'])){
|
||||
@@ -344,6 +345,30 @@ abstract class BasicModel extends \DB\Cortex {
|
||||
return $valid;
|
||||
}
|
||||
|
||||
/**
|
||||
* validates a model field to be not empty
|
||||
* @param $key
|
||||
* @param $val
|
||||
* @return bool
|
||||
*/
|
||||
protected function validate_notEmpty($key, $val) : bool {
|
||||
$valid = false;
|
||||
|
||||
if($colConf = $this->fieldConf[$key]){
|
||||
switch($colConf['type']){
|
||||
case Schema::DT_INT:
|
||||
case Schema::DT_FLOAT:
|
||||
if( (is_int($val) || ctype_digit($val)) && (int)$val > 0){
|
||||
$valid = true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
return $valid;
|
||||
}
|
||||
|
||||
/**
|
||||
* get key for for all objects in this table
|
||||
* @return string
|
||||
@@ -628,7 +653,7 @@ abstract class BasicModel extends \DB\Cortex {
|
||||
* function should be overwritten in parent classes
|
||||
* @return bool
|
||||
*/
|
||||
public function isValid(): bool {
|
||||
public function isValid() : bool {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -776,7 +801,7 @@ abstract class BasicModel extends \DB\Cortex {
|
||||
* @param string $action
|
||||
* @return Logging\LogInterface
|
||||
*/
|
||||
protected function newLog($action = ''): Logging\LogInterface{
|
||||
protected function newLog($action = '') : Logging\LogInterface{
|
||||
return new Logging\DefaultLog($action);
|
||||
}
|
||||
|
||||
@@ -800,7 +825,7 @@ abstract class BasicModel extends \DB\Cortex {
|
||||
* get all validation errors
|
||||
* @return array
|
||||
*/
|
||||
public function getErrors(): array {
|
||||
public function getErrors() : array {
|
||||
return $this->validationError;
|
||||
}
|
||||
|
||||
@@ -808,7 +833,7 @@ abstract class BasicModel extends \DB\Cortex {
|
||||
* checks whether data is outdated and should be refreshed
|
||||
* @return bool
|
||||
*/
|
||||
protected function isOutdated(): bool {
|
||||
protected function isOutdated() : bool {
|
||||
$outdated = true;
|
||||
if(!$this->dry()){
|
||||
$timezone = $this->getF3()->get('getTimeZone')();
|
||||
@@ -832,7 +857,7 @@ abstract class BasicModel extends \DB\Cortex {
|
||||
}catch(ValidationException $e){
|
||||
$this->setValidationError($e);
|
||||
}catch(DatabaseException $e){
|
||||
self::getF3()->error($e->getCode(), $e->getMessage(), $e->getTrace());
|
||||
self::getF3()->error($e->getResponseCode(), $e->getMessage(), $e->getTrace());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -913,7 +938,6 @@ abstract class BasicModel extends \DB\Cortex {
|
||||
* debug log function
|
||||
* @param string $text
|
||||
* @param string $type
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
public static function log($text, $type = 'DEBUG'){
|
||||
Controller\LogController::getLogger($type)->write($text);
|
||||
|
||||
@@ -473,7 +473,6 @@ class CharacterModel extends BasicModel {
|
||||
* get ESI API "access_token" from OAuth
|
||||
* @return bool|mixed
|
||||
* @throws \Exception
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
public function getAccessToken(){
|
||||
$accessToken = false;
|
||||
@@ -544,7 +543,6 @@ class CharacterModel extends BasicModel {
|
||||
* checks whether this character is authorized to log in
|
||||
* -> check corp/ally whitelist config (pathfinder.ini)
|
||||
* @return bool
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
public function isAuthorized(){
|
||||
$authStatus = 'UNKNOWN';
|
||||
@@ -614,7 +612,6 @@ class CharacterModel extends BasicModel {
|
||||
* get Pathfinder role for character
|
||||
* @return RoleModel
|
||||
* @throws \Exception
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
public function requestRole() : RoleModel{
|
||||
$role = null;
|
||||
@@ -660,7 +657,6 @@ class CharacterModel extends BasicModel {
|
||||
* request all corporation roles granted to this character
|
||||
* @return array
|
||||
* @throws \Exception
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
protected function requestRoles(){
|
||||
$rolesData = [];
|
||||
@@ -1021,7 +1017,6 @@ class CharacterModel extends BasicModel {
|
||||
/**
|
||||
* get all accessible map models for this character
|
||||
* @return MapModel[]
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
public function getMaps(){
|
||||
$this->filter(
|
||||
|
||||
@@ -30,11 +30,19 @@ class ConnectionLogModel extends BasicModel {
|
||||
'table' => 'connection',
|
||||
'on-delete' => 'CASCADE'
|
||||
]
|
||||
]
|
||||
],
|
||||
'validate' => 'notDry'
|
||||
],
|
||||
'record' => [
|
||||
'type' => Schema::DT_BOOL,
|
||||
'nullable' => false,
|
||||
'default' => 1,
|
||||
'index' => true
|
||||
],
|
||||
'shipTypeId' => [
|
||||
'type' => Schema::DT_INT,
|
||||
'index' => true
|
||||
'index' => true,
|
||||
'validate' => 'notEmpty'
|
||||
],
|
||||
'shipTypeName' => [
|
||||
'type' => Schema::DT_VARCHAR128,
|
||||
@@ -44,11 +52,13 @@ class ConnectionLogModel extends BasicModel {
|
||||
'shipMass' => [
|
||||
'type' => Schema::DT_FLOAT,
|
||||
'nullable' => false,
|
||||
'default' => 0
|
||||
'default' => 0,
|
||||
'validate' => 'notEmpty'
|
||||
],
|
||||
'characterId' => [
|
||||
'type' => Schema::DT_INT,
|
||||
'index' => true
|
||||
'index' => true,
|
||||
'validate' => 'notEmpty'
|
||||
],
|
||||
'characterName' => [
|
||||
'type' => Schema::DT_VARCHAR128,
|
||||
@@ -57,6 +67,14 @@ class ConnectionLogModel extends BasicModel {
|
||||
]
|
||||
];
|
||||
|
||||
/**
|
||||
* set map data by an associative array
|
||||
* @param array $data
|
||||
*/
|
||||
public function setData(array $data){
|
||||
$this->copyfrom($data, ['shipTypeId', 'shipTypeName', 'shipMass', 'characterId', 'characterName']);
|
||||
}
|
||||
|
||||
/**
|
||||
* get connection log data
|
||||
* @return \stdClass
|
||||
@@ -64,6 +82,8 @@ class ConnectionLogModel extends BasicModel {
|
||||
public function getData() : \stdClass {
|
||||
$logData = (object) [];
|
||||
$logData->id = $this->id;
|
||||
$logData->active = $this->active;
|
||||
$logData->record = $this->record;
|
||||
|
||||
$logData->connection = (object) [];
|
||||
$logData->connection->id = $this->get('connectionId', true);
|
||||
@@ -73,12 +93,46 @@ class ConnectionLogModel extends BasicModel {
|
||||
$logData->ship->typeName = $this->shipTypeName;
|
||||
$logData->ship->mass = $this->shipMass;
|
||||
|
||||
$logData->character = (object) [];
|
||||
$logData->character->id = $this->characterId;
|
||||
$logData->character->name = $this->characterName;
|
||||
|
||||
$logData->created = (object) [];
|
||||
$logData->created->created = strtotime($this->created);
|
||||
$logData->created->character = (object) [];
|
||||
$logData->created->character->id = $this->characterId;
|
||||
$logData->created->character->name = $this->characterName;
|
||||
|
||||
$logData->updated = (object) [];
|
||||
$logData->updated->updated = strtotime($this->updated);
|
||||
|
||||
return $logData;
|
||||
}
|
||||
|
||||
/**
|
||||
* validate shipTypeId
|
||||
* @param string $key
|
||||
* @param string $val
|
||||
* @return bool
|
||||
*/
|
||||
protected function validate_shipTypeId(string $key, string $val): bool {
|
||||
return !empty((int)$val);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ConnectionModel
|
||||
*/
|
||||
public function getConnection() : ConnectionModel {
|
||||
return $this->get('connectionId');
|
||||
}
|
||||
|
||||
/**
|
||||
* check object for model access
|
||||
* @param CharacterModel $characterModel
|
||||
* @return bool
|
||||
*/
|
||||
public function hasAccess(CharacterModel $characterModel) : bool {
|
||||
$access = false;
|
||||
if( !$this->dry() ){
|
||||
$access = $this->getConnection()->hasAccess($characterModel);
|
||||
}
|
||||
return $access;
|
||||
}
|
||||
}
|
||||
@@ -137,9 +137,9 @@ class ConnectionModel extends AbstractMapTrackingModel {
|
||||
/**
|
||||
* check object for model access
|
||||
* @param CharacterModel $characterModel
|
||||
* @return mixed
|
||||
* @return bool
|
||||
*/
|
||||
public function hasAccess(CharacterModel $characterModel){
|
||||
public function hasAccess(CharacterModel $characterModel) : bool {
|
||||
$access = false;
|
||||
if( !$this->dry() ){
|
||||
$access = $this->mapId->hasAccess($characterModel);
|
||||
@@ -149,7 +149,7 @@ class ConnectionModel extends AbstractMapTrackingModel {
|
||||
|
||||
/**
|
||||
* set default connection type by search route between endpoints
|
||||
* @throws \Exception\PathfinderException
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function setDefaultTypeData(){
|
||||
if(
|
||||
@@ -215,7 +215,6 @@ class ConnectionModel extends AbstractMapTrackingModel {
|
||||
* @param $pkeys
|
||||
* @return bool
|
||||
* @throws \Exception\DatabaseException
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
public function beforeInsertEvent($self, $pkeys){
|
||||
// check for "default" connection type and add them if missing
|
||||
@@ -266,8 +265,8 @@ class ConnectionModel extends AbstractMapTrackingModel {
|
||||
|
||||
/**
|
||||
* @param string $action
|
||||
* @return Logging\LogInterface
|
||||
* @throws \Exception\PathfinderException
|
||||
* @return logging\LogInterface
|
||||
* @throws \Exception\ConfigException
|
||||
*/
|
||||
public function newLog($action = ''): Logging\LogInterface{
|
||||
return $this->getMap()->newLog($action)->setTempData($this->getLogObjectData());
|
||||
@@ -335,10 +334,6 @@ class ConnectionModel extends AbstractMapTrackingModel {
|
||||
*/
|
||||
public function getLogs(){
|
||||
$logs = [];
|
||||
$this->filter('connectionLog', [
|
||||
'active = :active',
|
||||
':active' => 1
|
||||
]);
|
||||
|
||||
if($this->connectionLog){
|
||||
$logs = $this->connectionLog;
|
||||
@@ -377,20 +372,34 @@ class ConnectionModel extends AbstractMapTrackingModel {
|
||||
return $logsData;
|
||||
}
|
||||
|
||||
/**
|
||||
* get blank connectionLog model
|
||||
* @return ConnectionLogModel
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function getNewLog() : ConnectionLogModel {
|
||||
/**
|
||||
* @var $log ConnectionLogModel
|
||||
*/
|
||||
$log = self::getNew('ConnectionLogModel');
|
||||
$log->connectionId = $this;
|
||||
return $log;
|
||||
}
|
||||
|
||||
/**
|
||||
* log new mass for this connection
|
||||
* @param CharacterLogModel $characterLog
|
||||
* @return $this
|
||||
* @return ConnectionModel
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function logMass(CharacterLogModel $characterLog){
|
||||
public function logMass(CharacterLogModel $characterLog) : self {
|
||||
if( !$characterLog->dry() ){
|
||||
$log = $this->rel('connectionLog');
|
||||
$log = $this->getNewLog();
|
||||
$log->shipTypeId = $characterLog->shipTypeId;
|
||||
$log->shipTypeName = $characterLog->shipTypeName;
|
||||
$log->shipMass = $characterLog->shipMass;
|
||||
$log->characterId = $characterLog->characterId->_id;
|
||||
$log->characterName = $characterLog->characterId->name;
|
||||
$log->connectionId = $this;
|
||||
$log->save();
|
||||
}
|
||||
|
||||
|
||||
@@ -181,7 +181,6 @@ class CorporationModel extends BasicModel {
|
||||
* @param array $mapIds
|
||||
* @param array $options
|
||||
* @return array
|
||||
* @throws \Exception\PathfinderException
|
||||
*/
|
||||
public function getMaps($mapIds = [], $options = []){
|
||||
$maps = [];
|
||||
|
||||
@@ -10,9 +10,9 @@ namespace Model;
|
||||
|
||||
use DB\SQL\Schema;
|
||||
use data\file\FileHandler;
|
||||
use Exception\ConfigException;
|
||||
use lib\Config;
|
||||
use lib\logging;
|
||||
use Exception\PathfinderException;
|
||||
|
||||
class MapModel extends AbstractMapTrackingModel {
|
||||
|
||||
@@ -44,7 +44,7 @@ class MapModel extends AbstractMapTrackingModel {
|
||||
'on-delete' => 'CASCADE'
|
||||
]
|
||||
],
|
||||
'validate' => 'validate_notDry',
|
||||
'validate' => 'notDry',
|
||||
'activity-log' => true
|
||||
],
|
||||
'typeId' => [
|
||||
@@ -57,7 +57,7 @@ class MapModel extends AbstractMapTrackingModel {
|
||||
'on-delete' => 'CASCADE'
|
||||
]
|
||||
],
|
||||
'validate' => 'validate_notDry',
|
||||
'validate' => 'notDry',
|
||||
'activity-log' => true
|
||||
],
|
||||
'name' => [
|
||||
@@ -199,7 +199,6 @@ class MapModel extends AbstractMapTrackingModel {
|
||||
* get data
|
||||
* -> this includes system and connection data as well
|
||||
* @return \stdClass
|
||||
* @throws PathfinderException
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function getData(){
|
||||
@@ -791,7 +790,6 @@ class MapModel extends AbstractMapTrackingModel {
|
||||
* checks whether a character has access to this map or not
|
||||
* @param CharacterModel $characterModel
|
||||
* @return bool
|
||||
* @throws PathfinderException
|
||||
*/
|
||||
public function hasAccess(CharacterModel $characterModel) : bool {
|
||||
$hasAccess = false;
|
||||
@@ -972,8 +970,8 @@ class MapModel extends AbstractMapTrackingModel {
|
||||
|
||||
/**
|
||||
* @param string $action
|
||||
* @return Logging\LogInterface
|
||||
* @throws PathfinderException
|
||||
* @return logging\LogInterface
|
||||
* @throws ConfigException
|
||||
*/
|
||||
public function newLog($action = ''): Logging\LogInterface{
|
||||
$logChannelData = $this->getLogChannelData();
|
||||
@@ -1048,7 +1046,6 @@ class MapModel extends AbstractMapTrackingModel {
|
||||
/**
|
||||
* check if "activity logging" is enabled for this map type
|
||||
* @return bool
|
||||
* @throws PathfinderException
|
||||
*/
|
||||
public function isActivityLogEnabled(): bool {
|
||||
return $this->logActivity && (bool) Config::getMapsDefaultConfig($this->typeId->name)['log_activity_enabled'];
|
||||
@@ -1057,7 +1054,6 @@ class MapModel extends AbstractMapTrackingModel {
|
||||
/**
|
||||
* check if "history logging" is enabled for this map type
|
||||
* @return bool
|
||||
* @throws PathfinderException
|
||||
*/
|
||||
public function isHistoryLogEnabled(): bool {
|
||||
return $this->logHistory && (bool) Config::getMapsDefaultConfig($this->typeId->name)['log_history_enabled'];
|
||||
@@ -1067,7 +1063,7 @@ class MapModel extends AbstractMapTrackingModel {
|
||||
* check if "Slack WebHook" is enabled for this map type
|
||||
* @param string $channel
|
||||
* @return bool
|
||||
* @throws PathfinderException
|
||||
* @throws ConfigException
|
||||
*/
|
||||
public function isSlackChannelEnabled(string $channel): bool {
|
||||
$enabled = false;
|
||||
@@ -1077,7 +1073,7 @@ class MapModel extends AbstractMapTrackingModel {
|
||||
switch($channel){
|
||||
case 'slackChannelHistory': $defaultMapConfigKey = 'send_history_slack_enabled'; break;
|
||||
case 'slackChannelRally': $defaultMapConfigKey = 'send_rally_slack_enabled'; break;
|
||||
default: throw new PathfinderException(sprintf(self::ERROR_SLACK_CHANNEL, $channel));
|
||||
default: throw new ConfigException(sprintf(self::ERROR_SLACK_CHANNEL, $channel));
|
||||
}
|
||||
|
||||
if((bool) Config::getMapsDefaultConfig($this->typeId->name)[$defaultMapConfigKey]){
|
||||
@@ -1095,7 +1091,7 @@ class MapModel extends AbstractMapTrackingModel {
|
||||
* check if "Discord WebHook" is enabled for this map type
|
||||
* @param string $channel
|
||||
* @return bool
|
||||
* @throws PathfinderException
|
||||
* @throws ConfigException
|
||||
*/
|
||||
public function isDiscordChannelEnabled(string $channel): bool {
|
||||
$enabled = false;
|
||||
@@ -1105,7 +1101,7 @@ class MapModel extends AbstractMapTrackingModel {
|
||||
switch($channel){
|
||||
case 'discordWebHookURLHistory': $defaultMapConfigKey = 'send_history_discord_enabled'; break;
|
||||
case 'discordWebHookURLRally': $defaultMapConfigKey = 'send_rally_discord_enabled'; break;
|
||||
default: throw new PathfinderException(sprintf(self::ERROR_DISCORD_CHANNEL, $channel));
|
||||
default: throw new ConfigException(sprintf(self::ERROR_DISCORD_CHANNEL, $channel));
|
||||
}
|
||||
|
||||
if((bool) Config::getMapsDefaultConfig($this->typeId->name)[$defaultMapConfigKey]){
|
||||
@@ -1123,7 +1119,6 @@ class MapModel extends AbstractMapTrackingModel {
|
||||
* check if "E-Mail" Log is enabled for this map
|
||||
* @param string $type
|
||||
* @return bool
|
||||
* @throws PathfinderException
|
||||
*/
|
||||
public function isMailSendEnabled(string $type): bool{
|
||||
$enabled = false;
|
||||
@@ -1197,7 +1192,6 @@ class MapModel extends AbstractMapTrackingModel {
|
||||
* @param string $type
|
||||
* @param bool $addJson
|
||||
* @return \stdClass
|
||||
* @throws PathfinderException
|
||||
*/
|
||||
public function getSMTPConfig(string $type, bool $addJson = true): \stdClass{
|
||||
$config = Config::getSMTPConfig();
|
||||
@@ -1350,7 +1344,6 @@ class MapModel extends AbstractMapTrackingModel {
|
||||
* get all active characters (with active log)
|
||||
* grouped by systems
|
||||
* @return \stdClass
|
||||
* @throws PathfinderException
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function getUserData(){
|
||||
|
||||
@@ -95,8 +95,6 @@ class SystemModel extends AbstractMapTrackingModel {
|
||||
],
|
||||
'description' => [
|
||||
'type' => Schema::DT_TEXT,
|
||||
'nullable' => false,
|
||||
'default' => '',
|
||||
'activity-log' => true,
|
||||
'validate' => true
|
||||
],
|
||||
@@ -151,7 +149,7 @@ class SystemModel extends AbstractMapTrackingModel {
|
||||
$systemData->locked = $this->locked;
|
||||
$systemData->rallyUpdated = strtotime($this->rallyUpdated);
|
||||
$systemData->rallyPoke = $this->rallyPoke;
|
||||
$systemData->description = $this->description;
|
||||
$systemData->description = $this->description ? : '';
|
||||
|
||||
$systemData->position = (object) [];
|
||||
$systemData->position->x = $this->posX;
|
||||
@@ -490,8 +488,8 @@ class SystemModel extends AbstractMapTrackingModel {
|
||||
|
||||
/**
|
||||
* @param string $action
|
||||
* @return Logging\LogInterface
|
||||
* @throws \Exception\PathfinderException
|
||||
* @return logging\LogInterface
|
||||
* @throws \Exception\ConfigException
|
||||
*/
|
||||
public function newLog($action = ''): Logging\LogInterface{
|
||||
return $this->getMap()->newLog($action)->setTempData($this->getLogObjectData());
|
||||
@@ -654,7 +652,7 @@ class SystemModel extends AbstractMapTrackingModel {
|
||||
* -> send to an Email
|
||||
* @param array $rallyData
|
||||
* @param CharacterModel $characterModel
|
||||
* @throws \Exception\PathfinderException
|
||||
* @throws \Exception\ConfigException
|
||||
*/
|
||||
public function sendRallyPoke(array $rallyData, CharacterModel $characterModel){
|
||||
// rally log needs at least one handler to be valid
|
||||
|
||||
@@ -162,8 +162,8 @@ class SystemSignatureModel extends AbstractMapTrackingModel {
|
||||
|
||||
/**
|
||||
* @param string $action
|
||||
* @return Logging\LogInterface
|
||||
* @throws \Exception\PathfinderException
|
||||
* @return logging\LogInterface
|
||||
* @throws \Exception\ConfigException
|
||||
*/
|
||||
public function newLog($action = ''): Logging\LogInterface{
|
||||
return $this->getMap()->newLog($action)->setTempData($this->getLogObjectData());
|
||||
|
||||
@@ -33,14 +33,15 @@ class CategoryModel extends BasicUniverseModel {
|
||||
|
||||
/**
|
||||
* get category data
|
||||
* @return object
|
||||
* @param array $additionalData
|
||||
* @return null|object
|
||||
*/
|
||||
public function getData(){
|
||||
public function getData(array $additionalData = []){
|
||||
$categoryData = (object) [];
|
||||
$categoryData->id = $this->id;
|
||||
$categoryData->name = $this->name;
|
||||
|
||||
if($groupsData = $this->getGroupsData()){
|
||||
if($groupsData = $this->getGroupsData($additionalData)){
|
||||
$categoryData->groups = $groupsData;
|
||||
}
|
||||
|
||||
@@ -69,14 +70,15 @@ class CategoryModel extends BasicUniverseModel {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $additionalData
|
||||
* @return array
|
||||
*/
|
||||
protected function getGroupsData() : array {
|
||||
protected function getGroupsData(array $additionalData = []) : array {
|
||||
$groupsData = [];
|
||||
$groups = $this->getGroups();
|
||||
|
||||
foreach($groups as $group){
|
||||
$groupsData[] = $group->getData();
|
||||
$groupsData[] = $group->getData($additionalData);
|
||||
}
|
||||
|
||||
return $groupsData;
|
||||
|
||||
@@ -30,7 +30,7 @@ class ConstellationModel extends BasicUniverseModel {
|
||||
'on-delete' => 'CASCADE'
|
||||
]
|
||||
],
|
||||
'validate' => 'validate_notDry'
|
||||
'validate' => 'notDry'
|
||||
],
|
||||
'x' => [
|
||||
'type' => Schema::DT_BIGINT,
|
||||
|
||||
@@ -36,7 +36,7 @@ class GroupModel extends BasicUniverseModel {
|
||||
'on-delete' => 'CASCADE'
|
||||
]
|
||||
],
|
||||
'validate' => 'validate_notDry'
|
||||
'validate' => 'notDry'
|
||||
],
|
||||
'types' => [
|
||||
'has-many' => ['Model\Universe\TypeModel', 'groupId']
|
||||
@@ -45,14 +45,15 @@ class GroupModel extends BasicUniverseModel {
|
||||
|
||||
/**
|
||||
* get group data
|
||||
* @return object
|
||||
* @param array $additionalData
|
||||
* @return null|object
|
||||
*/
|
||||
public function getData(){
|
||||
public function getData(array $additionalData = []){
|
||||
$groupData = (object) [];
|
||||
$groupData->id = $this->id;
|
||||
$groupData->name = $this->name;
|
||||
|
||||
if($typesData = $this->getTypesData()){
|
||||
if($typesData = $this->getTypesData($additionalData)){
|
||||
$groupData->types = $typesData;
|
||||
}
|
||||
|
||||
@@ -81,14 +82,15 @@ class GroupModel extends BasicUniverseModel {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $additionalData
|
||||
* @return array
|
||||
*/
|
||||
protected function getTypesData() : array {
|
||||
protected function getTypesData(array $additionalData = []) : array {
|
||||
$typesData = [];
|
||||
$types = $this->getTypes();
|
||||
|
||||
foreach($types as $type){
|
||||
$typesData[] = $type->getData();
|
||||
$typesData[] = $type->getData($additionalData);
|
||||
}
|
||||
|
||||
return $typesData;
|
||||
|
||||
@@ -30,7 +30,7 @@ class PlanetModel extends BasicUniverseModel {
|
||||
'on-delete' => 'CASCADE'
|
||||
]
|
||||
],
|
||||
'validate' => 'validate_notDry'
|
||||
'validate' => 'notDry'
|
||||
],
|
||||
'typeId' => [
|
||||
'type' => Schema::DT_INT,
|
||||
@@ -42,7 +42,7 @@ class PlanetModel extends BasicUniverseModel {
|
||||
'on-delete' => 'SET NULL'
|
||||
]
|
||||
],
|
||||
'validate' => 'validate_notDry'
|
||||
'validate' => 'notDry'
|
||||
],
|
||||
'x' => [
|
||||
'type' => Schema::DT_BIGINT,
|
||||
|
||||
@@ -30,7 +30,7 @@ class StargateModel extends BasicUniverseModel {
|
||||
'on-delete' => 'CASCADE'
|
||||
]
|
||||
],
|
||||
'validate' => 'validate_notDry'
|
||||
'validate' => 'notDry'
|
||||
],
|
||||
'typeId' => [
|
||||
'type' => Schema::DT_INT,
|
||||
@@ -42,7 +42,7 @@ class StargateModel extends BasicUniverseModel {
|
||||
'on-delete' => 'SET NULL'
|
||||
]
|
||||
],
|
||||
'validate' => 'validate_notDry'
|
||||
'validate' => 'notDry'
|
||||
],
|
||||
'destinationSystemId' => [
|
||||
'type' => Schema::DT_INT,
|
||||
@@ -54,7 +54,7 @@ class StargateModel extends BasicUniverseModel {
|
||||
'on-delete' => 'CASCADE'
|
||||
]
|
||||
],
|
||||
'validate' => 'validate_notDry'
|
||||
'validate' => 'notDry'
|
||||
],
|
||||
'x' => [
|
||||
'type' => Schema::DT_BIGINT,
|
||||
|
||||
@@ -30,7 +30,7 @@ class StarModel extends BasicUniverseModel {
|
||||
'on-delete' => 'SET NULL'
|
||||
]
|
||||
],
|
||||
'validate' => 'validate_notDry'
|
||||
'validate' => 'notDry'
|
||||
],
|
||||
'age' => [
|
||||
'type' => Schema::DT_BIGINT,
|
||||
|
||||
@@ -37,7 +37,7 @@ class StructureModel extends BasicUniverseModel {
|
||||
'on-delete' => 'CASCADE'
|
||||
]
|
||||
],
|
||||
'validate' => 'validate_notDry'
|
||||
'validate' => 'notDry'
|
||||
],
|
||||
'x' => [
|
||||
'type' => Schema::DT_FLOAT,
|
||||
|
||||
@@ -32,7 +32,7 @@ class SystemModel extends BasicUniverseModel {
|
||||
'on-delete' => 'CASCADE'
|
||||
]
|
||||
],
|
||||
'validate' => 'validate_notDry'
|
||||
'validate' => 'notDry'
|
||||
],
|
||||
'starId' => [
|
||||
'type' => Schema::DT_INT,
|
||||
@@ -44,7 +44,7 @@ class SystemModel extends BasicUniverseModel {
|
||||
'on-delete' => 'CASCADE'
|
||||
]
|
||||
],
|
||||
'validate' => 'validate_notDry'
|
||||
'validate' => 'notDry'
|
||||
],
|
||||
'security' => [
|
||||
'type' => Schema::DT_VARCHAR128
|
||||
|
||||
@@ -25,7 +25,7 @@ class SystemStaticModel extends BasicUniverseModel {
|
||||
'on-delete' => 'CASCADE'
|
||||
]
|
||||
],
|
||||
'validate' => 'validate_notDry'
|
||||
'validate' => 'notDry'
|
||||
],
|
||||
'wormholeId' => [
|
||||
'type' => Schema::DT_INT,
|
||||
@@ -37,7 +37,7 @@ class SystemStaticModel extends BasicUniverseModel {
|
||||
'on-delete' => 'CASCADE'
|
||||
]
|
||||
],
|
||||
'validate' => 'validate_notDry'
|
||||
'validate' => 'notDry'
|
||||
]
|
||||
];
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@ class TypeModel extends BasicUniverseModel {
|
||||
'on-delete' => 'CASCADE'
|
||||
]
|
||||
],
|
||||
'validate' => 'validate_notDry',
|
||||
'validate' => 'notDry',
|
||||
],
|
||||
'marketGroupId' => [
|
||||
'type' => Schema::DT_INT,
|
||||
@@ -99,13 +99,18 @@ class TypeModel extends BasicUniverseModel {
|
||||
|
||||
/**
|
||||
* get type data
|
||||
* @return object
|
||||
* @param array $additionalData
|
||||
* @return null|object
|
||||
*/
|
||||
public function getData(){
|
||||
public function getData(array $additionalData = []){
|
||||
$typeData = (object) [];
|
||||
$typeData->id = $this->id;
|
||||
$typeData->name = $this->name;
|
||||
|
||||
foreach($additionalData as $key){
|
||||
$typeData->$key = $this->$key;
|
||||
}
|
||||
|
||||
return $typeData;
|
||||
}
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ class WormholeModel extends BasicUniverseModel {
|
||||
'on-delete' => 'SET NULL'
|
||||
]
|
||||
],
|
||||
'validate' => 'validate_notDry'
|
||||
'validate' => 'notDry'
|
||||
],
|
||||
'static' => [
|
||||
'type' => Schema::DT_BOOL,
|
||||
|
||||
@@ -94,7 +94,6 @@ class UserModel extends BasicModel {
|
||||
* @param UserModel $self
|
||||
* @param $pkeys
|
||||
* @return bool
|
||||
* @throws Exception\PathfinderException
|
||||
* @throws Exception\RegistrationException
|
||||
*/
|
||||
public function beforeInsertEvent($self, $pkeys){
|
||||
@@ -137,7 +136,6 @@ class UserModel extends BasicModel {
|
||||
/**
|
||||
* checks whether user has a valid email address and pathfinder has a valid SMTP config
|
||||
* @return bool
|
||||
* @throws Exception\PathfinderException
|
||||
*/
|
||||
protected function isMailSendEnabled() : bool{
|
||||
return Config::isValidSMTPConfig($this->getSMTPConfig());
|
||||
@@ -146,7 +144,6 @@ class UserModel extends BasicModel {
|
||||
/**
|
||||
* get SMTP config for this user
|
||||
* @return \stdClass
|
||||
* @throws Exception\PathfinderException
|
||||
*/
|
||||
protected function getSMTPConfig() : \stdClass{
|
||||
$config = Config::getSMTPConfig();
|
||||
|
||||
@@ -18,3 +18,6 @@ GET|POST /api/@controller/@action [ajax] = Controller\Api\@cont
|
||||
GET|POST /api/@controller/@action/@arg1 [ajax] = Controller\Api\@controller->@action, 0, 512
|
||||
GET|POST /api/@controller/@action/@arg1/@arg2 [ajax] = Controller\Api\@controller->@action, 0, 512
|
||||
|
||||
[maps]
|
||||
/api/rest/@controller* [ajax] = Controller\Api\Rest\@controller, 0, 512
|
||||
/api/rest/@controller/@id [ajax] = Controller\Api\Rest\@controller, 0, 512
|
||||
@@ -21,6 +21,8 @@
|
||||
}],
|
||||
"require": {
|
||||
"php-64bit": ">=7.0",
|
||||
"ext-pdo": "*",
|
||||
"ext-openssl": "*",
|
||||
"ext-curl": "*",
|
||||
"ext-json": "*",
|
||||
"ext-mbstring": "*",
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
}],
|
||||
"require": {
|
||||
"php-64bit": ">=7.0",
|
||||
"ext-pdo": "*",
|
||||
"ext-openssl": "*",
|
||||
"ext-curl": "*",
|
||||
"ext-json": "*",
|
||||
"ext-mbstring": "*",
|
||||
|
||||
@@ -54,7 +54,7 @@ requirejs.config({
|
||||
blueImpGalleryBootstrap: 'lib/bootstrap-image-gallery', // v3.4.2 Bootstrap extension for Blue Imp Gallery - https://blueimp.github.io/Bootstrap-Image-Gallery
|
||||
bootstrapConfirmation: 'lib/bootstrap-confirmation', // v1.0.5 Bootstrap extension for inline confirm dialog - https://github.com/tavicu/bs-confirmation
|
||||
bootstrapToggle: 'lib/bootstrap-toggle.min', // v2.2.0 Bootstrap Toggle (Checkbox) - http://www.bootstraptoggle.com
|
||||
lazyload: 'lib/jquery.lazyload.min', // v1.9.5 LazyLoader images - http://www.appelsiini.net/projects/lazyload
|
||||
lazyload: 'lib/jquery.lazyload.min', // v1.9.7 LazyLoader images - http://www.appelsiini.net/projects/lazyload
|
||||
sortable: 'lib/sortable.min', // v1.6.0 Sortable - drag&drop reorder - https://github.com/rubaxa/Sortable
|
||||
|
||||
'summernote.loader': './app/summernote.loader', // v0.8.10 Summernote WYSIWYG editor -https://summernote.org
|
||||
|
||||
@@ -18,6 +18,9 @@ define([
|
||||
lengthMenu: [[5, 10, 25, 50, -1], [5, 10, 25, 50, 'All']],
|
||||
order: [], // no default order because columnDefs is empty
|
||||
autoWidth: false,
|
||||
language: {
|
||||
info: '_START_ - _END_ of _TOTAL_ entries'
|
||||
},
|
||||
responsive: {
|
||||
breakpoints: Init.breakpoints,
|
||||
details: false
|
||||
|
||||
@@ -9,6 +9,7 @@ define(['jquery'], ($) => {
|
||||
let Config = {
|
||||
path: {
|
||||
img: '/public/img/', // path for images
|
||||
api: '/api/rest', //ajax URL - REST API
|
||||
// user API
|
||||
getCaptcha: '/api/user/getCaptcha', // ajax URL - get captcha image
|
||||
getServerStatus: '/api/user/getEveServerStatus', // ajax URL - get EVE-Online server status
|
||||
|
||||
@@ -343,7 +343,7 @@ define([
|
||||
let initGallery = (newElements) => {
|
||||
if( newElements.length > 0){
|
||||
// We have to add ALL thumbnail elements to the gallery!
|
||||
// -> even those wthat are invisible (not lazyLoaded) now!
|
||||
// -> even those which are invisible (not lazyLoaded) now!
|
||||
// -> This is required for "swipe" through all images
|
||||
let allThumbLinks = getThumbnailElements();
|
||||
|
||||
@@ -814,7 +814,7 @@ define([
|
||||
// init carousel
|
||||
initCarousel();
|
||||
|
||||
// init scrollspy
|
||||
// init scrollSpy
|
||||
// -> after "Carousel"! required for correct "viewport" calculation (Gallery)!
|
||||
initScrollSpy();
|
||||
|
||||
|
||||
@@ -79,15 +79,21 @@ define([
|
||||
|
||||
let reason = status + ' ' + jqXHR.status + ': ' + error;
|
||||
let errorData = [];
|
||||
let redirect = false; // redirect user to other page e.g. login
|
||||
let reload = true; // reload current page (default: true)
|
||||
|
||||
if(jqXHR.responseJSON){
|
||||
// handle JSON
|
||||
let errorObj = jqXHR.responseJSON;
|
||||
let responseObj = jqXHR.responseJSON;
|
||||
if(
|
||||
errorObj.error &&
|
||||
errorObj.error.length > 0
|
||||
responseObj.error &&
|
||||
responseObj.error.length > 0
|
||||
){
|
||||
errorData = errorObj.error;
|
||||
errorData = responseObj.error;
|
||||
}
|
||||
|
||||
if(responseObj.reroute){
|
||||
redirect = responseObj.reroute;
|
||||
}
|
||||
}else{
|
||||
// handle HTML
|
||||
@@ -98,7 +104,13 @@ define([
|
||||
}
|
||||
|
||||
console.error(' ↪ %s Error response: %o', jqXHR.url, errorData);
|
||||
$(document).trigger('pf:shutdown', {status: jqXHR.status, reason: reason, error: errorData});
|
||||
$(document).trigger('pf:shutdown', {
|
||||
status: jqXHR.status,
|
||||
reason: reason,
|
||||
error: errorData,
|
||||
redirect: redirect,
|
||||
reload: reload
|
||||
});
|
||||
};
|
||||
|
||||
// map init functions =========================================================================================
|
||||
|
||||
@@ -787,12 +787,14 @@ define([
|
||||
label: '<i class="fas fa-fw fa-sync"></i> restart',
|
||||
className: ['btn-primary'].join(' '),
|
||||
callback: function(){
|
||||
// check if error was 5xx -> reload page
|
||||
// -> else try to logout -> ajax request
|
||||
if(data.status >= 500 && data.status < 600){
|
||||
// redirect to login
|
||||
window.location = '../';
|
||||
if(data.redirect) {
|
||||
// ... redirect user to e.g. login form page ...
|
||||
Util.redirect(data.redirect, ['logout']);
|
||||
}else if(data.reload){
|
||||
// ... or reload current page ...
|
||||
location.reload();
|
||||
}else{
|
||||
// ... fallback try to logout user
|
||||
documentElement.trigger('pf:menuLogout');
|
||||
}
|
||||
}
|
||||
@@ -811,12 +813,9 @@ define([
|
||||
};
|
||||
|
||||
// add error information (if available)
|
||||
if(
|
||||
data.error &&
|
||||
data.error.length
|
||||
){
|
||||
for(let i = 0; i < data.error.length; i++){
|
||||
options.content.textSmaller.push(data.error[i].message);
|
||||
if(data.error && data.error.length){
|
||||
for(let error of data.error){
|
||||
options.content.textSmaller.push(error.message);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -76,7 +76,7 @@ define([
|
||||
dialogElement.find('.modal-content').hideLoadingAnimation();
|
||||
|
||||
if(responseData.reroute !== undefined){
|
||||
Util.redirect(responseData.reroute, []);
|
||||
Util.redirect(responseData.reroute);
|
||||
}else if(
|
||||
responseData.error &&
|
||||
responseData.error.length > 0
|
||||
|
||||
@@ -753,7 +753,7 @@ define([
|
||||
* show activity stats dialog
|
||||
*/
|
||||
$.fn.showStatsDialog = function(){
|
||||
requirejs(['text!templates/dialog/stats.html', 'mustache', 'datatables.loader'], function(template, Mustache){
|
||||
requirejs(['text!templates/dialog/stats.html', 'mustache', 'datatables.loader'], (template, Mustache) => {
|
||||
// get current statistics map settings
|
||||
let logActivityEnabled = false;
|
||||
let activeMap = Util.getMapModule().getActiveMap();
|
||||
|
||||
@@ -12,7 +12,8 @@ define([
|
||||
|
||||
let config = {
|
||||
// Select2
|
||||
resultOptionImageClass: 'pf-result-image' // class for Select2 result option entry with image
|
||||
resultOptionImageClass: 'pf-result-image', // class for Select2 result option entry with image
|
||||
select2ImageLazyLoadClass: 'pf-select2-image-lazyLoad' // class for Select2 result images that should be lazy loaded
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -60,7 +61,7 @@ define([
|
||||
}
|
||||
|
||||
if(imagePath){
|
||||
thumb = '<img src="' + imagePath + '" style="max-width: 100%" />';
|
||||
thumb = '<img class="' + config.select2ImageLazyLoadClass + '" data-original="' + imagePath + '" style="max-width: 100%"/>';
|
||||
}else if(iconName){
|
||||
thumb = '<i class="fas fa-fw ' + iconName + '" ></i>';
|
||||
}
|
||||
@@ -564,6 +565,7 @@ define([
|
||||
return group;
|
||||
});
|
||||
},*/
|
||||
disabled: options.hasOwnProperty('disabled') ? options.disabled : false,
|
||||
allowClear: options.maxSelectionLength <= 1,
|
||||
maximumSelectionLength: options.maxSelectionLength,
|
||||
templateResult: formatCategoryTypeResultData
|
||||
@@ -605,6 +607,7 @@ define([
|
||||
return {
|
||||
id: type.id,
|
||||
text: type.name,
|
||||
mass: type.hasOwnProperty('mass') ? type.mass : null,
|
||||
groupId: this.groupId,
|
||||
categoryId: this.categoryId,
|
||||
categoryType: this.categoryType
|
||||
|
||||
@@ -6,8 +6,9 @@ define([
|
||||
'jquery',
|
||||
'app/init',
|
||||
'app/util',
|
||||
'bootbox',
|
||||
'app/map/util'
|
||||
], ($, Init, Util, MapUtil) => {
|
||||
], ($, Init, Util, bootbox, MapUtil) => {
|
||||
'use strict';
|
||||
|
||||
let config = {
|
||||
@@ -46,9 +47,17 @@ define([
|
||||
connectionInfoTableCellMassLeftClass: 'pf-connection-info-mass-left', // class for "mass left" table cell
|
||||
|
||||
// dataTable
|
||||
tableToolbarCondensedClass: 'pf-dataTable-condensed-toolbar', // class for condensed table toolbar
|
||||
connectionInfoTableClass: 'pf-connection-info-table', // class for connection tables
|
||||
tableCellImageClass: 'pf-table-image-cell', // class for table "image" cells
|
||||
tableCellCounterClass: 'pf-table-counter-cell', // class for table "counter" cells
|
||||
tableCellActionClass: 'pf-table-action-cell', // class for "action" cells
|
||||
|
||||
// connection dialog
|
||||
connectionDialogId: 'pf-connection-info-dialog', // id for "connection" dialog
|
||||
typeSelectId: 'pf-connection-info-dialog-type-select', // id for "ship type" select
|
||||
shipMassId: 'pf-connection-info-dialog-mass', // id for "ship mass" input
|
||||
characterSelectId: 'pf-connection-info-dialog-character-select', // id for "character" select
|
||||
|
||||
// config
|
||||
showShip: true // default for "show current ship mass" toggle
|
||||
@@ -511,6 +520,34 @@ define([
|
||||
return moduleElement.find('.' + config.connectionInfoPanelClass).not('#' + getConnectionElementId(0));
|
||||
};
|
||||
|
||||
/**
|
||||
* enrich connectionData with "logs" data (if available) and other "missing" data
|
||||
* @param connectionsData
|
||||
* @param newConnectionsData
|
||||
* @returns {*}
|
||||
*/
|
||||
let enrichConnectionsData = (connectionsData, newConnectionsData) => {
|
||||
for(let i = 0; i < connectionsData.length; i++){
|
||||
for(let newConnectionData of newConnectionsData){
|
||||
if(connectionsData[i].id === newConnectionData.id){
|
||||
// copy some missing data
|
||||
connectionsData[i].character = newConnectionData.character;
|
||||
connectionsData[i].created = newConnectionData.created;
|
||||
// check for mass logs and copy data
|
||||
if(newConnectionData.logs && newConnectionData.logs.length){
|
||||
connectionsData[i].logs = newConnectionData.logs;
|
||||
}
|
||||
// check for signatures and copy data
|
||||
if(newConnectionData.signatures && newConnectionData.signatures.length){
|
||||
connectionsData[i].signatures = newConnectionData.signatures;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return connectionsData;
|
||||
};
|
||||
|
||||
/**
|
||||
* request connection log data
|
||||
* @param requestData
|
||||
@@ -530,24 +567,7 @@ define([
|
||||
dataType: 'json',
|
||||
context: context
|
||||
}).done(function(connectionsData){
|
||||
// enrich connectionData with "logs" data (if available) and other "missing" data
|
||||
for(let i = 0; i < this.connectionsData.length; i++){
|
||||
for(let connectionData of connectionsData){
|
||||
if(this.connectionsData[i].id === connectionData.id){
|
||||
// copy some missing data
|
||||
this.connectionsData[i].created = connectionData.created;
|
||||
// check for mass logs and copy data
|
||||
if(connectionData.logs && connectionData.logs.length){
|
||||
this.connectionsData[i].logs = connectionData.logs;
|
||||
}
|
||||
// check for signatures and copy data
|
||||
if(connectionData.signatures && connectionData.signatures.length){
|
||||
this.connectionsData[i].signatures = connectionData.signatures;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
this.connectionsData = enrichConnectionsData(this.connectionsData, connectionsData);
|
||||
|
||||
callback(this.moduleElement, this.connectionsData);
|
||||
}).always(function(){
|
||||
@@ -592,9 +612,9 @@ define([
|
||||
*/
|
||||
let addConnectionsData = (moduleElement, connectionsData) => {
|
||||
|
||||
let getRowIndexesByData = (dataTable, colName, value) => {
|
||||
return dataTable.rows().eq(0).filter((rowIdx) => {
|
||||
return (dataTable.cell(rowIdx, colName + ':name').data() === value);
|
||||
let getRowIndexesByData = (tableApi, colName, value) => {
|
||||
return tableApi.rows().eq(0).filter((rowIdx) => {
|
||||
return (tableApi.cell(rowIdx, colName + ':name').data() === value);
|
||||
});
|
||||
};
|
||||
|
||||
@@ -607,42 +627,47 @@ define([
|
||||
connectionInfoElement.data('connectionData', connectionData);
|
||||
|
||||
// update dataTable ---------------------------------------------------------------
|
||||
let dataTable = connectionElement.find('.dataTable').dataTable().api();
|
||||
let tableApi = connectionElement.find('.dataTable').dataTable().api();
|
||||
|
||||
if(connectionData.logs && connectionData.logs.length > 0){
|
||||
for(let i = 0; i < connectionData.logs.length; i++){
|
||||
let rowData = connectionData.logs[i];
|
||||
let row = null;
|
||||
let rowNew = null;
|
||||
let animationStatus = null;
|
||||
let indexes = getRowIndexesByData(dataTable, 'index', rowData.id);
|
||||
let indexes = getRowIndexesByData(tableApi, 'index', rowData.id);
|
||||
if(indexes.length === 0){
|
||||
// row not found -> add new row
|
||||
row = dataTable.row.add( rowData );
|
||||
rowNew = tableApi.row.add(rowData);
|
||||
animationStatus = 'added';
|
||||
}
|
||||
/* else{
|
||||
// we DON´t expect changes -> no row update)
|
||||
}else{
|
||||
// update row with FIRST index
|
||||
//row = dataTable.row( parseInt(indexes[0]) );
|
||||
// update row data
|
||||
//row.data(connectionData.logs[i]);
|
||||
//animationStatus = 'changed';
|
||||
} */
|
||||
let row = tableApi.row( parseInt(indexes[0]));
|
||||
let rowDataCurrent = row.data();
|
||||
|
||||
// check if row data changed
|
||||
if(rowDataCurrent.updated.updated !== rowData.updated.updated){
|
||||
// ... row changed -> delete old and re-add
|
||||
// -> cell actions might have changed
|
||||
row.remove();
|
||||
rowNew = tableApi.row.add(rowData);
|
||||
animationStatus = 'changed';
|
||||
}
|
||||
}
|
||||
|
||||
if(
|
||||
animationStatus !== null &&
|
||||
row.length > 0
|
||||
rowNew.length > 0
|
||||
){
|
||||
row.nodes().to$().data('animationStatus', animationStatus);
|
||||
rowNew.nodes().to$().data('animationStatus', animationStatus);
|
||||
}
|
||||
}
|
||||
}else{
|
||||
// clear table or leave empty
|
||||
dataTable.clear();
|
||||
tableApi.clear();
|
||||
}
|
||||
|
||||
// redraw dataTable
|
||||
dataTable.draw(false);
|
||||
tableApi.draw(false);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -663,11 +688,45 @@ define([
|
||||
|
||||
let table = $('<table>', {
|
||||
class: ['compact', 'stripe', 'order-column', 'row-border', 'nowrap', config.connectionInfoTableClass].join(' ')
|
||||
}).append('<tfoot><tr><th></th><th></th><th></th><th></th><th></th></tr></tfoot>');
|
||||
}).append('<tfoot><tr><th></th><th></th><th></th><th></th><th></th><th></th><th></th></tr></tfoot>');
|
||||
connectionElement.append(table);
|
||||
|
||||
// init empty table
|
||||
let logTable = table.DataTable({
|
||||
dom: '<"container-fluid"' +
|
||||
'<"row ' + config.tableToolbarCondensedClass + '"' +
|
||||
'<"col-xs-5"i><"col-xs-5"p><"col-xs-2 text-right"B>>' +
|
||||
'<"row"tr>>',
|
||||
buttons: {
|
||||
name: 'tableTools',
|
||||
buttons: [
|
||||
{
|
||||
name: 'addLog',
|
||||
className: config.moduleHeadlineIconClass,
|
||||
text: '<i class="fa fa-plus"></i>',
|
||||
action: function(e, tableApi, node, conf){
|
||||
let logData = {};
|
||||
|
||||
// pre-fill form with current character data (if available)
|
||||
let currentUserData = Util.getCurrentUserData();
|
||||
if(currentUserData && currentUserData.character){
|
||||
logData.character = {
|
||||
id: currentUserData.character.id,
|
||||
name: currentUserData.character.name
|
||||
};
|
||||
if(currentUserData.character.log){
|
||||
logData.ship = {
|
||||
id: currentUserData.character.log.ship.typeId,
|
||||
name: currentUserData.character.log.ship.typeName
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
showLogDialog(moduleElement, connectionElement, connectionData, logData);
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
pageLength: 8,
|
||||
paging: true,
|
||||
pagingType: 'simple',
|
||||
@@ -678,11 +737,14 @@ define([
|
||||
searching: false,
|
||||
hover: false,
|
||||
autoWidth: false,
|
||||
// rowId: 'systemTo',
|
||||
language: {
|
||||
emptyTable: 'No jumps recorded',
|
||||
info: '_START_ to _END_ of _MAX_',
|
||||
infoEmpty: ''
|
||||
info: '_START_ - _END_ of _MAX_',
|
||||
infoEmpty: '',
|
||||
paginate: {
|
||||
previous: '',
|
||||
next: ''
|
||||
}
|
||||
},
|
||||
columnDefs: [
|
||||
{
|
||||
@@ -692,10 +754,25 @@ define([
|
||||
orderable: false,
|
||||
searchable: false,
|
||||
width: 20,
|
||||
class: 'text-center',
|
||||
data: 'id'
|
||||
className: ['text-center', 'txt-color'].join(' '),
|
||||
data: 'id',
|
||||
createdCell: function(cell, cellData, rowData, rowIndex, colIndex){
|
||||
if(
|
||||
!rowData.record ||
|
||||
(rowData.updated.updated !== rowData.created.created)
|
||||
){
|
||||
// log was manually modified or added
|
||||
$(cell)
|
||||
.addClass(Util.config.helpClass)
|
||||
.addClass( 'txt-color-orange').tooltip({
|
||||
container: 'body',
|
||||
title: 'added/updated manually'
|
||||
});
|
||||
}
|
||||
}
|
||||
},{
|
||||
targets: 1,
|
||||
name: 'ship',
|
||||
title: '',
|
||||
width: 26,
|
||||
orderable: false,
|
||||
@@ -715,16 +792,17 @@ define([
|
||||
}
|
||||
},{
|
||||
targets: 2,
|
||||
name: 'character',
|
||||
title: '',
|
||||
width: 26,
|
||||
orderable: false,
|
||||
className: [Util.config.helpDefaultClass, 'text-center', config.tableCellImageClass].join(' '),
|
||||
data: 'created.character',
|
||||
data: 'character',
|
||||
render: {
|
||||
_: function(data, type, row){
|
||||
let value = data.name;
|
||||
_: (cellData, type, rowData, meta) => {
|
||||
let value = cellData.name;
|
||||
if(type === 'display'){
|
||||
value = '<img src="' + Init.url.ccpImageServer + '/Character/' + data.id + '_32.jpg" title="' + value + '" data-toggle="tooltip" />';
|
||||
value = '<img src="' + Init.url.ccpImageServer + '/Character/' + cellData.id + '_32.jpg" title="' + value + '" data-toggle="tooltip" />';
|
||||
}
|
||||
return value;
|
||||
}
|
||||
@@ -734,20 +812,26 @@ define([
|
||||
}
|
||||
},{
|
||||
targets: 3,
|
||||
name: 'mass',
|
||||
title: 'mass',
|
||||
className: ['text-right'].join(' ') ,
|
||||
data: 'ship.mass',
|
||||
render: {
|
||||
_: function(data, type, row){
|
||||
let value = data;
|
||||
_: (cellData, type, rowData, meta) => {
|
||||
let value = cellData;
|
||||
if(type === 'display'){
|
||||
value = Util.formatMassValue(value);
|
||||
if(!rowData.active){
|
||||
// log is "deleted"
|
||||
value = '<span class="pf-font-line-through txt-color txt-color-red">' + value + '</span>';
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
},{
|
||||
targets: 4,
|
||||
name: 'created',
|
||||
title: 'log',
|
||||
width: 55,
|
||||
className: ['text-right', config.tableCellCounterClass].join(' '),
|
||||
@@ -755,6 +839,108 @@ define([
|
||||
createdCell: function(cell, cellData, rowData, rowIndex, colIndex){
|
||||
$(cell).initTimestampCounter('d');
|
||||
}
|
||||
},{
|
||||
targets: 5,
|
||||
name: 'edit',
|
||||
title: '',
|
||||
orderable: false,
|
||||
searchable: false,
|
||||
width: 10,
|
||||
className: ['text-center', config.tableCellActionClass, config.moduleHeadlineIconClass].join(' '),
|
||||
data: null,
|
||||
render: {
|
||||
display: data => {
|
||||
let icon = '';
|
||||
if(data.active){
|
||||
icon = '<i class="fas fa-pen"></i>';
|
||||
}
|
||||
return icon;
|
||||
}
|
||||
},
|
||||
createdCell: function(cell, cellData, rowData, rowIndex, colIndex){
|
||||
let tableApi = this.api();
|
||||
|
||||
if($(cell).is(':empty')){
|
||||
$(cell).removeClass(config.tableCellActionClass + ' ' + config.moduleHeadlineIconClass);
|
||||
}else{
|
||||
$(cell).on('click', function(e){
|
||||
showLogDialog(moduleElement, connectionElement, connectionData, rowData);
|
||||
});
|
||||
}
|
||||
}
|
||||
},{
|
||||
targets: 6,
|
||||
name: 'delete',
|
||||
title: '',
|
||||
orderable: false,
|
||||
searchable: false,
|
||||
width: 10,
|
||||
className: ['text-center', config.tableCellActionClass].join(' '),
|
||||
data: 'active',
|
||||
render: {
|
||||
display: data => {
|
||||
let val = '<i class="fas fa-plus"></i>';
|
||||
if(data){
|
||||
val = '<i class="fas fa-times txt-color txt-color-redDarker"></i>';
|
||||
}
|
||||
return val;
|
||||
}
|
||||
},
|
||||
createdCell: function(cell, cellData, rowData, rowIndex, colIndex){
|
||||
let tableApi = this.api();
|
||||
|
||||
if(rowData.active){
|
||||
let confirmationSettings = {
|
||||
container: 'body',
|
||||
placement: 'left',
|
||||
btnCancelClass: 'btn btn-sm btn-default',
|
||||
btnCancelLabel: 'cancel',
|
||||
btnCancelIcon: 'fas fa-fw fa-ban',
|
||||
title: 'delete jump log',
|
||||
btnOkClass: 'btn btn-sm btn-danger',
|
||||
btnOkLabel: 'delete',
|
||||
btnOkIcon: 'fas fa-fw fa-times',
|
||||
onConfirm : function(e, target){
|
||||
// get current row data (important!)
|
||||
// -> "rowData" param is not current state, values are "on createCell()" state
|
||||
rowData = tableApi.row($(cell).parents('tr')).data();
|
||||
|
||||
connectionElement.find('table').showLoadingAnimation();
|
||||
|
||||
request('DELETE', 'log', rowData.id, {}, {
|
||||
connectionElement: connectionElement
|
||||
}, requestAlways)
|
||||
.then(
|
||||
payload => {
|
||||
addConnectionsData(moduleElement, enrichConnectionsData([connectionData], payload.data));
|
||||
},
|
||||
Util.handleAjaxErrorResponse
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
// init confirmation dialog
|
||||
$(cell).confirmation(confirmationSettings);
|
||||
}else {
|
||||
$(cell).on('click', function(e){
|
||||
connectionElement.find('table').showLoadingAnimation();
|
||||
|
||||
let requestData = {
|
||||
active: 1
|
||||
};
|
||||
|
||||
request('PATCH', 'log', rowData.id, requestData, {
|
||||
connectionElement: connectionElement
|
||||
}, requestAlways)
|
||||
.then(
|
||||
payload => {
|
||||
addConnectionsData(moduleElement, enrichConnectionsData([connectionData], payload.data));
|
||||
},
|
||||
Util.handleAjaxErrorResponse
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
drawCallback: function(settings){
|
||||
@@ -772,27 +958,34 @@ define([
|
||||
|
||||
},
|
||||
footerCallback: function(row, data, start, end, display ){
|
||||
|
||||
let api = this.api();
|
||||
let sumColumnIndexes = [3];
|
||||
let tableApi = this.api();
|
||||
let sumColumnIndexes = ['mass:name', 'delete:name'];
|
||||
|
||||
// column data for "sum" columns over this page
|
||||
let pageTotalColumns = api
|
||||
let pageTotalColumns = tableApi
|
||||
.columns( sumColumnIndexes, { page: 'all'} )
|
||||
.data();
|
||||
|
||||
// sum columns for "total" sum
|
||||
pageTotalColumns.each((colData, index) => {
|
||||
pageTotalColumns[index] = colData.reduce((a, b) => {
|
||||
return parseInt(a) + parseInt(b);
|
||||
pageTotalColumns.each((colData, colIndex) => {
|
||||
pageTotalColumns[colIndex] = colData.reduce((sum, val, rowIndex) => {
|
||||
// sum "mass" (colIndex 0) only if not "deleted" (colIndex 1)
|
||||
if(colIndex === 0 && pageTotalColumns[1][rowIndex]){
|
||||
return sum + parseInt(val);
|
||||
}else{
|
||||
return sum;
|
||||
}
|
||||
}, 0);
|
||||
});
|
||||
|
||||
$(sumColumnIndexes).each((index, value) => {
|
||||
$( api.column( value ).footer() ).text( Util.formatMassValue(pageTotalColumns[index]) );
|
||||
sumColumnIndexes.forEach((colSelector, index) => {
|
||||
// only "mass" column footer needs updates
|
||||
if(colSelector === 'mass:name'){
|
||||
$(tableApi.column(colSelector).footer()).text( Util.formatMassValue(pageTotalColumns[index]) );
|
||||
|
||||
// save mass for further reCalculation of "info" table
|
||||
connectionElement.find('.' + config.connectionInfoTableCellMassLogClass).data('mass', pageTotalColumns[index]);
|
||||
// save mass for further reCalculation of "info" table
|
||||
connectionElement.find('.' + config.connectionInfoTableCellMassLogClass).data('mass', pageTotalColumns[index]);
|
||||
}
|
||||
});
|
||||
|
||||
// calculate "info" table -----------------------------------------------------
|
||||
@@ -805,14 +998,186 @@ define([
|
||||
|
||||
logTable.on('order.dt search.dt', function(){
|
||||
let pageInfo = logTable.page.info();
|
||||
logTable.column(0, {search:'applied', order:'applied'}).nodes().each((cell, i) => {
|
||||
let content = (pageInfo.recordsTotal - i) + '. ';
|
||||
logTable.column('index:name', {search:'applied', order:'applied'}).nodes().each((cell, i) => {
|
||||
let content = (pageInfo.recordsTotal - i) + '.';
|
||||
$(cell).html(content);
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
let request = (action, entity, ids = [], data = {}, context = {}, always = null) => {
|
||||
|
||||
let requestExecutor = (resolve, reject) => {
|
||||
let payload = {
|
||||
action: 'request',
|
||||
name: action.toLowerCase() + entity.charAt(0).toUpperCase() + entity.slice(1)
|
||||
};
|
||||
|
||||
// build request url --------------------------------------------------------------------------------------
|
||||
let url = Init.path.api + '/' + entity;
|
||||
|
||||
let path = '';
|
||||
if(isNaN(ids)){
|
||||
if(Array.isArray(ids)){
|
||||
path += '/' + ids.join(',');
|
||||
}
|
||||
}else{
|
||||
let id = parseInt(ids, 10);
|
||||
path += id ? '/' + id : '';
|
||||
}
|
||||
url += path;
|
||||
|
||||
$.ajax({
|
||||
type: action,
|
||||
url: url,
|
||||
data: JSON.stringify(data),
|
||||
contentType: 'application/json; charset=utf-8',
|
||||
dataType: 'json',
|
||||
context: context
|
||||
}).done(function(response){
|
||||
payload.data = response;
|
||||
payload.context = this;
|
||||
resolve(payload);
|
||||
}).fail(function(jqXHR, status, error){
|
||||
payload.data = {
|
||||
jqXHR: jqXHR,
|
||||
status: status,
|
||||
error: error
|
||||
};
|
||||
payload.context = this;
|
||||
reject(payload);
|
||||
}).always(function(){
|
||||
if(always){
|
||||
always(this);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
return new Promise(requestExecutor);
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param context
|
||||
*/
|
||||
let requestAlways = (context) => {
|
||||
context.connectionElement.find('table').hideLoadingAnimation();
|
||||
};
|
||||
|
||||
/**
|
||||
* show jump log dialog
|
||||
* @param moduleElement
|
||||
* @param connectionElement
|
||||
* @param connectionData
|
||||
* @param logData
|
||||
*/
|
||||
let showLogDialog = (moduleElement, connectionElement, connectionData, logData = {}) => {
|
||||
|
||||
let data = {
|
||||
id: config.connectionDialogId,
|
||||
typeSelectId: config.typeSelectId,
|
||||
shipMassId: config.shipMassId,
|
||||
characterSelectId: config.characterSelectId,
|
||||
logData: logData,
|
||||
massFormat: () => {
|
||||
return (val, render) => {
|
||||
return (parseInt(render(val) || 0) / 1000) || '';
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
requirejs(['text!templates/dialog/connection_log.html', 'mustache'], (template, Mustache) => {
|
||||
let content = Mustache.render(template, data);
|
||||
|
||||
let connectionDialog = bootbox.dialog({
|
||||
title: 'Jump log',
|
||||
message: content,
|
||||
show: false,
|
||||
buttons: {
|
||||
close: {
|
||||
label: 'cancel',
|
||||
className: 'btn-default'
|
||||
},
|
||||
success: {
|
||||
label: '<i class="fas fa-fw fa-check"></i> save',
|
||||
className: 'btn-success',
|
||||
callback: function(){
|
||||
let form = this.find('form');
|
||||
|
||||
// validate form
|
||||
form.validator('validate');
|
||||
|
||||
// check whether the form is valid
|
||||
let formValid = form.isValidForm();
|
||||
|
||||
if(formValid){
|
||||
// get form data
|
||||
let formData = form.getFormValues();
|
||||
formData.id = Util.getObjVal(logData, 'id') || 0;
|
||||
formData.connectionId = Util.getObjVal(connectionData, 'id') || 0;
|
||||
formData.shipTypeId = Util.getObjVal(formData, 'shipTypeId') || 0;
|
||||
formData.shipMass = parseInt((Util.getObjVal(formData, 'shipMass') || 0) * 1000);
|
||||
formData.characterId = Util.getObjVal(formData, 'characterId') || 0;
|
||||
|
||||
// we need some "additional" form data from the Select2 dropdown
|
||||
// -> data is required on the backend side
|
||||
let formDataShip = form.find('#' + config.typeSelectId).select2('data');
|
||||
let formDataCharacter = form.find('#' + config.characterSelectId).select2('data');
|
||||
formData.shipTypeName = formDataShip.length ? formDataShip[0].text : '';
|
||||
formData.characterName = formDataCharacter.length ? formDataCharacter[0].text : '';
|
||||
|
||||
let method = formData.id ? 'PATCH' : 'PUT';
|
||||
|
||||
request(method, 'log', formData.id, formData, {
|
||||
connectionElement: connectionElement,
|
||||
formElement: form
|
||||
}, requestAlways)
|
||||
.then(
|
||||
payload => {
|
||||
addConnectionsData(moduleElement, enrichConnectionsData([connectionData], payload.data));
|
||||
this.modal('hide');
|
||||
},
|
||||
Util.handleAjaxErrorResponse
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
connectionDialog.on('show.bs.modal', function(e){
|
||||
let modalContent = $('#' + config.connectionDialogId);
|
||||
|
||||
// init type select live search
|
||||
let selectElementType = modalContent.find('#' + config.typeSelectId);
|
||||
selectElementType.initUniverseTypeSelect({
|
||||
categoryIds: [6],
|
||||
maxSelectionLength: 1,
|
||||
selected: [Util.getObjVal(logData, 'ship.typeId')]
|
||||
}).on('select2:select select2:unselecting', function(e){
|
||||
// get ship mass from selected ship type and update mass input field
|
||||
let shipMass = e.params.data ? e.params.data.mass / 1000 : '';
|
||||
modalContent.find('#' + config.shipMassId).val(shipMass);
|
||||
});
|
||||
|
||||
// init character select live search
|
||||
let selectElementCharacter = modalContent.find('#' + config.characterSelectId);
|
||||
selectElementCharacter.initUniverseSearch({
|
||||
categoryNames: ['character'],
|
||||
maxSelectionLength: 1
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
// show dialog
|
||||
connectionDialog.modal('show');
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* remove connection Panel from moduleElement
|
||||
* @param connectionElement
|
||||
|
||||
@@ -337,7 +337,7 @@ define([
|
||||
data: statusData
|
||||
});
|
||||
|
||||
// init character counter
|
||||
// init char counter
|
||||
let textarea = modalContent.find('#' + config.descriptionTextareaId);
|
||||
let charCounter = modalContent.find('.' + config.descriptionTextareaCharCounter);
|
||||
Util.updateCounter(textarea, charCounter, maxDescriptionLength);
|
||||
|
||||
@@ -8,6 +8,7 @@ define([
|
||||
'conf/signature_type',
|
||||
'bootbox',
|
||||
'localForage',
|
||||
'lazyload',
|
||||
'velocity',
|
||||
'velocityUI',
|
||||
'customScrollbar',
|
||||
@@ -70,6 +71,7 @@ define([
|
||||
|
||||
// select2
|
||||
select2Class: 'pf-select2', // class for all "Select2" <select> elements
|
||||
select2ImageLazyLoadClass: 'pf-select2-image-lazyLoad',
|
||||
|
||||
// animation
|
||||
animationPulseSuccessClass: 'pf-animation-pulse-success', // animation class
|
||||
@@ -1059,6 +1061,9 @@ define([
|
||||
// in order to make mCustomScrollbar mouseWheel enable works correctly
|
||||
$(resultsWrapper).find('ul.select2-results__options').off('mousewheel');
|
||||
|
||||
// preload images that are not visible yet
|
||||
let lazyLoadImagesOffset = 240;
|
||||
|
||||
resultsWrapper.mCustomScrollbar({
|
||||
mouseWheel: {
|
||||
enable: true,
|
||||
@@ -1085,10 +1090,35 @@ define([
|
||||
// -> this is because the initPassiveEvents() delegates the mouseWheel events
|
||||
togglePageScroll(false);
|
||||
},
|
||||
onUpdate: function(a){
|
||||
// whenever the scroll content updates -> init lazyLoad for potential images
|
||||
$('.' + config.select2ImageLazyLoadClass).lazyload({
|
||||
container: this,
|
||||
threshold: lazyLoadImagesOffset,
|
||||
event: 'pf:lazyLoad'
|
||||
});
|
||||
},
|
||||
onTotalScroll: function(){
|
||||
// we want to "trigger" Select2´s 'scroll' event
|
||||
// in order to make its "infinite scrolling" function working
|
||||
this.mcs.content.find(':first-child').trigger('scroll');
|
||||
},
|
||||
whileScrolling: function(){
|
||||
|
||||
// lazy load for images -> reduce number of calculations by % 10
|
||||
if(0 === this.mcs.top % 10){
|
||||
let scroller = $(this).find('.mCSB_container');
|
||||
let scrollerBox = scroller.closest('.mCustomScrollBox');
|
||||
|
||||
scrollerBox.find('.' + config.select2ImageLazyLoadClass).filter(function(){
|
||||
let $this = $(this);
|
||||
if($this.attr('src') === $this.attr('data-original')) return false;
|
||||
let scrollerTop = scroller.position().top;
|
||||
let scrollerHeight = scrollerBox.height();
|
||||
let offset = $this.closest('div').position();
|
||||
return (offset.top - lazyLoadImagesOffset < scrollerHeight - scrollerTop);
|
||||
}).trigger('pf:lazyLoad');
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -1108,7 +1138,7 @@ define([
|
||||
return wrapper;
|
||||
};
|
||||
|
||||
// global open event
|
||||
// global opened event
|
||||
$(document).on('select2:open', '.' + config.select2Class, function(e){
|
||||
let resultsWrapper = getResultsWrapper(this);
|
||||
if(resultsWrapper){
|
||||
@@ -1497,6 +1527,37 @@ define([
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* global ajax error handler -> handles .fail() requests
|
||||
* @param payload
|
||||
*/
|
||||
let handleAjaxErrorResponse = (payload) => {
|
||||
// handle only request errors
|
||||
if(payload.action === 'request'){
|
||||
let jqXHR = payload.data.jqXHR;
|
||||
let reason = '';
|
||||
|
||||
if(jqXHR.responseJSON){
|
||||
// ... valid JSON response
|
||||
let response = jqXHR.responseJSON;
|
||||
|
||||
if(response.error && response.error.length > 0){
|
||||
// build error notification reason from errors
|
||||
reason = response.error.map(error => error.status).join('\n');
|
||||
|
||||
// check if errors might belong to a HTML form -> check "context"
|
||||
if(payload.context.formElement){
|
||||
// show form messages e.g. validation errors
|
||||
payload.context.formElement.showFormMessage(response.error);
|
||||
}
|
||||
}
|
||||
}else{
|
||||
reason = 'Invalid JSON response';
|
||||
}
|
||||
showNotify({title: jqXHR.status + ': ' + payload.name, text: reason, type: 'error'});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* get WebSocket readyState description from ID
|
||||
* https://developer.mozilla.org/de/docs/Web/API/WebSocket
|
||||
@@ -2864,7 +2925,7 @@ define([
|
||||
* @param url
|
||||
* @param params
|
||||
*/
|
||||
let redirect = (url, params) => {
|
||||
let redirect = (url, params = []) => {
|
||||
let currentUrl = document.URL;
|
||||
|
||||
if(url !== currentUrl){
|
||||
@@ -2976,6 +3037,7 @@ define([
|
||||
stopTabBlink: stopTabBlink,
|
||||
getLogInfo: getLogInfo,
|
||||
ajaxSetup: ajaxSetup,
|
||||
handleAjaxErrorResponse: handleAjaxErrorResponse,
|
||||
setSyncStatus: setSyncStatus,
|
||||
getSyncType: getSyncType,
|
||||
isXHRAborted: isXHRAborted,
|
||||
|
||||
2
js/lib/jquery.lazyload.min.js
vendored
2
js/lib/jquery.lazyload.min.js
vendored
@@ -1,2 +1,2 @@
|
||||
/*! Lazy Load 1.9.5 - MIT license - Copyright 2010-2015 Mika Tuupola */
|
||||
/*! Lazy Load 1.9.7 - MIT license - Copyright 2010-2015 Mika Tuupola */
|
||||
!function(a,b,c,d){var e=a(b);a.fn.lazyload=function(f){function g(){var b=0;i.each(function(){var c=a(this);if(!j.skip_invisible||c.is(":visible"))if(a.abovethetop(this,j)||a.leftofbegin(this,j));else if(a.belowthefold(this,j)||a.rightoffold(this,j)){if(++b>j.failure_limit)return!1}else c.trigger("appear"),b=0})}var h,i=this,j={threshold:0,failure_limit:0,event:"scroll",effect:"show",container:b,data_attribute:"original",skip_invisible:!1,appear:null,load:null,placeholder:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC"};return f&&(d!==f.failurelimit&&(f.failure_limit=f.failurelimit,delete f.failurelimit),d!==f.effectspeed&&(f.effect_speed=f.effectspeed,delete f.effectspeed),a.extend(j,f)),h=j.container===d||j.container===b?e:a(j.container),0===j.event.indexOf("scroll")&&h.bind(j.event,function(){return g()}),this.each(function(){var b=this,c=a(b);b.loaded=!1,(c.attr("src")===d||c.attr("src")===!1)&&c.is("img")&&c.attr("src",j.placeholder),c.one("appear",function(){if(!this.loaded){if(j.appear){var d=i.length;j.appear.call(b,d,j)}a("<img />").bind("load",function(){var d=c.attr("data-"+j.data_attribute);c.hide(),c.is("img")?c.attr("src",d):c.css("background-image","url('"+d+"')"),c[j.effect](j.effect_speed),b.loaded=!0;var e=a.grep(i,function(a){return!a.loaded});if(i=a(e),j.load){var f=i.length;j.load.call(b,f,j)}}).attr("src",c.attr("data-"+j.data_attribute))}}),0!==j.event.indexOf("scroll")&&c.bind(j.event,function(){b.loaded||c.trigger("appear")})}),e.bind("resize",function(){g()}),/(?:iphone|ipod|ipad).*os 5/gi.test(navigator.appVersion)&&e.bind("pageshow",function(b){b.originalEvent&&b.originalEvent.persisted&&i.each(function(){a(this).trigger("appear")})}),a(c).ready(function(){g()}),this},a.belowthefold=function(c,f){var g;return g=f.container===d||f.container===b?(b.innerHeight?b.innerHeight:e.height())+e.scrollTop():a(f.container).offset().top+a(f.container).height(),g<=a(c).offset().top-f.threshold},a.rightoffold=function(c,f){var g;return g=f.container===d||f.container===b?e.width()+e.scrollLeft():a(f.container).offset().left+a(f.container).width(),g<=a(c).offset().left-f.threshold},a.abovethetop=function(c,f){var g;return g=f.container===d||f.container===b?e.scrollTop():a(f.container).offset().top,g>=a(c).offset().top+f.threshold+a(c).height()},a.leftofbegin=function(c,f){var g;return g=f.container===d||f.container===b?e.scrollLeft():a(f.container).offset().left,g>=a(c).offset().left+f.threshold+a(c).width()},a.inviewport=function(b,c){return!(a.rightoffold(b,c)||a.leftofbegin(b,c)||a.belowthefold(b,c)||a.abovethetop(b,c))},a.extend(a.expr[":"],{"below-the-fold":function(b){return a.belowthefold(b,{threshold:0})},"above-the-top":function(b){return!a.belowthefold(b,{threshold:0})},"right-of-screen":function(b){return a.rightoffold(b,{threshold:0})},"left-of-screen":function(b){return!a.rightoffold(b,{threshold:0})},"in-viewport":function(b){return a.inviewport(b,{threshold:0})},"above-the-fold":function(b){return!a.belowthefold(b,{threshold:0})},"right-of-fold":function(b){return a.rightoffold(b,{threshold:0})},"left-of-fold":function(b){return!a.rightoffold(b,{threshold:0})}})}(jQuery,window,document);
|
||||
41
package.json
41
package.json
@@ -6,36 +6,35 @@
|
||||
},
|
||||
"description": "Pathfinder is a system mapping tool for EVE ONLINE",
|
||||
"main": "index.php",
|
||||
"dependencies": {
|
||||
},
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
"ansi-colors": "^3.1.0",
|
||||
"fancy-log": "1.3.x",
|
||||
"file-extension": "^4.0.5",
|
||||
"flat": "^4.1.0",
|
||||
"gulp": "next",
|
||||
"gulp-requirejs-optimize": "1.3.x",
|
||||
"gulp-brotli": "1.2.x",
|
||||
"gulp-bytediff": "1.0.x",
|
||||
"gulp-clean-css": "^3.10.0",
|
||||
"gulp-compass": "2.1.x",
|
||||
"gulp-debug": "^4.0.0",
|
||||
"gulp-filter": "5.1.x",
|
||||
"gulp-gzip": "1.x.x",
|
||||
"gulp-if": "2.0.x",
|
||||
"gulp-jshint": "2.1.x",
|
||||
"gulp-rename": "^1.4.0",
|
||||
"gulp-requirejs-optimize": "1.3.x",
|
||||
"gulp-sourcemaps": "2.6.x",
|
||||
"gulp-gzip": "1.x.x",
|
||||
"gulp-brotli": "1.2.x",
|
||||
"gulp-uglify": "^3.0.x",
|
||||
"gulp-rename": "1.2.x",
|
||||
"gulp-compass": "2.1.x",
|
||||
"gulp-clean-css": "3.x.x",
|
||||
"gulp-bytediff": "1.0.x",
|
||||
"gulp-debug": "^3.1.x",
|
||||
"node-notifier": "5.2.x",
|
||||
"uglify-es": "^3.0.x",
|
||||
"jshint": "^2.9.x",
|
||||
"gulp-uglify": "^3.0.1",
|
||||
"jshint": "^2.9.6",
|
||||
"jshint-stylish": "^2.x.x",
|
||||
"terminal-table": "0.0.x",
|
||||
"pretty-bytes": "4.0.x",
|
||||
"promised-del": "1.0.x",
|
||||
"flat": "2.0.x",
|
||||
"lodash.padend": "4.6.x",
|
||||
"node-notifier": "5.2.x",
|
||||
"pretty-bytes": "^5.1.0",
|
||||
"promised-del": "1.0.x",
|
||||
"slash": "2.x.x",
|
||||
"file-extension": "3.1.x",
|
||||
"fancy-log": "1.3.x",
|
||||
"ansi-colors": "1.x.x"
|
||||
"terminal-table": "0.0.x",
|
||||
"uglify-es": "^3.0.x"
|
||||
},
|
||||
"scripts": {
|
||||
"gulp": "gulp"
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -54,7 +54,7 @@ requirejs.config({
|
||||
blueImpGalleryBootstrap: 'lib/bootstrap-image-gallery', // v3.4.2 Bootstrap extension for Blue Imp Gallery - https://blueimp.github.io/Bootstrap-Image-Gallery
|
||||
bootstrapConfirmation: 'lib/bootstrap-confirmation', // v1.0.5 Bootstrap extension for inline confirm dialog - https://github.com/tavicu/bs-confirmation
|
||||
bootstrapToggle: 'lib/bootstrap-toggle.min', // v2.2.0 Bootstrap Toggle (Checkbox) - http://www.bootstraptoggle.com
|
||||
lazyload: 'lib/jquery.lazyload.min', // v1.9.5 LazyLoader images - http://www.appelsiini.net/projects/lazyload
|
||||
lazyload: 'lib/jquery.lazyload.min', // v1.9.7 LazyLoader images - http://www.appelsiini.net/projects/lazyload
|
||||
sortable: 'lib/sortable.min', // v1.6.0 Sortable - drag&drop reorder - https://github.com/rubaxa/Sortable
|
||||
|
||||
'summernote.loader': './app/summernote.loader', // v0.8.10 Summernote WYSIWYG editor -https://summernote.org
|
||||
|
||||
@@ -18,6 +18,9 @@ define([
|
||||
lengthMenu: [[5, 10, 25, 50, -1], [5, 10, 25, 50, 'All']],
|
||||
order: [], // no default order because columnDefs is empty
|
||||
autoWidth: false,
|
||||
language: {
|
||||
info: '_START_ - _END_ of _TOTAL_ entries'
|
||||
},
|
||||
responsive: {
|
||||
breakpoints: Init.breakpoints,
|
||||
details: false
|
||||
|
||||
@@ -9,6 +9,7 @@ define(['jquery'], ($) => {
|
||||
let Config = {
|
||||
path: {
|
||||
img: '/public/img/', // path for images
|
||||
api: '/api/rest', //ajax URL - REST API
|
||||
// user API
|
||||
getCaptcha: '/api/user/getCaptcha', // ajax URL - get captcha image
|
||||
getServerStatus: '/api/user/getEveServerStatus', // ajax URL - get EVE-Online server status
|
||||
|
||||
@@ -343,7 +343,7 @@ define([
|
||||
let initGallery = (newElements) => {
|
||||
if( newElements.length > 0){
|
||||
// We have to add ALL thumbnail elements to the gallery!
|
||||
// -> even those wthat are invisible (not lazyLoaded) now!
|
||||
// -> even those which are invisible (not lazyLoaded) now!
|
||||
// -> This is required for "swipe" through all images
|
||||
let allThumbLinks = getThumbnailElements();
|
||||
|
||||
@@ -814,7 +814,7 @@ define([
|
||||
// init carousel
|
||||
initCarousel();
|
||||
|
||||
// init scrollspy
|
||||
// init scrollSpy
|
||||
// -> after "Carousel"! required for correct "viewport" calculation (Gallery)!
|
||||
initScrollSpy();
|
||||
|
||||
|
||||
@@ -79,15 +79,21 @@ define([
|
||||
|
||||
let reason = status + ' ' + jqXHR.status + ': ' + error;
|
||||
let errorData = [];
|
||||
let redirect = false; // redirect user to other page e.g. login
|
||||
let reload = true; // reload current page (default: true)
|
||||
|
||||
if(jqXHR.responseJSON){
|
||||
// handle JSON
|
||||
let errorObj = jqXHR.responseJSON;
|
||||
let responseObj = jqXHR.responseJSON;
|
||||
if(
|
||||
errorObj.error &&
|
||||
errorObj.error.length > 0
|
||||
responseObj.error &&
|
||||
responseObj.error.length > 0
|
||||
){
|
||||
errorData = errorObj.error;
|
||||
errorData = responseObj.error;
|
||||
}
|
||||
|
||||
if(responseObj.reroute){
|
||||
redirect = responseObj.reroute;
|
||||
}
|
||||
}else{
|
||||
// handle HTML
|
||||
@@ -98,7 +104,13 @@ define([
|
||||
}
|
||||
|
||||
console.error(' ↪ %s Error response: %o', jqXHR.url, errorData);
|
||||
$(document).trigger('pf:shutdown', {status: jqXHR.status, reason: reason, error: errorData});
|
||||
$(document).trigger('pf:shutdown', {
|
||||
status: jqXHR.status,
|
||||
reason: reason,
|
||||
error: errorData,
|
||||
redirect: redirect,
|
||||
reload: reload
|
||||
});
|
||||
};
|
||||
|
||||
// map init functions =========================================================================================
|
||||
|
||||
@@ -787,12 +787,14 @@ define([
|
||||
label: '<i class="fas fa-fw fa-sync"></i> restart',
|
||||
className: ['btn-primary'].join(' '),
|
||||
callback: function(){
|
||||
// check if error was 5xx -> reload page
|
||||
// -> else try to logout -> ajax request
|
||||
if(data.status >= 500 && data.status < 600){
|
||||
// redirect to login
|
||||
window.location = '../';
|
||||
if(data.redirect) {
|
||||
// ... redirect user to e.g. login form page ...
|
||||
Util.redirect(data.redirect, ['logout']);
|
||||
}else if(data.reload){
|
||||
// ... or reload current page ...
|
||||
location.reload();
|
||||
}else{
|
||||
// ... fallback try to logout user
|
||||
documentElement.trigger('pf:menuLogout');
|
||||
}
|
||||
}
|
||||
@@ -811,12 +813,9 @@ define([
|
||||
};
|
||||
|
||||
// add error information (if available)
|
||||
if(
|
||||
data.error &&
|
||||
data.error.length
|
||||
){
|
||||
for(let i = 0; i < data.error.length; i++){
|
||||
options.content.textSmaller.push(data.error[i].message);
|
||||
if(data.error && data.error.length){
|
||||
for(let error of data.error){
|
||||
options.content.textSmaller.push(error.message);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -76,7 +76,7 @@ define([
|
||||
dialogElement.find('.modal-content').hideLoadingAnimation();
|
||||
|
||||
if(responseData.reroute !== undefined){
|
||||
Util.redirect(responseData.reroute, []);
|
||||
Util.redirect(responseData.reroute);
|
||||
}else if(
|
||||
responseData.error &&
|
||||
responseData.error.length > 0
|
||||
|
||||
@@ -753,7 +753,7 @@ define([
|
||||
* show activity stats dialog
|
||||
*/
|
||||
$.fn.showStatsDialog = function(){
|
||||
requirejs(['text!templates/dialog/stats.html', 'mustache', 'datatables.loader'], function(template, Mustache){
|
||||
requirejs(['text!templates/dialog/stats.html', 'mustache', 'datatables.loader'], (template, Mustache) => {
|
||||
// get current statistics map settings
|
||||
let logActivityEnabled = false;
|
||||
let activeMap = Util.getMapModule().getActiveMap();
|
||||
|
||||
@@ -12,7 +12,8 @@ define([
|
||||
|
||||
let config = {
|
||||
// Select2
|
||||
resultOptionImageClass: 'pf-result-image' // class for Select2 result option entry with image
|
||||
resultOptionImageClass: 'pf-result-image', // class for Select2 result option entry with image
|
||||
select2ImageLazyLoadClass: 'pf-select2-image-lazyLoad' // class for Select2 result images that should be lazy loaded
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -60,7 +61,7 @@ define([
|
||||
}
|
||||
|
||||
if(imagePath){
|
||||
thumb = '<img src="' + imagePath + '" style="max-width: 100%" />';
|
||||
thumb = '<img class="' + config.select2ImageLazyLoadClass + '" data-original="' + imagePath + '" style="max-width: 100%"/>';
|
||||
}else if(iconName){
|
||||
thumb = '<i class="fas fa-fw ' + iconName + '" ></i>';
|
||||
}
|
||||
@@ -564,6 +565,7 @@ define([
|
||||
return group;
|
||||
});
|
||||
},*/
|
||||
disabled: options.hasOwnProperty('disabled') ? options.disabled : false,
|
||||
allowClear: options.maxSelectionLength <= 1,
|
||||
maximumSelectionLength: options.maxSelectionLength,
|
||||
templateResult: formatCategoryTypeResultData
|
||||
@@ -605,6 +607,7 @@ define([
|
||||
return {
|
||||
id: type.id,
|
||||
text: type.name,
|
||||
mass: type.hasOwnProperty('mass') ? type.mass : null,
|
||||
groupId: this.groupId,
|
||||
categoryId: this.categoryId,
|
||||
categoryType: this.categoryType
|
||||
|
||||
@@ -6,8 +6,9 @@ define([
|
||||
'jquery',
|
||||
'app/init',
|
||||
'app/util',
|
||||
'bootbox',
|
||||
'app/map/util'
|
||||
], ($, Init, Util, MapUtil) => {
|
||||
], ($, Init, Util, bootbox, MapUtil) => {
|
||||
'use strict';
|
||||
|
||||
let config = {
|
||||
@@ -46,9 +47,17 @@ define([
|
||||
connectionInfoTableCellMassLeftClass: 'pf-connection-info-mass-left', // class for "mass left" table cell
|
||||
|
||||
// dataTable
|
||||
tableToolbarCondensedClass: 'pf-dataTable-condensed-toolbar', // class for condensed table toolbar
|
||||
connectionInfoTableClass: 'pf-connection-info-table', // class for connection tables
|
||||
tableCellImageClass: 'pf-table-image-cell', // class for table "image" cells
|
||||
tableCellCounterClass: 'pf-table-counter-cell', // class for table "counter" cells
|
||||
tableCellActionClass: 'pf-table-action-cell', // class for "action" cells
|
||||
|
||||
// connection dialog
|
||||
connectionDialogId: 'pf-connection-info-dialog', // id for "connection" dialog
|
||||
typeSelectId: 'pf-connection-info-dialog-type-select', // id for "ship type" select
|
||||
shipMassId: 'pf-connection-info-dialog-mass', // id for "ship mass" input
|
||||
characterSelectId: 'pf-connection-info-dialog-character-select', // id for "character" select
|
||||
|
||||
// config
|
||||
showShip: true // default for "show current ship mass" toggle
|
||||
@@ -511,6 +520,34 @@ define([
|
||||
return moduleElement.find('.' + config.connectionInfoPanelClass).not('#' + getConnectionElementId(0));
|
||||
};
|
||||
|
||||
/**
|
||||
* enrich connectionData with "logs" data (if available) and other "missing" data
|
||||
* @param connectionsData
|
||||
* @param newConnectionsData
|
||||
* @returns {*}
|
||||
*/
|
||||
let enrichConnectionsData = (connectionsData, newConnectionsData) => {
|
||||
for(let i = 0; i < connectionsData.length; i++){
|
||||
for(let newConnectionData of newConnectionsData){
|
||||
if(connectionsData[i].id === newConnectionData.id){
|
||||
// copy some missing data
|
||||
connectionsData[i].character = newConnectionData.character;
|
||||
connectionsData[i].created = newConnectionData.created;
|
||||
// check for mass logs and copy data
|
||||
if(newConnectionData.logs && newConnectionData.logs.length){
|
||||
connectionsData[i].logs = newConnectionData.logs;
|
||||
}
|
||||
// check for signatures and copy data
|
||||
if(newConnectionData.signatures && newConnectionData.signatures.length){
|
||||
connectionsData[i].signatures = newConnectionData.signatures;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return connectionsData;
|
||||
};
|
||||
|
||||
/**
|
||||
* request connection log data
|
||||
* @param requestData
|
||||
@@ -530,24 +567,7 @@ define([
|
||||
dataType: 'json',
|
||||
context: context
|
||||
}).done(function(connectionsData){
|
||||
// enrich connectionData with "logs" data (if available) and other "missing" data
|
||||
for(let i = 0; i < this.connectionsData.length; i++){
|
||||
for(let connectionData of connectionsData){
|
||||
if(this.connectionsData[i].id === connectionData.id){
|
||||
// copy some missing data
|
||||
this.connectionsData[i].created = connectionData.created;
|
||||
// check for mass logs and copy data
|
||||
if(connectionData.logs && connectionData.logs.length){
|
||||
this.connectionsData[i].logs = connectionData.logs;
|
||||
}
|
||||
// check for signatures and copy data
|
||||
if(connectionData.signatures && connectionData.signatures.length){
|
||||
this.connectionsData[i].signatures = connectionData.signatures;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
this.connectionsData = enrichConnectionsData(this.connectionsData, connectionsData);
|
||||
|
||||
callback(this.moduleElement, this.connectionsData);
|
||||
}).always(function(){
|
||||
@@ -592,9 +612,9 @@ define([
|
||||
*/
|
||||
let addConnectionsData = (moduleElement, connectionsData) => {
|
||||
|
||||
let getRowIndexesByData = (dataTable, colName, value) => {
|
||||
return dataTable.rows().eq(0).filter((rowIdx) => {
|
||||
return (dataTable.cell(rowIdx, colName + ':name').data() === value);
|
||||
let getRowIndexesByData = (tableApi, colName, value) => {
|
||||
return tableApi.rows().eq(0).filter((rowIdx) => {
|
||||
return (tableApi.cell(rowIdx, colName + ':name').data() === value);
|
||||
});
|
||||
};
|
||||
|
||||
@@ -607,42 +627,47 @@ define([
|
||||
connectionInfoElement.data('connectionData', connectionData);
|
||||
|
||||
// update dataTable ---------------------------------------------------------------
|
||||
let dataTable = connectionElement.find('.dataTable').dataTable().api();
|
||||
let tableApi = connectionElement.find('.dataTable').dataTable().api();
|
||||
|
||||
if(connectionData.logs && connectionData.logs.length > 0){
|
||||
for(let i = 0; i < connectionData.logs.length; i++){
|
||||
let rowData = connectionData.logs[i];
|
||||
let row = null;
|
||||
let rowNew = null;
|
||||
let animationStatus = null;
|
||||
let indexes = getRowIndexesByData(dataTable, 'index', rowData.id);
|
||||
let indexes = getRowIndexesByData(tableApi, 'index', rowData.id);
|
||||
if(indexes.length === 0){
|
||||
// row not found -> add new row
|
||||
row = dataTable.row.add( rowData );
|
||||
rowNew = tableApi.row.add(rowData);
|
||||
animationStatus = 'added';
|
||||
}
|
||||
/* else{
|
||||
// we DON´t expect changes -> no row update)
|
||||
}else{
|
||||
// update row with FIRST index
|
||||
//row = dataTable.row( parseInt(indexes[0]) );
|
||||
// update row data
|
||||
//row.data(connectionData.logs[i]);
|
||||
//animationStatus = 'changed';
|
||||
} */
|
||||
let row = tableApi.row( parseInt(indexes[0]));
|
||||
let rowDataCurrent = row.data();
|
||||
|
||||
// check if row data changed
|
||||
if(rowDataCurrent.updated.updated !== rowData.updated.updated){
|
||||
// ... row changed -> delete old and re-add
|
||||
// -> cell actions might have changed
|
||||
row.remove();
|
||||
rowNew = tableApi.row.add(rowData);
|
||||
animationStatus = 'changed';
|
||||
}
|
||||
}
|
||||
|
||||
if(
|
||||
animationStatus !== null &&
|
||||
row.length > 0
|
||||
rowNew.length > 0
|
||||
){
|
||||
row.nodes().to$().data('animationStatus', animationStatus);
|
||||
rowNew.nodes().to$().data('animationStatus', animationStatus);
|
||||
}
|
||||
}
|
||||
}else{
|
||||
// clear table or leave empty
|
||||
dataTable.clear();
|
||||
tableApi.clear();
|
||||
}
|
||||
|
||||
// redraw dataTable
|
||||
dataTable.draw(false);
|
||||
tableApi.draw(false);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -663,11 +688,45 @@ define([
|
||||
|
||||
let table = $('<table>', {
|
||||
class: ['compact', 'stripe', 'order-column', 'row-border', 'nowrap', config.connectionInfoTableClass].join(' ')
|
||||
}).append('<tfoot><tr><th></th><th></th><th></th><th></th><th></th></tr></tfoot>');
|
||||
}).append('<tfoot><tr><th></th><th></th><th></th><th></th><th></th><th></th><th></th></tr></tfoot>');
|
||||
connectionElement.append(table);
|
||||
|
||||
// init empty table
|
||||
let logTable = table.DataTable({
|
||||
dom: '<"container-fluid"' +
|
||||
'<"row ' + config.tableToolbarCondensedClass + '"' +
|
||||
'<"col-xs-5"i><"col-xs-5"p><"col-xs-2 text-right"B>>' +
|
||||
'<"row"tr>>',
|
||||
buttons: {
|
||||
name: 'tableTools',
|
||||
buttons: [
|
||||
{
|
||||
name: 'addLog',
|
||||
className: config.moduleHeadlineIconClass,
|
||||
text: '<i class="fa fa-plus"></i>',
|
||||
action: function(e, tableApi, node, conf){
|
||||
let logData = {};
|
||||
|
||||
// pre-fill form with current character data (if available)
|
||||
let currentUserData = Util.getCurrentUserData();
|
||||
if(currentUserData && currentUserData.character){
|
||||
logData.character = {
|
||||
id: currentUserData.character.id,
|
||||
name: currentUserData.character.name
|
||||
};
|
||||
if(currentUserData.character.log){
|
||||
logData.ship = {
|
||||
id: currentUserData.character.log.ship.typeId,
|
||||
name: currentUserData.character.log.ship.typeName
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
showLogDialog(moduleElement, connectionElement, connectionData, logData);
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
pageLength: 8,
|
||||
paging: true,
|
||||
pagingType: 'simple',
|
||||
@@ -678,11 +737,14 @@ define([
|
||||
searching: false,
|
||||
hover: false,
|
||||
autoWidth: false,
|
||||
// rowId: 'systemTo',
|
||||
language: {
|
||||
emptyTable: 'No jumps recorded',
|
||||
info: '_START_ to _END_ of _MAX_',
|
||||
infoEmpty: ''
|
||||
info: '_START_ - _END_ of _MAX_',
|
||||
infoEmpty: '',
|
||||
paginate: {
|
||||
previous: '',
|
||||
next: ''
|
||||
}
|
||||
},
|
||||
columnDefs: [
|
||||
{
|
||||
@@ -692,10 +754,25 @@ define([
|
||||
orderable: false,
|
||||
searchable: false,
|
||||
width: 20,
|
||||
class: 'text-center',
|
||||
data: 'id'
|
||||
className: ['text-center', 'txt-color'].join(' '),
|
||||
data: 'id',
|
||||
createdCell: function(cell, cellData, rowData, rowIndex, colIndex){
|
||||
if(
|
||||
!rowData.record ||
|
||||
(rowData.updated.updated !== rowData.created.created)
|
||||
){
|
||||
// log was manually modified or added
|
||||
$(cell)
|
||||
.addClass(Util.config.helpClass)
|
||||
.addClass( 'txt-color-orange').tooltip({
|
||||
container: 'body',
|
||||
title: 'added/updated manually'
|
||||
});
|
||||
}
|
||||
}
|
||||
},{
|
||||
targets: 1,
|
||||
name: 'ship',
|
||||
title: '',
|
||||
width: 26,
|
||||
orderable: false,
|
||||
@@ -715,16 +792,17 @@ define([
|
||||
}
|
||||
},{
|
||||
targets: 2,
|
||||
name: 'character',
|
||||
title: '',
|
||||
width: 26,
|
||||
orderable: false,
|
||||
className: [Util.config.helpDefaultClass, 'text-center', config.tableCellImageClass].join(' '),
|
||||
data: 'created.character',
|
||||
data: 'character',
|
||||
render: {
|
||||
_: function(data, type, row){
|
||||
let value = data.name;
|
||||
_: (cellData, type, rowData, meta) => {
|
||||
let value = cellData.name;
|
||||
if(type === 'display'){
|
||||
value = '<img src="' + Init.url.ccpImageServer + '/Character/' + data.id + '_32.jpg" title="' + value + '" data-toggle="tooltip" />';
|
||||
value = '<img src="' + Init.url.ccpImageServer + '/Character/' + cellData.id + '_32.jpg" title="' + value + '" data-toggle="tooltip" />';
|
||||
}
|
||||
return value;
|
||||
}
|
||||
@@ -734,20 +812,26 @@ define([
|
||||
}
|
||||
},{
|
||||
targets: 3,
|
||||
name: 'mass',
|
||||
title: 'mass',
|
||||
className: ['text-right'].join(' ') ,
|
||||
data: 'ship.mass',
|
||||
render: {
|
||||
_: function(data, type, row){
|
||||
let value = data;
|
||||
_: (cellData, type, rowData, meta) => {
|
||||
let value = cellData;
|
||||
if(type === 'display'){
|
||||
value = Util.formatMassValue(value);
|
||||
if(!rowData.active){
|
||||
// log is "deleted"
|
||||
value = '<span class="pf-font-line-through txt-color txt-color-red">' + value + '</span>';
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
},{
|
||||
targets: 4,
|
||||
name: 'created',
|
||||
title: 'log',
|
||||
width: 55,
|
||||
className: ['text-right', config.tableCellCounterClass].join(' '),
|
||||
@@ -755,6 +839,108 @@ define([
|
||||
createdCell: function(cell, cellData, rowData, rowIndex, colIndex){
|
||||
$(cell).initTimestampCounter('d');
|
||||
}
|
||||
},{
|
||||
targets: 5,
|
||||
name: 'edit',
|
||||
title: '',
|
||||
orderable: false,
|
||||
searchable: false,
|
||||
width: 10,
|
||||
className: ['text-center', config.tableCellActionClass, config.moduleHeadlineIconClass].join(' '),
|
||||
data: null,
|
||||
render: {
|
||||
display: data => {
|
||||
let icon = '';
|
||||
if(data.active){
|
||||
icon = '<i class="fas fa-pen"></i>';
|
||||
}
|
||||
return icon;
|
||||
}
|
||||
},
|
||||
createdCell: function(cell, cellData, rowData, rowIndex, colIndex){
|
||||
let tableApi = this.api();
|
||||
|
||||
if($(cell).is(':empty')){
|
||||
$(cell).removeClass(config.tableCellActionClass + ' ' + config.moduleHeadlineIconClass);
|
||||
}else{
|
||||
$(cell).on('click', function(e){
|
||||
showLogDialog(moduleElement, connectionElement, connectionData, rowData);
|
||||
});
|
||||
}
|
||||
}
|
||||
},{
|
||||
targets: 6,
|
||||
name: 'delete',
|
||||
title: '',
|
||||
orderable: false,
|
||||
searchable: false,
|
||||
width: 10,
|
||||
className: ['text-center', config.tableCellActionClass].join(' '),
|
||||
data: 'active',
|
||||
render: {
|
||||
display: data => {
|
||||
let val = '<i class="fas fa-plus"></i>';
|
||||
if(data){
|
||||
val = '<i class="fas fa-times txt-color txt-color-redDarker"></i>';
|
||||
}
|
||||
return val;
|
||||
}
|
||||
},
|
||||
createdCell: function(cell, cellData, rowData, rowIndex, colIndex){
|
||||
let tableApi = this.api();
|
||||
|
||||
if(rowData.active){
|
||||
let confirmationSettings = {
|
||||
container: 'body',
|
||||
placement: 'left',
|
||||
btnCancelClass: 'btn btn-sm btn-default',
|
||||
btnCancelLabel: 'cancel',
|
||||
btnCancelIcon: 'fas fa-fw fa-ban',
|
||||
title: 'delete jump log',
|
||||
btnOkClass: 'btn btn-sm btn-danger',
|
||||
btnOkLabel: 'delete',
|
||||
btnOkIcon: 'fas fa-fw fa-times',
|
||||
onConfirm : function(e, target){
|
||||
// get current row data (important!)
|
||||
// -> "rowData" param is not current state, values are "on createCell()" state
|
||||
rowData = tableApi.row($(cell).parents('tr')).data();
|
||||
|
||||
connectionElement.find('table').showLoadingAnimation();
|
||||
|
||||
request('DELETE', 'log', rowData.id, {}, {
|
||||
connectionElement: connectionElement
|
||||
}, requestAlways)
|
||||
.then(
|
||||
payload => {
|
||||
addConnectionsData(moduleElement, enrichConnectionsData([connectionData], payload.data));
|
||||
},
|
||||
Util.handleAjaxErrorResponse
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
// init confirmation dialog
|
||||
$(cell).confirmation(confirmationSettings);
|
||||
}else {
|
||||
$(cell).on('click', function(e){
|
||||
connectionElement.find('table').showLoadingAnimation();
|
||||
|
||||
let requestData = {
|
||||
active: 1
|
||||
};
|
||||
|
||||
request('PATCH', 'log', rowData.id, requestData, {
|
||||
connectionElement: connectionElement
|
||||
}, requestAlways)
|
||||
.then(
|
||||
payload => {
|
||||
addConnectionsData(moduleElement, enrichConnectionsData([connectionData], payload.data));
|
||||
},
|
||||
Util.handleAjaxErrorResponse
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
drawCallback: function(settings){
|
||||
@@ -772,27 +958,34 @@ define([
|
||||
|
||||
},
|
||||
footerCallback: function(row, data, start, end, display ){
|
||||
|
||||
let api = this.api();
|
||||
let sumColumnIndexes = [3];
|
||||
let tableApi = this.api();
|
||||
let sumColumnIndexes = ['mass:name', 'delete:name'];
|
||||
|
||||
// column data for "sum" columns over this page
|
||||
let pageTotalColumns = api
|
||||
let pageTotalColumns = tableApi
|
||||
.columns( sumColumnIndexes, { page: 'all'} )
|
||||
.data();
|
||||
|
||||
// sum columns for "total" sum
|
||||
pageTotalColumns.each((colData, index) => {
|
||||
pageTotalColumns[index] = colData.reduce((a, b) => {
|
||||
return parseInt(a) + parseInt(b);
|
||||
pageTotalColumns.each((colData, colIndex) => {
|
||||
pageTotalColumns[colIndex] = colData.reduce((sum, val, rowIndex) => {
|
||||
// sum "mass" (colIndex 0) only if not "deleted" (colIndex 1)
|
||||
if(colIndex === 0 && pageTotalColumns[1][rowIndex]){
|
||||
return sum + parseInt(val);
|
||||
}else{
|
||||
return sum;
|
||||
}
|
||||
}, 0);
|
||||
});
|
||||
|
||||
$(sumColumnIndexes).each((index, value) => {
|
||||
$( api.column( value ).footer() ).text( Util.formatMassValue(pageTotalColumns[index]) );
|
||||
sumColumnIndexes.forEach((colSelector, index) => {
|
||||
// only "mass" column footer needs updates
|
||||
if(colSelector === 'mass:name'){
|
||||
$(tableApi.column(colSelector).footer()).text( Util.formatMassValue(pageTotalColumns[index]) );
|
||||
|
||||
// save mass for further reCalculation of "info" table
|
||||
connectionElement.find('.' + config.connectionInfoTableCellMassLogClass).data('mass', pageTotalColumns[index]);
|
||||
// save mass for further reCalculation of "info" table
|
||||
connectionElement.find('.' + config.connectionInfoTableCellMassLogClass).data('mass', pageTotalColumns[index]);
|
||||
}
|
||||
});
|
||||
|
||||
// calculate "info" table -----------------------------------------------------
|
||||
@@ -805,14 +998,186 @@ define([
|
||||
|
||||
logTable.on('order.dt search.dt', function(){
|
||||
let pageInfo = logTable.page.info();
|
||||
logTable.column(0, {search:'applied', order:'applied'}).nodes().each((cell, i) => {
|
||||
let content = (pageInfo.recordsTotal - i) + '. ';
|
||||
logTable.column('index:name', {search:'applied', order:'applied'}).nodes().each((cell, i) => {
|
||||
let content = (pageInfo.recordsTotal - i) + '.';
|
||||
$(cell).html(content);
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
let request = (action, entity, ids = [], data = {}, context = {}, always = null) => {
|
||||
|
||||
let requestExecutor = (resolve, reject) => {
|
||||
let payload = {
|
||||
action: 'request',
|
||||
name: action.toLowerCase() + entity.charAt(0).toUpperCase() + entity.slice(1)
|
||||
};
|
||||
|
||||
// build request url --------------------------------------------------------------------------------------
|
||||
let url = Init.path.api + '/' + entity;
|
||||
|
||||
let path = '';
|
||||
if(isNaN(ids)){
|
||||
if(Array.isArray(ids)){
|
||||
path += '/' + ids.join(',');
|
||||
}
|
||||
}else{
|
||||
let id = parseInt(ids, 10);
|
||||
path += id ? '/' + id : '';
|
||||
}
|
||||
url += path;
|
||||
|
||||
$.ajax({
|
||||
type: action,
|
||||
url: url,
|
||||
data: JSON.stringify(data),
|
||||
contentType: 'application/json; charset=utf-8',
|
||||
dataType: 'json',
|
||||
context: context
|
||||
}).done(function(response){
|
||||
payload.data = response;
|
||||
payload.context = this;
|
||||
resolve(payload);
|
||||
}).fail(function(jqXHR, status, error){
|
||||
payload.data = {
|
||||
jqXHR: jqXHR,
|
||||
status: status,
|
||||
error: error
|
||||
};
|
||||
payload.context = this;
|
||||
reject(payload);
|
||||
}).always(function(){
|
||||
if(always){
|
||||
always(this);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
return new Promise(requestExecutor);
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param context
|
||||
*/
|
||||
let requestAlways = (context) => {
|
||||
context.connectionElement.find('table').hideLoadingAnimation();
|
||||
};
|
||||
|
||||
/**
|
||||
* show jump log dialog
|
||||
* @param moduleElement
|
||||
* @param connectionElement
|
||||
* @param connectionData
|
||||
* @param logData
|
||||
*/
|
||||
let showLogDialog = (moduleElement, connectionElement, connectionData, logData = {}) => {
|
||||
|
||||
let data = {
|
||||
id: config.connectionDialogId,
|
||||
typeSelectId: config.typeSelectId,
|
||||
shipMassId: config.shipMassId,
|
||||
characterSelectId: config.characterSelectId,
|
||||
logData: logData,
|
||||
massFormat: () => {
|
||||
return (val, render) => {
|
||||
return (parseInt(render(val) || 0) / 1000) || '';
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
requirejs(['text!templates/dialog/connection_log.html', 'mustache'], (template, Mustache) => {
|
||||
let content = Mustache.render(template, data);
|
||||
|
||||
let connectionDialog = bootbox.dialog({
|
||||
title: 'Jump log',
|
||||
message: content,
|
||||
show: false,
|
||||
buttons: {
|
||||
close: {
|
||||
label: 'cancel',
|
||||
className: 'btn-default'
|
||||
},
|
||||
success: {
|
||||
label: '<i class="fas fa-fw fa-check"></i> save',
|
||||
className: 'btn-success',
|
||||
callback: function(){
|
||||
let form = this.find('form');
|
||||
|
||||
// validate form
|
||||
form.validator('validate');
|
||||
|
||||
// check whether the form is valid
|
||||
let formValid = form.isValidForm();
|
||||
|
||||
if(formValid){
|
||||
// get form data
|
||||
let formData = form.getFormValues();
|
||||
formData.id = Util.getObjVal(logData, 'id') || 0;
|
||||
formData.connectionId = Util.getObjVal(connectionData, 'id') || 0;
|
||||
formData.shipTypeId = Util.getObjVal(formData, 'shipTypeId') || 0;
|
||||
formData.shipMass = parseInt((Util.getObjVal(formData, 'shipMass') || 0) * 1000);
|
||||
formData.characterId = Util.getObjVal(formData, 'characterId') || 0;
|
||||
|
||||
// we need some "additional" form data from the Select2 dropdown
|
||||
// -> data is required on the backend side
|
||||
let formDataShip = form.find('#' + config.typeSelectId).select2('data');
|
||||
let formDataCharacter = form.find('#' + config.characterSelectId).select2('data');
|
||||
formData.shipTypeName = formDataShip.length ? formDataShip[0].text : '';
|
||||
formData.characterName = formDataCharacter.length ? formDataCharacter[0].text : '';
|
||||
|
||||
let method = formData.id ? 'PATCH' : 'PUT';
|
||||
|
||||
request(method, 'log', formData.id, formData, {
|
||||
connectionElement: connectionElement,
|
||||
formElement: form
|
||||
}, requestAlways)
|
||||
.then(
|
||||
payload => {
|
||||
addConnectionsData(moduleElement, enrichConnectionsData([connectionData], payload.data));
|
||||
this.modal('hide');
|
||||
},
|
||||
Util.handleAjaxErrorResponse
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
connectionDialog.on('show.bs.modal', function(e){
|
||||
let modalContent = $('#' + config.connectionDialogId);
|
||||
|
||||
// init type select live search
|
||||
let selectElementType = modalContent.find('#' + config.typeSelectId);
|
||||
selectElementType.initUniverseTypeSelect({
|
||||
categoryIds: [6],
|
||||
maxSelectionLength: 1,
|
||||
selected: [Util.getObjVal(logData, 'ship.typeId')]
|
||||
}).on('select2:select select2:unselecting', function(e){
|
||||
// get ship mass from selected ship type and update mass input field
|
||||
let shipMass = e.params.data ? e.params.data.mass / 1000 : '';
|
||||
modalContent.find('#' + config.shipMassId).val(shipMass);
|
||||
});
|
||||
|
||||
// init character select live search
|
||||
let selectElementCharacter = modalContent.find('#' + config.characterSelectId);
|
||||
selectElementCharacter.initUniverseSearch({
|
||||
categoryNames: ['character'],
|
||||
maxSelectionLength: 1
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
// show dialog
|
||||
connectionDialog.modal('show');
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* remove connection Panel from moduleElement
|
||||
* @param connectionElement
|
||||
|
||||
@@ -337,7 +337,7 @@ define([
|
||||
data: statusData
|
||||
});
|
||||
|
||||
// init character counter
|
||||
// init char counter
|
||||
let textarea = modalContent.find('#' + config.descriptionTextareaId);
|
||||
let charCounter = modalContent.find('.' + config.descriptionTextareaCharCounter);
|
||||
Util.updateCounter(textarea, charCounter, maxDescriptionLength);
|
||||
|
||||
@@ -8,6 +8,7 @@ define([
|
||||
'conf/signature_type',
|
||||
'bootbox',
|
||||
'localForage',
|
||||
'lazyload',
|
||||
'velocity',
|
||||
'velocityUI',
|
||||
'customScrollbar',
|
||||
@@ -70,6 +71,7 @@ define([
|
||||
|
||||
// select2
|
||||
select2Class: 'pf-select2', // class for all "Select2" <select> elements
|
||||
select2ImageLazyLoadClass: 'pf-select2-image-lazyLoad',
|
||||
|
||||
// animation
|
||||
animationPulseSuccessClass: 'pf-animation-pulse-success', // animation class
|
||||
@@ -1059,6 +1061,9 @@ define([
|
||||
// in order to make mCustomScrollbar mouseWheel enable works correctly
|
||||
$(resultsWrapper).find('ul.select2-results__options').off('mousewheel');
|
||||
|
||||
// preload images that are not visible yet
|
||||
let lazyLoadImagesOffset = 240;
|
||||
|
||||
resultsWrapper.mCustomScrollbar({
|
||||
mouseWheel: {
|
||||
enable: true,
|
||||
@@ -1085,10 +1090,35 @@ define([
|
||||
// -> this is because the initPassiveEvents() delegates the mouseWheel events
|
||||
togglePageScroll(false);
|
||||
},
|
||||
onUpdate: function(a){
|
||||
// whenever the scroll content updates -> init lazyLoad for potential images
|
||||
$('.' + config.select2ImageLazyLoadClass).lazyload({
|
||||
container: this,
|
||||
threshold: lazyLoadImagesOffset,
|
||||
event: 'pf:lazyLoad'
|
||||
});
|
||||
},
|
||||
onTotalScroll: function(){
|
||||
// we want to "trigger" Select2´s 'scroll' event
|
||||
// in order to make its "infinite scrolling" function working
|
||||
this.mcs.content.find(':first-child').trigger('scroll');
|
||||
},
|
||||
whileScrolling: function(){
|
||||
|
||||
// lazy load for images -> reduce number of calculations by % 10
|
||||
if(0 === this.mcs.top % 10){
|
||||
let scroller = $(this).find('.mCSB_container');
|
||||
let scrollerBox = scroller.closest('.mCustomScrollBox');
|
||||
|
||||
scrollerBox.find('.' + config.select2ImageLazyLoadClass).filter(function(){
|
||||
let $this = $(this);
|
||||
if($this.attr('src') === $this.attr('data-original')) return false;
|
||||
let scrollerTop = scroller.position().top;
|
||||
let scrollerHeight = scrollerBox.height();
|
||||
let offset = $this.closest('div').position();
|
||||
return (offset.top - lazyLoadImagesOffset < scrollerHeight - scrollerTop);
|
||||
}).trigger('pf:lazyLoad');
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -1108,7 +1138,7 @@ define([
|
||||
return wrapper;
|
||||
};
|
||||
|
||||
// global open event
|
||||
// global opened event
|
||||
$(document).on('select2:open', '.' + config.select2Class, function(e){
|
||||
let resultsWrapper = getResultsWrapper(this);
|
||||
if(resultsWrapper){
|
||||
@@ -1497,6 +1527,37 @@ define([
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* global ajax error handler -> handles .fail() requests
|
||||
* @param payload
|
||||
*/
|
||||
let handleAjaxErrorResponse = (payload) => {
|
||||
// handle only request errors
|
||||
if(payload.action === 'request'){
|
||||
let jqXHR = payload.data.jqXHR;
|
||||
let reason = '';
|
||||
|
||||
if(jqXHR.responseJSON){
|
||||
// ... valid JSON response
|
||||
let response = jqXHR.responseJSON;
|
||||
|
||||
if(response.error && response.error.length > 0){
|
||||
// build error notification reason from errors
|
||||
reason = response.error.map(error => error.status).join('\n');
|
||||
|
||||
// check if errors might belong to a HTML form -> check "context"
|
||||
if(payload.context.formElement){
|
||||
// show form messages e.g. validation errors
|
||||
payload.context.formElement.showFormMessage(response.error);
|
||||
}
|
||||
}
|
||||
}else{
|
||||
reason = 'Invalid JSON response';
|
||||
}
|
||||
showNotify({title: jqXHR.status + ': ' + payload.name, text: reason, type: 'error'});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* get WebSocket readyState description from ID
|
||||
* https://developer.mozilla.org/de/docs/Web/API/WebSocket
|
||||
@@ -2864,7 +2925,7 @@ define([
|
||||
* @param url
|
||||
* @param params
|
||||
*/
|
||||
let redirect = (url, params) => {
|
||||
let redirect = (url, params = []) => {
|
||||
let currentUrl = document.URL;
|
||||
|
||||
if(url !== currentUrl){
|
||||
@@ -2976,6 +3037,7 @@ define([
|
||||
stopTabBlink: stopTabBlink,
|
||||
getLogInfo: getLogInfo,
|
||||
ajaxSetup: ajaxSetup,
|
||||
handleAjaxErrorResponse: handleAjaxErrorResponse,
|
||||
setSyncStatus: setSyncStatus,
|
||||
getSyncType: getSyncType,
|
||||
isXHRAborted: isXHRAborted,
|
||||
|
||||
2
public/js/v1.4.3/lib/jquery.lazyload.min.js
vendored
2
public/js/v1.4.3/lib/jquery.lazyload.min.js
vendored
@@ -1,2 +1,2 @@
|
||||
/*! Lazy Load 1.9.5 - MIT license - Copyright 2010-2015 Mika Tuupola */
|
||||
/*! Lazy Load 1.9.7 - MIT license - Copyright 2010-2015 Mika Tuupola */
|
||||
!function(a,b,c,d){var e=a(b);a.fn.lazyload=function(f){function g(){var b=0;i.each(function(){var c=a(this);if(!j.skip_invisible||c.is(":visible"))if(a.abovethetop(this,j)||a.leftofbegin(this,j));else if(a.belowthefold(this,j)||a.rightoffold(this,j)){if(++b>j.failure_limit)return!1}else c.trigger("appear"),b=0})}var h,i=this,j={threshold:0,failure_limit:0,event:"scroll",effect:"show",container:b,data_attribute:"original",skip_invisible:!1,appear:null,load:null,placeholder:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC"};return f&&(d!==f.failurelimit&&(f.failure_limit=f.failurelimit,delete f.failurelimit),d!==f.effectspeed&&(f.effect_speed=f.effectspeed,delete f.effectspeed),a.extend(j,f)),h=j.container===d||j.container===b?e:a(j.container),0===j.event.indexOf("scroll")&&h.bind(j.event,function(){return g()}),this.each(function(){var b=this,c=a(b);b.loaded=!1,(c.attr("src")===d||c.attr("src")===!1)&&c.is("img")&&c.attr("src",j.placeholder),c.one("appear",function(){if(!this.loaded){if(j.appear){var d=i.length;j.appear.call(b,d,j)}a("<img />").bind("load",function(){var d=c.attr("data-"+j.data_attribute);c.hide(),c.is("img")?c.attr("src",d):c.css("background-image","url('"+d+"')"),c[j.effect](j.effect_speed),b.loaded=!0;var e=a.grep(i,function(a){return!a.loaded});if(i=a(e),j.load){var f=i.length;j.load.call(b,f,j)}}).attr("src",c.attr("data-"+j.data_attribute))}}),0!==j.event.indexOf("scroll")&&c.bind(j.event,function(){b.loaded||c.trigger("appear")})}),e.bind("resize",function(){g()}),/(?:iphone|ipod|ipad).*os 5/gi.test(navigator.appVersion)&&e.bind("pageshow",function(b){b.originalEvent&&b.originalEvent.persisted&&i.each(function(){a(this).trigger("appear")})}),a(c).ready(function(){g()}),this},a.belowthefold=function(c,f){var g;return g=f.container===d||f.container===b?(b.innerHeight?b.innerHeight:e.height())+e.scrollTop():a(f.container).offset().top+a(f.container).height(),g<=a(c).offset().top-f.threshold},a.rightoffold=function(c,f){var g;return g=f.container===d||f.container===b?e.width()+e.scrollLeft():a(f.container).offset().left+a(f.container).width(),g<=a(c).offset().left-f.threshold},a.abovethetop=function(c,f){var g;return g=f.container===d||f.container===b?e.scrollTop():a(f.container).offset().top,g>=a(c).offset().top+f.threshold+a(c).height()},a.leftofbegin=function(c,f){var g;return g=f.container===d||f.container===b?e.scrollLeft():a(f.container).offset().left,g>=a(c).offset().left+f.threshold+a(c).width()},a.inviewport=function(b,c){return!(a.rightoffold(b,c)||a.leftofbegin(b,c)||a.belowthefold(b,c)||a.abovethetop(b,c))},a.extend(a.expr[":"],{"below-the-fold":function(b){return a.belowthefold(b,{threshold:0})},"above-the-top":function(b){return!a.belowthefold(b,{threshold:0})},"right-of-screen":function(b){return a.rightoffold(b,{threshold:0})},"left-of-screen":function(b){return!a.rightoffold(b,{threshold:0})},"in-viewport":function(b){return a.inviewport(b,{threshold:0})},"above-the-fold":function(b){return!a.belowthefold(b,{threshold:0})},"right-of-fold":function(b){return a.rightoffold(b,{threshold:0})},"left-of-fold":function(b){return!a.rightoffold(b,{threshold:0})}})}(jQuery,window,document);
|
||||
51
public/templates/dialog/connection_log.html
Normal file
51
public/templates/dialog/connection_log.html
Normal file
@@ -0,0 +1,51 @@
|
||||
<div id="{{id}}">
|
||||
<form role="form" class="form-horizontal">
|
||||
|
||||
<div class="row">
|
||||
<div class="col-xs-9 col-sm-7">
|
||||
<div class="form-group">
|
||||
<label class="col-sm-2 control-label" for="{{typeSelectId}}">Ship</label>
|
||||
<div class="col-sm-10">
|
||||
<div class="input-group">
|
||||
<label for="{{typeSelectId}}"></label>
|
||||
<select id="{{typeSelectId}}" class="pf-select2" name="shipTypeId" data-error="Ship type is required" required {{#logData.id}}readonly{{/logData.id}}></select>
|
||||
<span class="note help-block with-errors"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-xs-3 col-sm-5">
|
||||
<div class="form-group">
|
||||
<label class="col-sm-6 control-label" for="{{shipMassId}}">Jump mass</label>
|
||||
<div class="col-sm-6">
|
||||
<div class="input-icon-right">
|
||||
<i class="fas">t</i>
|
||||
<input id="{{shipMassId}}" class="form-control text-right" name="shipMass" type="number" value="{{#massFormat}}{{logData.ship.mass}}{{/massFormat}}" min="32" max="2400000" step="1" data-error="Mass required" data-min-error="a POD has 32t" data-max-error="a Titan has 2.400.000t" required>
|
||||
</div>
|
||||
<div class="note help-block with-errors"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-xs-9 col-sm-7">
|
||||
<div class="form-group">
|
||||
<label class="col-sm-2 control-label" for="{{characterSelectId}}">Character</label>
|
||||
<div class="col-sm-10">
|
||||
<div class="input-group">
|
||||
<label for="{{characterSelectId}}"></label>
|
||||
<select id="{{characterSelectId}}" class="pf-select2" name="characterId" data-error="Character is required" required {{#logData.id}}readonly{{/logData.id}}>
|
||||
{{#logData.character}}
|
||||
<option value="{{id}}" selected="selected">{{name}}</option>
|
||||
{{/logData.character}}
|
||||
</select>
|
||||
<span class="note help-block with-errors"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
@@ -43,7 +43,7 @@
|
||||
{{#hasRightMapUpdate}}
|
||||
<form role="form" class="form-horizontal">
|
||||
|
||||
<div class="row ">
|
||||
<div class="row">
|
||||
<div class="col-sm-6">
|
||||
<h4 class="pf-dynamic-area">Map options</h4>
|
||||
|
||||
@@ -116,7 +116,7 @@
|
||||
|
||||
<div id="pf-map-dialog-slack-section" class="collapse {{#slackSectionShow}}in{{/slackSectionShow}}">
|
||||
<fieldset {{^slackEnabled}}disabled{{/slackEnabled}}>
|
||||
<div class="row ">
|
||||
<div class="row">
|
||||
<div class="col-xs-12 col-sm-12 col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="{{slackWebHookURLId}}" class="col-sm-3 col-md-4 control-label">WebHook
|
||||
@@ -155,15 +155,14 @@
|
||||
</label>
|
||||
<div class="col-sm-6 col-md-8">
|
||||
<div class="input-icon-left input-icon-right">
|
||||
<span class="fa-stack">
|
||||
<i class="fas fa-fw fa-lg fa-ellipsis-v fa-stack-1x"></i>
|
||||
<i class="fas fa-fw fa-2x fa-minus fa-stack-1x"></i>
|
||||
</span>
|
||||
<span class="fa-stack">
|
||||
<i class="fas fa-fw fa-lg fa-ellipsis-v fa-stack-1x"></i>
|
||||
<i class="fas fa-fw fa-2x fa-minus fa-stack-1x"></i>
|
||||
</span>
|
||||
|
||||
<i class="fas fa-fw fa-lg fa-ellipsis-v fa-stack-1x"></i>
|
||||
<i class="fas fa-fw fa-2x fa-minus fa-stack-1x"></i>
|
||||
</span>
|
||||
<span class="fa-stack">
|
||||
<i class="fas fa-fw fa-lg fa-ellipsis-v fa-stack-1x"></i>
|
||||
<i class="fas fa-fw fa-2x fa-minus fa-stack-1x"></i>
|
||||
</span>
|
||||
<input name="slackIcon" type="text" class="form-control text-center" id="{{slackIconId}}" value="{{slackIcon}}" placeholder="slack" pattern="^[_\-A-z0-9]{1,}$" data-error="Allowed chars (A-z, 0-9, _, -)">
|
||||
</div>
|
||||
<div class="note help-block with-errors"></div>
|
||||
@@ -181,23 +180,24 @@
|
||||
</label>
|
||||
<div class="col-sm-6 col-md-8">
|
||||
<div class="input-icon-left" {{^slackRallyEnabled}}title="Globally disabled for this map type"{{/slackRallyEnabled}}>
|
||||
<i class="fas fa-hashtag"></i>
|
||||
<input name="slackChannelRally" type="text" class="form-control" id="{{slackChannelRallyId}}" value="{{slackChannelRally}}" placeholder="map_rally" pattern="^[_\-A-z0-9]{1,}$" data-error="Allowed chars (A-z, 0-9, _, -)" {{^slackRallyEnabled}}disabled{{/slackRallyEnabled}}>
|
||||
<i class="fas fa-hashtag"></i>
|
||||
<input name="slackChannelRally" type="text" class="form-control" id="{{slackChannelRallyId}}" value="{{slackChannelRally}}" placeholder="map_rally" pattern="^[_\-A-z0-9]{1,}$" data-error="Allowed chars (A-z, 0-9, _, -)" {{^slackRallyEnabled}}disabled{{/slackRallyEnabled}}>
|
||||
</div>
|
||||
</div>
|
||||
<div class="note help-block with-errors"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-xs-6 col-sm-6 col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="{{slackChannelHistoryId}}" class="col-sm-6 col-md-4 control-label">Channel 'map changes'
|
||||
<i class="fas fa-fw fa-question-circle pf-help-light" title="Send map changes to a Slack channel. This can be used in addition or replacement for the logfiles. (check 'Map logging' section above)"></i>
|
||||
</label>
|
||||
<div class="col-sm-6 col-md-8">
|
||||
<div class="input-icon-left" {{^slackHistoryEnabled}}title="Globally disabled for this map type"{{/slackHistoryEnabled}}>
|
||||
<i class="fas fa-hashtag"></i>
|
||||
<input name="slackChannelHistory" type="text" class="form-control" id="{{slackChannelHistoryId}}" value="{{slackChannelHistory}}" placeholder="map_logging" pattern="^[_\-A-z0-9]{1,}$" data-error="Allowed chars (A-z, 0-9, _, -)" {{^slackHistoryEnabled}}disabled{{/slackHistoryEnabled}}>
|
||||
<div class="col-xs-6 col-sm-6 col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="{{slackChannelHistoryId}}" class="col-sm-6 col-md-4 control-label">Channel 'map changes'
|
||||
<i class="fas fa-fw fa-question-circle pf-help-light" title="Send map changes to a Slack channel. This can be used in addition or replacement for the logfiles. (check 'Map logging' section above)"></i>
|
||||
</label>
|
||||
<div class="col-sm-6 col-md-8">
|
||||
<div class="input-icon-left" {{^slackHistoryEnabled}}title="Globally disabled for this map type"{{/slackHistoryEnabled}}>
|
||||
<i class="fas fa-hashtag"></i>
|
||||
<input name="slackChannelHistory" type="text" class="form-control" id="{{slackChannelHistoryId}}" value="{{slackChannelHistory}}" placeholder="map_logging" pattern="^[_\-A-z0-9]{1,}$" data-error="Allowed chars (A-z, 0-9, _, -)" {{^slackHistoryEnabled}}disabled{{/slackHistoryEnabled}}>
|
||||
</div>
|
||||
</div>
|
||||
<div class="help-block with-errors"></div>
|
||||
</div>
|
||||
@@ -219,7 +219,7 @@
|
||||
|
||||
<div id="pf-map-dialog-discord-section" class="collapse {{#discordSectionShow}}in{{/discordSectionShow}}">
|
||||
<fieldset {{^discordEnabled}}disabled{{/discordEnabled}}>
|
||||
<div class="row ">
|
||||
<div class="row">
|
||||
<div class="col-xs-12 col-sm-12 col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="{{discordWebHookURLRallyId}}" class="col-sm-3 col-md-4 control-label">WebHook 'rally point'
|
||||
|
||||
@@ -339,7 +339,7 @@ input[type="email"]{
|
||||
* WITH ICON
|
||||
*/
|
||||
.input-icon-right {
|
||||
//position:relative; why?
|
||||
position:relative;
|
||||
}
|
||||
.input-icon-right > i, .input-icon-left > i {
|
||||
position:absolute;
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
.modal-content, .panel-body {
|
||||
|
||||
// dialog headline ==========================================================
|
||||
h2 {
|
||||
font-family: $font-family-sans-serif;
|
||||
@@ -59,7 +58,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.modal-content {
|
||||
// data tables ==============================================================
|
||||
.dataTables_wrapper{
|
||||
@@ -142,13 +140,11 @@
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// settings dialog ============================================================
|
||||
#pf-settings-dialog{
|
||||
|
||||
// smaller buttons
|
||||
.form-group .btn-sm{
|
||||
padding: 4px 7px 3px;
|
||||
@@ -226,6 +222,13 @@
|
||||
}
|
||||
}
|
||||
|
||||
// connection log dialog ======================================================
|
||||
#pf-connection-info-dialog{
|
||||
#pf-connection-info-dialog-type-select, #pf-connection-info-dialog-character-select{
|
||||
width: 310px !important;
|
||||
}
|
||||
}
|
||||
|
||||
// jump info dialog ===========================================================
|
||||
.pf-jump-info-dialog{
|
||||
blockquote{
|
||||
@@ -233,6 +236,7 @@
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
// changelog
|
||||
.pf-changelog-dialog{
|
||||
.pf-dynamic-message-container{
|
||||
@@ -242,7 +246,6 @@
|
||||
|
||||
// credits dialog =============================================================
|
||||
.pf-credits-dialog{
|
||||
|
||||
.pf-credits-logo-background{
|
||||
overflow: visible;
|
||||
background: url("#{$base-url}/logo_bg.png");
|
||||
|
||||
@@ -37,6 +37,16 @@ input, select{
|
||||
}
|
||||
}
|
||||
|
||||
input[type='number']{
|
||||
&::-webkit-inner-spin-button,
|
||||
&::-webkit-outer-spin-button {
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
textarea{
|
||||
min-height: 32px;
|
||||
max-height: 400px;
|
||||
|
||||
@@ -258,7 +258,7 @@ select:active, select:hover {
|
||||
margin: 0 3px; // <select> for page size
|
||||
padding: 1px;
|
||||
}
|
||||
|
||||
|
||||
.dt-buttons{
|
||||
.dt-button{
|
||||
line-height: 22px;
|
||||
@@ -275,6 +275,53 @@ select:active, select:hover {
|
||||
}
|
||||
}
|
||||
|
||||
// condensed dataTable toolbar
|
||||
.pf-dataTable-condensed-toolbar{
|
||||
padding-top: 3px;
|
||||
|
||||
.dataTables_info{
|
||||
padding-top: 0;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
& > div{
|
||||
padding-left: 5px;
|
||||
padding-right: 5px;
|
||||
}
|
||||
|
||||
.dataTables_paginate{
|
||||
padding-top: 0;
|
||||
margin-top: 0;
|
||||
|
||||
.paginate_button{
|
||||
padding: 0;
|
||||
height: 13px;
|
||||
border: 0 !important;
|
||||
|
||||
&:before, &:after{
|
||||
top: 0;
|
||||
}
|
||||
&:hover{
|
||||
background: transparent !important;
|
||||
color: $orange !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.dt-buttons{
|
||||
text-align: right;
|
||||
margin-bottom: 0;
|
||||
|
||||
.dt-button{
|
||||
line-height: 18px;
|
||||
|
||||
.fa{
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.dataTable{
|
||||
th{
|
||||
&.pf-table-image-cell,
|
||||
|
||||
@@ -215,10 +215,6 @@
|
||||
|
||||
td{
|
||||
text-transform: capitalize;
|
||||
|
||||
& > .fas, & > .far{
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
.fa-sync, .fa-search{
|
||||
@extend .pf-dialog-icon-button;
|
||||
@@ -374,7 +370,7 @@
|
||||
|
||||
// connection info module ==================================================
|
||||
.pf-connection-info-module{
|
||||
.row{
|
||||
& > .row{
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
flex-wrap: wrap;
|
||||
@@ -385,8 +381,8 @@
|
||||
font-size: 10px;
|
||||
|
||||
td{
|
||||
& > .fas, & > .far{
|
||||
font-size: 10px;
|
||||
.fa-plus{
|
||||
@extend .pf-dialog-icon-button;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,9 +91,44 @@
|
||||
&.select2-container--open .select2-dropdown {
|
||||
border-color: $focus-border-color;
|
||||
}
|
||||
|
||||
&.select2-container--disabled {
|
||||
.select2-selection {
|
||||
background-color: $gray;
|
||||
cursor: not-allowed;
|
||||
border: 1px solid $gray-light;
|
||||
|
||||
.select2-selection__arrow{
|
||||
background-color: $gray;
|
||||
}
|
||||
|
||||
.select2-selection__clear{
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// hide small "arrow" for hidden select elements
|
||||
select.select2-hidden-accessible{
|
||||
select.select2-hidden-accessible {
|
||||
@include appearance( none );
|
||||
}
|
||||
|
||||
select[readonly].select2-hidden-accessible {
|
||||
+ .select2-container {
|
||||
pointer-events: none;
|
||||
touch-action: none;
|
||||
|
||||
.select2-selection {
|
||||
background-color: $gray;
|
||||
|
||||
.select2-selection__arrow{
|
||||
background-color: $gray;
|
||||
}
|
||||
|
||||
.select2-selection__clear{
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user