htdocs/assets/js/views/alerts/alert.js
"use strict";
define(function(require) {
var _ = require('underscore'),
View = require('view'),
ModelView = require('views/model'),
NavbarView = require('views/navbar'),
ListView = require('views/list'),
CollectionView = require('views/collection'),
ActionsView = require('views/alerts/actions'),
Renderer = require('views/renderer'),
Templates = require('templates'),
Util = require('util'),
Alert = require('models/alert'),
AlertCollection = require('collections/alert'),
AlertLogCollection = require('collections/alertlog');
var AlertLogView = View.extend({
template: Templates['alerts/changelogentry'],
simple: false,
initialize: function(options) {
this.simple = options.simple;
this.listenTo(this.model, 'destroy', $.proxy(this.destroy, this));
},
_render: function() {
var model_data = this.model.toJSON();
var desc_parts = [];
var alert = this.App.Data.Alerts.get(this.model.get('alert_id'));
var search = this.App.Data.Searches.get(alert.get('search_id'));
var name = 'Unknown';
if(search) {
name = search.get('name');
}
var users = this.App.Data.Users;
var getName = function(user_id) {
if(user_id === 0) {
return 'System';
}
return Util.getAssigneeName(0, user_id, users);
};
var level = 'default';
switch(this.model.get('action')) {
case 1:
level = 'info';
desc_parts.push('Alert created');
break;
case 4:
level = 'danger';
desc_parts.push(getName(model_data.user_id));
desc_parts.push(['de-escalated', 'escalated'][model_data.a]);
break;
case 5:
level = 'default';
desc_parts.push(getName(model_data.user_id));
var assign = model_data.a !== 0 || model_data.b !== 0;
desc_parts.push(assign ? 'assigned':'unassigned');
if(assign) {
desc_parts.push('to');
desc_parts.push(Util.getAssigneeName(model_data.a, model_data.b, this.App.Data.Users, this.App.Data.Groups));
}
break;
case 6:
level = 'success';
desc_parts.push(getName(model_data.user_id));
desc_parts.push('marked');
desc_parts.push(Alert.Data().States[model_data.a]);
break;
case 7:
level = 'success';
desc_parts.push(getName(model_data.user_id));
desc_parts.push('added a note');
break;
}
var vars = {
alert_id: model_data.alert_id,
name: name,
simple: this.simple,
level: level,
description: desc_parts.join(' '),
note: model_data.note,
resolutions: Alert.Data().Resolutions,
create_date: model_data.create_date,
states: Alert.Data().States,
};
this.$el.html(this.template(vars));
},
selectAction: function(action) {
switch(action) {
case 'open': this.open(); break;
}
},
open: function() {
this.$('a')[0].click();
},
});
var AlertLogTableView = ListView.extend({
template: _.constant('<h1>Changelog</h1><div class="well well-sm col-xs-12 list"></div>'),
className: 'col-xs-12',
hiddenForm: true,
fold: false,
folded: false,
subView: AlertLogView,
initializeSubView: function(model) {
return ListView.prototype.initializeSubView.call(this, model, {simple: true});
}
});
var AlertNavbarView = NavbarView.extend({
title: 'Alert',
events: {
'click .search-button': 'gotoSearch',
'click .download-button': 'download',
},
sidelinks: [
{name: 'Go to Search', action: 'search', icon: 'link'},
{name: 'Download', action: 'download', icon: 'download-alt'}
],
_render: function() {
NavbarView.prototype._render.call(this);
this.App.registerSelectableKbdShortcut('d', 'delete', 'Delete the current item', false);
},
download: function() {
this.App.Bus.trigger('download');
},
gotoSearch: function() {
this.App.Router.navigate('/search/' + this.model.get('search_id'), {trigger: true});
}
});
var AlertFieldView = View.extend({
template: Templates['alerts/alertfield'],
tagName: 'tr',
key: null,
value: null,
temp: false,
events: {
'click .edit-button': 'toggleEdit',
'click .apply-button': 'apply',
'click .delete-button': 'delete',
'focus .content': 'copy',
},
initialize: function(options) {
this.key = options.key;
this.value = options.value;
this.temp = options.temp;
},
_render: function() {
this.$el.html(this.template({
key: this.key, value: this.value, temp: this.temp
}));
var elem = this.registerElement('.renderer-select');
Util.initRendererSelect(elem, Renderer.renderers);
var content_elem = this.registerElement('.content');
Util.autosize(content_elem);
content_elem.on('keydown', function(e) {
if(e.keyCode == 27) {
content_elem.blur();
}
});
// Unfocus the select so that hotkeys work.
var apply_button = this.$('.apply-button');
elem.on('select2-close', function() {
setTimeout(function() {
apply_button.focus();
}, 0);
});
},
selectAction: function(action) {
switch(action) {
case 'open': this.toggleEdit(); break;
case 'delete': this.delete(); break;
}
},
update: function(renderer_list, val) {
this.$('.view').html(val);
this.$('.renderer-select').select2('val', renderer_list);
},
delete: function() {
if(this.temp) {
this.destroy();
}
},
toggleEdit: function(focus_sel) {
var val_elem = this.$('.view');
var edit_elem = this.$('.edit');
var content_elem = this.$('.content');
var edit = edit_elem.hasClass('hidden');
val_elem.toggleClass('hidden', edit);
edit_elem.toggleClass('hidden', !edit);
if(edit) {
content_elem.val(this.value);
if(focus_sel) {
this.$('.renderer-select').select2('focus');
} else {
this.$('.content').focus();
}
}
},
apply: function() {
this.toggleEdit();
if(this.temp) {
this.value = this.$('.content').val();
}
this.processRenderers();
},
getRenderers: function() {
var val = this.$('.renderer-select').select2('val');
return val !== '' ? [val]:[];
},
processRenderers: function() {
var val = this.getRenderers();
this.trigger('update', this, val);
},
copy: function() {
if(!this.temp) {
this.trigger('copy', this);
this.toggleEdit(true);
}
}
});
/**
* The alert View
*/
var AlertView = ModelView.extend({
modelName: 'Alert',
modelClass: Alert,
modelUrl: '/alert/',
template: Templates['alerts/alert'],
_load: function(id) {
// Load dependencies and the single requested alert.
this.collection = new AlertLogCollection([], {id: id});
this.loadCollectionsAndModel(
[this.App.Data.Searches, this.App.Data.Users, this.App.Data.Groups, this.collection],
this.App.Data.Alerts, id
);
},
_render: function() {
this.App.setTitle('Alert: ' + this.model.get('id'));
this.registerView(new AlertNavbarView(this.App, {model: this.model}), true);
this.App.registerSelectableGroup(this);
var search = this.App.Data.Searches.get(this.model.get('search_id'));
var vars = this.model.toJSON();
_.extend(vars, {
search_id: search ? search.get('id'):0,
states: Alert.Data().States,
resolutions: Alert.Data().Resolutions,
name: search ? search.get('name'):'Unknown',
assignee_name: Util.getAssigneeName(
this.model.get('assignee_type'), this.model.get('assignee'),
this.App.Data.Users, this.App.Data.Groups
)
});
this.$el.append(this.template(vars));
var content = this.model.get('content');
var tbody = this.$('tbody');
for(var k in content) {
var fieldview = this.registerView(
new AlertFieldView(this.App, {key: k, value: content[k]}),
true, tbody, 'collection[]'
);
this.listenTo(fieldview, 'update', this.renderField);
this.listenTo(fieldview, 'copy', this.copyField);
}
this.registerView(new AlertLogTableView(this.App, {collection: this.collection}), true);
var view = this.registerView(new ActionsView(this.App), true, undefined, 'actions');
var user_id = this.App.Data.User.id;
var assignee_type = this.model.get('assignee_type');
var assignee = this.model.get('assignee');
var assignee_bit = assignee_type === 0 && assignee === user_id ? 2:
(assignee_type === 0 && assignee === 0 ? 0:1);
view.setData({
count: 1,
esc: 1 << this.model.get('escalated'),
assign: 1 << assignee_bit,
state: 1 << this.model.get('state'),
single: true
});
view.rerender();
Util.autosize(this.registerElement('textarea'));
var alert_renderers = this.model.get('renderer_data');
var search_renderers = search ? search.get('renderer_data'):null;
var renderers = !_.isEmpty(alert_renderers) ? alert_renderers:
!_.isEmpty(search_renderers) ? search_renderers:{};
if(!_.isEmpty(renderers)) {
var mapping = Renderer.deserialize(this.App, renderers, this.model.id, this.getView('collection[]'));
Renderer.process(this.App, mapping);
} else {
var mapping = {};
mapping[this.model.id] = this.getView('collection[]');
Renderer.autoProcess(this.App, mapping);
}
this.listenTo(this.App.Bus, 'download', this.downloadAlert);
this.registerActions();
this.App.hideLoader();
},
update: function() {
this.rerender();
},
renderField: function(view, renderers) {
this.App.showLoader();
var mapping = {};
mapping[this.model.id] = {};
mapping[this.model.id][view.key] = [view, renderers];
Renderer.process(this.App, mapping, $.proxy(this.App.hideLoader, this.App));
},
copyField: function(view) {
var num = (Math.random() * 1000) | 0;
var fieldview = this.registerView(
new AlertFieldView(this.App, {key: view.key + '_' + num, value: view.value, temp: true}),
false, undefined, 'collection[]'
);
view.$el.after(fieldview.el);
fieldview.load();
fieldview.update(view.getRenderers(), '');
fieldview.toggleEdit();
this.listenTo(fieldview, 'update', this.renderField);
this.listenTo(fieldview, 'copy', this.copyField);
},
processAction: function(action) {
var data = [this.model.get('id')];
var func = this[action];
if(_.isFunction(func)) {
func.call(this, data);
}
},
updateAlerts: function(action, data) {
this.App.showLoader();
return AlertCollection.action(action, data, {
success: this.cbRendered(function(resp) {
this.App.addMessage('Alert update successful', 2);
delete data.id;
this.model.set(data);
this.update();
}),
complete: $.proxy(this.App.hideLoader, this.App)
});
},
downloadAlert: function() {
var data = JSON.stringify(this.model);
Util.download(data, 'alert_' + this.model.id + '.json');
},
saverenderers: function() {
this.App.showLoader();
var search = this.App.Data.Searches.get(this.model.get('search_id'));
var out_mapping = _.extend({}, search.get('renderer_data'), Renderer.serialize(this.getView('collection[]')));
var data = {
renderer_data: out_mapping,
change_description: 'Modify renderer mapping'
};
search.save(data, {
success: this.cbRendered(function(r) {
this.App.addMessage('Search update successful', 2);
}),
complete: $.proxy(this.App.hideLoader, this.App)
});
}
}, {
AlertLogView: AlertLogView
});
_.extend(AlertView.prototype, ActionsView.ActionsMixin, CollectionView.SelectionMixin, {
setSelectableDisplay: function(sel, selected, down) {
$(sel.el).toggleClass('active', selected);
},
});
return AlertView;
});