- switched "system search" Ajax endpoint data source from _SDE_ DB to new _eve_universe_ DB, #628 closed #644

- switched "constellation search" Ajax endpoint data source from _SDE_ DB to new _eve_universe_ DB, #628
- improved "system search" field, multiple changes/fixes see #644
This commit is contained in:
Mark Friedrich
2018-06-23 14:26:42 +02:00
parent 38ceb9275c
commit ae04715465
23 changed files with 237 additions and 152 deletions

View File

@@ -10,7 +10,6 @@ namespace Controller\Api;
use Controller;
use Data\Mapper as Mapper;
use lib\Config;
use Model;
class System extends Controller\AccessController {
@@ -131,48 +130,6 @@ class System extends Controller\AccessController {
return $mapper->getData();
}
/**
* search systems by name
* @param \Base $f3
* @param array $params
*/
public function search(\Base $f3, $params){
$ccpDB = $this->getDB('CCP');
$searchToken = '';
// check for search parameter
if( isset($params['arg1']) ){
$searchToken = $params['arg1'];
}
// some "edge cases" for testing trueSec rounding...
//$searchToken = 'H472-N'; // -0.000001 -> 0.0
//$searchToken = 'X1E-OQ'; // -0.099426 -> -0.10
//$searchToken = 'BKK4-H'; // -0.049954 -> -0.05
//$searchToken = 'Uhtafal'; // 0.499612 -> 0.5 (HS)
//$searchToken = 'Oshaima'; // 0.453128 -> 0.5 (HS)
//$searchToken = 'Ayeroilen'; // 0.446568 -> 0.4 (LS)
//$searchToken = 'Enderailen'; // 0.448785 -> 0.4 (LS)
//$searchToken = 'Neziel'; // 0.449943 -> 0.4 (LS)
//$searchToken = 'Naga'; // 0.033684 -> 0.1 (LS)
$this->whereQuery = "WHERE
map_sys.solarSystemName LIKE '%" . $searchToken . "%'";
$query = $this->_getQuery();
$rows = $ccpDB->exec($query);
// format result
$mapper = new Mapper\CcpSystemsMapper($rows);
$data = $mapper->getData();
echo json_encode($data);
}
/**
* save a new system to a a map
* @param \Base $f3
@@ -330,43 +287,6 @@ class System extends Controller\AccessController {
echo json_encode($graphData);
}
/**
* get system data for all systems within a constellation
* @param \Base $f3
* @param array $params
* @throws \Exception
* @throws \Exception\PathfinderException
*/
public function constellationData(\Base $f3, $params){
$return = (object) [];
$return->error = [];
$return->systemData = [];
$constellationId = 0;
// check for search parameter
if( isset($params['arg1']) ){
$constellationId = (int)$params['arg1'];
}
$cacheKey = 'CACHE_CONSTELLATION_SYSTEMS_' . self::formatHiveKey($constellationId);
if($f3->exists($cacheKey, $cachedData)){
$return->systemData = $cachedData;
}else{
if($constellationId > 0){
$systemModels = $this->getSystemModelByIds([$constellationId], 'constellationID');
foreach($systemModels as $systemModel){
$return->systemData[] = $systemModel->getData();
}
$f3->set($cacheKey, $return->systemData, Config::getPathfinderData('cache.constellation_systems'));
}
}
echo json_encode($return);
}
/**
* set destination for specific systemIds
* @param \Base $f3

View File

@@ -10,9 +10,12 @@ namespace Controller\Api;
use Controller;
use Controller\Ccp as Ccp;
use Model;
class Universe extends Controller\AccessController {
const PAGE_SIZE_SYSTEMS = 50;
/**
* search static Universe data by string within categories
* @param \Base $f3
@@ -33,4 +36,93 @@ class Universe extends Controller\AccessController {
echo json_encode($universeNameData);
}
/**
* search systems by name
* @param \Base $f3
* @param $params
* @throws \Exception
*/
public function systems(\Base $f3, $params){
$getData = (array)$f3->get('GET');
$page = isset($getData['page']) ? (int)max($getData['page'],1) : 1;
$search = isset($params['arg1']) ? (string)$params['arg1'] : '';
$morePages = false;
$count = 0;
$return = (object) [];
$return->results = [];
// some "edge cases" for testing trueSec rounding...
//$searchToken = 'H472-N'; // -0.000001 -> 0.0
//$searchToken = 'X1E-OQ'; // -0.099426 -> -0.10
//$searchToken = 'BKK4-H'; // -0.049954 -> -0.05
//$searchToken = 'Uhtafal'; // 0.499612 -> 0.5 (HS)
//$searchToken = 'Oshaima'; // 0.453128 -> 0.5 (HS)
//$searchToken = 'Ayeroilen'; // 0.446568 -> 0.4 (LS)
//$searchToken = 'Enderailen'; // 0.448785 -> 0.4 (LS)
//$searchToken = 'Neziel'; // 0.449943 -> 0.4 (LS)
//$searchToken = 'Naga'; // 0.033684 -> 0.1 (LS)
if( strlen($search) >= 3 ){
$offset = ($page - 1) * self::PAGE_SIZE_SYSTEMS;
$system = Model\Universe\BasicUniverseModel::getNew('SystemModel');
$filter = [
'id LIKE :id OR name LIKE :name',
':id' => $search . '%',
':name' => '%' . $search . '%'
];
$options = [
'order' => 'name',
'offset' => $offset,
'limit' => self::PAGE_SIZE_SYSTEMS
];
$count = $system->count($filter);
$endCount = $offset + self::PAGE_SIZE_SYSTEMS;
$morePages = $endCount < $count;
$systems = $system->find($filter, $options);
if($systems){
foreach($systems as $system){
if($systemData = $system->fromIndex()){
$return->results[] = $systemData;
}
}
}
}
$return->pagination = ['more' => $morePages, 'count' => $count];
echo json_encode($return);
}
/**
* get system data for all systems within a constellation
* @param \Base $f3
* @param array $params
* @throws \Exception
*/
public function constellationData(\Base $f3, $params){
$constellationId = isset($params['arg1']) ? (int)$params['arg1'] : 0;
$return = (object) [];
$return->error = [];
$return->systemsData = [];
$constellation = Model\Universe\BasicUniverseModel::getNew('ConstellationModel');
$constellation->getById($constellationId);
if( !$constellation->dry() && $constellation->systems){
/**
* @var Model\Universe\SystemModel $system
*/
foreach($constellation->systems as $system){
if($systemData = $system->fromIndex()){
$return->systemsData[] = $systemData;
}
}
}
echo json_encode($return);
}
}

View File

@@ -101,7 +101,7 @@ class Universe extends Controller {
* @return array
* @throws \Exception
*/
public function setupCategories(array $categoriesWhitelist = []){
protected function setupCategories(array $categoriesWhitelist = []){
$return = [];
$categoryIds = $this->getF3()->ccpClient->getUniverseCategories();
$categoryIds = array_intersect ($categoriesWhitelist, $categoryIds);

View File

@@ -896,6 +896,18 @@ abstract class BasicModel extends \DB\Cortex {
$cache->set(self::getF3()->hash($key).'.var', $data, $ttl);
}
/**
* check whether a cache $key exists
* -> §val (reference) get updated with the cache data
* -> equivalent to $f3->exists()
* @param string $key
* @param null $val
* @return bool
*/
public static function existsCacheValue(string $key, &$val = null){
return self::getF3()->exists($key, $val);
}
/**
* debug log function
* @param string $text

View File

@@ -302,10 +302,10 @@ class MapModel extends AbstractMapTrackingModel {
$mapDataAll->mapData = $mapData;
// map system data ----------------------------------------------------------------------------------------
$mapDataAll->systems = $this->getSystemData();
$mapDataAll->systems = $this->getSystemsData();
// map connection data ------------------------------------------------------------------------------------
$mapDataAll->connections = $this->getConnectionData();
$mapDataAll->connections = $this->getConnectionsData();
// max caching time for a map
// the cached date has to be cleared manually on any change
@@ -582,7 +582,7 @@ class MapModel extends AbstractMapTrackingModel {
* @return \stdClass[]
* @throws \Exception
*/
public function getSystemData(){
public function getSystemsData(){
$systemData = [];
$systems = $this->getSystems();
@@ -651,7 +651,7 @@ class MapModel extends AbstractMapTrackingModel {
* get all connection data in this map
* @return \stdClass[]
*/
public function getConnectionData() : array {
public function getConnectionsData() : array {
$connectionData = [];
$connections = $this->getConnections();

View File

@@ -8,7 +8,6 @@
namespace Model\Universe;
use DB\Database;
use Model\BasicModel;
@@ -97,8 +96,11 @@ abstract class BasicUniverseModel extends BasicModel {
/**
* build up a "search" index for this model
* -> stores getData() result into Cache (RAM) for faster access
* @return null|\stdClass
*/
public function buildIndex(){
$data = null;
if($hashKeyId = $this->getHashKey()){
$f3 = self::getF3();
$hashKeyTable = self::generateHashKeyTable($this->getTable());
@@ -115,10 +117,29 @@ abstract class BasicUniverseModel extends BasicModel {
$f3->clear($hashKeyId);
$f3->clear($hashKeyTable);
$data = $this->getData();
// straight into cache (no $f->set() ), no sync with hive here -> save ram
self::setCacheValue($hashKeyId, $this->getData(), self::CACHE_INDEX_EXPIRE_KEY);
self::setCacheValue($hashKeyId, $data, self::CACHE_INDEX_EXPIRE_KEY);
self::setCacheValue($hashKeyTable, $cachedData, self::CACHE_INDEX_EXPIRE_KEY);
}
return $data;
}
/**
* get data from "search" index for this model
* -> if data not found -> try to build up index for this model
* @return null|\stdClass
*/
public function fromIndex(){
$data = null;
if($hashKeyId = $this->getHashKey()){
if( !self::existsCacheValue($hashKeyId, $data)){
$data = $this->buildIndex();
}
}
return $data;
}
/**

View File

@@ -108,7 +108,7 @@ class SystemModel extends BasicUniverseModel {
$systemData->name = $this->name;
$systemData->constellation = $this->constellationId->getData();
$systemData->security = $this->security;
$systemData->trueSec = $this->trueSec;
$systemData->trueSec = (float)$this->trueSec;
$systemData->effect = $this->effect;
$systemData->shattered = $this->shattered;

View File

@@ -171,8 +171,6 @@ EXECUTION_LIMIT = 50
[PATHFINDER.CACHE]
; delete character log data if if nothing (ship/system/...) for X seconds (seconds) (default: 3min)
CHARACTER_LOG_INACTIVE = 180
; expire time for static system data (seconds) (default: 20d)
CONSTELLATION_SYSTEMS = 1728000
; max expire time. Expired cache files will be deleted by cronjob (seconds) (default: 10d)
EXPIRE_MAX = 864000
; expire time for EOL (end of life) connections (seconds) (default: 4h + 15min)

View File

@@ -34,11 +34,9 @@ define(['jquery'], ($) => {
getMapLogData: '/api/map/getLogData', // ajax URL - get logs data
// system API
getSystemData: '/api/system/getData', // ajax URL - get system data
searchSystem: '/api/system/search', // ajax URL - search system by name
saveSystem: '/api/system/save', // ajax URL - saves system to map
deleteSystem: '/api/system/delete', // ajax URL - delete system from map
getSystemGraphData: '/api/system/graphData', // ajax URL - get all system graph data
getConstellationData: '/api/system/constellationData', // ajax URL - get system constellation data
setDestination: '/api/system/setDestination', // ajax URL - set destination
pokeRally: '/api/system/pokeRally', // ajax URL - send rally point pokes
// connection API
@@ -56,7 +54,9 @@ define(['jquery'], ($) => {
// stats API
getStatisticsData: '/api/statistic/getData', // ajax URL - get statistics data (activity log)
// universe API
searchUniverseData: '/api/universe/search', // ajax URL - search universe data
searchUniverseData: '/api/universe/search', // ajax URL - search universe data by category Ids
searchUniverseSystemData: '/api/universe/systems', // ajax URL - search universe system data by name
getConstellationData: '/api/universe/constellationData', // ajax URL - get system constellation data
// GitHub API
gitHubReleases: '/api/github/releases' // ajax URL - get release info from GitHub
},

View File

@@ -1634,7 +1634,7 @@ define([
// init system select live search - some delay until modal transition has finished
let selectElement = modalContent.find('.' + config.systemDialogSelectClass);
selectElement.delay(240).initSystemSelect({
key: 'systemId',
key: 'id',
disabledOptions: mapSystemIds
});
});

View File

@@ -94,26 +94,30 @@ define([
};
options = $.extend({}, config, options);
let shatteredClass = Util.getSecurityClassForSystem('SH');
// format result data
function formatResultData (data) {
if(data.loading) return data.text;
if (data.loading){
return data.text;
}
// abyss system font
let systemNameClass = data.security === 'A' ? Util.config.fontTriglivianClass : '' ;
// show effect info just for wormholes
let hideEffectClass = '';
if(data.effect === ''){
hideEffectClass = 'hide';
}
let hideEffectClass = data.effect === null ? 'hide' : '';
let hideShatteredClass = !data.shattered ? 'hide' : '';
let markup = '<div class="clearfix">';
markup += '<div class="col-sm-5 pf-select-item-anchor">' + data.text + '</div>';
markup += '<div class="col-sm-4 pf-select-item-anchor ' + systemNameClass + '">' + data.text + '</div>';
markup += '<div class="col-sm-2 text-right ' + data.effectClass + '">';
markup += '<i class="fas fa-fw fa-square ' + hideEffectClass + '"></i>';
markup += '</div>';
markup += '<div class="col-sm-2 text-right ' + data.secClass + '">' + data.security + '</div>';
markup += '<div class="col-sm-3 text-right ' + data.trueSecClass + '">' + data.trueSec + '</div></div>';
markup += '<div class="col-sm-2 text-right ' + shatteredClass + '">';
markup += '<i class="fas fa-fw fa-skull ' + hideShatteredClass + '"></i>';
markup += '</div>';
markup += '<div class="col-sm-2 text-right ' + data.trueSecClass + '">' + data.trueSec + '</div></div>';
return markup;
}
@@ -123,22 +127,22 @@ define([
ajax: {
url: function(params){
// add params to URL
return Init.path.searchSystem + '/' + params.term.trim();
return Init.path.searchUniverseSystemData + '/' + params.term.trim();
},
dataType: 'json',
delay: 250,
timeout: 5000,
cache: true,
data: function(params) {
// no url params here
return;
data: function(params){
return {
page: params.page || 1
};
},
processResults: function(data) {
processResults: function(data, params) {
// parse the results into the format expected by Select2.
return {
results: data.map( function(item){
// "systemId" or "name"
results: data.results.map( function(item){
// "id" or "name"
let id = item[options.key];
let disabled = false;
let trueSec = parseFloat(item.trueSec);
@@ -167,16 +171,20 @@ define([
return {
id: id,
text: item.name,
systemId: parseInt(item.systemId),
// systemId: parseInt(item.systemId),
security: item.security,
secClass: secClass,
trueSec: trueSec.toFixed(1),
trueSecClass: trueSecClass,
effect: item.effect,
effectClass: effectClass,
shattered: item.shattered,
disabled: disabled
};
})
}),
pagination: {
more: data.pagination.more
}
};
},
error: function (jqXHR, status, error) {

View File

@@ -363,7 +363,7 @@ define([
$.ajax({
url: popoverElement.data('url'),
success: function(data){
let systemEffectTable = Util.getSystemsInfoTable( data.systemData );
let systemEffectTable = Util.getSystemsInfoTable( data.systemsData );
popover.options.content = systemEffectTable;
// reopen popover (new content size)
popover.show();

View File

@@ -999,6 +999,15 @@ define([
autoHideScrollbar: false,
advanced: {
updateOnContentResize: true
},
callbacks: {
alwaysTriggerOffsets: false, // only trigger callback.onTotalScroll() once
onTotalScrollOffset: 300, // trigger callback.onTotalScroll() 100px before end
onTotalScroll: function(a){
// 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');
}
}
});
};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -34,11 +34,9 @@ define(['jquery'], ($) => {
getMapLogData: '/api/map/getLogData', // ajax URL - get logs data
// system API
getSystemData: '/api/system/getData', // ajax URL - get system data
searchSystem: '/api/system/search', // ajax URL - search system by name
saveSystem: '/api/system/save', // ajax URL - saves system to map
deleteSystem: '/api/system/delete', // ajax URL - delete system from map
getSystemGraphData: '/api/system/graphData', // ajax URL - get all system graph data
getConstellationData: '/api/system/constellationData', // ajax URL - get system constellation data
setDestination: '/api/system/setDestination', // ajax URL - set destination
pokeRally: '/api/system/pokeRally', // ajax URL - send rally point pokes
// connection API
@@ -56,7 +54,9 @@ define(['jquery'], ($) => {
// stats API
getStatisticsData: '/api/statistic/getData', // ajax URL - get statistics data (activity log)
// universe API
searchUniverseData: '/api/universe/search', // ajax URL - search universe data
searchUniverseData: '/api/universe/search', // ajax URL - search universe data by category Ids
searchUniverseSystemData: '/api/universe/systems', // ajax URL - search universe system data by name
getConstellationData: '/api/universe/constellationData', // ajax URL - get system constellation data
// GitHub API
gitHubReleases: '/api/github/releases' // ajax URL - get release info from GitHub
},

View File

@@ -1560,7 +1560,8 @@ define([
let form = $('#' + config.systemDialogId).find('form');
let systemDialogData = $(form).getFormValues();
console.log(systemDialogData);
return false;
// validate form
form.validator('validate');
@@ -1634,7 +1635,7 @@ define([
// init system select live search - some delay until modal transition has finished
let selectElement = modalContent.find('.' + config.systemDialogSelectClass);
selectElement.delay(240).initSystemSelect({
key: 'systemId',
key: 'id',
disabledOptions: mapSystemIds
});
});

View File

@@ -94,26 +94,30 @@ define([
};
options = $.extend({}, config, options);
let shatteredClass = Util.getSecurityClassForSystem('SH');
// format result data
function formatResultData (data) {
if(data.loading) return data.text;
if (data.loading){
return data.text;
}
// abyss system font
let systemNameClass = data.security === 'A' ? Util.config.fontTriglivianClass : '' ;
// show effect info just for wormholes
let hideEffectClass = '';
if(data.effect === ''){
hideEffectClass = 'hide';
}
let hideEffectClass = data.effect === null ? 'hide' : '';
let hideShatteredClass = !data.shattered ? 'hide' : '';
let markup = '<div class="clearfix">';
markup += '<div class="col-sm-5 pf-select-item-anchor">' + data.text + '</div>';
markup += '<div class="col-sm-4 pf-select-item-anchor ' + systemNameClass + '">' + data.text + '</div>';
markup += '<div class="col-sm-2 text-right ' + data.effectClass + '">';
markup += '<i class="fas fa-fw fa-square ' + hideEffectClass + '"></i>';
markup += '</div>';
markup += '<div class="col-sm-2 text-right ' + data.secClass + '">' + data.security + '</div>';
markup += '<div class="col-sm-3 text-right ' + data.trueSecClass + '">' + data.trueSec + '</div></div>';
markup += '<div class="col-sm-2 text-right ' + shatteredClass + '">';
markup += '<i class="fas fa-fw fa-skull ' + hideShatteredClass + '"></i>';
markup += '</div>';
markup += '<div class="col-sm-2 text-right ' + data.trueSecClass + '">' + data.trueSec + '</div></div>';
return markup;
}
@@ -123,22 +127,22 @@ define([
ajax: {
url: function(params){
// add params to URL
return Init.path.searchSystem + '/' + params.term.trim();
return Init.path.searchUniverseSystemData + '/' + params.term.trim();
},
dataType: 'json',
delay: 250,
timeout: 5000,
cache: true,
data: function(params) {
// no url params here
return;
data: function(params){
return {
page: params.page || 1
};
},
processResults: function(data) {
processResults: function(data, params) {
// parse the results into the format expected by Select2.
return {
results: data.map( function(item){
// "systemId" or "name"
results: data.results.map( function(item){
// "id" or "name"
let id = item[options.key];
let disabled = false;
let trueSec = parseFloat(item.trueSec);
@@ -167,16 +171,20 @@ define([
return {
id: id,
text: item.name,
systemId: parseInt(item.systemId),
// systemId: parseInt(item.systemId),
security: item.security,
secClass: secClass,
trueSec: trueSec.toFixed(1),
trueSecClass: trueSecClass,
effect: item.effect,
effectClass: effectClass,
shattered: item.shattered,
disabled: disabled
};
})
}),
pagination: {
more: data.pagination.more
}
};
},
error: function (jqXHR, status, error) {

View File

@@ -363,7 +363,7 @@ define([
$.ajax({
url: popoverElement.data('url'),
success: function(data){
let systemEffectTable = Util.getSystemsInfoTable( data.systemData );
let systemEffectTable = Util.getSystemsInfoTable( data.systemsData );
popover.options.content = systemEffectTable;
// reopen popover (new content size)
popover.show();

View File

@@ -999,6 +999,15 @@ define([
autoHideScrollbar: false,
advanced: {
updateOnContentResize: true
},
callbacks: {
alwaysTriggerOffsets: false, // only trigger callback.onTotalScroll() once
onTotalScrollOffset: 300, // trigger callback.onTotalScroll() 100px before end
onTotalScroll: function(a){
// 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');
}
}
});
};

View File

@@ -193,7 +193,7 @@
// ad system dialog ===========================================================
.pf-system-dialog-select{
width: 270px !important;
width: 300px !important;
}
// task-manager dialog ========================================================

View File

@@ -185,7 +185,10 @@ select:active, select:hover {
// select2 custom template ========================================================================
.select2-results{
[class*="col-"]{
// smaller and less padding
line-height: 22px;
padding-left: 3px;
padding-right: 3px;
}
}

View File

@@ -57,15 +57,19 @@
background-color: $results-choice-bg-unselectable-color;
// add a icon to all "disabled" options
.pf-select-item-anchor:before{
content: "\f05e";
font-family: "Font Awesome 5 Free";
font-weight: bold;
font-size: 9px;
position: absolute;
left: 0;
top: 0;
color: $gray-light;
.pf-select-item-anchor {
padding-left: 15px; // leave space for :before icon
&:before {
content: "\f05e";
font-family: "Font Awesome 5 Free";
font-weight: bold;
font-size: 9px;
position: absolute;
left: 2px;
top: 0;
color: $gray-light;
}
}
}
}