@ -0,0 +1,59 @@
|
||||
MS Windows AD Objects = 4.1.1
|
||||
- Release Notes:
|
||||
- Fixed Dashboards:
|
||||
- Fixed several css's for Dashboards, including getting started wizard
|
||||
- Removed hardcoded content from AD Object - Group Changes
|
||||
- New Features:
|
||||
- Multi-Domain - Splitting Lookups:
|
||||
- Added the capability to split out AD_Obj_(User/Group/Computer) lookups into separate lookups for domains.
|
||||
- This will help with the issue where large, mult-domain, environments were having issues with KV Store Lookup sizing.
|
||||
- With this capability, the sizes of the Lookups will be greatly reduced.
|
||||
- Use the dashboard "AD Objects - CFG - Split KVs" dashboard in the Configuration Dashboards - Advance Configuration menu
|
||||
- NOTE: This configuration does require some manual steps, which is outlined in the "AD Objects - CFG - Split KVs" dashboard.
|
||||
- Important Note: In order to provide this support, updated macros had to be created to replace previous ones, for building lookups and correlation searches. Also, there is now a Domain Dropdown that will need to be selected first in most of the dashboards.
|
||||
- Added multiple Reports for analyzing collected Registry Data.
|
||||
- Updated css styling, to establish a common look and feel with the dashboards.
|
||||
- Updated several of the lookups multivalue columns, to speed up searches and take advantage of KV Store's multivalue searching capabilities.
|
||||
- Multiple other fixes to dashboards, reports and field extractions based off of customer feedback.
|
||||
Required TA: Splunk Add-On for Microsoft Windows version 4+
|
||||
Configuration:
|
||||
Required: For first time installation and upgrading from version 3.x and below
|
||||
- You will need to first walk through the "Configuration - Getting Data In" dashboard located in "MS Windows AD Objects --> Configuration --> Configuration - Getting Data In".
|
||||
Optional: If you are upgrading from version 4.0.3, you do not need to run through the Getting Started dashboard wizard.
|
||||
|
||||
Configuration - Getting Data dashboard wizard Overview:
|
||||
- This dashboard will walk you through the process for installation, enabling data inputs, configuration and the required
|
||||
building of the AD Objects Lookup Tables. The specific steps for your environment are determined by the selections you
|
||||
make in the second task of the wizard "Scope Definition".
|
||||
- Below are the different tasks that are covered in this initial configuration wizard:
|
||||
- This Guide is specifically designed to help you not only configure the MS Windows Application,
|
||||
but also to help quickly get your Windows and Active Directory data in to Splunk.
|
||||
- To aligned the configuration steps to your Splunk Environment and Deplyoment needs,
|
||||
the 1. Scope Definition will collect some basic information about your environment and deployment plans.
|
||||
- How to use this Guide
|
||||
- Each Section Step of this guide builds on the previous Part, verify each of the previous steps or requirements
|
||||
have been completed before proceeding to the next Part.
|
||||
- Goals for the Guide
|
||||
- At the end, you will have your Windows/Active Directory data flowing into Splunk, have the MS Windows AD Objects
|
||||
application configured and well on your way to start leveraging the power of Splunk.
|
||||
Guide Part Descriptions
|
||||
- Section Step 1: Scope Definition
|
||||
- Required: This step is used to align the subsequent steps with your environment and deployment plans.
|
||||
- Section Step 2: Preparation
|
||||
- Provides the preparation steps for the Splunk Core components, MS Windows AD Objects and TA Configuration are ready to receive the Windows data and deployment.
|
||||
- Section Step 3: Deployment
|
||||
- Covers the steps for distributing the previously configured Splunk Technical Add-Ons to the target Windows Systems.
|
||||
- Section Step 4: Check Data
|
||||
- This section provides you a way of verifying, and if necessary troubleshooting, previous configuration steps.
|
||||
- Section Step 5: Build Lookups
|
||||
- This last section walks through the the final step of building the MS Windows AD Object's lookup tables.
|
||||
|
||||
MS Windows AD Objects = 4.0.3
|
||||
- Release Notes:
|
||||
- Fixed the dn_path field extractions that is now required to be embedded in the searches/macros, since the ActiveDirectory sourcetype is a pre-trained sourcetype it cannot be done in the props/transforms.
|
||||
- Added a lookup field that can be leveraged for filtering the lookup data. AD_Obj_User (lookup_usr), AD_Obj_Group (lookup_grp), AD_Obj_Computer (lookup_cmp) and AD_Obj_OU (lookup_ou)
|
||||
- This way you can lookup a user/group/computer/ou details using the | lookup AD_Obj_... lookup_... AS ... search. So if an event has the distinguishedName or cn or sAMAccountName then it will match the lookup_... values
|
||||
- Update the wineventlog props to put the user, and distinguishedName fields in lowercase for linking with the kvstore.
|
||||
- Update the File Auditing Dashboards and Added in a couple reports.
|
||||
- Update the searches to use the new field lookup_... vs having to run multiple lookups.
|
||||
- Fixed Windows Eventlog fields extractions and EVAL's in props.conf for user_obj_...,group_obj_...,computer_obj_... and member_obj_... fields,
|
||||
@ -0,0 +1,38 @@
|
||||
{
|
||||
"schemaVersion": "1.0.0",
|
||||
"info": {
|
||||
"title": "MS Windows AD Objects",
|
||||
"id": {
|
||||
"group": null,
|
||||
"name": "ms_windows_ad_objects",
|
||||
"version": "4.1.1"
|
||||
},
|
||||
"author": [
|
||||
{
|
||||
"name": "Steve Hogan",
|
||||
"email": "shogan@splunk.com",
|
||||
"company": "Splunk, Inc."
|
||||
}
|
||||
],
|
||||
"releaseDate": null,
|
||||
"description": "Splunk Application to build and update AD Object Lookup Files using admon data collected from Splunk Universal Forwarders on a domain controller in the Active Directory environment.",
|
||||
"classification": {
|
||||
"intendedAudience": "IT",
|
||||
"categories": [
|
||||
"IT Operations",
|
||||
"Utilities",
|
||||
"Security, Fraud & Compliance"
|
||||
],
|
||||
"developmentStatus": "Production/Stable"
|
||||
},
|
||||
"commonInformationModels": null,
|
||||
"releaseNotes": {
|
||||
"name": "README",
|
||||
"text": "README.txt",
|
||||
"uri": "https://splunkbase.splunk.com/app/3177/#/details"
|
||||
}
|
||||
},
|
||||
"dependencies": null,
|
||||
"supportedDeployments": ["_standalone", "_distributed", "_search_head_clustering"],
|
||||
"targetWorkloads": ["_search_heads"]
|
||||
}
|
||||
|
After Width: | Height: | Size: 314 KiB |
|
After Width: | Height: | Size: 141 KiB |
@ -0,0 +1,23 @@
|
||||
require.config({
|
||||
paths: {
|
||||
"common": "../app/ms_windows_ad_objects/js/common",
|
||||
"ms_windows_ad_objects": "../app/ms_windows_ad_objects/js/ms_windows_ad_objects",
|
||||
},
|
||||
});
|
||||
require([
|
||||
'underscore',
|
||||
'jquery',
|
||||
'splunkjs/mvc/utils',
|
||||
'splunkjs/mvc',
|
||||
"splunkjs/mvc/utils",
|
||||
'ms_windows_ad_objects/components/ms_ad_obj_ldaprecordview',
|
||||
"splunkjs/mvc/searchmanager",
|
||||
'splunkjs/mvc/simplexml/ready!'
|
||||
], function(_, $, utils, mvc, utils, LDAPRecordView, SearchManager) {
|
||||
|
||||
var report = new LDAPRecordView({
|
||||
"id": "audit_report",
|
||||
"managerid": "audit_query",
|
||||
"el": $("#audit_report")
|
||||
}).render();
|
||||
});
|
||||
|
After Width: | Height: | Size: 137 KiB |
|
After Width: | Height: | Size: 268 KiB |
|
After Width: | Height: | Size: 44 KiB |
|
After Width: | Height: | Size: 40 KiB |
@ -0,0 +1,69 @@
|
||||
define([
|
||||
'underscore',
|
||||
'backbone',
|
||||
'jquery',
|
||||
'splunkjs/mvc',
|
||||
'splunkjs/mvc/simplexml/element/table'
|
||||
], function(_, Backbone, $, mvc, TableElement) {
|
||||
var ms_ad_obj_modal_template = "<div id=\"pivotModal\" class=\"modal prev_ms_ad_obj_modal\">" +
|
||||
"<div class=\"modal-header\"><h3 style=\"text-align:center;margin-bottom:0px !important;margin-top:0px !important;padding-bottom:2px !important;padding-top:0px !important;\"><i class=\"icon-mail\" style=\"height:20px;padding-right:3px;\"/><%- title %></h3><button class=\"close\">Close</button>" +
|
||||
"</div><h4 style=\"text-align:center;\"><center><div id=\"prev_ms_ad_obj_modal_hdr_box\" style=\"text-align:center;width:95%;background-color: #F2F4F5;border: 3px solid #49B849;padding: 2px;margin: 2px;\">" +
|
||||
"<div id=\"prev_ms_ad_obj_modal_hdr_subject\" style=\"text-align:left;width:90%:background-color: #F2F4F5;border: 1px solid black;padding-left: 5px;margin: 2px;\"><b>Subject:</b> <%- prev_ms_ad_obj_modal_subject %></div></div></center></h4>" +
|
||||
"<div class=\"modal-body\"><h4 style=\"text-align:left;margin-bottom:0px !important;margin-top:0px !important;padding-bottom:2px !important;padding-top:0px !important;\"><b><i>Message Content:</i></b></h4><div class=\"prev_ms_ad_obj_modal_msg_table\"></div></div>" +
|
||||
"<div class=\"modal-footer\">" +
|
||||
"<center><button class=\"btn btn-primary close\"><i class=\"icon-x-circle\" style=\"height:15px;padding-right:3px;\"/>Close</button></center>" +
|
||||
"</div>" +
|
||||
"</div>" +
|
||||
"<div class=\"modal-backdrop\"></div>";
|
||||
var ms_ad_obj_modal_template_o = "<div id=\"pivotModal\" class=\"modal prev_ms_ad_obj_modal\">" +
|
||||
"<%- t_inner_html %>" +
|
||||
"</div>" +
|
||||
"<div class=\"modal-backdrop\"></div>";
|
||||
var submittedTokens = mvc.Components.get('submitted');
|
||||
var defaultTokens = mvc.Components.get('default');
|
||||
var url_em_body_msg= ""
|
||||
var ms_ad_obj_modal_preview = Backbone.View.extend({
|
||||
defaults: {
|
||||
title: 'Not set'
|
||||
},
|
||||
initialize: function(options) {
|
||||
this.options = options;
|
||||
this.options = _.extend({}, this.defaults, this.options);
|
||||
this.childViews = [];
|
||||
this.template = _.template(ms_ad_obj_modal_template_o);
|
||||
},
|
||||
events: {
|
||||
'click .close': 'close',
|
||||
'click .close_btn': 'close',
|
||||
'click .modal-backdrop': 'close'
|
||||
},
|
||||
render: function() {
|
||||
var data = { title : this.options.t_title,t_inner_html : this.options.t_inner_p_html};
|
||||
var msg_p="<div id=\"" + this.options.t_title + "_modal\" class=\"modal prev_ms_ad_obj_modal\">" + this.options.t_inner_p_html + "</div><div class=\"modal-backdrop\"></div>"
|
||||
this.$el.html(msg_p);
|
||||
return this;
|
||||
},
|
||||
show: function() {
|
||||
$(document.body).append(this.render().el);
|
||||
//width:'80%',
|
||||
$(this.el).find('.prev_ms_ad_obj_modal').css({
|
||||
'max-width': '90%',
|
||||
width:'70%',
|
||||
height:'auto',
|
||||
left: '15%',
|
||||
'margin-left': '0',
|
||||
'max-height':'90%',
|
||||
overflow: 'none'
|
||||
});
|
||||
},
|
||||
close: function() {
|
||||
this.unbind();
|
||||
this.remove();
|
||||
_.each(this.childViews, function(childView) {
|
||||
childView.unbind();
|
||||
childView.remove();
|
||||
});
|
||||
}
|
||||
});
|
||||
return ms_ad_obj_modal_preview;
|
||||
});
|
||||
@ -0,0 +1,10 @@
|
||||
require.config({
|
||||
paths: {
|
||||
"app": "../app"
|
||||
}
|
||||
});
|
||||
require(['splunkjs/mvc/simplexml/ready!'], function(){
|
||||
require(['splunkjs/ready!'], function(){
|
||||
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,14 @@
|
||||
.app-bar.shared-appbar .nav-pills>li>a{
|
||||
color: black;
|
||||
}
|
||||
|
||||
.btn_build {
|
||||
background-color: #4CAF50; /* Green */
|
||||
border: 2px solid #555555; /* Green */
|
||||
color: white;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.btn_build:hover {
|
||||
box-shadow: 0 12px 16px 0 rgba(0,0,0,0.24), 0 17px 50px 0 rgba(0,0,0,0.19);
|
||||
}
|
||||
@ -0,0 +1,155 @@
|
||||
(function() {
|
||||
require([
|
||||
'underscore',
|
||||
'backbone',
|
||||
'splunkjs/mvc',
|
||||
'../app/ms_windows_ad_objects/components/ms_ad_obj_modal/ms_ad_obj_modal_popup',
|
||||
'splunkjs/mvc/simplexml/ready!'
|
||||
], function(_, Backbone, mvc, ms_ad_obj_modal_preview) {
|
||||
$(document).ready(function () {
|
||||
function setToken(name, value) {
|
||||
var defaultTokenModel = mvc.Components.get('default');
|
||||
if (defaultTokenModel) {
|
||||
defaultTokenModel.set(name, value);
|
||||
}
|
||||
var submittedTokenModel = mvc.Components.get('submitted');
|
||||
if (submittedTokenModel) {
|
||||
submittedTokenModel.set(name, value);
|
||||
}
|
||||
}
|
||||
var defaultTokenModel = mvc.Components.get("default");
|
||||
var submittedTokenModel = mvc.Components.get("submitted");
|
||||
defaultTokenModel.on("change:set_dyn_object_embed_val", function(e) {
|
||||
//Hide the html content whenever a new one is selected //
|
||||
$("#content_obj").hide();
|
||||
$("#content_obj_title").hide();
|
||||
$("#dyn_pan_content_obj").hide();
|
||||
//Get the updated tokens for the object content
|
||||
var object_set_val = defaultTokenModel.get("set_dyn_object_embed_val");
|
||||
var object_show_flag = defaultTokenModel.get("tok_show_object_flag");
|
||||
//If token (tok_show_object_flag) is True then add the html object to the #content_obj html id Otherwise show default if used
|
||||
if(object_show_flag==="True") {
|
||||
setToken("tok_object_src", object_set_val)
|
||||
var addDObjView = '<object id="dyn_pan_content_obj" width="95%" height="640px" data="' + object_set_val + '" border="1" frameborder="2" style="display: inline;overflow:scroll;min-height:600px;"></object>'+
|
||||
'<h4 style="text-align:center;"><b><i><a href="' + object_set_val + '" target="_blank"><i class="icon-external" style="padding-left:5px;"/>Click Here</a> to open video or document in a seperate browser window.</i></b></h4>'
|
||||
$("#content_obj").html(addDObjView)
|
||||
$("#main_content_obj").show();
|
||||
$("#content_obj").show();
|
||||
$("#content_obj_title").show();
|
||||
$("#dyn_pan_content_obj").show();
|
||||
} else {
|
||||
setToken("tok_show_object_flag", undefined);
|
||||
setToken("tok_show_obj_default", "True");
|
||||
};
|
||||
});
|
||||
$('.dashboard-body').on("click", '[data-t-mod-id]', function (ms_ad_obj_modal_pop) {
|
||||
var target = $(ms_ad_obj_modal_pop.currentTarget);
|
||||
t_modal = target.data('t-mod-id');
|
||||
var t_m_obj=document.getElementById(t_modal);
|
||||
var t_obj_i_html=t_m_obj.innerHTML
|
||||
var prev_ms_ad_obj_modal = new ms_ad_obj_modal_preview({ t_title: t_modal,t_inner_p_html: t_obj_i_html});
|
||||
prev_ms_ad_obj_modal.show();
|
||||
});
|
||||
var defaultTokenModel = mvc.Components.get("default");
|
||||
var submittedTokenModel = mvc.Components.get("submitted");
|
||||
var items_icon_array = defaultTokenModel.get("tok_dash_mod_icons");
|
||||
if(items_icon_array) {
|
||||
var items_icon_array_set = items_icon_array.split(",");
|
||||
for(var i = 0; i <= items_icon_array_set.length; i++) {
|
||||
var item_src = items_icon_array_set[i]
|
||||
|
||||
if(item_src !== undefined,item_src){
|
||||
console.log("item_src",item_src)
|
||||
var item_src_array = item_src.split(":")
|
||||
var mod_trigger_m_id = item_src_array[0];
|
||||
var mod_trigger_h_id = '#'+mod_trigger_m_id
|
||||
var mod_trigger_icon = item_src_array[1];
|
||||
var mod_link_label = '#'+mod_trigger_h_id + ' label:first-child'
|
||||
var w_mod_input_trigger = '<i class="icon-'+mod_trigger_icon+' ms-obj-mod-icon" data-t-mod-id="'+mod_trigger_m_id+'_pop"/>'
|
||||
$(mod_trigger_h_id).find("label:first-child").prepend(w_mod_input_trigger)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$('.dashboard-body').on("click", '[data-ms-ad-obj-obj-type],[data-ms-ad-obj-obj-used],[data-ms-ad-obj-obj-title],[data-ms-ad-obj-obj-src],[data-ms-ad-obj-obj-refresh]', function (ms_ad_obj_obj_set) {
|
||||
var target = $(ms_ad_obj_obj_set.currentTarget);
|
||||
var object_used = target.data('ms-ad-obj-obj-used');
|
||||
var object_type = target.data('ms-ad-obj-obj-type');
|
||||
var object_h_id = "#content_"+object_type
|
||||
var object_h_dyn_id = "#content_dyn_"+object_type
|
||||
var object_title = target.data('ms-ad-obj-obj-title');
|
||||
var object_src = target.data('ms-ad-obj-obj-src');
|
||||
var object_refresh = target.data('ms-ad-obj-obj-refresh');
|
||||
$("#content_f_object").hide();
|
||||
$("#content_dyn_f_object").hide();
|
||||
$("#content_dyn_f_title").hide();
|
||||
$("#content_vid_object").hide();
|
||||
$("#content_view_object").hide();
|
||||
$("#content_srch_object").hide();
|
||||
$("#content_dash_object").hide();
|
||||
$("#content_rpt_object").hide();
|
||||
$(object_h_id).show()
|
||||
$(object_h_dyn_id).attr("src",object_src);
|
||||
$(object_h_dyn_id).show()
|
||||
var object_w_title='<h1 id="content_dyn_f_title" style="text-align:center;font-family:proxima_nova;padding:5px 10px 5px 10px;box-sizing: border-box !important;box-shadow: 1px 1px 7px -1px rgb(198,211,222,1) !important;box-sizing: border-box;display: block;margin: 5px 10px 5px 10px;"><b><i>'+object_title+'</i></b></h1>'
|
||||
if(object_used==="True") {
|
||||
$("#pan_right_f").show();
|
||||
$("#h_r_f_object").show();
|
||||
if(object_title==="none"){
|
||||
$("#content_dyn_f_title").hide();
|
||||
} else {
|
||||
$("#content_dyn_f_title").show();
|
||||
}
|
||||
$("#pan_right_p_o").hide();
|
||||
} else {
|
||||
//Hide the html content whenever a new one is selected //
|
||||
if(object_type==="Hide_Object_Show_Page"){
|
||||
$("#pan_right_p_o").show();
|
||||
$("#h_r_n_page").show();
|
||||
$("#h_r_n_page .panel-body.html").show();
|
||||
$("#pan_right_f").hide();
|
||||
$("#h_r_f_object").hide();
|
||||
} else {
|
||||
$("#pan_right_p_o").hide();
|
||||
$("#h_r_n_page").hide();
|
||||
$("#h_r_n_page .panel-body.html").hide();
|
||||
$("#pan_right_f").hide();
|
||||
$("#h_r_f_object").hide();
|
||||
}
|
||||
};
|
||||
});
|
||||
$('.dashboard-body').on('click', '[data-set-token],[data-unset-token],[data-token-json]', function(e) {
|
||||
e.preventDefault();
|
||||
var target = $(e.currentTarget);
|
||||
var setTokenName = target.data('set-token');
|
||||
if (setTokenName) {
|
||||
setToken(setTokenName, target.data('value'));
|
||||
}
|
||||
var unsetTokenName = target.data('unset-token');
|
||||
if (unsetTokenName) {
|
||||
setToken(unsetTokenName, undefined);
|
||||
}
|
||||
var tokenJson = target.data('token-json');
|
||||
if (tokenJson) {
|
||||
try {
|
||||
if (_.isObject(tokenJson)) {
|
||||
_(tokenJson).each(function(value, key) {
|
||||
if (value == null ) {
|
||||
// Unset the token
|
||||
setToken(key, undefined);
|
||||
} else if (value =='undefined') {
|
||||
setToken(key, undefined);
|
||||
} else {
|
||||
setToken(key, value);
|
||||
}
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
console.warn('Cannot parse token JSON: ', e);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}).call(this);
|
||||
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 973 B |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 854 B |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 3.7 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 854 B |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 3.8 KiB |
|
After Width: | Height: | Size: 7.2 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 24 KiB |
|
After Width: | Height: | Size: 346 B |
|
After Width: | Height: | Size: 216 B |
|
After Width: | Height: | Size: 347 B |
|
After Width: | Height: | Size: 353 B |
|
After Width: | Height: | Size: 37 KiB |
|
After Width: | Height: | Size: 102 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 45 KiB |
|
After Width: | Height: | Size: 65 KiB |
|
After Width: | Height: | Size: 34 KiB |
|
After Width: | Height: | Size: 160 KiB |
|
After Width: | Height: | Size: 50 KiB |
|
After Width: | Height: | Size: 110 KiB |
|
After Width: | Height: | Size: 52 KiB |
|
After Width: | Height: | Size: 93 KiB |
|
After Width: | Height: | Size: 46 KiB |
|
After Width: | Height: | Size: 92 KiB |
|
After Width: | Height: | Size: 38 KiB |
|
After Width: | Height: | Size: 55 KiB |
|
After Width: | Height: | Size: 35 KiB |
|
After Width: | Height: | Size: 43 KiB |
|
After Width: | Height: | Size: 134 KiB |
|
After Width: | Height: | Size: 590 KiB |
|
After Width: | Height: | Size: 88 KiB |
|
After Width: | Height: | Size: 28 KiB |
|
After Width: | Height: | Size: 54 KiB |
|
After Width: | Height: | Size: 54 KiB |
|
After Width: | Height: | Size: 43 KiB |
|
After Width: | Height: | Size: 58 KiB |
|
After Width: | Height: | Size: 71 KiB |
|
After Width: | Height: | Size: 64 KiB |
|
After Width: | Height: | Size: 54 KiB |
|
After Width: | Height: | Size: 47 KiB |
|
After Width: | Height: | Size: 60 KiB |
|
After Width: | Height: | Size: 60 KiB |
|
After Width: | Height: | Size: 45 KiB |
|
After Width: | Height: | Size: 59 KiB |
|
After Width: | Height: | Size: 78 KiB |
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Class is an abstraction to define classes and inheritance based on the
|
||||
* classes. It is a lightweight prototype chaining based inheritance abstraction.
|
||||
*
|
||||
* It is highly recommended to keep this implementation as simple as possible
|
||||
* and only use classes in our apps when there is a demand for it. In regular
|
||||
* cases use the conventional JS methodology. Examples for necessary conditions
|
||||
* for using classes are: UnitTestBase class that all unit tests could extend from,
|
||||
* generic classes like SyncTaskRunner that are implementation that may be extended
|
||||
* for specific implementations in different scenarios, when multiple instances of an
|
||||
* are to be created for a use case like two SyncTaskQueues.
|
||||
*/
|
||||
|
||||
define(function() {
|
||||
var Class = {
|
||||
makeClass: function(classFn) {
|
||||
return classFn.prototype;
|
||||
},
|
||||
|
||||
makeInheritedClass: function(baseClass, subClassFn) {
|
||||
subClassFn.prototype = new baseClass();
|
||||
subClassFn.prototype.constructor = subClassFn;
|
||||
|
||||
return subClassFn.prototype;
|
||||
}
|
||||
};
|
||||
|
||||
return Class;
|
||||
});
|
||||
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* The PageMessagesView is a wrapper to display errors on a page
|
||||
*/
|
||||
|
||||
define([
|
||||
'jquery',
|
||||
'underscore',
|
||||
'common/Class'
|
||||
],
|
||||
function(
|
||||
$,
|
||||
_,
|
||||
Class
|
||||
) {
|
||||
|
||||
var PageMessagesView = function(pageSel) {
|
||||
this._pageSel = pageSel;
|
||||
this._messagesPaneSel = this._pageSel + ' #page-messages-view';
|
||||
};
|
||||
|
||||
var PageMessagesViewClass = Class.makeClass(PageMessagesView);
|
||||
|
||||
PageMessagesViewClass.addMessage = function(message, messageType, messageId) {
|
||||
if (!$(this._messagesPaneSel).length) {
|
||||
$(this._pageSel).prepend(' \
|
||||
<div id="page-messages-view"> \
|
||||
</div>'
|
||||
);
|
||||
}
|
||||
|
||||
$(this._messagesPaneSel).show();
|
||||
|
||||
if (_.isUndefined(messageType) || _.isNull(messageType)) {
|
||||
messageType = PageMessagesViewClass.InfoMessageType;
|
||||
}
|
||||
|
||||
var messageIdPart = !_.isUndefined(messageId) && !_.isNull(messageId) ?
|
||||
'id="' + messageId + '"' : '';
|
||||
|
||||
$(this._messagesPaneSel).append(' \
|
||||
<div class="alert ' + messageType + ' page-message" ' + messageIdPart +
|
||||
' style="border-color: #a62f2f; border-style: solid; border-width: 1px;"> \
|
||||
<i class="icon-alert" style="font-size: 24px; padding-left: 5px"> </i> \
|
||||
<p>' + message + '</p> \
|
||||
</div>'
|
||||
);
|
||||
return this;
|
||||
};
|
||||
|
||||
PageMessagesViewClass.clearMessage = function(messageId) {
|
||||
$(this._messagesPaneSel).find('#' + messageId).remove();
|
||||
return this;
|
||||
};
|
||||
|
||||
PageMessagesViewClass.clearAllMessages = function() {
|
||||
$(this._messagesPaneSel).hide();
|
||||
$(this._messagesPaneSel).empty();
|
||||
return this;
|
||||
};
|
||||
|
||||
PageMessagesViewClass.InfoMessageType = 'alert-info';
|
||||
PageMessagesViewClass.WarningMessageType = 'alert-warning';
|
||||
PageMessagesViewClass.ErrorMessageType = 'alert-error';
|
||||
|
||||
return PageMessagesView;
|
||||
});
|
||||
@ -0,0 +1,67 @@
|
||||
/*
|
||||
* This file implements a property bag that could be serialized for use at search
|
||||
* time to construct a string representation of 'N' fields to extract and perform
|
||||
* post search deserialization
|
||||
*/
|
||||
|
||||
define(['jquery', 'underscore', 'common/Class'], function($, _, Class) {
|
||||
|
||||
var PropertyBag = function(searchFieldNames) {
|
||||
if (_.isUndefined(searchFieldNames) ||
|
||||
_.isNull(searchFieldNames) ||
|
||||
!_.isArray(searchFieldNames)) {
|
||||
throw('Invalid search fields list passed to PropertyBag');
|
||||
}
|
||||
|
||||
// The names used here are passed into the search term in
|
||||
// serializeSearchPhrase, so they must be the field names from search
|
||||
this._propertyNames = searchFieldNames;
|
||||
|
||||
this._separator = '|';
|
||||
}
|
||||
|
||||
var PropertyBagClass = Class.makeClass(PropertyBag);
|
||||
|
||||
PropertyBagClass.serializeToSearchPhrase = function() {
|
||||
var that = this;
|
||||
|
||||
// Serialize to format: prop1 . "|" . prop2 . "|" . prop3
|
||||
// The resulting search phrase could be used in a search command like
|
||||
// eval as is to create the string representation of the concatenated fields
|
||||
var searchPhrase = _.reduce(
|
||||
this._propertyNames,
|
||||
function(propertyName1, propertyName2) {
|
||||
return propertyName1 + ' . "' + that._separator + '" . ' + propertyName2;
|
||||
}
|
||||
);
|
||||
|
||||
return searchPhrase;
|
||||
}
|
||||
|
||||
PropertyBagClass.deserialize = function(propertyValuesString) {
|
||||
var that = this;
|
||||
|
||||
if (_.isUndefined(propertyValuesString) || _.isNull(propertyValuesString)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var propertyValues = propertyValuesString.split(this._separator);
|
||||
|
||||
if (_.isArray(propertyValues) &&
|
||||
propertyValues.length == this._propertyNames.length) {
|
||||
var propertyValuesDict = {};
|
||||
|
||||
_.each(propertyValues, function(propertyValue, index) {
|
||||
propertyValuesDict[that._propertyNames[index]] = propertyValue;
|
||||
});
|
||||
|
||||
return propertyValuesDict;
|
||||
} else {
|
||||
// Since inputs here come from search results, don't throw errors,
|
||||
// just return null
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return PropertyBag;
|
||||
});
|
||||
@ -0,0 +1,86 @@
|
||||
/*
|
||||
* This file contains helper methods that could be used in the app pages
|
||||
* to manipulate data returned from searches
|
||||
*/
|
||||
|
||||
define(['jquery', 'underscore'], function($, _) {
|
||||
var SearchDataHelpers = {
|
||||
|
||||
/*
|
||||
* Given a map of fields to html selectors (in fieldsToElSelsMap), search fields
|
||||
* returned from running a search (in searchFields), a row returned in the result
|
||||
* set of a search (in searchRow) and a html renderer function (in elRenderer) that
|
||||
* does specific action to convert result from the search to the html selector
|
||||
* specified element, this function extracts the values for the fields from the
|
||||
* row and invokes the renderer resulting in the values from a search row
|
||||
* being populated to different html elements
|
||||
*/
|
||||
populateSearchBasedFields: function(fieldsToElSelsMap, searchFields, searchRow, elRenderer) {
|
||||
_.each(searchFields, function(fieldName, index) {
|
||||
var elSel = fieldsToElSelsMap[fieldName];
|
||||
if (!_.isUndefined(elSel) && !_.isNull(elSel)) {
|
||||
elRenderer(elSel, searchRow[index]);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/*
|
||||
* This is a specialization of populateSearchBasedFields to specifically
|
||||
* extract and display search results as sparklines in the html elements
|
||||
*/
|
||||
populateSearchBasedSparklineFields: function(fieldsToSparklineSelsMap, searchFields, searchRow, sparklineSettings) {
|
||||
this.populateSearchBasedFields(
|
||||
fieldsToSparklineSelsMap,
|
||||
searchFields,
|
||||
searchRow,
|
||||
function(sparklineSel, sparklineData) {
|
||||
$(sparklineSel).empty();
|
||||
|
||||
var sparks = _.isArray(sparklineData) ?
|
||||
_.map(sparklineData.slice(1), function(value) {
|
||||
return (value && parseFloat(value)) || 0;
|
||||
}) : [];
|
||||
|
||||
$(sparklineSel).sparkline(
|
||||
sparks,
|
||||
sparklineSettings
|
||||
);
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
/*
|
||||
* This is a specialization of populateSearchBasedFields to specifically
|
||||
* extract and display search results as texts in the html elements
|
||||
*/
|
||||
populateSearchBasedTextFields: function(fieldsToTextSelsMap, searchFields, searchRow) {
|
||||
this.populateSearchBasedFields(
|
||||
fieldsToTextSelsMap,
|
||||
searchFields,
|
||||
searchRow,
|
||||
function(textSel, textValue) {
|
||||
$(textSel).text(textValue);
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
makeDisplayNameFromResultField: function(resultFieldName) {
|
||||
// Convert all _ in field name to spaces
|
||||
// Capitalize first character of each word part
|
||||
var nameParts = resultFieldName.replace('_', ' ').split(' ');
|
||||
|
||||
var displayNameParts = _.map(nameParts, function(namePart) {
|
||||
if (/^[a-z]/.test(namePart)) {
|
||||
var firstChar = namePart[0].toUpperCase();
|
||||
return firstChar + namePart.substr(1);
|
||||
} else {
|
||||
return namePart;
|
||||
}
|
||||
});
|
||||
|
||||
return displayNameParts.join(' ');
|
||||
}
|
||||
}
|
||||
|
||||
return SearchDataHelpers;
|
||||
});
|
||||