You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

396 lines
18 KiB

define(function (require) {
var $ = require('jquery');
var _ = require('underscore');
var mvc = require('splunkjs/mvc');
var TableView = require('splunkjs/mvc/tableview');
var splunkjsUtils = require('splunkjs/mvc/utils');
var SearchManager = require('splunkjs/mvc/searchmanager');
//Entity information dictionary object which will contain itsi entity id, entity title, service id and service title
var entitySearchResult = {};
/**
* EntityDrilldownUtils contains common utils which can be used to get entity drilldown link in module drilldown views.
* @module EntityDrilldownUtils
* @type {{
* getOtherEntityDrilldownUrl: Function,
* getDrillDownPayloadURL: Function,
* getDrillDownSimpleURL: Function,
* getEntityDetailUrl: Function,
* createEntitySearchManager: Function,
* fetchEntityFromSearchManager: Function,
* renderTableLinks: Function,
* searchResultsToDictionary: Function,
* getCurrentLocationPathName: Function,
* getCurrentLocationOrigin: Function,
* getCurrentLocationSearch: Function
* redirectURL: Function}}
*/
var EntityDrilldownUtils = {
/**
* Get entity drilldown url by update entity title, entity id, service title and service id in the drilldown_payload of current uri.
*
* @param {string} newEntityTitle -- New value of entity title field
* @param {string} newViewName -- View name which need to redirect from table
* @param {string} fieldsToAdd -- [Optional parameter] Extra fields need to pass with paylod.entities id and title. If no other fields to pass leave it blank as '{}'
* @returns {string} -- Updated drilldown_payload json URL or simple URL
*/
getOtherEntityDrilldownUrl: function (newEntityTitle, newViewName, fieldsToAdd) {
// Try to get new entity details from entity search result
var entityDetails = _.first(_.where(entitySearchResult, {entity_title: newEntityTitle}));
if (_.isUndefined(entityDetails)) {
throw new Error("Failed to retrieve drilldown url because no such entity id in the kvstore.");
}
var searchString = '?';
// Try to get drilldown_payload from query parameters first
var queryParams = {};
_.each(this.getCurrentLocationSearch().substring(1).split("&"), function (kvp) {
var pairs = kvp.split('=');
queryParams[pairs[0]] = decodeURIComponent(pairs[1]);
});
if (!_.isEmpty(queryParams['drilldown_payload'])) {
searchString += this.getDrillDownPayloadURL(queryParams, entityDetails, newEntityTitle, fieldsToAdd);
}
else if (!_.isEmpty(queryParams['entity.id']) && !_.isEmpty(queryParams['entity.title'])) {
searchString += this.getDrillDownSimpleURL(queryParams, entityDetails, newEntityTitle, fieldsToAdd);
}
else {
throw new Error("Failed to retrieve drilldown url because no drilldown_payload or simple type URL found in current URL.");
}
if (searchString === '?') {
throw new Error("Failed to retrieve drilldown url.");
}
var pathName = this.getCurrentLocationPathName();
var url = this.getCurrentLocationOrigin() + pathName.substr(0, pathName.lastIndexOf('/')) + newViewName + searchString;
return url;
},
/**
* Get entity drilldown url by update entity title, entity id, service title and service id in current uri.
*
* @param {string} queryParams -- Parameter list of current URL
* @param {string} newEntityTitle -- New value of entity title field
* @param {string} entityDetails -- entity details from kvstore
* @param {string} fieldsToAdd -- [Optional parameter] Extra fields need to pass with paylod.entities id and title. If no other fields to pass leave it blank as '{}'
* @returns {string} -- Updated drilldown_payload json parameters
*/
getDrillDownPayloadURL: function (queryParams, entityDetails, newEntityTitle, fieldsToAdd) {
var searchString = '';
var payload = JSON.parse(queryParams['drilldown_payload']);
//Now Update payload entity and service details
if (!_.isUndefined(payload.entities)) {
//Created updated entity object
updatedEntity = {};
updatedEntity['title'] = newEntityTitle;
updatedEntity['id'] = entityDetails['entity_key'];
//Add extra fields in entity if any
if (!_.isUndefined(fieldsToAdd)) {
_.each(fieldsToAdd, function (value, key) {
updatedEntity[key] = value;
});
}
//Create new entities array object for payload
payload.entities = [];
payload.entities.push(updatedEntity);
//Update curent service id
if (!_.isEmpty(entityDetails['service_key'])) {
//Update first service id and title if an entity has more than one service
if(Array.isArray(entityDetails['service_key'])){
payload.context.service_id = entityDetails['service_key'][0];
payload.context.service_title = entityDetails['service_title'][0];
}
else{
payload.context.service_id = entityDetails['service_key'];
payload.context.service_title = entityDetails['service_title'];
}
}else{
throw new Error("Failed to find service for selected entity.");
}
}else{
throw new Error("Failed to find the entity key in the payload JSON.");
}
// Now generate drilldown_payload, query paramters and final url
queryParams.drilldown_payload = JSON.stringify(payload);
searchString += _.map(queryParams, function (value, key) {
return key + '=' + encodeURIComponent(value);
}).join('&');
return searchString;
},
/**
* Get entity drilldown url by update entity title, entity id, service title and service id in the current uri.
*
* @param {string} queryParams -- Parameter list of current URL
* @param {string} newEntityTitle -- New value of entity title field
* @param {string} entityDetails -- entity details from kvstore
* @param {string} fieldsToAdd -- [Optional parameter] Extra fields need to pass with paylod.entities id and title. If no other fields to pass leave it blank as '{}'
* @returns {string} -- Updated drilldown_payload simple URL parameters
*/
getDrillDownSimpleURL: function (queryParams, entityDetails, newEntityTitle, fieldsToAdd) {
var searchString = '';
var newQueryParams = {};
if (!_.isEmpty(entityDetails['service_key'])) {
//Update curent service id. If an entity has more than one service, update first service id and title.
if(Array.isArray(entityDetails['service_key'])){
newQueryParams['service_id'] = entityDetails['service_key'][0];
newQueryParams['service_title'] = entityDetails['service_title'][0];
}
else{
newQueryParams['service_id'] = entityDetails['service_key'];
newQueryParams['service_title'] = entityDetails['service_title'];
}
//Update entity id and title for new drill down
newQueryParams['entity.id'] = entityDetails['entity_key'];
newQueryParams['entity.title'] = newEntityTitle;
//Add extra fields in entity if any
if (!_.isUndefined(fieldsToAdd)) {
_.each(fieldsToAdd, function (value, key) {
newQueryParams['entity.'+key] = value;
});
}
// Get required params from queryParams
var requiredParams = ['kpi_id','kpi_title','earliest','latest'];
_.each(requiredParams, function (value, index) {
if (!_.isEmpty(queryParams[value])) {
newQueryParams[value] = queryParams[value];
}
});
serialize = function(obj) {
var str = [];
for(var p in obj)
if (obj.hasOwnProperty(p)) {
str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
}
return str.join("&");
}
searchString = serialize(newQueryParams);
}
return searchString;
},
/**
* Get Entity detail URL (To View Entity Health)
*
* @param {string} entity -- Current entity title for which user want to show Entity Health
* @returns {string} -- Entity Detail URL
*/
getEntityDetailUrl: function (entityTitle) {
// Try to get new entity details from entity search result
var entityDetails = _.first(_.where(entitySearchResult, {entity_title: entityTitle}));
if (_.isUndefined(entityDetails)) {
throw new Error("Failed to retrieve entity detail url because no such entity id in the kvstore.");
}
var searchString = '?';
if (!_.isEmpty(entityDetails['entity_key'])){
searchString += 'entity_key=' + entityDetails['entity_key'];
}
if (searchString === '?') {
throw new Error("Failed to retrieve entity detail url.");
}
var pathName = this.getCurrentLocationPathName();
var url = this.getCurrentLocationOrigin() + pathName.substr(0, pathName.lastIndexOf('/')) + '/entity_detail' + searchString;
return url;
},
///**
// * Create a search manager for itsi entity lookup.
// * It can be called from Drill Down view based on view related filters.
// *
// * @param {string} moduleSavedSearch -- module saved search for entity
// * @param {string} entityFilterPhrase -- additional filter phase for entity, for example, only entity types that are for drilldown links.
// * @returns {object} -- search manager
// */
createEntitySearchManager: function (moduleSavedSearch, entityFilterPhrase) {
return new SearchManager({
id: 'entity-id-search',
search: mvc.tokenSafe('| savedsearch ' + moduleSavedSearch + ' | lookup itsi_entities title as entity_title OUTPUT _key as entity_key, services._key as service_key | lookup alarm_console_lookup _key as service_key output title as service_title ' + entityFilterPhrase + ' | fields + entity_key,entity_title,service_key,service_title'),
'auto_cancel': 90,
'preview': true,
'wait': 0,
'runOnSubmit': true,
'cache': false
});
},
///**
// * Fetch entity information using passed search manager.
// * It is used to fill up global object "entitySearchResult" which will used in getOtherEntityDrilldownUrl to find clicked entity details from this object.
// * The search manager can be created using createEntitySearchManager, or directly from Drill Down view.
// * The result of search must include fields: entity_key,entity_title,service_key,service_title.
// *
// * @param {object} entityIdSearch -- search manager for entity.
// */
fetchEntityFromSearchManager: function (entityIdSearch) {
var entityIdSearchResults = entityIdSearch.data('results', {count: 0});
var that = this;
entityIdSearchResults.on('data', function() {
if (!_.isUndefined(entityIdSearchResults.data())){
entitySearchResult = that.searchResultsToDictionary(entityIdSearchResults.data().rows,
entityIdSearchResults.data().fields);
}
});
},
/**
* Add customization to table. Use the BaseCellRenderer class to create a custom table cell renderer
*
* @param {Object} link_configurations - configuration object to link table with other entity drill down or entity detail view
* One example:
* link_configurations = [{
"table_panel_id": "vmdstable_panel_vmdstable",
"table_columns": [{"column_name": "Datastore Id","link_type": "entity_view","entity_title_column":"Datastore Id"},
{"column_name": "Datastore Name","link_type": "drill_down","entity_title_column":"Datastore Id",
"view_name":"/DA-ITSI-VIRTUALIZATION-Datastore_Entity_View","fields_to_add": {"datastore_id": "Datastore Id","datastore_name": "Datastore Name"}}]
}];
*/
renderTableLinks: function (link_configurations) {
var that = this;
_.each(link_configurations, function (table_value, table_key) {
var table_panel_id = table_value['table_panel_id'];
var table_columns = table_value['table_columns'];
var link_table = [];
mvc.Components.get(table_panel_id).getVisualization(function(table) {
link_table[table_key] = table;
// Add link on table cell value
_.each(table_columns, function (value, key) {
var CustomCellRenderer = TableView.BaseCellRenderer.extend({
canRender: function(cellData) {
return cellData.field === value['column_name'];
},
// This render function only works when canRender returns 'true'
render: function($td, cellData) {
$td.html(that._linkTemplate({
name: cellData.value
}));
}
});
link_table[table_key].addCellRenderer(new CustomCellRenderer());
});
// Bind link when user click on value
_.each(table_columns, function (value, key) {
link_table[table_key].on("click:cell", function (e) {
var url = "";
if (e.key === value['column_name'] && value['link_type'] === "entity_view") {
e.preventDefault();
url = that.getEntityDetailUrl(e.data["row."+value['entity_title_column']+""]);
}
else if (e.key === value['column_name'] && value['link_type'] === "drill_down") {
e.preventDefault();
var fieldsToAdd = {};
_.each(value['fields_to_add'], function (field_value, field_key) {
fieldsToAdd[field_key] = e.data["row."+field_value+""];
});
url = that.getOtherEntityDrilldownUrl(e.data["row."+value['entity_title_column']+""], value['view_name'], fieldsToAdd);
}
that.redirectURL(url);
});
});
});
});
},
/**
* Convert Splunk search result rows into a dictionary
*
* @param {Array} rows
* @param {Array} fields
* @returns {Object}
*/
searchResultsToDictionary: function (rows, fields) {
var rowItems = {};
_.each(rows, function (row, index) {
var rowItem = {};
_.each(row, function (item, index) {
rowItem[fields[index]] = item;
});
rowItems[index] = rowItem;
});
return rowItems;
},
/**
* Redirect url if not empty
*
* @param {string} url to direct
*/
redirectURL: function (url) {
if (!_.isEmpty(url)) {
splunkjsUtils.redirect(url, true);
}
},
/**
* Get current window location pathname.
*
* @returns {string} -- current window location pathname.
*/
getCurrentLocationPathName: function () {
return window.location.pathname;
},
/**
* Get current window location origin.
*
* @returns {string} -- current window location origin.
*/
getCurrentLocationOrigin: function () {
return window.location.origin;
},
/**
* Get current window location search.
*
* @returns {string} -- current window location search string.
*/
getCurrentLocationSearch: function () {
return window.location.search;
},
_linkTemplate: _.template('<a class="external"><%- name %></a>')
};
return EntityDrilldownUtils;
});