- moved ajax endpoints (connections, systems) into new REST API endpoints, #274

- improved error handling in case an Exception is thrown
This commit is contained in:
Mark Friedrich
2018-11-16 19:09:12 +01:00
parent 07d5be71b2
commit 703091949b
28 changed files with 754 additions and 904 deletions

View File

@@ -1,51 +1,40 @@
<?php
/**
* Created by PhpStorm.
* User: exodus4d
* Date: 01.03.15
* Time: 18:37
* User: Exodus 4D
* Date: 10.11.2018
* Time: 12:10
*/
namespace Controller\Api;
namespace Controller\Api\Rest;
use Controller;
use Model;
class Connection extends Controller\AccessController {
class Connection extends AbstractRestController {
/**
* save a new connection or updates an existing (drag/drop) between two systems
* if a connection is changed (drag&drop) to another system. -> this function is called for update
* @param \Base $f3
* @throws \Exception
* @throws \ZMQSocketException
*/
public function save(\Base $f3){
$postData = (array)$f3->get('POST');
$return = (object) [];
$return->error = [];
$return->connectionData = (object) [];
if(
isset($postData['connectionData']) &&
isset($postData['mapData'])
){
$mapData = (array)$postData['mapData'];
$connectionData = (array)$postData['connectionData'];
public function put(\Base $f3){
$requestData = $this->getRequestData($f3);
$connectionData = [];
if($mapId = (int)$requestData['mapId']){
$activeCharacter = $this->getCharacter();
// get map model and check map access
/**
* @var Model\MapModel $map
*/
$map = Model\BasicModel::getNew('MapModel');
$map->getById( (int)$mapData['id'] );
$map->getById($mapId);
if( $map->hasAccess($activeCharacter) ){
$source = $map->getSystemById( $connectionData['source'] );
$target = $map->getSystemById( $connectionData['target'] );
if($map->hasAccess($activeCharacter)){
$source = $map->getSystemById((int)$requestData['source']);
$target = $map->getSystemById((int)$requestData['target']);
if(
!is_null($source) &&
@@ -55,7 +44,7 @@ class Connection extends Controller\AccessController {
* @var $connection Model\ConnectionModel
*/
$connection = Model\BasicModel::getNew('ConnectionModel');
$connection->getById( (int)$connectionData['id'] );
$connection->getById((int)$requestData['id']);
$connection->mapId = $map;
$connection->source = $source;
@@ -66,30 +55,30 @@ class Connection extends Controller\AccessController {
$connection->setDefaultTypeData();
if($connection->save($activeCharacter)){
$return->connectionData = $connection->getData();
$connectionData = $connection->getData();
// broadcast map changes
$this->broadcastMapData($connection->mapId);
}else{
$return->error = $connection->getErrors();
}
}
}
}
echo json_encode($return);
$this->out($connectionData);
}
/**
* delete connection
* @param \Base $f3
* @param $params
* @throws \Exception
* @throws \ZMQSocketException
*/
public function delete(\Base $f3){
$mapId = (int)$f3->get('POST.mapId');
$connectionIds = (array)$f3->get('POST.connectionIds');
public function delete(\Base $f3, $params){
$requestData = $this->getRequestData($f3);
$connectionIds = array_map('intval', explode(',', (string)$params['id']));
$deletedConnectionIds = [];
if($mapId){
if($mapId = (int)$requestData['mapId']){
$activeCharacter = $this->getCharacter();
/**
@@ -100,20 +89,21 @@ class Connection extends Controller\AccessController {
if($map->hasAccess($activeCharacter)){
foreach($connectionIds as $connectionId){
if( $connection = $map->getConnectionById($connectionId) ){
if($connection = $map->getConnectionById($connectionId)){
$connection->delete( $activeCharacter );
$connection->reset();
$deletedConnectionIds[] = $connectionId;
}
}
// broadcast map changes
$this->broadcastMapData($map);
if(count($deletedConnectionIds)){
$this->broadcastMapData($map);
}
}
}
echo json_encode([]);
$this->out($deletedConnectionIds);
}
}
}

View File

@@ -60,7 +60,6 @@ class Log extends AbstractRestController {
$this->out($connectionData);
}
/**
* update log data
* @param \Base $f3

View File

@@ -0,0 +1,190 @@
<?php
/**
* Created by PhpStorm.
* User: Exodus 4D
* Date: 09.11.2018
* Time: 12:34
*/
namespace Controller\Api\Rest;
use Model;
class System extends AbstractRestController {
/**
* put (insert) system
* @param \Base $f3
* @throws \Exception
*/
public function put(\Base $f3){
$requestData = $this->getRequestData($f3);
$systemData = [];
if($mapId = (int)$requestData['mapId']){
$activeCharacter = $this->getCharacter();
/**
* @var $map Model\MapModel
*/
$map = Model\BasicModel::getNew('MapModel');
$map->getById($mapId);
if($map->hasAccess($activeCharacter)){
$system = $map->getNewSystem($requestData['systemId']);
$systemData = $this->update($system, $requestData)->getData();
}
}
$this->out($systemData);
}
/**
* update existing system
* @param \Base $f3
* @param $params
* @throws \Exception
*/
public function patch(\Base $f3, $params){
$requestData = $this->getRequestData($f3);
$systemData = [];
if($systemId = (int)$params['id']){
$activeCharacter = $this->getCharacter();
/**
* @var $system Model\SystemModel
*/
$system = Model\BasicModel::getNew('SystemModel');
$system->getById($systemId);
if($system->hasAccess($activeCharacter)){
$systemData = $this->update($system, $requestData)->getData();
}
}
$this->out($systemData);
}
/**
* @param \Base $f3
* @param $params
* @throws \ZMQSocketException
* @throws \Exception
*/
public function delete(\Base $f3, $params){
$requestData = $this->getRequestData($f3);
$systemIds = array_map('intval', explode(',', (string)$params['id']));
$deletedSystemIds = [];
if($mapId = (int)$requestData['mapId']){
$activeCharacter = $this->getCharacter();
/**
* @var Model\MapModel $map
*/
$map = Model\BasicModel::getNew('MapModel');
$map->getById($mapId);
if($map->hasAccess($activeCharacter)){
$newSystemModel = Model\BasicModel::getNew('SystemModel');
foreach($systemIds as $systemId){
if($system = $map->getSystemById($systemId)){
// check whether system should be deleted OR set "inactive"
if($this->checkDeleteMode($map, $system)){
// delete log
// -> first set updatedCharacterId -> required for activity log
$system->updatedCharacterId = $activeCharacter;
$system->update();
// ... now get fresh object and delete..
$newSystemModel->getById($system->_id, 0);
$newSystemModel->erase();
$newSystemModel->reset();
}else{
// keep data -> set "inactive"
$system->setActive(false);
$system->save($activeCharacter);
}
$system->reset();
$deletedSystemIds[] = $systemId;
}
}
// broadcast map changes
if(count($deletedSystemIds)){
$this->broadcastMapData($map);
}
}
}
$this->out($deletedSystemIds);
}
// ----------------------------------------------------------------------------------------------------------------
/**
* update system with new data
* @param Model\SystemModel $system
* @param array $systemData
* @return Model\SystemModel
* @throws \ZMQSocketException
* @throws \Exception
*/
private function update(Model\SystemModel $system, array $systemData) : Model\SystemModel {
$activeCharacter = $this->getCharacter();
// statusId === 0 is 'auto' status -> keep current status
// -> relevant systems that already have a status (inactive systems)
if( (int)$systemData['statusId'] <= 0 ){
unset($systemData['statusId']);
}
if( !$system->dry() ){
// activate system (e.g. was inactive))
$system->setActive(true);
}
$system->setData($systemData);
$system->save($activeCharacter);
// get data from "fresh" model (e.g. some relational data has changed: "statusId")
/**
* @var $newSystem Model\SystemModel
*/
$newSystem = Model\BasicModel::getNew('SystemModel');
$newSystem->getById($system->_id, 0);
$newSystem->clearCacheData();
// broadcast map changes
$this->broadcastMapData($newSystem->mapId);
return $newSystem;
}
/**
* checks whether a system should be "deleted" or set "inactive" (keep some data)
* @param Model\MapModel $map
* @param Model\SystemModel $system
* @return bool
*/
private function checkDeleteMode(Model\MapModel $map, Model\SystemModel $system) : bool {
$delete = true;
if( !empty($system->description) ){
// never delete systems with custom description set!
$delete = false;
}elseif(
$map->persistentAliases &&
!empty($system->alias) &&
($system->alias != $system->name)
){
// map setting "persistentAliases" is active (default) AND
// alias is set and != name
$delete = false;
}
return $delete;
}
}

View File

@@ -10,7 +10,6 @@ namespace Controller\Api;
use Controller;
use Model;
use Exception;
class System extends Controller\AccessController {
@@ -26,88 +25,6 @@ class System extends Controller\AccessController {
return sprintf(self::CACHE_KEY_GRAPH, 'SYSTEM_' . $systemId);
}
/**
* save a new system to a a map
* @param \Base $f3
* @throws \Exception
*/
public function save(\Base $f3){
$postData = (array)$f3->get('POST');
$return = (object) [];
$return->error = [];
$return->systemData = (object) [];
if(
isset($postData['systemData']) &&
isset($postData['mapData'])
){
$activeCharacter = $this->getCharacter();
$systemData = (array)$postData['systemData'];
$mapData = (array)$postData['mapData'];
$systemModel = null;
if( (int)$systemData['statusId'] <= 0 ){
unset($systemData['statusId']);
}
if( isset($systemData['id']) ){
// update existing system (e.g. set description) ------------------------------------------------------
/**
* @var $system Model\SystemModel
*/
$system = Model\BasicModel::getNew('SystemModel');
$system->getById($systemData['id']);
if(
!$system->dry() &&
$system->hasAccess($activeCharacter)
){
// system model found
// activate system (e.g. was inactive))
$system->setActive(true);
$systemModel = $system;
}
}elseif( isset($mapData['id']) ){
// save NEW system ------------------------------------------------------------------------------------
/**
* @var $map Model\MapModel
*/
$map = Model\BasicModel::getNew('MapModel');
$map->getById($mapData['id']);
if($map->hasAccess($activeCharacter)){
$systemModel = $map->getNewSystem($systemData['systemId']);
}
}
if( !is_null($systemModel) ){
try{
// set/update system custom data
$systemModel->copyfrom($systemData, ['statusId', 'locked', 'rallyUpdated', 'position', 'description']);
if($systemModel->save($activeCharacter)){
// get data from "fresh" model (e.g. some relational data has changed: "statusId")
/**
* @var $newSystemModel Model\SystemModel
*/
$newSystemModel = Model\BasicModel::getNew('SystemModel');
$newSystemModel->getById( $systemModel->_id, 0);
$newSystemModel->clearCacheData();
$return->systemData = $newSystemModel->getData();
// broadcast map changes
$this->broadcastMapData($newSystemModel->mapId);
}else{
$return->error = $systemModel->getErrors();
}
}catch(Exception\ValidationException $e){
$return->error[] = $e->getError();
}
}
}
echo json_encode($return);
}
/**
* get system log data from CCP API import
* system Kills, Jumps,....
@@ -294,87 +211,5 @@ class System extends Controller\AccessController {
echo json_encode($return);
}
/**
* delete systems and all its connections from map
* -> set "active" flag
* @param \Base $f3
* @throws \Exception
*/
public function delete(\Base $f3){
$mapId = (int)$f3->get('POST.mapId');
$systemIds = array_map('intval', (array)$f3->get('POST.systemIds'));
$return = (object) [];
$return->deletedSystemIds = [];
if($mapId){
$activeCharacter = $this->getCharacter();
/**
* @var Model\MapModel $map
*/
$map = Model\BasicModel::getNew('MapModel');
$map->getById($mapId);
if($map->hasAccess($activeCharacter)){
$newSystemModel = Model\BasicModel::getNew('SystemModel');
foreach($systemIds as $systemId){
if( $system = $map->getSystemById($systemId) ){
// check whether system should be deleted OR set "inactive"
if( $this->checkDeleteMode($map, $system) ){
// delete log
// -> first set updatedCharacterId -> required for activity log
$system->updatedCharacterId = $activeCharacter;
$system->update();
// ... now get fresh object and delete..
$newSystemModel->getById( $system->id, 0);
$newSystemModel->erase();
$newSystemModel->reset();
}else{
// keep data -> set "inactive"
$system->setActive(false);
$system->save($activeCharacter);
}
$system->reset();
$return->deletedSystemIds[] = $systemId;
}
}
// broadcast map changes
if(count($return->deletedSystemIds)){
$this->broadcastMapData($map);
}
}
}
echo json_encode($return);
}
/**
* checks whether a system should be "deleted" or set "inactive" (keep some data)
* @param Model\MapModel $map
* @param Model\SystemModel $system
* @return bool
*/
protected function checkDeleteMode(Model\MapModel $map, Model\SystemModel $system){
$delete = true;
if( !empty($system->description) ){
// never delete systems with custom description set!
$delete = false;
}elseif(
$map->persistentAliases &&
!empty($system->alias) &&
($system->alias != $system->name)
){
// map setting "persistentAliases" is active (default) AND
// alias is set and != name
$delete = false;
}
return $delete;
}
}

View File

@@ -690,7 +690,7 @@ class Controller {
$errorData['code'],
$errorData['status'],
$errorData['text'],
$f3->get('DEBUG') === 3 ? $errorData['trace'] : null
$f3->get('DEBUG') >= 1 ? $errorData['trace'] : null
);
}

View File

@@ -127,7 +127,7 @@ class Database extends \Prefab {
];
// set ERRMODE depending on pathfinders global DEBUG level
if($f3->get('DEBUG') >= 3){
if($f3->get('DEBUG') >= 1){
$options[\PDO::ATTR_ERRMODE] = \PDO::ERRMODE_WARNING;
}else{
$options[\PDO::ATTR_ERRMODE] = \PDO::ERRMODE_EXCEPTION;

View File

@@ -8,6 +8,7 @@
namespace Exception;
use lib\Config;
class PathfinderException extends \Exception {
@@ -41,10 +42,11 @@ class PathfinderException extends \Exception {
$error = (object) [];
$error->type = 'error';
$error->code = $this->getResponseCode();
$error->status = @constant('Base::HTTP_' . $this->getResponseCode());
$error->status = Config::getHttpStatusByCode($this->getResponseCode());
$error->message = $this->getMessage();
//$error->trace = $this->getTraceAsString();
$error->trace = $this->getTrace();
if(\Base::instance()->get('DEBUG') >= 1){
$error->trace = preg_split('/\R/', $this->getTraceAsString()); // no $this->>getTrace() here -> to much data
}
return $error;
}

View File

@@ -12,7 +12,7 @@ namespace Exception;
class ValidationException extends PathfinderException {
protected $codes = [
2000 => 593
2000 => 422
];
/**

View File

@@ -30,6 +30,9 @@ class Config extends \Prefab {
*/
const ARRAY_KEYS = ['CCP_ESI_SCOPES', 'CCP_ESI_SCOPES_ADMIN'];
const
HTTP_422='Unprocessable Entity';
/**
* all environment data
* @var array
@@ -392,4 +395,18 @@ class Config extends \Prefab {
return $data;
}
/**
* get HTTP status message by HTTP return code
* -> either from F3 or from self::Config constants
* @param int $code
* @return string
*/
static function getHttpStatusByCode(int $code) : string {
if(empty($status = @constant('Base::HTTP_' . $code))){
$status = @constant('self::HTTP_' . $code);
}
return $status;
}
}

View File

@@ -119,6 +119,14 @@ class SystemModel extends AbstractMapTrackingModel {
]
];
/**
* set map data by an associative array
* @param array $data
*/
public function setData(array $data){
$this->copyfrom($data, ['statusId', 'locked', 'rallyUpdated', 'position', 'description']);
}
/**
* get map data as object
* @return \stdClass
@@ -271,7 +279,7 @@ class SystemModel extends AbstractMapTrackingModel {
$valid = true;
if(mb_strlen($val) > 9000){
$valid = false;
$this->throwValidationException($key);
$this->throwValidationException($key, 'Validation failed: "' . $key . '" too long');
}
return $valid;
}

View File

@@ -13,11 +13,12 @@ GET @map: /map* [sync] = Controller\MapContro
; admin panel
GET @admin: /admin* [sync] = Controller\Admin->dispatch
; ajax wildcard APIs (throttled)
; AJAX API wildcard endpoints (not cached, throttled)
GET|POST /api/@controller/@action [ajax] = Controller\Api\@controller->@action, 0, 512
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]
; REST API wildcard endpoints (not cached, throttled)
/api/rest/@controller* [ajax] = Controller\Api\Rest\@controller, 0, 512
/api/rest/@controller/@id [ajax] = Controller\Api\Rest\@controller, 0, 512

View File

@@ -35,14 +35,9 @@ define(['jquery'], ($) => {
getMapLogData: '/api/map/getLogData', // ajax URL - get logs data
// system API
getSystemData: '/api/system/getData', // ajax URL - get system data
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
setDestination: '/api/system/setDestination', // ajax URL - set destination
pokeRally: '/api/system/pokeRally', // ajax URL - send rally point pokes
// connection API
saveConnection: '/api/connection/save', // ajax URL - save new connection to map
deleteConnection: '/api/connection/delete', // ajax URL - delete connection from map
// signature API
saveSignatureData: '/api/signature/save', // ajax URL - save signature data for system
deleteSignatureData: '/api/signature/delete', // ajax URL - delete signature data for system

View File

@@ -559,7 +559,7 @@ define([
// confirm dialog
bootbox.confirm('Is this connection really gone?', function(result){
if(result){
$().deleteConnections([activeConnection]);
MapUtil.deleteConnections([activeConnection]);
}
});
break;
@@ -1385,158 +1385,73 @@ define([
* @param connection
*/
let saveConnection = function(connection){
if( connection instanceof jsPlumb.Connection ){
if(connection instanceof jsPlumb.Connection){
let map = connection._jsPlumb.instance;
let mapContainer = $( map.getContainer() );
let mapContainer = $(map.getContainer());
let mapId = mapContainer.data('id');
let connectionData = MapUtil.getDataByConnection(connection);
connectionData.mapId = mapId;
let requestData = {
mapData: {
id: mapId
},
connectionData: connectionData
};
Util.request('PUT', 'connection', [], connectionData, {
connection: connection,
map: map,
mapId: mapId,
oldConnectionData: connectionData
}).then(
payload => {
let newConnectionData = payload.data;
$.ajax({
type: 'POST',
url: Init.path.saveConnection,
data: requestData,
dataType: 'json',
context: {
connection: connection,
map: map,
mapId: mapId,
oldConnectionData: connectionData
}
}).done(function(responseData){
let newConnectionData = responseData.connectionData;
if( !$.isEmptyObject(newConnectionData) ){
let updateCon = false;
if( !$.isEmptyObject(newConnectionData) ){
let updateCon = false;
if(this.oldConnectionData.id > 0){
// connection exists (e.g. drag&drop new target system... (ids should never changed)
let connection = $().getConnectionById(this.mapId, this.oldConnectionData.id);
updateCon = true;
}else{
// new connection, check if connectionId was already updated (webSocket push is faster than ajax callback)
let connection = $().getConnectionById(this.mapId, newConnectionData.id);
if(connection){
// connection already updated
this.map.detach(this.connection, {fireEvent: false});
}else{
// .. else update this connection
connection = this.connection;
if(payload.context.oldConnectionData.id > 0){
// connection exists (e.g. drag&drop new target system... (ids should never changed)
let connection = $().getConnectionById(payload.context.mapId, payload.context.oldConnectionData.id);
updateCon = true;
}else{
// new connection, check if connectionId was already updated (webSocket push is faster than ajax callback)
let connection = $().getConnectionById(payload.context.mapId, newConnectionData.id);
if(connection){
// connection already updated
payload.context.map.detach(payload.context.connection, {fireEvent: false});
}else{
// .. else update this connection
connection = payload.context.connection;
updateCon = true;
}
}
if(updateCon){
// update connection data e.g. "scope" has auto detected
connection = updateConnection(connection, payload.context.oldConnectionData, newConnectionData);
// new/updated connection should be cached immediately!
updateConnectionCache(payload.context.mapId, connection);
}
// connection scope
let scope = MapUtil.getScopeInfoForConnection(newConnectionData.scope, 'label');
let title = 'New connection established';
if(payload.context.oldConnectionData.id > 0){
title = 'Connection switched';
}
Util.showNotify({title: title, text: 'Scope: ' + scope, type: 'success'});
}else{
// some save errors
payload.context.map.detach(payload.context.connection, {fireEvent: false});
}
if(updateCon){
// update connection data e.g. "scope" has auto detected
connection = updateConnection(connection, this.oldConnectionData, newConnectionData);
// new/updated connection should be cached immediately!
updateConnectionCache(this.mapId, connection);
}
// connection scope
let scope = MapUtil.getScopeInfoForConnection(newConnectionData.scope, 'label');
let title = 'New connection established';
if(this.oldConnectionData.id > 0){
title = 'Connection switched';
}
Util.showNotify({title: title, text: 'Scope: ' + scope, type: 'success'});
}else{
// some save errors
this.map.detach(this.connection, {fireEvent: false});
},
payload => {
// remove this connection from map
payload.context.map.detach(payload.context.connection, {fireEvent: false});
Util.handleAjaxErrorResponse(payload);
}
// show errors
if(
responseData.error &&
responseData.error.length > 0
){
for(let i = 0; i < responseData.error.length; i++){
let error = responseData.error[i];
Util.showNotify({title: error.field + ' error', text: 'System: ' + error.message, type: error.type});
}
}
}).fail(function(jqXHR, status, error){
// remove this connection from map
this.map.detach(this.connection, {fireEvent: false});
let reason = status + ' ' + error;
Util.showNotify({title: jqXHR.status + ': saveConnection', text: reason, type: 'warning'});
$(document).setProgramStatus('problem');
});
}
};
/**
* delete a connection and all related data
* @param connections
* @param callback
*/
$.fn.deleteConnections = function(connections, callback){
if(connections.length > 0){
// remove connections from map
let removeConnections = function(tempConnections){
for(let i = 0; i < tempConnections.length; i++){
// if a connection is manually (drag&drop) detached, the jsPlumb instance does not exist any more
// connection is already deleted!
if(tempConnections[i]._jsPlumb){
tempConnections[i]._jsPlumb.instance.detach(tempConnections[i], {fireEvent: false});
}
}
};
// prepare delete request
let map = connections[0]._jsPlumb.instance;
let mapContainer = $( map.getContainer() );
let connectionIds = [];
// connectionIds for delete request
for(let i = 0; i < connections.length; i++){
let connectionId = connections[i].getParameter('connectionId');
// drag&drop a new connection does not have an id yet, if connection is not established correct
if(connectionId !== undefined){
connectionIds[i] = connections[i].getParameter('connectionId');
}
}
if(connectionIds.length > 0){
let requestData = {
mapId: mapContainer.data('id'),
connectionIds: connectionIds
};
$.ajax({
type: 'POST',
url: Init.path.deleteConnection,
data: requestData,
dataType: 'json',
context: connections
}).done(function(data){
// remove connections from map
removeConnections(this);
// optional callback
if(callback){
callback();
}
}).fail(function(jqXHR, status, error){
let reason = status + ' ' + error;
Util.showNotify({title: jqXHR.status + ': deleteSystem', text: reason, type: 'warning'});
$(document).setProgramStatus('problem');
});
}
);
}
};
@@ -2181,7 +2096,7 @@ define([
newJsPlumbInstance.bind('connectionDetached', function(info, e){
// a connection is manually (drag&drop) detached! otherwise this event should not be send!
let connection = info.connection;
$().deleteConnections([connection]);
MapUtil.deleteConnections([connection]);
});
newJsPlumbInstance.bind('checkDropAllowed', function(params){

View File

@@ -56,47 +56,6 @@ define([
'- DPS and Logistic ships needed'
};
/**
* save a new system and add it to the map
* @param requestData
* @param context
* @param callback
*/
let saveSystem = (requestData, context, callback) => {
$.ajax({
type: 'POST',
url: Init.path.saveSystem,
data: requestData,
dataType: 'json',
context: context
}).done(function(responseData){
let newSystemData = responseData.systemData;
if( !$.isEmptyObject(newSystemData) ){
Util.showNotify({title: 'New system', text: newSystemData.name, type: 'success'});
callback(newSystemData);
}
if(
responseData.error &&
responseData.error.length > 0
){
for(let i = 0; i < responseData.error.length; i++){
let error = responseData.error[i];
Util.showNotify({title: error.field + ' error', text: 'System: ' + error.message, type: error.type});
}
}
}).fail(function(jqXHR, status, error){
let reason = status + ' ' + error;
Util.showNotify({title: jqXHR.status + ': saveSystem', text: reason, type: 'warning'});
$(document).setProgramStatus('problem');
}).always(function(){
this.systemDialog.find('.modal-content').hideLoadingAnimation();
});
};
/**
* open "new system" dialog and add the system to map
* optional the new system is connected to a "sourceSystem" (if available)
@@ -256,7 +215,7 @@ define([
// get form Values
let form = this.find('form');
let systemDialogData = $(form).getFormValues();
let formData = $(form).getFormValues();
// validate form
form.validator('validate');
@@ -288,27 +247,31 @@ define([
};
}
systemDialogData.position = newPosition;
formData.position = newPosition;
formData.mapId = mapId;
// ----------------------------------------------------------------------------------------
let requestData = {
systemData: systemDialogData,
mapData: {
id: mapId
}
};
this.find('.modal-content').showLoadingAnimation();
saveSystem(requestData, {
systemDialog: this
}, (newSystemData) => {
// success callback
callback(map, newSystemData, sourceSystem);
Util.request('PUT', 'system', [], formData, {
systemDialog: systemDialog,
formElement: form,
map: map,
sourceSystem: sourceSystem
}, context => {
// always do
context.systemDialog.find('.modal-content').hideLoadingAnimation();
}).then(
payload => {
Util.showNotify({title: 'New system', text: payload.data.name, type: 'success'});
callback(payload.context.map, payload.data, payload.context.sourceSystem);
bootbox.hideAll();
},
Util.handleAjaxErrorResponse
);
bootbox.hideAll();
});
return false;
}
}
@@ -695,36 +658,29 @@ define([
*/
let deleteSystems = (map, systems = [], callback = (systems) => {}) => {
let mapContainer = $( map.getContainer() );
let systemIds = systems.map(system => $(system).data('id'));
$.ajax({
type: 'POST',
url: Init.path.deleteSystem,
data: {
mapId: mapContainer.data('id'),
systemIds: systems.map( system => $(system).data('id') )
Util.request('DELETE', 'system', systemIds, {
mapId: mapContainer.data('id')
}, {
map: map,
systems: systems
}).then(
payload => {
// check if all systems were deleted that should get deleted
let deletedSystems = payload.context.systems.filter(
function(system){
return this.indexOf( $(system).data('id') ) !== -1;
}, payload.data
);
// remove systems from map
removeSystems(payload.context.map, deletedSystems);
callback(deletedSystems);
},
dataType: 'json',
context: {
map: map,
systems: systems
}
}).done(function(data){
// check if all systems were deleted that should get deleted
let deletedSystems = this.systems.filter(
function(system){
return this.indexOf( $(system).data('id') ) !== -1;
}, data.deletedSystemIds
);
// remove systems from map
removeSystems(this.map, deletedSystems);
callback(deletedSystems);
}).fail(function(jqXHR, status, error){
let reason = status + ' ' + error;
Util.showNotify({title: jqXHR.status + ': deleteSystem', text: reason, type: 'warning'});
$(document).setProgramStatus('problem');
});
Util.handleAjaxErrorResponse
);
};
/**
@@ -733,7 +689,7 @@ define([
* @param systems
*/
let removeSystems = (map, systems) => {
let removeSystemCallbak = deleteSystem => {
let removeSystemCallback = deleteSystem => {
map.remove(deleteSystem);
};
@@ -741,10 +697,10 @@ define([
system = $(system);
// check if system is "active"
if( system.hasClass(config.systemActiveClass) ){
if(system.hasClass(config.systemActiveClass)){
delete Init.currentSystemData;
// get parent Tab Content and fire clear modules event
let tabContentElement = MapUtil.getTabContentElementByMapElement( system );
let tabContentElement = MapUtil.getTabContentElementByMapElement(system);
$(tabContentElement).trigger('pf:removeSystemModules');
}
@@ -759,7 +715,7 @@ define([
// remove system
system.velocity('transition.whirlOut', {
duration: Init.animationSpeed.mapDeleteSystem,
complete: removeSystemCallbak
complete: removeSystemCallback
});
}
};

View File

@@ -350,6 +350,67 @@ define([
return data;
};
/**
* delete a connection and all related data
* @param connections
* @param callback
*/
let deleteConnections = (connections, callback) => {
if(connections.length > 0){
// remove connections from map
let removeConnections = connections => {
for(let connection of connections){
connection._jsPlumb.instance.detach(connection, {fireEvent: false});
}
};
// prepare delete request
let map = connections[0]._jsPlumb.instance;
let mapContainer = $(map.getContainer());
// connectionIds for delete request
let connectionIds = [];
for(let connection of connections){
let connectionId = connection.getParameter('connectionId');
// drag&drop a new connection does not have an id yet, if connection is not established correct
if(connectionId !== undefined){
connectionIds.push(connectionId);
}
}
if(connectionIds.length > 0){
Util.request('DELETE', 'connection', connectionIds, {
mapId: mapContainer.data('id')
}, {
connections: connections
}).then(
payload => {
// check if all connections were deleted that should get deleted
let deletedConnections = payload.context.connections.filter(
function(connection){
// if a connection is manually (drag&drop) detached, the jsPlumb instance does not exist any more
// connection is already deleted!
return (
connection._jsPlumb &&
this.indexOf( connection.getParameter('connectionId') ) !== -1
);
}, payload.data
);
// remove connections from map
removeConnections(deletedConnections);
if(callback){
callback();
}
},
Util.handleAjaxErrorResponse
);
}
}
};
/**
* get connection related data from a connection
* -> data requires a signature bind to that connection
@@ -1682,6 +1743,7 @@ define([
setConnectionWHStatus: setConnectionWHStatus,
getScopeInfoForConnection: getScopeInfoForConnection,
getDataByConnections: getDataByConnections,
deleteConnections: deleteConnections,
getConnectionDataFromSignatures: getConnectionDataFromSignatures,
getEndpointOverlayContent: getEndpointOverlayContent,
getTabContentElementByMapElement: getTabContentElementByMapElement,

View File

@@ -654,7 +654,7 @@ define([
// deleteSignatures(row);
let connection = $().getConnectionById(mapData.config.id, rowData.id);
$().deleteConnections([connection], function(){
MapUtil.deleteConnections([connection], () => {
// callback function after ajax "delete" success
// remove table row
tempTableElement.DataTable().rows(deleteRowElement).remove().draw();

View File

@@ -907,7 +907,7 @@ define([
connectionElement.find('table').showLoadingAnimation();
request('DELETE', 'log', rowData.id, {}, {
Util.request('DELETE', 'log', rowData.id, {}, {
connectionElement: connectionElement
}, requestAlways)
.then(
@@ -929,7 +929,7 @@ define([
active: 1
};
request('PATCH', 'log', rowData.id, requestData, {
Util.request('PATCH', 'log', rowData.id, requestData, {
connectionElement: connectionElement
}, requestAlways)
.then(
@@ -1006,57 +1006,6 @@ define([
}
};
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
@@ -1129,7 +1078,7 @@ define([
let method = formData.id ? 'PATCH' : 'PUT';
request(method, 'log', formData.id, formData, {
Util.request(method, 'log', formData.id, formData, {
connectionElement: connectionElement,
formElement: form
}, requestAlways)

View File

@@ -51,44 +51,6 @@ define([
// max character length for system description
let maxDescriptionLength = 9000;
/**
* save system (description)
* @param requestData
* @param context
* @param callback
*/
let saveSystem = (requestData, context, callback) => {
context.descriptionArea.showLoadingAnimation();
$.ajax({
type: 'POST',
url: Init.path.saveSystem,
data: requestData,
dataType: 'json',
context: context
}).done(function(responseData){
let newSystemData = responseData.systemData;
if( !$.isEmptyObject(newSystemData) ){
callback(newSystemData);
}
if(
responseData.error &&
responseData.error.length > 0
){
for(let error of responseData.error){
Util.showNotify({title: error.field + ' error', text: 'System: ' + error.message, type: error.type});
}
}
}).fail(function(jqXHR, status, error){
let reason = status + ' ' + error;
Util.showNotify({title: jqXHR.status + ': saveSystem', text: reason, type: 'warning'});
}).always(function(){
this.descriptionArea.hideLoadingAnimation();
});
};
/**
* update trigger function for this module
* compare data and update module
@@ -307,21 +269,22 @@ define([
if(validDescription){
// ... valid -> save()
saveSystem({
mapData: {
id: mapId
},
systemData: {
id: systemData.id,
description: description
}
descriptionArea.showLoadingAnimation();
Util.request('PATCH', 'system', systemData.id, {
description: description
}, {
descriptionArea: descriptionArea
}, (systemData) => {
// .. save callback
context.$note.summernote('destroy');
updateModule(moduleElement, systemData);
});
}, context => {
// always do
context.descriptionArea.hideLoadingAnimation();
}).then(
payload => {
context.$note.summernote('destroy');
updateModule(moduleElement, payload.data);
},
Util.handleAjaxErrorResponse
);
}
}else{
// ... no changes -> no save()

View File

@@ -1527,6 +1527,69 @@ define([
});
};
/**
* Request data from Server
* -> This function should be used (in future) for all Ajax and REST API calls
* -> works as a "wrapper" for jQueries ajax() method
* @param action
* @param entity
* @param ids
* @param data
* @param context
* @param always
* @returns {Promise<any>}
*/
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);
};
/**
* global ajax error handler -> handles .fail() requests
* @param payload
@@ -1543,7 +1606,7 @@ define([
if(response.error && response.error.length > 0){
// build error notification reason from errors
reason = response.error.map(error => error.status).join('\n');
reason = response.error.map(error => error.message ? error.message : error.status).join('\n');
// check if errors might belong to a HTML form -> check "context"
if(payload.context.formElement){
@@ -3037,6 +3100,7 @@ define([
stopTabBlink: stopTabBlink,
getLogInfo: getLogInfo,
ajaxSetup: ajaxSetup,
request: request,
handleAjaxErrorResponse: handleAjaxErrorResponse,
setSyncStatus: setSyncStatus,
getSyncType: getSyncType,

View File

@@ -29,7 +29,7 @@
"jshint": "^2.9.6",
"jshint-stylish": "^2.x.x",
"lodash.padend": "4.6.x",
"node-notifier": "5.2.x",
"node-notifier": "^5.3.0",
"pretty-bytes": "^5.1.0",
"promised-del": "1.0.x",
"slash": "2.x.x",

View File

@@ -35,14 +35,9 @@ define(['jquery'], ($) => {
getMapLogData: '/api/map/getLogData', // ajax URL - get logs data
// system API
getSystemData: '/api/system/getData', // ajax URL - get system data
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
setDestination: '/api/system/setDestination', // ajax URL - set destination
pokeRally: '/api/system/pokeRally', // ajax URL - send rally point pokes
// connection API
saveConnection: '/api/connection/save', // ajax URL - save new connection to map
deleteConnection: '/api/connection/delete', // ajax URL - delete connection from map
// signature API
saveSignatureData: '/api/signature/save', // ajax URL - save signature data for system
deleteSignatureData: '/api/signature/delete', // ajax URL - delete signature data for system

View File

@@ -559,7 +559,7 @@ define([
// confirm dialog
bootbox.confirm('Is this connection really gone?', function(result){
if(result){
$().deleteConnections([activeConnection]);
MapUtil.deleteConnections([activeConnection]);
}
});
break;
@@ -1385,158 +1385,73 @@ define([
* @param connection
*/
let saveConnection = function(connection){
if( connection instanceof jsPlumb.Connection ){
if(connection instanceof jsPlumb.Connection){
let map = connection._jsPlumb.instance;
let mapContainer = $( map.getContainer() );
let mapContainer = $(map.getContainer());
let mapId = mapContainer.data('id');
let connectionData = MapUtil.getDataByConnection(connection);
connectionData.mapId = mapId;
let requestData = {
mapData: {
id: mapId
},
connectionData: connectionData
};
Util.request('PUT', 'connection', [], connectionData, {
connection: connection,
map: map,
mapId: mapId,
oldConnectionData: connectionData
}).then(
payload => {
let newConnectionData = payload.data;
$.ajax({
type: 'POST',
url: Init.path.saveConnection,
data: requestData,
dataType: 'json',
context: {
connection: connection,
map: map,
mapId: mapId,
oldConnectionData: connectionData
}
}).done(function(responseData){
let newConnectionData = responseData.connectionData;
if( !$.isEmptyObject(newConnectionData) ){
let updateCon = false;
if( !$.isEmptyObject(newConnectionData) ){
let updateCon = false;
if(this.oldConnectionData.id > 0){
// connection exists (e.g. drag&drop new target system... (ids should never changed)
let connection = $().getConnectionById(this.mapId, this.oldConnectionData.id);
updateCon = true;
}else{
// new connection, check if connectionId was already updated (webSocket push is faster than ajax callback)
let connection = $().getConnectionById(this.mapId, newConnectionData.id);
if(connection){
// connection already updated
this.map.detach(this.connection, {fireEvent: false});
}else{
// .. else update this connection
connection = this.connection;
if(payload.context.oldConnectionData.id > 0){
// connection exists (e.g. drag&drop new target system... (ids should never changed)
let connection = $().getConnectionById(payload.context.mapId, payload.context.oldConnectionData.id);
updateCon = true;
}else{
// new connection, check if connectionId was already updated (webSocket push is faster than ajax callback)
let connection = $().getConnectionById(payload.context.mapId, newConnectionData.id);
if(connection){
// connection already updated
payload.context.map.detach(payload.context.connection, {fireEvent: false});
}else{
// .. else update this connection
connection = payload.context.connection;
updateCon = true;
}
}
if(updateCon){
// update connection data e.g. "scope" has auto detected
connection = updateConnection(connection, payload.context.oldConnectionData, newConnectionData);
// new/updated connection should be cached immediately!
updateConnectionCache(payload.context.mapId, connection);
}
// connection scope
let scope = MapUtil.getScopeInfoForConnection(newConnectionData.scope, 'label');
let title = 'New connection established';
if(payload.context.oldConnectionData.id > 0){
title = 'Connection switched';
}
Util.showNotify({title: title, text: 'Scope: ' + scope, type: 'success'});
}else{
// some save errors
payload.context.map.detach(payload.context.connection, {fireEvent: false});
}
if(updateCon){
// update connection data e.g. "scope" has auto detected
connection = updateConnection(connection, this.oldConnectionData, newConnectionData);
// new/updated connection should be cached immediately!
updateConnectionCache(this.mapId, connection);
}
// connection scope
let scope = MapUtil.getScopeInfoForConnection(newConnectionData.scope, 'label');
let title = 'New connection established';
if(this.oldConnectionData.id > 0){
title = 'Connection switched';
}
Util.showNotify({title: title, text: 'Scope: ' + scope, type: 'success'});
}else{
// some save errors
this.map.detach(this.connection, {fireEvent: false});
},
payload => {
// remove this connection from map
payload.context.map.detach(payload.context.connection, {fireEvent: false});
Util.handleAjaxErrorResponse(payload);
}
// show errors
if(
responseData.error &&
responseData.error.length > 0
){
for(let i = 0; i < responseData.error.length; i++){
let error = responseData.error[i];
Util.showNotify({title: error.field + ' error', text: 'System: ' + error.message, type: error.type});
}
}
}).fail(function(jqXHR, status, error){
// remove this connection from map
this.map.detach(this.connection, {fireEvent: false});
let reason = status + ' ' + error;
Util.showNotify({title: jqXHR.status + ': saveConnection', text: reason, type: 'warning'});
$(document).setProgramStatus('problem');
});
}
};
/**
* delete a connection and all related data
* @param connections
* @param callback
*/
$.fn.deleteConnections = function(connections, callback){
if(connections.length > 0){
// remove connections from map
let removeConnections = function(tempConnections){
for(let i = 0; i < tempConnections.length; i++){
// if a connection is manually (drag&drop) detached, the jsPlumb instance does not exist any more
// connection is already deleted!
if(tempConnections[i]._jsPlumb){
tempConnections[i]._jsPlumb.instance.detach(tempConnections[i], {fireEvent: false});
}
}
};
// prepare delete request
let map = connections[0]._jsPlumb.instance;
let mapContainer = $( map.getContainer() );
let connectionIds = [];
// connectionIds for delete request
for(let i = 0; i < connections.length; i++){
let connectionId = connections[i].getParameter('connectionId');
// drag&drop a new connection does not have an id yet, if connection is not established correct
if(connectionId !== undefined){
connectionIds[i] = connections[i].getParameter('connectionId');
}
}
if(connectionIds.length > 0){
let requestData = {
mapId: mapContainer.data('id'),
connectionIds: connectionIds
};
$.ajax({
type: 'POST',
url: Init.path.deleteConnection,
data: requestData,
dataType: 'json',
context: connections
}).done(function(data){
// remove connections from map
removeConnections(this);
// optional callback
if(callback){
callback();
}
}).fail(function(jqXHR, status, error){
let reason = status + ' ' + error;
Util.showNotify({title: jqXHR.status + ': deleteSystem', text: reason, type: 'warning'});
$(document).setProgramStatus('problem');
});
}
);
}
};
@@ -2181,7 +2096,7 @@ define([
newJsPlumbInstance.bind('connectionDetached', function(info, e){
// a connection is manually (drag&drop) detached! otherwise this event should not be send!
let connection = info.connection;
$().deleteConnections([connection]);
MapUtil.deleteConnections([connection]);
});
newJsPlumbInstance.bind('checkDropAllowed', function(params){

View File

@@ -56,47 +56,6 @@ define([
'- DPS and Logistic ships needed'
};
/**
* save a new system and add it to the map
* @param requestData
* @param context
* @param callback
*/
let saveSystem = (requestData, context, callback) => {
$.ajax({
type: 'POST',
url: Init.path.saveSystem,
data: requestData,
dataType: 'json',
context: context
}).done(function(responseData){
let newSystemData = responseData.systemData;
if( !$.isEmptyObject(newSystemData) ){
Util.showNotify({title: 'New system', text: newSystemData.name, type: 'success'});
callback(newSystemData);
}
if(
responseData.error &&
responseData.error.length > 0
){
for(let i = 0; i < responseData.error.length; i++){
let error = responseData.error[i];
Util.showNotify({title: error.field + ' error', text: 'System: ' + error.message, type: error.type});
}
}
}).fail(function(jqXHR, status, error){
let reason = status + ' ' + error;
Util.showNotify({title: jqXHR.status + ': saveSystem', text: reason, type: 'warning'});
$(document).setProgramStatus('problem');
}).always(function(){
this.systemDialog.find('.modal-content').hideLoadingAnimation();
});
};
/**
* open "new system" dialog and add the system to map
* optional the new system is connected to a "sourceSystem" (if available)
@@ -256,7 +215,7 @@ define([
// get form Values
let form = this.find('form');
let systemDialogData = $(form).getFormValues();
let formData = $(form).getFormValues();
// validate form
form.validator('validate');
@@ -288,27 +247,31 @@ define([
};
}
systemDialogData.position = newPosition;
formData.position = newPosition;
formData.mapId = mapId;
// ----------------------------------------------------------------------------------------
let requestData = {
systemData: systemDialogData,
mapData: {
id: mapId
}
};
this.find('.modal-content').showLoadingAnimation();
saveSystem(requestData, {
systemDialog: this
}, (newSystemData) => {
// success callback
callback(map, newSystemData, sourceSystem);
Util.request('PUT', 'system', [], formData, {
systemDialog: systemDialog,
formElement: form,
map: map,
sourceSystem: sourceSystem
}, context => {
// always do
context.systemDialog.find('.modal-content').hideLoadingAnimation();
}).then(
payload => {
Util.showNotify({title: 'New system', text: payload.data.name, type: 'success'});
callback(payload.context.map, payload.data, payload.context.sourceSystem);
bootbox.hideAll();
},
Util.handleAjaxErrorResponse
);
bootbox.hideAll();
});
return false;
}
}
@@ -695,36 +658,29 @@ define([
*/
let deleteSystems = (map, systems = [], callback = (systems) => {}) => {
let mapContainer = $( map.getContainer() );
let systemIds = systems.map(system => $(system).data('id'));
$.ajax({
type: 'POST',
url: Init.path.deleteSystem,
data: {
mapId: mapContainer.data('id'),
systemIds: systems.map( system => $(system).data('id') )
Util.request('DELETE', 'system', systemIds, {
mapId: mapContainer.data('id')
}, {
map: map,
systems: systems
}).then(
payload => {
// check if all systems were deleted that should get deleted
let deletedSystems = payload.context.systems.filter(
function(system){
return this.indexOf( $(system).data('id') ) !== -1;
}, payload.data
);
// remove systems from map
removeSystems(payload.context.map, deletedSystems);
callback(deletedSystems);
},
dataType: 'json',
context: {
map: map,
systems: systems
}
}).done(function(data){
// check if all systems were deleted that should get deleted
let deletedSystems = this.systems.filter(
function(system){
return this.indexOf( $(system).data('id') ) !== -1;
}, data.deletedSystemIds
);
// remove systems from map
removeSystems(this.map, deletedSystems);
callback(deletedSystems);
}).fail(function(jqXHR, status, error){
let reason = status + ' ' + error;
Util.showNotify({title: jqXHR.status + ': deleteSystem', text: reason, type: 'warning'});
$(document).setProgramStatus('problem');
});
Util.handleAjaxErrorResponse
);
};
/**
@@ -733,7 +689,7 @@ define([
* @param systems
*/
let removeSystems = (map, systems) => {
let removeSystemCallbak = deleteSystem => {
let removeSystemCallback = deleteSystem => {
map.remove(deleteSystem);
};
@@ -741,10 +697,10 @@ define([
system = $(system);
// check if system is "active"
if( system.hasClass(config.systemActiveClass) ){
if(system.hasClass(config.systemActiveClass)){
delete Init.currentSystemData;
// get parent Tab Content and fire clear modules event
let tabContentElement = MapUtil.getTabContentElementByMapElement( system );
let tabContentElement = MapUtil.getTabContentElementByMapElement(system);
$(tabContentElement).trigger('pf:removeSystemModules');
}
@@ -759,7 +715,7 @@ define([
// remove system
system.velocity('transition.whirlOut', {
duration: Init.animationSpeed.mapDeleteSystem,
complete: removeSystemCallbak
complete: removeSystemCallback
});
}
};

View File

@@ -350,6 +350,67 @@ define([
return data;
};
/**
* delete a connection and all related data
* @param connections
* @param callback
*/
let deleteConnections = (connections, callback) => {
if(connections.length > 0){
// remove connections from map
let removeConnections = connections => {
for(let connection of connections){
connection._jsPlumb.instance.detach(connection, {fireEvent: false});
}
};
// prepare delete request
let map = connections[0]._jsPlumb.instance;
let mapContainer = $(map.getContainer());
// connectionIds for delete request
let connectionIds = [];
for(let connection of connections){
let connectionId = connection.getParameter('connectionId');
// drag&drop a new connection does not have an id yet, if connection is not established correct
if(connectionId !== undefined){
connectionIds.push(connectionId);
}
}
if(connectionIds.length > 0){
Util.request('DELETE', 'connection', connectionIds, {
mapId: mapContainer.data('id')
}, {
connections: connections
}).then(
payload => {
// check if all connections were deleted that should get deleted
let deletedConnections = payload.context.connections.filter(
function(connection){
// if a connection is manually (drag&drop) detached, the jsPlumb instance does not exist any more
// connection is already deleted!
return (
connection._jsPlumb &&
this.indexOf( connection.getParameter('connectionId') ) !== -1
);
}, payload.data
);
// remove connections from map
removeConnections(deletedConnections);
if(callback){
callback();
}
},
Util.handleAjaxErrorResponse
);
}
}
};
/**
* get connection related data from a connection
* -> data requires a signature bind to that connection
@@ -1682,6 +1743,7 @@ define([
setConnectionWHStatus: setConnectionWHStatus,
getScopeInfoForConnection: getScopeInfoForConnection,
getDataByConnections: getDataByConnections,
deleteConnections: deleteConnections,
getConnectionDataFromSignatures: getConnectionDataFromSignatures,
getEndpointOverlayContent: getEndpointOverlayContent,
getTabContentElementByMapElement: getTabContentElementByMapElement,

View File

@@ -654,7 +654,7 @@ define([
// deleteSignatures(row);
let connection = $().getConnectionById(mapData.config.id, rowData.id);
$().deleteConnections([connection], function(){
MapUtil.deleteConnections([connection], () => {
// callback function after ajax "delete" success
// remove table row
tempTableElement.DataTable().rows(deleteRowElement).remove().draw();

View File

@@ -907,7 +907,7 @@ define([
connectionElement.find('table').showLoadingAnimation();
request('DELETE', 'log', rowData.id, {}, {
Util.request('DELETE', 'log', rowData.id, {}, {
connectionElement: connectionElement
}, requestAlways)
.then(
@@ -929,7 +929,7 @@ define([
active: 1
};
request('PATCH', 'log', rowData.id, requestData, {
Util.request('PATCH', 'log', rowData.id, requestData, {
connectionElement: connectionElement
}, requestAlways)
.then(
@@ -1006,57 +1006,6 @@ define([
}
};
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
@@ -1129,7 +1078,7 @@ define([
let method = formData.id ? 'PATCH' : 'PUT';
request(method, 'log', formData.id, formData, {
Util.request(method, 'log', formData.id, formData, {
connectionElement: connectionElement,
formElement: form
}, requestAlways)

View File

@@ -51,44 +51,6 @@ define([
// max character length for system description
let maxDescriptionLength = 9000;
/**
* save system (description)
* @param requestData
* @param context
* @param callback
*/
let saveSystem = (requestData, context, callback) => {
context.descriptionArea.showLoadingAnimation();
$.ajax({
type: 'POST',
url: Init.path.saveSystem,
data: requestData,
dataType: 'json',
context: context
}).done(function(responseData){
let newSystemData = responseData.systemData;
if( !$.isEmptyObject(newSystemData) ){
callback(newSystemData);
}
if(
responseData.error &&
responseData.error.length > 0
){
for(let error of responseData.error){
Util.showNotify({title: error.field + ' error', text: 'System: ' + error.message, type: error.type});
}
}
}).fail(function(jqXHR, status, error){
let reason = status + ' ' + error;
Util.showNotify({title: jqXHR.status + ': saveSystem', text: reason, type: 'warning'});
}).always(function(){
this.descriptionArea.hideLoadingAnimation();
});
};
/**
* update trigger function for this module
* compare data and update module
@@ -307,21 +269,22 @@ define([
if(validDescription){
// ... valid -> save()
saveSystem({
mapData: {
id: mapId
},
systemData: {
id: systemData.id,
description: description
}
descriptionArea.showLoadingAnimation();
Util.request('PATCH', 'system', systemData.id, {
description: description
}, {
descriptionArea: descriptionArea
}, (systemData) => {
// .. save callback
context.$note.summernote('destroy');
updateModule(moduleElement, systemData);
});
}, context => {
// always do
context.descriptionArea.hideLoadingAnimation();
}).then(
payload => {
context.$note.summernote('destroy');
updateModule(moduleElement, payload.data);
},
Util.handleAjaxErrorResponse
);
}
}else{
// ... no changes -> no save()

View File

@@ -1527,6 +1527,69 @@ define([
});
};
/**
* Request data from Server
* -> This function should be used (in future) for all Ajax and REST API calls
* -> works as a "wrapper" for jQueries ajax() method
* @param action
* @param entity
* @param ids
* @param data
* @param context
* @param always
* @returns {Promise<any>}
*/
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);
};
/**
* global ajax error handler -> handles .fail() requests
* @param payload
@@ -1543,7 +1606,7 @@ define([
if(response.error && response.error.length > 0){
// build error notification reason from errors
reason = response.error.map(error => error.status).join('\n');
reason = response.error.map(error => error.message ? error.message : error.status).join('\n');
// check if errors might belong to a HTML form -> check "context"
if(payload.context.formElement){
@@ -3037,6 +3100,7 @@ define([
stopTabBlink: stopTabBlink,
getLogInfo: getLogInfo,
ajaxSetup: ajaxSetup,
request: request,
handleAjaxErrorResponse: handleAjaxErrorResponse,
setSyncStatus: setSyncStatus,
getSyncType: getSyncType,