diff --git a/app/main/controller/api/system.php b/app/main/controller/api/system.php index a2a8d633..0fb67ff7 100644 --- a/app/main/controller/api/system.php +++ b/app/main/controller/api/system.php @@ -34,12 +34,8 @@ class System extends Controller\AccessController { $mapData = (array)$postData['mapData']; $systemModel = null; - if( isset($systemData['statusId']) ){ - if( (int)$systemData['statusId'] <= 0){ - unset($systemData['statusId']); - }else{ - $systemData['statusId'] = (int)$systemData['statusId']; - } + if( (int)$systemData['statusId'] <= 0 ){ + unset($systemData['statusId']); } if( isset($systemData['id']) ){ @@ -72,7 +68,7 @@ class System extends Controller\AccessController { if( !is_null($systemModel) ){ // set/update system custom data - $systemModel->copyfrom($systemData, ['locked', 'rallyUpdated', 'position', 'description']); + $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") diff --git a/app/main/model/systemmodel.php b/app/main/model/systemmodel.php index 4eb63695..a5ee8c9f 100644 --- a/app/main/model/systemmodel.php +++ b/app/main/model/systemmodel.php @@ -74,6 +74,7 @@ class SystemModel extends AbstractMapTrackingModel { 'on-delete' => 'CASCADE' ] ], + 'validate' => true, 'activity-log' => true ], 'locked' => [ @@ -142,9 +143,9 @@ class SystemModel extends AbstractMapTrackingModel { $systemData->type = $this->typeId->getData(); } - $systemData->status = (object) []; - $systemData->status->id = is_object($this->statusId) ? $this->statusId->id : 1; - $systemData->status->name = is_object($this->statusId) ? $this->statusId->name : 'unknown'; + if(is_object($this->statusId)){ + $systemData->status = $this->statusId->getData(); + } $systemData->locked = $this->locked; $systemData->rallyUpdated = strtotime($this->rallyUpdated); @@ -245,6 +246,22 @@ class SystemModel extends AbstractMapTrackingModel { return $valid; } + /** + * @param string $key + * @param int $val + * @return bool + * @throws \Exception\ValidationException + */ + protected function validate_statusId(string $key, int $val): bool { + $valid = true; + if( !$this->rel('statusId')::getStatusById($val) ){ + $valid = false; + $this->throwValidationException($key, 'Validation failed: "' . $key . '" = "' . $val . '"'); + } + + return $valid; + } + /** * setter for system alias * @param string $alias diff --git a/app/main/model/systemstatusmodel.php b/app/main/model/systemstatusmodel.php index 02b7be01..0781d5bf 100644 --- a/app/main/model/systemstatusmodel.php +++ b/app/main/model/systemstatusmodel.php @@ -77,4 +77,26 @@ class SystemStatusModel extends BasicModel { ] ]; + /** + * get system status data + * @return \stdClass + */ + public function getData(){ + + $statusData = (object)[]; + $statusData->id = $this->_id; + $statusData->name = $this->name; + + return $statusData; + } + + /** + * get status by id + * @param int $statusId + * @return self|null + */ + public static function getStatusById(int $statusId = 1){ + $status = (new self())->getById($statusId); + return $status->dry() ? null : $status; + } } \ No newline at end of file diff --git a/js/app/map/map.js b/js/app/map/map.js index 2b005d4e..027fefe0 100644 --- a/js/app/map/map.js +++ b/js/app/map/map.js @@ -58,6 +58,7 @@ define([ // dialogs systemDialogId: 'pf-system-dialog', // id for system dialog systemDialogSelectClass: 'pf-system-dialog-select', // class for system select Element + systemDialogStatusSelectId: 'pf-system-dialog-status-select', // id for "status" select // system security classes systemSec: 'pf-system-sec' @@ -1378,21 +1379,13 @@ define([ * @param map * @param options */ - let showNewSystemDialog = function(map, options){ + let showNewSystemDialog = (map, options) => { let mapContainer = $(map.getContainer()); // format system status for form select ----------------------------------------------------------------------- - let systemStatus = {}; // "default" selection (id = 0) prevents status from being overwritten // -> e.g. keep status information if system was just inactive (active = 0) - systemStatus[0] = 'default'; - - $.each(Init.systemStatus, function(status, statusData){ - systemStatus[statusData.id] = statusData.label; - }); - - // default system status -> first status entry - let defaultSystemStatus = 0; + let statusData = [{id: 0, text: 'auto'}]; // get current map data --------------------------------------------------------------------------------------- let mapData = mapContainer.getMapDataFromClient({forceData: true}); @@ -1416,7 +1409,10 @@ define([ // dialog data ------------------------------------------------------------------------------------------------ let data = { id: config.systemDialogId, - selectClass: config.systemDialogSelectClass + select2Class: Util.config.select2Class, + selectClass: config.systemDialogSelectClass, + statusSelectId: config.systemDialogStatusSelectId, + statusData: statusData }; // set current position as "default" system to add ------------------------------------------------------------ @@ -1438,6 +1434,7 @@ define([ let systemDialog = bootbox.dialog({ title: 'Add new system', message: content, + show: false, buttons: { close: { label: 'cancel', @@ -1517,9 +1514,21 @@ define([ } }); - // init dialog - systemDialog.on('shown.bs.modal', function(e) { + systemDialog.on('show.bs.modal', function(e) { + let modalContent = $('#' + config.systemDialogId); + // init "status" select2 + for (let [statusName, data] of Object.entries(Init.systemStatus)){ + statusData.push({id: data.id, text: data.label, class: data.class}); + } + + modalContent.find('#' + config.systemDialogStatusSelectId).initStatusSelect({ + data: statusData, + iconClass: 'fa-tag' + }); + }); + + systemDialog.on('shown.bs.modal', function(e) { let modalContent = $('#' + config.systemDialogId); // init system select live search - some delay until modal transition has finished @@ -1530,18 +1539,8 @@ define([ }); }); - // init system status select - let modalFields = $('.bootbox .modal-dialog').find('.pf-editable-system-status'); - - modalFields.editable({ - mode: 'inline', - emptytext: 'unknown', - onblur: 'submit', - showbuttons: false, - source: systemStatus, - value: defaultSystemStatus, - inputclass: config.systemDialogSelectClass - }); + // show dialog + systemDialog.modal('show'); }); }; diff --git a/js/app/ui/form_element.js b/js/app/ui/form_element.js index d0226bf7..00235494 100644 --- a/js/app/ui/form_element.js +++ b/js/app/ui/form_element.js @@ -15,7 +15,7 @@ define([ * @param data * @returns {*} */ - let formatCategoryTypeResultData = (data) => { + let formatCategoryTypeResultData = data => { if(data.loading) return data.text; if(data.placeholder) return data.placeholder; @@ -82,6 +82,52 @@ define([ ); }; + /** + * init a sselect element as "select2" for "status" selection + * @param options + * @returns {*} + */ + $.fn.initStatusSelect = function(options){ + + let config = { + minimumResultsForSearch: -1, + width: '100%', + iconClass: 'fa-circle' + }; + + config = $.extend({}, config, options); + + let formatStatusSelectionData = state => { + let markup = ''; + markup += '   ' + state.text; + markup += ''; + + return $(markup); + }; + + let formatStatusResultData = data => { + if(data.loading) return data.text; + if(data.placeholder) return data.placeholder; + + let markup = '
'; + markup += '
'; + markup += ''; + markup += '
'; + markup += '
' + data.text + '
'; + markup += '
'; + + return $(markup); + }; + + config.templateSelection = formatStatusSelectionData; + config.templateResult = formatStatusResultData; + + return this.each(function(){ + let selectElement = $(this); + selectElement.select2(config); + }); + }; + /** * init a select element as an ajax based "select2" object for system search * @param options @@ -304,7 +350,6 @@ define([ // after init finish }); }); - }; /** diff --git a/js/app/ui/system_intel.js b/js/app/ui/system_intel.js index 7e2c123d..91ee7846 100644 --- a/js/app/ui/system_intel.js +++ b/js/app/ui/system_intel.js @@ -242,14 +242,16 @@ define([ let structureStatusData = Util.getObjVal(Init, 'structureStatus'); let structureTypeData = Util.getObjVal(Init, 'structureStatus'); + let statusData = Object.keys(structureStatusData).map((k) => { + let data = structureStatusData[k]; + data.selected = data.id === Util.getObjVal(structureData, 'status.id'); + return data; + }); + let data = { id: config.structureDialogId, structureData: structureData, - structureStatus: Object.keys(structureStatusData).map((k) => { - let data = structureStatusData[k]; - data.selected = data.id === Util.getObjVal(structureData, 'status.id'); - return data; - }), + structureStatus: statusData, statusSelectId: config.statusSelectId, typeSelectId: config.typeSelectId, corporationSelectId: config.corporationSelectId, @@ -264,7 +266,7 @@ define([ let structureDialog = bootbox.dialog({ title: 'Structure', message: content, - show: true, + show: false, buttons: { close: { label: 'cancel', @@ -304,9 +306,11 @@ define([ } }); - structureDialog.on('shown.bs.modal', function(e) { + structureDialog.on('show.bs.modal', function(e) { + let modalContent = $('#' + config.structureDialogId); + // init type select live search - let selectElementType = $(this).find('#' + config.typeSelectId); + let selectElementType = modalContent.find('#' + config.typeSelectId); selectElementType.initUniverseTypeSelect({ categoryIds: [65], maxSelectionLength: 1, @@ -314,19 +318,20 @@ define([ }); // init corporation select live search - let selectElementCorporation = $(this).find('#' + config.corporationSelectId); + let selectElementCorporation = modalContent.find('#' + config.corporationSelectId); selectElementCorporation.initUniverseSearch({ categoryNames: ['corporation'], maxSelectionLength: 1 }); - $(this).find('#' + config.statusSelectId).select2({ - minimumResultsForSearch: -1 + // init status select2 + modalContent.find('#' + config.statusSelectId).initStatusSelect({ + data: statusData }); // init character counter - let textarea = $(this).find('#' + config.descriptionTextareaId); - let charCounter = $(this).find('.' + config.descriptionTextareaCharCounter); + let textarea = modalContent.find('#' + config.descriptionTextareaId); + let charCounter = modalContent.find('.' + config.descriptionTextareaCharCounter); Util.updateCounter(textarea, charCounter, maxDescriptionLength); textarea.on('keyup', function(){ @@ -334,9 +339,11 @@ define([ }); // set form validator (after select2 init finish) - $(this).find('form').initFormValidation(); + modalContent.find('form').initFormValidation(); }); + // show dialog + structureDialog.modal('show'); }); }; diff --git a/public/js/v1.4.1/app/map/map.js b/public/js/v1.4.1/app/map/map.js index 2b005d4e..027fefe0 100644 --- a/public/js/v1.4.1/app/map/map.js +++ b/public/js/v1.4.1/app/map/map.js @@ -58,6 +58,7 @@ define([ // dialogs systemDialogId: 'pf-system-dialog', // id for system dialog systemDialogSelectClass: 'pf-system-dialog-select', // class for system select Element + systemDialogStatusSelectId: 'pf-system-dialog-status-select', // id for "status" select // system security classes systemSec: 'pf-system-sec' @@ -1378,21 +1379,13 @@ define([ * @param map * @param options */ - let showNewSystemDialog = function(map, options){ + let showNewSystemDialog = (map, options) => { let mapContainer = $(map.getContainer()); // format system status for form select ----------------------------------------------------------------------- - let systemStatus = {}; // "default" selection (id = 0) prevents status from being overwritten // -> e.g. keep status information if system was just inactive (active = 0) - systemStatus[0] = 'default'; - - $.each(Init.systemStatus, function(status, statusData){ - systemStatus[statusData.id] = statusData.label; - }); - - // default system status -> first status entry - let defaultSystemStatus = 0; + let statusData = [{id: 0, text: 'auto'}]; // get current map data --------------------------------------------------------------------------------------- let mapData = mapContainer.getMapDataFromClient({forceData: true}); @@ -1416,7 +1409,10 @@ define([ // dialog data ------------------------------------------------------------------------------------------------ let data = { id: config.systemDialogId, - selectClass: config.systemDialogSelectClass + select2Class: Util.config.select2Class, + selectClass: config.systemDialogSelectClass, + statusSelectId: config.systemDialogStatusSelectId, + statusData: statusData }; // set current position as "default" system to add ------------------------------------------------------------ @@ -1438,6 +1434,7 @@ define([ let systemDialog = bootbox.dialog({ title: 'Add new system', message: content, + show: false, buttons: { close: { label: 'cancel', @@ -1517,9 +1514,21 @@ define([ } }); - // init dialog - systemDialog.on('shown.bs.modal', function(e) { + systemDialog.on('show.bs.modal', function(e) { + let modalContent = $('#' + config.systemDialogId); + // init "status" select2 + for (let [statusName, data] of Object.entries(Init.systemStatus)){ + statusData.push({id: data.id, text: data.label, class: data.class}); + } + + modalContent.find('#' + config.systemDialogStatusSelectId).initStatusSelect({ + data: statusData, + iconClass: 'fa-tag' + }); + }); + + systemDialog.on('shown.bs.modal', function(e) { let modalContent = $('#' + config.systemDialogId); // init system select live search - some delay until modal transition has finished @@ -1530,18 +1539,8 @@ define([ }); }); - // init system status select - let modalFields = $('.bootbox .modal-dialog').find('.pf-editable-system-status'); - - modalFields.editable({ - mode: 'inline', - emptytext: 'unknown', - onblur: 'submit', - showbuttons: false, - source: systemStatus, - value: defaultSystemStatus, - inputclass: config.systemDialogSelectClass - }); + // show dialog + systemDialog.modal('show'); }); }; diff --git a/public/js/v1.4.1/app/ui/form_element.js b/public/js/v1.4.1/app/ui/form_element.js index d0226bf7..00235494 100644 --- a/public/js/v1.4.1/app/ui/form_element.js +++ b/public/js/v1.4.1/app/ui/form_element.js @@ -15,7 +15,7 @@ define([ * @param data * @returns {*} */ - let formatCategoryTypeResultData = (data) => { + let formatCategoryTypeResultData = data => { if(data.loading) return data.text; if(data.placeholder) return data.placeholder; @@ -82,6 +82,52 @@ define([ ); }; + /** + * init a sselect element as "select2" for "status" selection + * @param options + * @returns {*} + */ + $.fn.initStatusSelect = function(options){ + + let config = { + minimumResultsForSearch: -1, + width: '100%', + iconClass: 'fa-circle' + }; + + config = $.extend({}, config, options); + + let formatStatusSelectionData = state => { + let markup = ''; + markup += '   ' + state.text; + markup += ''; + + return $(markup); + }; + + let formatStatusResultData = data => { + if(data.loading) return data.text; + if(data.placeholder) return data.placeholder; + + let markup = '
'; + markup += '
'; + markup += ''; + markup += '
'; + markup += '
' + data.text + '
'; + markup += '
'; + + return $(markup); + }; + + config.templateSelection = formatStatusSelectionData; + config.templateResult = formatStatusResultData; + + return this.each(function(){ + let selectElement = $(this); + selectElement.select2(config); + }); + }; + /** * init a select element as an ajax based "select2" object for system search * @param options @@ -304,7 +350,6 @@ define([ // after init finish }); }); - }; /** diff --git a/public/js/v1.4.1/app/ui/system_intel.js b/public/js/v1.4.1/app/ui/system_intel.js index 7e2c123d..91ee7846 100644 --- a/public/js/v1.4.1/app/ui/system_intel.js +++ b/public/js/v1.4.1/app/ui/system_intel.js @@ -242,14 +242,16 @@ define([ let structureStatusData = Util.getObjVal(Init, 'structureStatus'); let structureTypeData = Util.getObjVal(Init, 'structureStatus'); + let statusData = Object.keys(structureStatusData).map((k) => { + let data = structureStatusData[k]; + data.selected = data.id === Util.getObjVal(structureData, 'status.id'); + return data; + }); + let data = { id: config.structureDialogId, structureData: structureData, - structureStatus: Object.keys(structureStatusData).map((k) => { - let data = structureStatusData[k]; - data.selected = data.id === Util.getObjVal(structureData, 'status.id'); - return data; - }), + structureStatus: statusData, statusSelectId: config.statusSelectId, typeSelectId: config.typeSelectId, corporationSelectId: config.corporationSelectId, @@ -264,7 +266,7 @@ define([ let structureDialog = bootbox.dialog({ title: 'Structure', message: content, - show: true, + show: false, buttons: { close: { label: 'cancel', @@ -304,9 +306,11 @@ define([ } }); - structureDialog.on('shown.bs.modal', function(e) { + structureDialog.on('show.bs.modal', function(e) { + let modalContent = $('#' + config.structureDialogId); + // init type select live search - let selectElementType = $(this).find('#' + config.typeSelectId); + let selectElementType = modalContent.find('#' + config.typeSelectId); selectElementType.initUniverseTypeSelect({ categoryIds: [65], maxSelectionLength: 1, @@ -314,19 +318,20 @@ define([ }); // init corporation select live search - let selectElementCorporation = $(this).find('#' + config.corporationSelectId); + let selectElementCorporation = modalContent.find('#' + config.corporationSelectId); selectElementCorporation.initUniverseSearch({ categoryNames: ['corporation'], maxSelectionLength: 1 }); - $(this).find('#' + config.statusSelectId).select2({ - minimumResultsForSearch: -1 + // init status select2 + modalContent.find('#' + config.statusSelectId).initStatusSelect({ + data: statusData }); // init character counter - let textarea = $(this).find('#' + config.descriptionTextareaId); - let charCounter = $(this).find('.' + config.descriptionTextareaCharCounter); + let textarea = modalContent.find('#' + config.descriptionTextareaId); + let charCounter = modalContent.find('.' + config.descriptionTextareaCharCounter); Util.updateCounter(textarea, charCounter, maxDescriptionLength); textarea.on('keyup', function(){ @@ -334,9 +339,11 @@ define([ }); // set form validator (after select2 init finish) - $(this).find('form').initFormValidation(); + modalContent.find('form').initFormValidation(); }); + // show dialog + structureDialog.modal('show'); }); }; diff --git a/public/templates/dialog/system.html b/public/templates/dialog/system.html index 0d8cbb3b..0d7e73ae 100644 --- a/public/templates/dialog/system.html +++ b/public/templates/dialog/system.html @@ -46,9 +46,13 @@
- -
- + +
+