- added "signature" -> "connection" option, closed #290
- code refactorings map.js
This commit is contained in:
@@ -68,7 +68,6 @@ class Signature extends Controller\AccessController {
|
||||
// delete all signatures that are not available in this request
|
||||
$deleteOldSignatures = (bool)$requestData['deleteOld'];
|
||||
|
||||
|
||||
$return = (object) [];
|
||||
$return->error = [];
|
||||
$return->signatures = [];
|
||||
@@ -135,9 +134,17 @@ class Signature extends Controller\AccessController {
|
||||
$data['name'] => $data['value']
|
||||
];
|
||||
|
||||
// if groupID changed -> typeID set to 0
|
||||
// if groupId changed
|
||||
if($data['name'] == 'groupId'){
|
||||
// -> typeId set to 0
|
||||
$newData['typeId'] = 0;
|
||||
// -> connectionId set to 0
|
||||
$newData['connectionId'] = 0;
|
||||
}
|
||||
|
||||
// if connectionId changed
|
||||
if($data['name'] == 'connectionId'){
|
||||
$newData['connectionId'] = (int)$newData['connectionId'];
|
||||
}
|
||||
|
||||
}else{
|
||||
|
||||
@@ -79,9 +79,7 @@ class ConnectionModel extends BasicModel{
|
||||
* @param $systemData
|
||||
*/
|
||||
public function setData($systemData){
|
||||
|
||||
foreach((array)$systemData as $key => $value){
|
||||
|
||||
if( !is_array($value) ){
|
||||
if( $this->exists($key) ){
|
||||
$this->$key = $value;
|
||||
@@ -98,7 +96,6 @@ class ConnectionModel extends BasicModel{
|
||||
* @return array
|
||||
*/
|
||||
public function getData(){
|
||||
|
||||
$connectionData = [
|
||||
'id' => $this->id,
|
||||
'source' => $this->source->id,
|
||||
@@ -140,7 +137,11 @@ class ConnectionModel extends BasicModel{
|
||||
* @return mixed
|
||||
*/
|
||||
public function hasAccess(CharacterModel $characterModel){
|
||||
return $this->mapId->hasAccess($characterModel);
|
||||
$access = false;
|
||||
if( !$this->dry() ){
|
||||
$access = $this->mapId->hasAccess($characterModel);
|
||||
}
|
||||
return $access;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -46,6 +46,18 @@ class SystemSignatureModel extends BasicModel {
|
||||
'index' => true,
|
||||
'activity-log' => true
|
||||
],
|
||||
'connectionId' => [
|
||||
'type' => Schema::DT_INT,
|
||||
'index' => true,
|
||||
'belongs-to-one' => 'Model\ConnectionModel',
|
||||
'constraint' => [
|
||||
[
|
||||
'table' => 'connection',
|
||||
'on-delete' => 'CASCADE'
|
||||
]
|
||||
],
|
||||
'activity-log' => true
|
||||
],
|
||||
'name' => [
|
||||
'type' => Schema::DT_VARCHAR128,
|
||||
'nullable' => false,
|
||||
@@ -117,6 +129,11 @@ class SystemSignatureModel extends BasicModel {
|
||||
$signatureData->name = $this->name;
|
||||
$signatureData->description = $this->description;
|
||||
|
||||
if($connection = $this->getConnection()){
|
||||
$signatureData->connection = (object) [];
|
||||
$signatureData->connection->id = $connection->_id;
|
||||
}
|
||||
|
||||
$signatureData->created = (object) [];
|
||||
$signatureData->created->created = strtotime($this->created);
|
||||
if( is_object($this->createdCharacterId) ){
|
||||
@@ -132,6 +149,48 @@ class SystemSignatureModel extends BasicModel {
|
||||
return $signatureData;
|
||||
}
|
||||
|
||||
/**
|
||||
* setter for connectionId
|
||||
* @param $connectionId
|
||||
* @return int|null
|
||||
*/
|
||||
public function set_connectionId($connectionId){
|
||||
$connectionId = (int)$connectionId;
|
||||
$validConnectionId = null;
|
||||
|
||||
if($connectionId > 0){
|
||||
// check if connectionId is valid
|
||||
$systemId = (int) $this->get('systemId', true);
|
||||
|
||||
/**
|
||||
* @var $connection ConnectionModel
|
||||
*/
|
||||
$connection = $this->rel('connectionId');
|
||||
$connection->getById($connectionId);
|
||||
|
||||
if(
|
||||
!$connection->dry() &&
|
||||
(
|
||||
$connection->get('source', true) === $systemId||
|
||||
$connection->get('target', true) === $systemId
|
||||
)
|
||||
){
|
||||
// connectionId belongs to same system as $this signature -> is valid
|
||||
$validConnectionId = $connectionId;
|
||||
}
|
||||
}
|
||||
|
||||
return $validConnectionId;
|
||||
}
|
||||
|
||||
/**
|
||||
* get the connection (if attached)
|
||||
* @return \Model\ConnectionModel|null
|
||||
*/
|
||||
public function getConnection(){
|
||||
return $this->connectionId;
|
||||
}
|
||||
|
||||
/**
|
||||
* compares a new data set (array) with the current values
|
||||
* and checks if something has changed
|
||||
|
||||
@@ -32,7 +32,6 @@ define([
|
||||
|
||||
mapClass: 'pf-map', // class for all maps
|
||||
mapIdPrefix: 'pf-map-', // id prefix for all maps
|
||||
systemIdPrefix: 'pf-system-', // id prefix for a system
|
||||
systemClass: 'pf-system', // class for all systems
|
||||
systemActiveClass: 'pf-system-active', // class for an active system in a map
|
||||
systemSelectedClass: 'pf-system-selected', // class for selected systems in a map
|
||||
@@ -453,7 +452,7 @@ define([
|
||||
$.fn.getSystem = function(map, data){
|
||||
// get map container for mapId information
|
||||
let mapContainer = $(this);
|
||||
let systemId = config.systemIdPrefix + mapContainer.data('id') + '-' + data.id;
|
||||
let systemId = MapUtil.getSystemId(mapContainer.data('id'), data.id);
|
||||
|
||||
// check if system already exists
|
||||
let system = document.getElementById( systemId );
|
||||
@@ -753,8 +752,8 @@ define([
|
||||
let mapId = mapContainer.data('id');
|
||||
let connectionId = connectionData.id || 0;
|
||||
let connection;
|
||||
let sourceSystem = $('#' + config.systemIdPrefix + mapId + '-' + connectionData.source);
|
||||
let targetSystem = $('#' + config.systemIdPrefix + mapId + '-' + connectionData.target);
|
||||
let sourceSystem = $('#' + MapUtil.getSystemId(mapId, connectionData.source) );
|
||||
let targetSystem = $('#' + MapUtil.getSystemId(mapId, connectionData.target) );
|
||||
|
||||
// check if both systems exists
|
||||
// (If not -> something went wrong e.g. DB-Foreign keys for "ON DELETE",...)
|
||||
@@ -851,10 +850,10 @@ define([
|
||||
|
||||
// check if source or target has changed
|
||||
if(connectionData.source !== newConnectionData.source ){
|
||||
map.setSource(connection, config.systemIdPrefix + mapId + '-' + newConnectionData.source);
|
||||
map.setSource(connection, MapUtil.getSystemId(mapId, newConnectionData.source) );
|
||||
}
|
||||
if(connectionData.target !== newConnectionData.target ){
|
||||
map.setTarget(connection, config.systemIdPrefix + mapId + '-' + newConnectionData.target);
|
||||
map.setTarget(connection, MapUtil.getSystemId(mapId, newConnectionData.target) );
|
||||
}
|
||||
|
||||
// connection.targetId
|
||||
@@ -998,7 +997,7 @@ define([
|
||||
}
|
||||
|
||||
if(deleteThisSystem === true){
|
||||
let deleteSystem = $('#' + config.systemIdPrefix + mapContainer.data('id') + '-' + currentSystemData[a].id);
|
||||
let deleteSystem = $('#' + MapUtil.getSystemId(mapContainer.data('id'), currentSystemData[a].id) );
|
||||
|
||||
// system not found -> delete system
|
||||
System.removeSystems(mapConfig.map, deleteSystem);
|
||||
@@ -1423,7 +1422,6 @@ define([
|
||||
* @returns {{id: Number, source: Number, sourceName: (*|T|JQuery|{}), target: Number, targetName: (*|T|JQuery), scope: *, type: *, updated: Number}}
|
||||
*/
|
||||
let getDataByConnection = function(connection){
|
||||
|
||||
let source = $(connection.source);
|
||||
let target = $(connection.target);
|
||||
|
||||
@@ -2786,7 +2784,7 @@ define([
|
||||
|
||||
$(mapContainer).on('pf:menuSelectSystem', function(e, data){
|
||||
let tempMapContainer = $(this);
|
||||
let systemId = config.systemIdPrefix + tempMapContainer.data('id') + '-' + data.systemId;
|
||||
let systemId = MapUtil.getSystemId(tempMapContainer.data('id'), data.systemId);
|
||||
let system = $(this).find('#' + systemId);
|
||||
|
||||
if(system.length === 1){
|
||||
@@ -3309,7 +3307,6 @@ define([
|
||||
return {
|
||||
getMapInstance: getMapInstance,
|
||||
clearMapInstance: clearMapInstance,
|
||||
|
||||
getDataByConnection: getDataByConnection
|
||||
};
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ define([
|
||||
mapLocalStoragePrefix: 'map_', // prefix for map data local storage key
|
||||
mapTabContentClass: 'pf-map-tab-content', // Tab-Content element (parent element)
|
||||
|
||||
systemIdPrefix: 'pf-system-', // id prefix for a system
|
||||
systemClass: 'pf-system', // class for all systems
|
||||
mapGridClass: 'pf-grid-small' // class for map grid snapping
|
||||
};
|
||||
@@ -191,7 +192,6 @@ define([
|
||||
return this.find('.' + config.systemClass);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* search connections by systems
|
||||
* @param {Object} map - jsPlumb
|
||||
@@ -200,7 +200,7 @@ define([
|
||||
*/
|
||||
let searchConnectionsBySystems = function(map, systems){
|
||||
let connections = [];
|
||||
let withBackConnection = false;
|
||||
let withBackConnection = true;
|
||||
|
||||
$.each(systems, function(i, system){
|
||||
// get connections where system is source
|
||||
@@ -571,6 +571,16 @@ define([
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* get systemId string (selector
|
||||
* @param mapId
|
||||
* @param systemId
|
||||
* @returns {string}
|
||||
*/
|
||||
let getSystemId = (mapId, systemId) => {
|
||||
return config.systemIdPrefix + mapId + '-' + systemId;
|
||||
};
|
||||
|
||||
return {
|
||||
config: config,
|
||||
mapOptions: mapOptions,
|
||||
@@ -593,6 +603,7 @@ define([
|
||||
storeDefaultMapId: storeDefaultMapId,
|
||||
getLocaleData: getLocaleData,
|
||||
storeLocalData: storeLocalData,
|
||||
deleteLocalData: deleteLocalData
|
||||
deleteLocalData: deleteLocalData,
|
||||
getSystemId: getSystemId
|
||||
};
|
||||
});
|
||||
@@ -36,8 +36,6 @@ define([
|
||||
tableActionCellClass: 'pf-table-action-cell', // class for table "action" cells
|
||||
tableCounterCellClass: 'pf-table-counter-cell', // class for table "counter" cells
|
||||
|
||||
systemIdPrefix: 'pf-system-', // id prefix for a system
|
||||
|
||||
loadingOptions: { // config for loading overlay
|
||||
icon: {
|
||||
size: 'fa-2x'
|
||||
@@ -430,7 +428,7 @@ define([
|
||||
let deleteRowElement = $(target).parents('tr');
|
||||
|
||||
let activeMap = Util.getMapModule().getActiveMap();
|
||||
let systemElement = $('#' + config.systemIdPrefix + mapData.config.id + '-' + rowData.id);
|
||||
let systemElement = MapUtil.getSystemId(mapData.config.id, rowData.id);
|
||||
|
||||
if(systemElement){
|
||||
// trigger system delete event
|
||||
|
||||
@@ -7,8 +7,10 @@ define([
|
||||
'app/init',
|
||||
'app/util',
|
||||
'app/render',
|
||||
'bootbox'
|
||||
], function($, Init, Util, Render, bootbox) {
|
||||
'bootbox',
|
||||
'app/map/map',
|
||||
'app/map/util'
|
||||
], function($, Init, Util, Render, bootbox, Map, MapUtil) {
|
||||
'use strict';
|
||||
|
||||
let config = {
|
||||
@@ -40,10 +42,12 @@ define([
|
||||
sigTableEditSigNameInput: 'pf-sig-table-edit-name-input', // class for editable fields (input)
|
||||
sigTableEditSigGroupSelect: 'pf-sig-table-edit-group-select', // class for editable fields (sig group)
|
||||
sigTableEditSigTypeSelect: 'pf-sig-table-edit-type-select', // class for editable fields (sig type)
|
||||
sigTableEditSigConnectionSelect: 'pf-sig-table-edit-connection-select', // class for editable fields (sig connection)
|
||||
sigTableEditSigDescriptionTextarea: 'pf-sig-table-edit-desc-text', // class for editable fields (sig description)
|
||||
sigTableCreatedCellClass: 'pf-sig-table-created', // class for "created" cells
|
||||
sigTableUpdatedCellClass: 'pf-sig-table-updated', // class for "updated" cells
|
||||
|
||||
sigTableConnectionClass: 'pf-table-connection-cell', // class for "connection" cells
|
||||
sigTableCounterClass: 'pf-table-counter-cell', // class for "counter" cells
|
||||
sigTableActionCellClass: 'pf-table-action-cell', // class for "action" cells
|
||||
|
||||
@@ -159,7 +163,7 @@ define([
|
||||
let updateCell = signatureTableApi.cell( rowIndex, cellIndex );
|
||||
let updateCellElement = updateCell.nodes().to$();
|
||||
|
||||
if(cellIndex === 6){
|
||||
if(cellIndex === 7){
|
||||
// clear existing counter interval
|
||||
clearInterval( updateCellElement.data('interval') );
|
||||
}
|
||||
@@ -167,7 +171,7 @@ define([
|
||||
// set new value
|
||||
updateCell.data( data ).draw();
|
||||
|
||||
if(cellIndex === 6){
|
||||
if(cellIndex === 7){
|
||||
updateCellElement.initTimestampCounter();
|
||||
}
|
||||
};
|
||||
@@ -694,6 +698,27 @@ define([
|
||||
|
||||
tempData.type = sigType;
|
||||
|
||||
// set connection (to target system) ------------------------------------------------------------------
|
||||
let sigConnection = '<a href="#" class="' + config.sigTableEditSigConnectionSelect + '" ';
|
||||
if(data.id > 0){
|
||||
sigConnection += 'data-pk="' + data.id + '" ';
|
||||
}
|
||||
|
||||
// set disabled if group is not wromhole
|
||||
if(data.groupId !== 5){
|
||||
sigConnection += 'data-disabled="1" ';
|
||||
}
|
||||
|
||||
if(data.connection){
|
||||
sigConnection += 'data-value="' + data.connection.id + '" ';
|
||||
}
|
||||
sigConnection += '></a>';
|
||||
|
||||
tempData.connection = {
|
||||
render: sigConnection,
|
||||
connection: data.connection
|
||||
};
|
||||
|
||||
// set description ------------------------------------------------------------------------------------
|
||||
let sigDescription = '<a href="#" class="' + config.sigTableEditSigDescriptionTextarea + '" ';
|
||||
if(data.id > 0){
|
||||
@@ -1014,6 +1039,7 @@ define([
|
||||
let sigGroupFields = tableElement.find('.' + config.sigTableEditSigGroupSelect);
|
||||
let sigTypeFields = tableElement.find('.' + config.sigTableEditSigTypeSelect);
|
||||
let sigDescriptionFields = tableElement.find('.' + config.sigTableEditSigDescriptionTextarea);
|
||||
let sigConnectionFields = tableElement.find('.' + config.sigTableEditSigConnectionSelect);
|
||||
|
||||
// jump to "next" editable field on save
|
||||
let openNextEditDialogOnSave = function(fields){
|
||||
@@ -1038,8 +1064,16 @@ define([
|
||||
};
|
||||
|
||||
// helper function - get the next editable field in next table column
|
||||
let getNextEditableField = function(field){
|
||||
let nextEditableField = $(field).closest('td').next().find('.editable');
|
||||
let getNextEditableField = function(field, selector){
|
||||
let nextEditableField = null;
|
||||
if(selector){
|
||||
// search specific sibling
|
||||
nextEditableField = $(field).closest('td').nextAll(selector).find('.editable');
|
||||
}else{
|
||||
// get next sibling
|
||||
nextEditableField = $(field).closest('td').next().find('.editable');
|
||||
}
|
||||
|
||||
return $(nextEditableField);
|
||||
};
|
||||
|
||||
@@ -1108,7 +1142,7 @@ define([
|
||||
updateTooltip(columnElement, newValue);
|
||||
|
||||
// update "updated" cell
|
||||
updateSignatureCell(rowElement, 6, newRowData.updated);
|
||||
updateSignatureCell(rowElement, 7, newRowData.updated);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -1145,7 +1179,7 @@ define([
|
||||
let newRowData = response.signatures[0];
|
||||
|
||||
// update "updated" cell
|
||||
updateSignatureCell(rowElement, 6, newRowData.updated);
|
||||
updateSignatureCell(rowElement, 7, newRowData.updated);
|
||||
}
|
||||
|
||||
// find related "type" select (same row) and change options
|
||||
@@ -1166,6 +1200,18 @@ define([
|
||||
}else{
|
||||
typeSelect.editable('disable');
|
||||
}
|
||||
|
||||
// find "connection" select (same row) and change "enabled" flag
|
||||
let connectionSelect = getNextEditableField(signatureTypeField, '.' + config.sigTableConnectionClass);
|
||||
connectionSelect.editable('setValue', null);
|
||||
|
||||
if(newValue === 5){
|
||||
// wormhole
|
||||
connectionSelect.editable('enable');
|
||||
}else{
|
||||
checkConnectionConflicts();
|
||||
connectionSelect.editable('disable');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1204,7 +1250,7 @@ define([
|
||||
let newRowData = response.signatures[0];
|
||||
|
||||
// update "updated" cell
|
||||
updateSignatureCell(rowElement, 6, newRowData.updated);
|
||||
updateSignatureCell(rowElement, 7, newRowData.updated);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -1227,7 +1273,61 @@ define([
|
||||
let newRowData = response.signatures[0];
|
||||
|
||||
// update "updated" cell
|
||||
updateSignatureCell(rowElement, 6, newRowData.updated);
|
||||
updateSignatureCell(rowElement, 7, newRowData.updated);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Select connection (target system) --------------------------------------------------------------------------
|
||||
let initCount = 0;
|
||||
sigConnectionFields.on('init', function(e, editable) {
|
||||
if(++initCount >= sigConnectionFields.length){
|
||||
checkConnectionConflicts();
|
||||
}
|
||||
});
|
||||
|
||||
sigConnectionFields.editable({
|
||||
type: 'select',
|
||||
title: 'system',
|
||||
name: 'connectionId',
|
||||
emptytext: 'unknown',
|
||||
onblur: 'submit',
|
||||
showbuttons: false,
|
||||
params: modifyFieldParamsOnSend,
|
||||
display: function(value, sourceData) {
|
||||
let editableElement = $(this);
|
||||
let newValue = '';
|
||||
|
||||
if(value !== null){
|
||||
let selected = $.fn.editableutils.itemsByValue(value, sourceData);
|
||||
if(
|
||||
selected.length &&
|
||||
selected[0].text !== ''
|
||||
){
|
||||
newValue += '<i class="fa fa-exclamation-triangle txt-color txt-color-danger hide"></i>';
|
||||
newValue += ' ' + selected[0].text;
|
||||
}else{
|
||||
newValue = '<span class="editable-empty">unknown</span>';
|
||||
}
|
||||
}
|
||||
|
||||
editableElement.html(newValue);
|
||||
},
|
||||
source: function(a,b){
|
||||
let activeMap = Util.getMapModule().getActiveMap();
|
||||
let mapId = activeMap.data('id');
|
||||
let availableConnections = getSignatureConnectionOptions(mapId, systemData);
|
||||
|
||||
return availableConnections;
|
||||
},
|
||||
success: function(response, newValue){
|
||||
if(response){
|
||||
let signatureConnectionField = $(this);
|
||||
let rowElement = signatureConnectionField.parents('tr');
|
||||
let newRowData = response.signatures[0];
|
||||
|
||||
// update "updated" cell
|
||||
updateSignatureCell(rowElement, 7, newRowData.updated);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -1244,11 +1344,106 @@ define([
|
||||
tableElement.parents('.' + config.tableToolsActionClass).css( 'height', '-=35px' );
|
||||
});
|
||||
|
||||
// save events
|
||||
sigConnectionFields.on('save', function(e, editable){
|
||||
checkConnectionConflicts();
|
||||
});
|
||||
|
||||
// open next field dialog -------------------------------------------------------------------------------------
|
||||
openNextEditDialogOnSave(sigNameFields);
|
||||
openNextEditDialogOnSave(sigGroupFields);
|
||||
};
|
||||
|
||||
/**
|
||||
* get all connection select options
|
||||
* @param mapId
|
||||
* @param systemData
|
||||
* @returns {Array}
|
||||
*/
|
||||
let getSignatureConnectionOptions = (mapId, systemData) => {
|
||||
let map = Map.getMapInstance( mapId );
|
||||
let systemId = MapUtil.getSystemId(mapId, systemData.id);
|
||||
let systemConnections = MapUtil.searchConnectionsBySystems(map, [systemId]);
|
||||
let connectionOptions = [];
|
||||
|
||||
for(let i = 0; i < systemConnections.length; i++){
|
||||
let connectionData = Map.getDataByConnection(systemConnections[i]);
|
||||
|
||||
// connectionId is required (must be stored)
|
||||
if(connectionData.id){
|
||||
// check whether "source" or "target" system is relevant for this connection
|
||||
// -> hint "source" === 'target' --> loop
|
||||
if(systemData.id !== connectionData.target){
|
||||
// take target...
|
||||
connectionOptions.push({
|
||||
value: connectionData.id,
|
||||
text: connectionData.targetName
|
||||
});
|
||||
}else if(systemData.id !== connectionData.source){
|
||||
// take source...
|
||||
connectionOptions.push({
|
||||
value: connectionData.id,
|
||||
text: connectionData.sourceName
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// add empty entry
|
||||
connectionOptions.unshift({ value: null, text: ''});
|
||||
|
||||
return connectionOptions;
|
||||
};
|
||||
|
||||
/**
|
||||
* check connectionIds for conflicts (multiple signatures -> same connection)
|
||||
* -> show "conflict" icon next to select
|
||||
*/
|
||||
let checkConnectionConflicts = () => {
|
||||
setTimeout(function() {
|
||||
let connectionSelects = $('.' + config.sigTableConnectionClass + ' .editable');
|
||||
let connectionIds = [];
|
||||
let duplicateConnectionIds = [];
|
||||
let groupedSelects = [];
|
||||
|
||||
connectionSelects.each(function(){
|
||||
let select = $(this);
|
||||
let value = parseInt(select.editable('getValue', true) )|| 0;
|
||||
|
||||
if(
|
||||
connectionIds.indexOf(value) > -1 &&
|
||||
duplicateConnectionIds.indexOf(value) === -1
|
||||
){
|
||||
// duplicate found
|
||||
duplicateConnectionIds.push(value);
|
||||
}
|
||||
|
||||
if(groupedSelects[value] !== undefined){
|
||||
groupedSelects[value].push(select[0]);
|
||||
}else{
|
||||
groupedSelects[value] = [select[0]];
|
||||
}
|
||||
|
||||
connectionIds.push(value);
|
||||
});
|
||||
|
||||
// update "conflict" icon next to select label for connectionIds
|
||||
connectionSelects.each(function(){
|
||||
let select = $(this);
|
||||
let value = parseInt(select.editable('getValue', true) )|| 0;
|
||||
let conflictIcon = select.find('.fa-exclamation-triangle');
|
||||
if(
|
||||
duplicateConnectionIds.indexOf(value) > -1 &&
|
||||
groupedSelects[value].indexOf(select[0]) > -1
|
||||
){
|
||||
conflictIcon.removeClass('hide');
|
||||
}else{
|
||||
conflictIcon.addClass('hide');
|
||||
}
|
||||
});
|
||||
}, 200);
|
||||
};
|
||||
|
||||
/**
|
||||
* get all signatures that can exist for a given system
|
||||
* @param systemData
|
||||
@@ -1451,6 +1646,9 @@ define([
|
||||
// update signature bar
|
||||
moduleElement.updateScannedSignaturesBar({showNotice: false});
|
||||
|
||||
// update connection conflicts
|
||||
checkConnectionConflicts();
|
||||
|
||||
Util.showNotify({title: 'Signature deleted', text: signatureCount + ' signatures deleted', type: 'success'});
|
||||
}
|
||||
};
|
||||
@@ -1789,6 +1987,18 @@ define([
|
||||
data: 'description'
|
||||
},{
|
||||
targets: 5,
|
||||
orderable: false,
|
||||
searchable: false,
|
||||
className: [config.sigTableConnectionClass].join(' '),
|
||||
title: 'leads to',
|
||||
type: 'html',
|
||||
width: '70px',
|
||||
data: 'connection',
|
||||
render: {
|
||||
_: 'render'
|
||||
}
|
||||
},{
|
||||
targets: 6,
|
||||
title: 'created',
|
||||
width: '90px',
|
||||
searchable: false,
|
||||
@@ -1802,7 +2012,7 @@ define([
|
||||
$(cell).initTimestampCounter();
|
||||
}
|
||||
},{
|
||||
targets: 6,
|
||||
targets: 7,
|
||||
title: 'updated',
|
||||
width: '90px',
|
||||
searchable: false,
|
||||
@@ -1824,7 +2034,7 @@ define([
|
||||
}
|
||||
}
|
||||
},{
|
||||
targets: 7,
|
||||
targets: 8,
|
||||
title: '',
|
||||
orderable: false,
|
||||
searchable: false,
|
||||
@@ -1845,7 +2055,7 @@ define([
|
||||
}
|
||||
}
|
||||
},{
|
||||
targets: 8,
|
||||
targets: 9,
|
||||
title: '',
|
||||
orderable: false,
|
||||
searchable: false,
|
||||
|
||||
@@ -32,7 +32,6 @@ define([
|
||||
|
||||
mapClass: 'pf-map', // class for all maps
|
||||
mapIdPrefix: 'pf-map-', // id prefix for all maps
|
||||
systemIdPrefix: 'pf-system-', // id prefix for a system
|
||||
systemClass: 'pf-system', // class for all systems
|
||||
systemActiveClass: 'pf-system-active', // class for an active system in a map
|
||||
systemSelectedClass: 'pf-system-selected', // class for selected systems in a map
|
||||
@@ -453,7 +452,7 @@ define([
|
||||
$.fn.getSystem = function(map, data){
|
||||
// get map container for mapId information
|
||||
let mapContainer = $(this);
|
||||
let systemId = config.systemIdPrefix + mapContainer.data('id') + '-' + data.id;
|
||||
let systemId = MapUtil.getSystemId(mapContainer.data('id'), data.id);
|
||||
|
||||
// check if system already exists
|
||||
let system = document.getElementById( systemId );
|
||||
@@ -753,8 +752,8 @@ define([
|
||||
let mapId = mapContainer.data('id');
|
||||
let connectionId = connectionData.id || 0;
|
||||
let connection;
|
||||
let sourceSystem = $('#' + config.systemIdPrefix + mapId + '-' + connectionData.source);
|
||||
let targetSystem = $('#' + config.systemIdPrefix + mapId + '-' + connectionData.target);
|
||||
let sourceSystem = $('#' + MapUtil.getSystemId(mapId, connectionData.source) );
|
||||
let targetSystem = $('#' + MapUtil.getSystemId(mapId, connectionData.target) );
|
||||
|
||||
// check if both systems exists
|
||||
// (If not -> something went wrong e.g. DB-Foreign keys for "ON DELETE",...)
|
||||
@@ -851,10 +850,10 @@ define([
|
||||
|
||||
// check if source or target has changed
|
||||
if(connectionData.source !== newConnectionData.source ){
|
||||
map.setSource(connection, config.systemIdPrefix + mapId + '-' + newConnectionData.source);
|
||||
map.setSource(connection, MapUtil.getSystemId(mapId, newConnectionData.source) );
|
||||
}
|
||||
if(connectionData.target !== newConnectionData.target ){
|
||||
map.setTarget(connection, config.systemIdPrefix + mapId + '-' + newConnectionData.target);
|
||||
map.setTarget(connection, MapUtil.getSystemId(mapId, newConnectionData.target) );
|
||||
}
|
||||
|
||||
// connection.targetId
|
||||
@@ -998,7 +997,7 @@ define([
|
||||
}
|
||||
|
||||
if(deleteThisSystem === true){
|
||||
let deleteSystem = $('#' + config.systemIdPrefix + mapContainer.data('id') + '-' + currentSystemData[a].id);
|
||||
let deleteSystem = $('#' + MapUtil.getSystemId(mapContainer.data('id'), currentSystemData[a].id) );
|
||||
|
||||
// system not found -> delete system
|
||||
System.removeSystems(mapConfig.map, deleteSystem);
|
||||
@@ -1423,7 +1422,6 @@ define([
|
||||
* @returns {{id: Number, source: Number, sourceName: (*|T|JQuery|{}), target: Number, targetName: (*|T|JQuery), scope: *, type: *, updated: Number}}
|
||||
*/
|
||||
let getDataByConnection = function(connection){
|
||||
|
||||
let source = $(connection.source);
|
||||
let target = $(connection.target);
|
||||
|
||||
@@ -2786,7 +2784,7 @@ define([
|
||||
|
||||
$(mapContainer).on('pf:menuSelectSystem', function(e, data){
|
||||
let tempMapContainer = $(this);
|
||||
let systemId = config.systemIdPrefix + tempMapContainer.data('id') + '-' + data.systemId;
|
||||
let systemId = MapUtil.getSystemId(tempMapContainer.data('id'), data.systemId);
|
||||
let system = $(this).find('#' + systemId);
|
||||
|
||||
if(system.length === 1){
|
||||
@@ -3309,7 +3307,6 @@ define([
|
||||
return {
|
||||
getMapInstance: getMapInstance,
|
||||
clearMapInstance: clearMapInstance,
|
||||
|
||||
getDataByConnection: getDataByConnection
|
||||
};
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ define([
|
||||
mapLocalStoragePrefix: 'map_', // prefix for map data local storage key
|
||||
mapTabContentClass: 'pf-map-tab-content', // Tab-Content element (parent element)
|
||||
|
||||
systemIdPrefix: 'pf-system-', // id prefix for a system
|
||||
systemClass: 'pf-system', // class for all systems
|
||||
mapGridClass: 'pf-grid-small' // class for map grid snapping
|
||||
};
|
||||
@@ -191,7 +192,6 @@ define([
|
||||
return this.find('.' + config.systemClass);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* search connections by systems
|
||||
* @param {Object} map - jsPlumb
|
||||
@@ -200,7 +200,7 @@ define([
|
||||
*/
|
||||
let searchConnectionsBySystems = function(map, systems){
|
||||
let connections = [];
|
||||
let withBackConnection = false;
|
||||
let withBackConnection = true;
|
||||
|
||||
$.each(systems, function(i, system){
|
||||
// get connections where system is source
|
||||
@@ -571,6 +571,16 @@ define([
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* get systemId string (selector
|
||||
* @param mapId
|
||||
* @param systemId
|
||||
* @returns {string}
|
||||
*/
|
||||
let getSystemId = (mapId, systemId) => {
|
||||
return config.systemIdPrefix + mapId + '-' + systemId;
|
||||
};
|
||||
|
||||
return {
|
||||
config: config,
|
||||
mapOptions: mapOptions,
|
||||
@@ -593,6 +603,7 @@ define([
|
||||
storeDefaultMapId: storeDefaultMapId,
|
||||
getLocaleData: getLocaleData,
|
||||
storeLocalData: storeLocalData,
|
||||
deleteLocalData: deleteLocalData
|
||||
deleteLocalData: deleteLocalData,
|
||||
getSystemId: getSystemId
|
||||
};
|
||||
});
|
||||
@@ -36,8 +36,6 @@ define([
|
||||
tableActionCellClass: 'pf-table-action-cell', // class for table "action" cells
|
||||
tableCounterCellClass: 'pf-table-counter-cell', // class for table "counter" cells
|
||||
|
||||
systemIdPrefix: 'pf-system-', // id prefix for a system
|
||||
|
||||
loadingOptions: { // config for loading overlay
|
||||
icon: {
|
||||
size: 'fa-2x'
|
||||
@@ -430,7 +428,7 @@ define([
|
||||
let deleteRowElement = $(target).parents('tr');
|
||||
|
||||
let activeMap = Util.getMapModule().getActiveMap();
|
||||
let systemElement = $('#' + config.systemIdPrefix + mapData.config.id + '-' + rowData.id);
|
||||
let systemElement = MapUtil.getSystemId(mapData.config.id, rowData.id);
|
||||
|
||||
if(systemElement){
|
||||
// trigger system delete event
|
||||
|
||||
@@ -7,8 +7,10 @@ define([
|
||||
'app/init',
|
||||
'app/util',
|
||||
'app/render',
|
||||
'bootbox'
|
||||
], function($, Init, Util, Render, bootbox) {
|
||||
'bootbox',
|
||||
'app/map/map',
|
||||
'app/map/util'
|
||||
], function($, Init, Util, Render, bootbox, Map, MapUtil) {
|
||||
'use strict';
|
||||
|
||||
let config = {
|
||||
@@ -40,10 +42,12 @@ define([
|
||||
sigTableEditSigNameInput: 'pf-sig-table-edit-name-input', // class for editable fields (input)
|
||||
sigTableEditSigGroupSelect: 'pf-sig-table-edit-group-select', // class for editable fields (sig group)
|
||||
sigTableEditSigTypeSelect: 'pf-sig-table-edit-type-select', // class for editable fields (sig type)
|
||||
sigTableEditSigConnectionSelect: 'pf-sig-table-edit-connection-select', // class for editable fields (sig connection)
|
||||
sigTableEditSigDescriptionTextarea: 'pf-sig-table-edit-desc-text', // class for editable fields (sig description)
|
||||
sigTableCreatedCellClass: 'pf-sig-table-created', // class for "created" cells
|
||||
sigTableUpdatedCellClass: 'pf-sig-table-updated', // class for "updated" cells
|
||||
|
||||
sigTableConnectionClass: 'pf-table-connection-cell', // class for "connection" cells
|
||||
sigTableCounterClass: 'pf-table-counter-cell', // class for "counter" cells
|
||||
sigTableActionCellClass: 'pf-table-action-cell', // class for "action" cells
|
||||
|
||||
@@ -159,7 +163,7 @@ define([
|
||||
let updateCell = signatureTableApi.cell( rowIndex, cellIndex );
|
||||
let updateCellElement = updateCell.nodes().to$();
|
||||
|
||||
if(cellIndex === 6){
|
||||
if(cellIndex === 7){
|
||||
// clear existing counter interval
|
||||
clearInterval( updateCellElement.data('interval') );
|
||||
}
|
||||
@@ -167,7 +171,7 @@ define([
|
||||
// set new value
|
||||
updateCell.data( data ).draw();
|
||||
|
||||
if(cellIndex === 6){
|
||||
if(cellIndex === 7){
|
||||
updateCellElement.initTimestampCounter();
|
||||
}
|
||||
};
|
||||
@@ -694,6 +698,27 @@ define([
|
||||
|
||||
tempData.type = sigType;
|
||||
|
||||
// set connection (to target system) ------------------------------------------------------------------
|
||||
let sigConnection = '<a href="#" class="' + config.sigTableEditSigConnectionSelect + '" ';
|
||||
if(data.id > 0){
|
||||
sigConnection += 'data-pk="' + data.id + '" ';
|
||||
}
|
||||
|
||||
// set disabled if group is not wromhole
|
||||
if(data.groupId !== 5){
|
||||
sigConnection += 'data-disabled="1" ';
|
||||
}
|
||||
|
||||
if(data.connection){
|
||||
sigConnection += 'data-value="' + data.connection.id + '" ';
|
||||
}
|
||||
sigConnection += '></a>';
|
||||
|
||||
tempData.connection = {
|
||||
render: sigConnection,
|
||||
connection: data.connection
|
||||
};
|
||||
|
||||
// set description ------------------------------------------------------------------------------------
|
||||
let sigDescription = '<a href="#" class="' + config.sigTableEditSigDescriptionTextarea + '" ';
|
||||
if(data.id > 0){
|
||||
@@ -1014,6 +1039,7 @@ define([
|
||||
let sigGroupFields = tableElement.find('.' + config.sigTableEditSigGroupSelect);
|
||||
let sigTypeFields = tableElement.find('.' + config.sigTableEditSigTypeSelect);
|
||||
let sigDescriptionFields = tableElement.find('.' + config.sigTableEditSigDescriptionTextarea);
|
||||
let sigConnectionFields = tableElement.find('.' + config.sigTableEditSigConnectionSelect);
|
||||
|
||||
// jump to "next" editable field on save
|
||||
let openNextEditDialogOnSave = function(fields){
|
||||
@@ -1038,8 +1064,16 @@ define([
|
||||
};
|
||||
|
||||
// helper function - get the next editable field in next table column
|
||||
let getNextEditableField = function(field){
|
||||
let nextEditableField = $(field).closest('td').next().find('.editable');
|
||||
let getNextEditableField = function(field, selector){
|
||||
let nextEditableField = null;
|
||||
if(selector){
|
||||
// search specific sibling
|
||||
nextEditableField = $(field).closest('td').nextAll(selector).find('.editable');
|
||||
}else{
|
||||
// get next sibling
|
||||
nextEditableField = $(field).closest('td').next().find('.editable');
|
||||
}
|
||||
|
||||
return $(nextEditableField);
|
||||
};
|
||||
|
||||
@@ -1108,7 +1142,7 @@ define([
|
||||
updateTooltip(columnElement, newValue);
|
||||
|
||||
// update "updated" cell
|
||||
updateSignatureCell(rowElement, 6, newRowData.updated);
|
||||
updateSignatureCell(rowElement, 7, newRowData.updated);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -1145,7 +1179,7 @@ define([
|
||||
let newRowData = response.signatures[0];
|
||||
|
||||
// update "updated" cell
|
||||
updateSignatureCell(rowElement, 6, newRowData.updated);
|
||||
updateSignatureCell(rowElement, 7, newRowData.updated);
|
||||
}
|
||||
|
||||
// find related "type" select (same row) and change options
|
||||
@@ -1166,6 +1200,18 @@ define([
|
||||
}else{
|
||||
typeSelect.editable('disable');
|
||||
}
|
||||
|
||||
// find "connection" select (same row) and change "enabled" flag
|
||||
let connectionSelect = getNextEditableField(signatureTypeField, '.' + config.sigTableConnectionClass);
|
||||
connectionSelect.editable('setValue', null);
|
||||
|
||||
if(newValue === 5){
|
||||
// wormhole
|
||||
connectionSelect.editable('enable');
|
||||
}else{
|
||||
checkConnectionConflicts();
|
||||
connectionSelect.editable('disable');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1204,7 +1250,7 @@ define([
|
||||
let newRowData = response.signatures[0];
|
||||
|
||||
// update "updated" cell
|
||||
updateSignatureCell(rowElement, 6, newRowData.updated);
|
||||
updateSignatureCell(rowElement, 7, newRowData.updated);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -1227,7 +1273,61 @@ define([
|
||||
let newRowData = response.signatures[0];
|
||||
|
||||
// update "updated" cell
|
||||
updateSignatureCell(rowElement, 6, newRowData.updated);
|
||||
updateSignatureCell(rowElement, 7, newRowData.updated);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Select connection (target system) --------------------------------------------------------------------------
|
||||
let initCount = 0;
|
||||
sigConnectionFields.on('init', function(e, editable) {
|
||||
if(++initCount >= sigConnectionFields.length){
|
||||
checkConnectionConflicts();
|
||||
}
|
||||
});
|
||||
|
||||
sigConnectionFields.editable({
|
||||
type: 'select',
|
||||
title: 'system',
|
||||
name: 'connectionId',
|
||||
emptytext: 'unknown',
|
||||
onblur: 'submit',
|
||||
showbuttons: false,
|
||||
params: modifyFieldParamsOnSend,
|
||||
display: function(value, sourceData) {
|
||||
let editableElement = $(this);
|
||||
let newValue = '';
|
||||
|
||||
if(value !== null){
|
||||
let selected = $.fn.editableutils.itemsByValue(value, sourceData);
|
||||
if(
|
||||
selected.length &&
|
||||
selected[0].text !== ''
|
||||
){
|
||||
newValue += '<i class="fa fa-exclamation-triangle txt-color txt-color-danger hide"></i>';
|
||||
newValue += ' ' + selected[0].text;
|
||||
}else{
|
||||
newValue = '<span class="editable-empty">unknown</span>';
|
||||
}
|
||||
}
|
||||
|
||||
editableElement.html(newValue);
|
||||
},
|
||||
source: function(a,b){
|
||||
let activeMap = Util.getMapModule().getActiveMap();
|
||||
let mapId = activeMap.data('id');
|
||||
let availableConnections = getSignatureConnectionOptions(mapId, systemData);
|
||||
|
||||
return availableConnections;
|
||||
},
|
||||
success: function(response, newValue){
|
||||
if(response){
|
||||
let signatureConnectionField = $(this);
|
||||
let rowElement = signatureConnectionField.parents('tr');
|
||||
let newRowData = response.signatures[0];
|
||||
|
||||
// update "updated" cell
|
||||
updateSignatureCell(rowElement, 7, newRowData.updated);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -1244,11 +1344,106 @@ define([
|
||||
tableElement.parents('.' + config.tableToolsActionClass).css( 'height', '-=35px' );
|
||||
});
|
||||
|
||||
// save events
|
||||
sigConnectionFields.on('save', function(e, editable){
|
||||
checkConnectionConflicts();
|
||||
});
|
||||
|
||||
// open next field dialog -------------------------------------------------------------------------------------
|
||||
openNextEditDialogOnSave(sigNameFields);
|
||||
openNextEditDialogOnSave(sigGroupFields);
|
||||
};
|
||||
|
||||
/**
|
||||
* get all connection select options
|
||||
* @param mapId
|
||||
* @param systemData
|
||||
* @returns {Array}
|
||||
*/
|
||||
let getSignatureConnectionOptions = (mapId, systemData) => {
|
||||
let map = Map.getMapInstance( mapId );
|
||||
let systemId = MapUtil.getSystemId(mapId, systemData.id);
|
||||
let systemConnections = MapUtil.searchConnectionsBySystems(map, [systemId]);
|
||||
let connectionOptions = [];
|
||||
|
||||
for(let i = 0; i < systemConnections.length; i++){
|
||||
let connectionData = Map.getDataByConnection(systemConnections[i]);
|
||||
|
||||
// connectionId is required (must be stored)
|
||||
if(connectionData.id){
|
||||
// check whether "source" or "target" system is relevant for this connection
|
||||
// -> hint "source" === 'target' --> loop
|
||||
if(systemData.id !== connectionData.target){
|
||||
// take target...
|
||||
connectionOptions.push({
|
||||
value: connectionData.id,
|
||||
text: connectionData.targetName
|
||||
});
|
||||
}else if(systemData.id !== connectionData.source){
|
||||
// take source...
|
||||
connectionOptions.push({
|
||||
value: connectionData.id,
|
||||
text: connectionData.sourceName
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// add empty entry
|
||||
connectionOptions.unshift({ value: null, text: ''});
|
||||
|
||||
return connectionOptions;
|
||||
};
|
||||
|
||||
/**
|
||||
* check connectionIds for conflicts (multiple signatures -> same connection)
|
||||
* -> show "conflict" icon next to select
|
||||
*/
|
||||
let checkConnectionConflicts = () => {
|
||||
setTimeout(function() {
|
||||
let connectionSelects = $('.' + config.sigTableConnectionClass + ' .editable');
|
||||
let connectionIds = [];
|
||||
let duplicateConnectionIds = [];
|
||||
let groupedSelects = [];
|
||||
|
||||
connectionSelects.each(function(){
|
||||
let select = $(this);
|
||||
let value = parseInt(select.editable('getValue', true) )|| 0;
|
||||
|
||||
if(
|
||||
connectionIds.indexOf(value) > -1 &&
|
||||
duplicateConnectionIds.indexOf(value) === -1
|
||||
){
|
||||
// duplicate found
|
||||
duplicateConnectionIds.push(value);
|
||||
}
|
||||
|
||||
if(groupedSelects[value] !== undefined){
|
||||
groupedSelects[value].push(select[0]);
|
||||
}else{
|
||||
groupedSelects[value] = [select[0]];
|
||||
}
|
||||
|
||||
connectionIds.push(value);
|
||||
});
|
||||
|
||||
// update "conflict" icon next to select label for connectionIds
|
||||
connectionSelects.each(function(){
|
||||
let select = $(this);
|
||||
let value = parseInt(select.editable('getValue', true) )|| 0;
|
||||
let conflictIcon = select.find('.fa-exclamation-triangle');
|
||||
if(
|
||||
duplicateConnectionIds.indexOf(value) > -1 &&
|
||||
groupedSelects[value].indexOf(select[0]) > -1
|
||||
){
|
||||
conflictIcon.removeClass('hide');
|
||||
}else{
|
||||
conflictIcon.addClass('hide');
|
||||
}
|
||||
});
|
||||
}, 200);
|
||||
};
|
||||
|
||||
/**
|
||||
* get all signatures that can exist for a given system
|
||||
* @param systemData
|
||||
@@ -1451,6 +1646,9 @@ define([
|
||||
// update signature bar
|
||||
moduleElement.updateScannedSignaturesBar({showNotice: false});
|
||||
|
||||
// update connection conflicts
|
||||
checkConnectionConflicts();
|
||||
|
||||
Util.showNotify({title: 'Signature deleted', text: signatureCount + ' signatures deleted', type: 'success'});
|
||||
}
|
||||
};
|
||||
@@ -1789,6 +1987,18 @@ define([
|
||||
data: 'description'
|
||||
},{
|
||||
targets: 5,
|
||||
orderable: false,
|
||||
searchable: false,
|
||||
className: [config.sigTableConnectionClass].join(' '),
|
||||
title: 'leads to',
|
||||
type: 'html',
|
||||
width: '70px',
|
||||
data: 'connection',
|
||||
render: {
|
||||
_: 'render'
|
||||
}
|
||||
},{
|
||||
targets: 6,
|
||||
title: 'created',
|
||||
width: '90px',
|
||||
searchable: false,
|
||||
@@ -1802,7 +2012,7 @@ define([
|
||||
$(cell).initTimestampCounter();
|
||||
}
|
||||
},{
|
||||
targets: 6,
|
||||
targets: 7,
|
||||
title: 'updated',
|
||||
width: '90px',
|
||||
searchable: false,
|
||||
@@ -1824,7 +2034,7 @@ define([
|
||||
}
|
||||
}
|
||||
},{
|
||||
targets: 7,
|
||||
targets: 8,
|
||||
title: '',
|
||||
orderable: false,
|
||||
searchable: false,
|
||||
@@ -1845,7 +2055,7 @@ define([
|
||||
}
|
||||
}
|
||||
},{
|
||||
targets: 8,
|
||||
targets: 9,
|
||||
title: '',
|
||||
orderable: false,
|
||||
searchable: false,
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
<dd><a target="_blank" href="https://www.pathfinder.exodus4d.de"><em class="pf-brand">pathfinder</em></a></dd>
|
||||
<dt class="text-left txt-color txt-color-grayLight">Repository <i class="fa fa-lg fa-github fa-fw"></i></dt>
|
||||
<dd><a target="_blank" href="https://github.com/exodus4d/pathfinder">GitHub</a></dd>
|
||||
<dt class="text-left txt-color txt-color-grayLight">Community <i class="fa fa-lg fa-google-plus fa-fw"></i></dt>
|
||||
<dt class="text-left txt-color txt-color-grayLight">Social <i class="fa fa-lg fa-google-plus fa-fw"></i></dt>
|
||||
<dd><a target="_blank" href="https://plus.google.com/+Pathfinder-wSpace">Google+</a></dd>
|
||||
</dl>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user