mirror of
https://github.com/bluxmit/alnoda-workspaces.git
synced 2024-06-24 01:01:06 +12:00
427 lines
14 KiB
JavaScript
Executable file
427 lines
14 KiB
JavaScript
Executable file
Class.subclass( Page, "Page.Base", {
|
|
|
|
graph_colors: ["0,0,255", "138,43,226", "0,128,0", "255,20,147", "0,191,255", "210,105,30", "100,149,237", "220,20,60", "0,139,139", "128,128,128"],
|
|
|
|
requireLogin: function(args) {
|
|
// user must be logged into to continue
|
|
var self = this;
|
|
|
|
if (!app.user) {
|
|
// require login
|
|
app.navAfterLogin = this.ID;
|
|
if (args && num_keys(args)) app.navAfterLogin += compose_query_string(args);
|
|
|
|
this.div.hide();
|
|
|
|
var session_id = app.getPref('session_id') || '';
|
|
if (session_id) {
|
|
Debug.trace("User has cookie, recovering session: " + session_id);
|
|
|
|
app.api.post( 'user/resume_session', {
|
|
session_id: session_id
|
|
},
|
|
function(resp) {
|
|
if (resp.user) {
|
|
Debug.trace("User Session Resume: " + resp.username + ": " + resp.session_id);
|
|
app.hideProgress();
|
|
app.doUserLogin( resp );
|
|
Nav.refresh();
|
|
}
|
|
else {
|
|
Debug.trace("User cookie is invalid, redirecting to login page");
|
|
// Nav.go('Login');
|
|
self.setPref('session_id', '');
|
|
self.requireLogin(args);
|
|
}
|
|
} );
|
|
}
|
|
else if (app.config.external_users) {
|
|
Debug.trace("User is not logged in, querying external user API");
|
|
app.doExternalLogin();
|
|
}
|
|
else {
|
|
Debug.trace("User is not logged in, redirecting to login page (will return to " + this.ID + ")");
|
|
setTimeout( function() { Nav.go('Login'); }, 1 );
|
|
}
|
|
return false;
|
|
}
|
|
return true;
|
|
},
|
|
|
|
isAdmin: function() {
|
|
// return true if user is logged in and admin, false otherwise
|
|
// Note: This is used for UI decoration ONLY -- all privileges are checked on the server
|
|
return( app.user && app.user.privileges && app.user.privileges.admin );
|
|
},
|
|
|
|
getNiceJob: function(id) {
|
|
if (!id) return '(None)';
|
|
if (typeof(id) == 'object') id = id.id;
|
|
return '<div style="white-space:nowrap;"><i class="fa fa-pie-chart"> </i>' + id + '</div>';
|
|
},
|
|
|
|
getNiceEvent: function(title, width) {
|
|
if (!width) width = 500;
|
|
if (!title) return '(None)';
|
|
var icon_class = 'fa fa-clock-o';
|
|
if (typeof(title) == 'object') {
|
|
if (title.chain || title.chain_error) icon_class = 'fa fa-link';
|
|
title = title.title;
|
|
}
|
|
return '<div class="ellip" style="max-width:'+width+'px;"><i class="' + icon_class + '"> </i>' + title + '</div>';
|
|
},
|
|
|
|
getNiceCategory: function(cat, width) {
|
|
if (!width) width = 500;
|
|
if (!cat) return '(None)';
|
|
var title = cat.title;
|
|
if (!cat.enabled) title += ' (Disabled)';
|
|
return '<div class="ellip" style="max-width:'+width+'px;"><i class="fa fa-folder-open-o"> </i>' + title + '</div>';
|
|
},
|
|
|
|
getNiceGroup: function(group, target, width) {
|
|
if (!width) width = 500;
|
|
if (!group && !target) return '(None)';
|
|
if (group) {
|
|
var title = group.title;
|
|
if (group.multiplex) title += ' (<i class="fa fa-bolt" title="Multiplexed"></i>)';
|
|
return '<div class="ellip" style="max-width:'+width+'px;"><i class="mdi mdi-server-network"> </i>' + title + '</div>';
|
|
}
|
|
else {
|
|
return '<div class="ellip" style="max-width:'+width+'px;" title="'+target+'"><i class="mdi mdi-desktop-tower mdi-lg"> </i>' + target.replace(/\.[\w\-]+\.\w+$/, '') + '</div>';
|
|
}
|
|
},
|
|
|
|
getNicePlugin: function(plugin, width) {
|
|
if (!width) width = 500;
|
|
if (!plugin) return '(None)';
|
|
var title = plugin.title;
|
|
if (!plugin.enabled) title += ' (Disabled)';
|
|
return '<div class="ellip" style="max-width:'+width+'px;"><i class="fa fa-plug"> </i>' + title + '</div>';
|
|
},
|
|
|
|
getNiceAPIKey: function(item, link, width) {
|
|
if (!item) return 'n/a';
|
|
if (!width) width = 500;
|
|
var key = item.api_key || item.key;
|
|
var title = item.api_title || item.title;
|
|
|
|
var html = '<div class="ellip" style="max-width:'+width+'px;">';
|
|
if (link && key) html += '<a href="#Admin?sub=edit_api_key&id='+item.id+'">';
|
|
|
|
html += '<i class="mdi mdi-key-variant"> </i>' + title;
|
|
|
|
if (link && key) html += '</a>';
|
|
html += '</div>';
|
|
|
|
return html;
|
|
},
|
|
|
|
getNiceUsername: function(user, link, width) {
|
|
if (!user) return 'n/a';
|
|
if ((typeof(user) == 'object') && (user.key || user.api_title)) {
|
|
return this.getNiceAPIKey(user, link, width);
|
|
}
|
|
if (!width) width = 500;
|
|
var username = user.username ? user.username : user;
|
|
if (!username || (typeof(username) != 'string')) return 'n/a';
|
|
|
|
var html = '<div class="ellip" style="max-width:'+width+'px;">';
|
|
if (link) html += '<a href="#Admin?sub=edit_user&username='+username+'">';
|
|
|
|
html += '<i class="fa fa-user"> </i>' + username;
|
|
|
|
if (link) html += '</a>';
|
|
html += '</div>';
|
|
|
|
return html;
|
|
},
|
|
|
|
setGroupVisible: function(group, visible) {
|
|
// set web groups of form fields visible or invisible,
|
|
// according to master checkbox for each section
|
|
var selector = 'tr.' + group + 'group';
|
|
if (visible) {
|
|
if ($(selector).hasClass('collapse')) {
|
|
$(selector).hide().removeClass('collapse');
|
|
}
|
|
$(selector).show(250);
|
|
}
|
|
else $(selector).hide(250);
|
|
|
|
return this; // for chaining
|
|
},
|
|
|
|
checkUserExists: function(pre) {
|
|
// check if user exists, update UI checkbox
|
|
// called after field changes
|
|
var username = trim($('#fe_'+pre+'_username').val().toLowerCase());
|
|
var $elem = $('#d_'+pre+'_valid');
|
|
|
|
if (username.match(/^[\w\-\.]+$/)) {
|
|
// check with server
|
|
// $elem.css('color','#444').html('<span class="fa fa-spinner fa-spin fa-lg"> </span>');
|
|
app.api.get('app/check_user_exists', { username: username }, function(resp) {
|
|
if (resp.user_exists) {
|
|
// username taken
|
|
$elem.css('color','red').html('<span class="fa fa-exclamation-triangle fa-lg"> </span>Username Taken');
|
|
}
|
|
else {
|
|
// username is valid and available!
|
|
$elem.css('color','green').html('<span class="fa fa-check-circle fa-lg"> </span>Available');
|
|
}
|
|
} );
|
|
}
|
|
else if (username.length) {
|
|
// bad username
|
|
$elem.css('color','red').html('<span class="fa fa-exclamation-triangle fa-lg"> </span>Bad Username');
|
|
}
|
|
else {
|
|
// empty
|
|
$elem.html('');
|
|
}
|
|
},
|
|
|
|
check_add_remove_me: function($elem) {
|
|
// check if user's e-mail is contained in text field or not
|
|
var value = $elem.val().toLowerCase();
|
|
var email = app.user.email.toLowerCase();
|
|
var regexp = new RegExp( "\\b" + escape_regexp(email) + "\\b" );
|
|
return !!value.match(regexp);
|
|
},
|
|
|
|
update_add_remove_me: function($elems) {
|
|
// update add/remove me text based on if user's e-mail is contained in text field
|
|
var self = this;
|
|
|
|
$elems.each( function() {
|
|
var $elem = $(this);
|
|
var $span = $elem.next();
|
|
|
|
if (self.check_add_remove_me($elem)) $span.html( '» Remove me' );
|
|
else $span.html( '« Add me' );
|
|
} );
|
|
},
|
|
|
|
add_remove_me: function($elem) {
|
|
// toggle user's e-mail in/out of text field
|
|
var value = trim( $elem.val().replace(/\,\s*\,/g, ',').replace(/^\s*\,\s*/, '').replace(/\s*\,\s*$/, '') );
|
|
|
|
if (this.check_add_remove_me($elem)) {
|
|
// remove e-mail
|
|
var email = app.user.email.toLowerCase();
|
|
var regexp = new RegExp( "\\b" + escape_regexp(email) + "\\b", "i" );
|
|
value = value.replace( regexp, '' ).replace(/\,\s*\,/g, ',').replace(/^\s*\,\s*/, '').replace(/\s*\,\s*$/, '');
|
|
$elem.val( trim(value) );
|
|
}
|
|
else {
|
|
// add email
|
|
if (value) value += ', ';
|
|
$elem.val( value + app.user.email );
|
|
}
|
|
|
|
this.update_add_remove_me($elem);
|
|
},
|
|
|
|
get_custom_combo_unit_box: function(id, value, items, class_name) {
|
|
// get HTML for custom combo text/menu, where menu defines units of measurement
|
|
// items should be array for use in render_menu_options(), with an increasing numerical value
|
|
if (!class_name) class_name = 'std_combo_unit_table';
|
|
var units = 0;
|
|
var value = parseInt( value || 0 );
|
|
|
|
for (var idx = items.length - 1; idx >= 0; idx--) {
|
|
var max = items[idx][0];
|
|
if ((value >= max) && (value % max == 0)) {
|
|
units = max;
|
|
value = Math.floor( value / units );
|
|
idx = -1;
|
|
}
|
|
}
|
|
if (!units) {
|
|
// no exact match, so default to first unit in list
|
|
units = items[0][0];
|
|
value = Math.floor( value / units );
|
|
}
|
|
|
|
return (
|
|
'<table cellspacing="0" cellpadding="0" class="'+class_name+'"><tr>' +
|
|
'<td style="padding:0"><input type="text" id="'+id+'" style="width:30px;" value="'+value+'"/></td>' +
|
|
'<td style="padding:0"><select id="'+id+'_units">' + render_menu_options(items, units) + '</select></td>' +
|
|
'</tr></table>'
|
|
);
|
|
},
|
|
|
|
get_relative_time_combo_box: function(id, value, class_name, inc_seconds) {
|
|
// get HTML for combo textfield/menu for a relative time based input
|
|
// provides Minutes, Hours and Days units
|
|
var unit_items = [[60,'Minutes'], [3600,'Hours'], [86400,'Days']];
|
|
if (inc_seconds) unit_items.unshift( [1,'Seconds'] );
|
|
|
|
return this.get_custom_combo_unit_box( id, value, unit_items, class_name );
|
|
},
|
|
|
|
get_relative_size_combo_box: function(id, value, class_name) {
|
|
// get HTML for combo textfield/menu for a relative size based input
|
|
// provides MB, GB and TB units
|
|
var TB = 1024 * 1024 * 1024 * 1024;
|
|
var GB = 1024 * 1024 * 1024;
|
|
var MB = 1024 * 1024;
|
|
var KB = 1024;
|
|
|
|
return this.get_custom_combo_unit_box( id, value, [[KB, 'KB'], [MB,'MB'], [GB,'GB'], [TB,'TB']], class_name );
|
|
},
|
|
|
|
expand_fieldset: function($span) {
|
|
// expand neighboring fieldset, and hide click control
|
|
var $div = $span.parent();
|
|
var $fieldset = $div.next();
|
|
$fieldset.show( 350 );
|
|
$div.hide( 350 );
|
|
},
|
|
|
|
collapse_fieldset: function($legend) {
|
|
// collapse fieldset, and show click control again
|
|
var $fieldset = $legend.parent();
|
|
var $div = $fieldset.prev();
|
|
$fieldset.hide( 350 );
|
|
$div.show( 350 );
|
|
},
|
|
|
|
choose_date_time: function(args) {
|
|
// show dialog for selecting a date/time
|
|
// args: {
|
|
// when: default date/time (epoch or Date object, defaults to now)
|
|
// timezone: custom timezone (defaults to app.tz)
|
|
// title: dialog title
|
|
// description: optional description
|
|
// button: optional button label ("Select")
|
|
// callback: fired when complete, passed new date/time
|
|
// }
|
|
var self = this;
|
|
var html = '';
|
|
|
|
if (!args.when) args.when = time_now();
|
|
if (!args.timezone) args.timezone = app.tz;
|
|
if (!args.title) args.title = "Select Date/Time";
|
|
if (!args.button) args.button = "Select";
|
|
|
|
if (args.description) {
|
|
html += '<div style="font-size:12px; color:#777; margin-bottom:20px;">' + args.description + '</div>';
|
|
}
|
|
|
|
// var dargs = get_date_args( args.when );
|
|
var margs = moment.tz(args.when * 1000, args.timezone);
|
|
|
|
html += '<center><table><tr>';
|
|
|
|
// years
|
|
var year_items = [];
|
|
for (var idx = margs.year() - 10; idx <= margs.year() + 10; idx++) {
|
|
year_items.push(idx);
|
|
}
|
|
html += '<td align="left"><fieldset class="dt_fs"><legend>Year</legend>';
|
|
html += '<select id="fe_dt_year">' + render_menu_options(year_items, margs.year()) + '</select>';
|
|
html += '</fieldset></td>';
|
|
|
|
// months
|
|
html += '<td align="left"><fieldset class="dt_fs" style="margin-left:5px;"><legend>Month</legend>';
|
|
html += '<select id="fe_dt_month">' + render_menu_options(_months, margs.month() + 1) + '</select>';
|
|
html += '</fieldset></td>';
|
|
|
|
// days
|
|
html += '<td align="left"><fieldset class="dt_fs" style="margin-left:5px;"><legend>Day</legend>';
|
|
html += '<select id="fe_dt_day">' + render_menu_options(_days, margs.date()) + '</select>';
|
|
html += '</fieldset></td>';
|
|
|
|
// hours
|
|
var hour_items = _hour_names.map( function(value, idx) {
|
|
return [idx, value.toUpperCase().replace(/^(\d+)(\w+)$/, '$1 $2')];
|
|
} );
|
|
html += '<td align="left"><fieldset class="dt_fs" style="margin-left:5px;"><legend>Hour</legend>';
|
|
html += '<select id="fe_dt_hour">' + render_menu_options(hour_items, margs.hour()) + '</select>';
|
|
html += '</fieldset></td>';
|
|
|
|
// minutes
|
|
var min_items = [];
|
|
for (var idx = 0; idx < 60; idx++) {
|
|
min_items.push([ idx, (idx < 10) ? ('0'+idx) : (''+idx) ]);
|
|
}
|
|
html += '<td align="left"><fieldset class="dt_fs" style="margin-left:5px;"><legend>Minute</legend>';
|
|
html += '<select id="fe_dt_minute">' + render_menu_options(min_items, margs.minute()) + '</select>';
|
|
html += '</fieldset></td>';
|
|
|
|
html += '</tr>';
|
|
html += '<tr><td align="left" colspan="5">';
|
|
html += '<div class="caption">Timezone: ' + args.timezone + '</div>';
|
|
html += '</td></tr>';
|
|
html += '</table></center>';
|
|
|
|
app.confirm( '<i class="fa fa-calendar"> </i>' + args.title, html, args.button, function(result) {
|
|
app.clearError();
|
|
|
|
if (result) {
|
|
Dialog.hide();
|
|
|
|
margs.year( parseInt( $('#fe_dt_year').val() ) );
|
|
margs.month( parseInt( $('#fe_dt_month').val() ) - 1 );
|
|
margs.date( parseInt( $('#fe_dt_day').val() ) );
|
|
margs.hour( parseInt( $('#fe_dt_hour').val() ) );
|
|
margs.minute( parseInt( $('#fe_dt_minute').val() ) );
|
|
margs.second( 0 );
|
|
|
|
args.callback( margs.unix() );
|
|
}
|
|
} ); // app.confirm
|
|
},
|
|
|
|
render_target_menu_options: function(value) {
|
|
// render menu items for server group (target)
|
|
// including optgroups for both server group and individual servers
|
|
var html = '';
|
|
|
|
var server_groups = app.server_groups.sort( function(a, b) {
|
|
// return (b.title < a.title) ? 1 : -1;
|
|
return a.title.toLowerCase().localeCompare( b.title.toLowerCase() );
|
|
} )
|
|
.filter( function(group) {
|
|
if (!app.user.privileges.grp_limit) return true; // user is not limited by groups
|
|
return app.hasPrivilege( 'grp_' + group.id );
|
|
});
|
|
|
|
html += '<optgroup label="Groups:">' + render_menu_options(server_groups, value, false) + '</optgroup>';
|
|
|
|
if (find_object(server_groups, { id: value })) value = '';
|
|
|
|
// trim hostname suffixes
|
|
var hostnames = hash_keys_to_array(app.servers).sort();
|
|
if (value && !app.servers[value]) hostnames.push( value );
|
|
|
|
// filter hostnames by server group privilege
|
|
if (app.user.privileges.grp_limit) {
|
|
hostnames = hostnames.filter(function(hostname) {
|
|
var groups = server_groups.filter( function(group) {
|
|
return hostname.match( group.regexp );
|
|
} );
|
|
|
|
// we just need one group to match, then the user has permission to target the server
|
|
for (var idx = 0, len = groups.length; idx < len; idx++) {
|
|
priv_id = 'grp_' + groups[idx].id;
|
|
result = app.hasPrivilege(priv_id);
|
|
if (result) return true;
|
|
}
|
|
return false;
|
|
});
|
|
} // grp_limit
|
|
|
|
var short_hostnames = [];
|
|
for (var idx = 0, len = hostnames.length; idx < len; idx++) {
|
|
short_hostnames.push([ hostnames[idx], hostnames[idx].replace(/\.[\w\-]+\.\w+$/, '') ]);
|
|
}
|
|
|
|
html += '<optgroup label="Servers:">' + render_menu_options(short_hostnames, value, false) + '</optgroup>';
|
|
return html;
|
|
}
|
|
|
|
} );
|