forked from shaba/openuds
* Fixed xls export
* Fixed "cancel" on publications * Fixed (minor) ovirt issues * Removed "old-js" from trunk
This commit is contained in:
parent
63fc505bee
commit
23e3c385fd
@ -220,6 +220,10 @@ encoding//src/uds/services/Vmware_enterprise/client/Client.py=utf-8
|
|||||||
encoding//src/uds/services/Vmware_enterprise/client/Exceptions.py=utf-8
|
encoding//src/uds/services/Vmware_enterprise/client/Exceptions.py=utf-8
|
||||||
encoding//src/uds/services/Vmware_enterprise/client/Server.py=utf-8
|
encoding//src/uds/services/Vmware_enterprise/client/Server.py=utf-8
|
||||||
encoding//src/uds/services/Vmware_enterprise/client/Task.py=utf-8
|
encoding//src/uds/services/Vmware_enterprise/client/Task.py=utf-8
|
||||||
|
encoding//src/uds/services/Xen_enterprise/XenLinkedService.py=utf-8
|
||||||
|
encoding//src/uds/services/Xen_enterprise/XenProvider.py=utf-8
|
||||||
|
encoding//src/uds/services/Xen_enterprise/__init__.py=utf-8
|
||||||
|
encoding//src/uds/services/Xen_enterprise/xen_client/__init__.py=utf-8
|
||||||
encoding//src/uds/services/__init__.py=utf-8
|
encoding//src/uds/services/__init__.py=utf-8
|
||||||
encoding//src/uds/templatetags/REST.py=utf-8
|
encoding//src/uds/templatetags/REST.py=utf-8
|
||||||
encoding//src/uds/templatetags/html5.py=utf-8
|
encoding//src/uds/templatetags/html5.py=utf-8
|
||||||
|
@ -40,7 +40,7 @@ DATABASES = {
|
|||||||
'PASSWORD': 'dbuds', # Not used with sqlite3.
|
'PASSWORD': 'dbuds', # Not used with sqlite3.
|
||||||
'HOST': 'localhost', # Set to empty string for localhost. Not used with sqlite3.
|
'HOST': 'localhost', # Set to empty string for localhost. Not used with sqlite3.
|
||||||
'PORT': '3306', # Set to empty string for default. Not used with sqlite3.
|
'PORT': '3306', # Set to empty string for default. Not used with sqlite3.
|
||||||
'CONN_MAX_AGE': 600, # Enable DB Pooling, 10 minutes max connection duration
|
'CONN_MAX_AGE': 600, # Enable DB Pooling, 10 minutes max connection duration
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#DB_SECTION_END
|
#DB_SECTION_END
|
||||||
|
@ -14,4 +14,30 @@ $ = jQuery
|
|||||||
@api.spreadsheet.row = (cell) ->
|
@api.spreadsheet.row = (cell) ->
|
||||||
"<Row>" + cell + "</Row>"
|
"<Row>" + cell + "</Row>"
|
||||||
|
|
||||||
|
|
||||||
|
@api.spreadsheet.tableToExcel = (->
|
||||||
|
content_type = "application/vnd.ms-excel"
|
||||||
|
uri = "data:application/vnd.ms-excel;base64,"
|
||||||
|
template = "<html xmlns:o=\"urn:schemas-microsoft-com:office:office\" xmlns:x=\"urn:schemas-microsoft-com:office:excel\" xmlns=\"http://www.w3.org/TR/REC-html40\"><head><meta charset=\"utf-8\"><!--[if gte mso 9]><xml><x:ExcelWorkbook><x:ExcelWorksheets><x:ExcelWorksheet><x:Name>{worksheet}</x:Name><x:WorksheetOptions><x:DisplayGridlines/></x:WorksheetOptions></x:ExcelWorksheet></x:ExcelWorksheets></x:ExcelWorkbook></xml><![endif]--></head><body><table>{table}</table></body></html>"
|
||||||
|
#base64 = (s) ->
|
||||||
|
# window.btoa unescape(encodeURIComponent(s))
|
||||||
|
|
||||||
|
format = (s, c) ->
|
||||||
|
s.replace /{(\w+)}/g, (m, p) ->
|
||||||
|
c[p]
|
||||||
|
|
||||||
|
|
||||||
|
(table, name) ->
|
||||||
|
table = document.getElementById(table) unless table.nodeType
|
||||||
|
ctx =
|
||||||
|
worksheet: name or "Worksheet"
|
||||||
|
table: table.innerHTML
|
||||||
|
|
||||||
|
saveAs new Blob([format(template, ctx)],
|
||||||
|
type: content_type
|
||||||
|
), name + '.xls'
|
||||||
|
# window.location.href = uri + base64(format(template, ctx))
|
||||||
|
return
|
||||||
|
)()
|
||||||
|
|
||||||
return
|
return
|
||||||
|
@ -143,12 +143,10 @@ api.templates.get = (name, success_fnc) ->
|
|||||||
|
|
||||||
# Simple JavaScript Templating, using HandleBars
|
# Simple JavaScript Templating, using HandleBars
|
||||||
api.templates.evaluate = (str, context) ->
|
api.templates.evaluate = (str, context) ->
|
||||||
console.log "Evaluating ", str
|
|
||||||
# Figure out if we're getting a template, or if we need to
|
# Figure out if we're getting a template, or if we need to
|
||||||
# load the template - and be sure to cache the result (compiled template).
|
# load the template - and be sure to cache the result (compiled template).
|
||||||
cached = null
|
cached = null
|
||||||
unless /\W/.test(str)
|
unless /\W/.test(str)
|
||||||
console.log @cache
|
|
||||||
cached = @cache.get("_" + str)
|
cached = @cache.get("_" + str)
|
||||||
if not cached?
|
if not cached?
|
||||||
cached = api.templates.evaluate(document.getElementById(str).innerHTML)
|
cached = api.templates.evaluate(document.getElementById(str).innerHTML)
|
||||||
|
@ -82,6 +82,7 @@ gui.servicesPools.link = (event) ->
|
|||||||
'C': gettext("Cancelled")
|
'C': gettext("Cancelled")
|
||||||
}
|
}
|
||||||
$.each data, (index, value) ->
|
$.each data, (index, value) ->
|
||||||
|
value.origState = value.state # Save original state for "cancel" checking
|
||||||
if value.state is "U"
|
if value.state is "U"
|
||||||
value.state = if value.os_state isnt "" and value.os_state isnt "U" then gettext("Waiting OS") else value.state = gettext("Ready")
|
value.state = if value.os_state isnt "" and value.os_state isnt "U" then gettext("Waiting OS") else value.state = gettext("Ready")
|
||||||
return
|
return
|
||||||
@ -182,6 +183,7 @@ gui.servicesPools.link = (event) ->
|
|||||||
return
|
return
|
||||||
|
|
||||||
onRowSelect: (selected) ->
|
onRowSelect: (selected) ->
|
||||||
|
gui.do
|
||||||
cached = selected[0]
|
cached = selected[0]
|
||||||
if prevCacheLogTbl
|
if prevCacheLogTbl
|
||||||
$tbl = $(prevCacheLogTbl).dataTable()
|
$tbl = $(prevCacheLogTbl).dataTable()
|
||||||
|
@ -320,43 +320,7 @@
|
|||||||
sExtends: "text"
|
sExtends: "text"
|
||||||
sButtonText: gui.config.dataTableButtons.xls.text
|
sButtonText: gui.config.dataTableButtons.xls.text
|
||||||
fnClick: -> # Export to excel
|
fnClick: -> # Export to excel
|
||||||
api.templates.get "spreadsheet", (tmpl) ->
|
api.spreadsheet.tableToExcel(tableId, title)
|
||||||
styles = bold: "s21"
|
|
||||||
headings = []
|
|
||||||
rows = []
|
|
||||||
$.each columns, (index, heading) ->
|
|
||||||
return if heading.bVisible is false
|
|
||||||
headings.push api.spreadsheet.cell(heading.sTitle, "String", styles.bold)
|
|
||||||
return
|
|
||||||
|
|
||||||
rows.push api.spreadsheet.row(headings)
|
|
||||||
$.each data, (index1, row) ->
|
|
||||||
cells = []
|
|
||||||
$.each columns, (index2, col) ->
|
|
||||||
return if col.bVisible is false
|
|
||||||
type = (if col.sType is "numeric" then "Number" else "String")
|
|
||||||
cells.push api.spreadsheet.cell(row[col.mData], type)
|
|
||||||
return
|
|
||||||
|
|
||||||
rows.push api.spreadsheet.row(cells)
|
|
||||||
return
|
|
||||||
|
|
||||||
ctx =
|
|
||||||
creation_date: (new Date()).toISOString()
|
|
||||||
worksheet: title
|
|
||||||
columns_count: headings.length
|
|
||||||
rows_count: rows.length
|
|
||||||
rows: rows.join("\n")
|
|
||||||
|
|
||||||
gui.doLog ctx
|
|
||||||
setTimeout (->
|
|
||||||
saveAs new Blob([api.templates.evaluate(tmpl, ctx)],
|
|
||||||
type: "application/vnd.ms-excel"
|
|
||||||
), title + ".xls"
|
|
||||||
return
|
|
||||||
), 20
|
|
||||||
return
|
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
# End export to excell
|
# End export to excell
|
||||||
|
@ -17,7 +17,6 @@
|
|||||||
fix3dButtons: (selector) ->
|
fix3dButtons: (selector) ->
|
||||||
selector = selector or ""
|
selector = selector or ""
|
||||||
selector += " .btn3d"
|
selector += " .btn3d"
|
||||||
console.log selector
|
|
||||||
$.each $(selector), (index, value) ->
|
$.each $(selector), (index, value) ->
|
||||||
|
|
||||||
# If no events associated, return
|
# If no events associated, return
|
||||||
|
@ -1,15 +0,0 @@
|
|||||||
(function(spreadsheet, $, undefined) {
|
|
||||||
spreadsheet.cell = function(data, type, style) {
|
|
||||||
type = type || 'String';
|
|
||||||
if( style !== undefined ) {
|
|
||||||
style = ' ss:StyleID="' + style + '"';
|
|
||||||
} else {
|
|
||||||
style = '';
|
|
||||||
}
|
|
||||||
return '<Cell' + style + '><Data ss:Type="' + type + '">' + data + '</Data></Cell>';
|
|
||||||
};
|
|
||||||
|
|
||||||
spreadsheet.row = function(cell) {
|
|
||||||
return '<Row>' + cell + '</Row>';
|
|
||||||
};
|
|
||||||
}(api.spreadsheet = api.spreadsheet || {}, jQuery));
|
|
@ -1,139 +0,0 @@
|
|||||||
/* jshint strict: true */
|
|
||||||
// -------------------------------
|
|
||||||
// Templates related
|
|
||||||
// Inserted into api
|
|
||||||
// for the admin app
|
|
||||||
// -------------------------------
|
|
||||||
(function(api, $) {
|
|
||||||
"use strict";
|
|
||||||
// Registers Handlebar useful helpers
|
|
||||||
|
|
||||||
// Iterate thought dictionary
|
|
||||||
Handlebars.registerHelper('eachKey', function(context, options) {
|
|
||||||
var ret = "";
|
|
||||||
var first = true;
|
|
||||||
for(var prop in context) {
|
|
||||||
ret = ret + options.fn({key:prop,value:context[prop], first:first});
|
|
||||||
first = false;
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Equal comparision (like if helper, but with comparation)
|
|
||||||
// Use as block as {{#ifequals [element] [element]}}....{{/ifequals}}
|
|
||||||
Handlebars.registerHelper('ifequals', function(context1, context2, options) {
|
|
||||||
if(context1 == context2) {
|
|
||||||
return options.fn(this);
|
|
||||||
} else {
|
|
||||||
return options.inverse(this);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Belongs comparision (similar to "if xxx in yyyyy")
|
|
||||||
// Use as block as {{#ifbelong [element] [group]}}....{{/ifbelongs}}
|
|
||||||
Handlebars.registerHelper('ifbelongs', function(context1, context2, options) {
|
|
||||||
gui.doLog('belongs', context1, context2);
|
|
||||||
if($.inArray(context1, context2) != -1) {
|
|
||||||
gui.doLog('belongs is true');
|
|
||||||
return options.fn(this);
|
|
||||||
} else {
|
|
||||||
return options.inverse(this);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Counters.
|
|
||||||
// Create a counter with {{counter [id] [startValue]}}
|
|
||||||
// increment the counter with {{inc_counter [id]}}
|
|
||||||
// get the counter value tiwh {{get_counter [id}}
|
|
||||||
// Values are stored on current
|
|
||||||
Handlebars.registerHelper('set_counter', function(id, value, options){
|
|
||||||
options.data['_counter_'+id] = value;
|
|
||||||
});
|
|
||||||
|
|
||||||
Handlebars.registerHelper('get_counter', function(id, options){
|
|
||||||
return options.data['_counter_'+id];
|
|
||||||
});
|
|
||||||
|
|
||||||
Handlebars.registerHelper('inc_counter', function(id, options){
|
|
||||||
options.data['_counter_'+id] += 1;
|
|
||||||
});
|
|
||||||
|
|
||||||
// For inserting "inline" javascript scripts, due to the fact that we cannot
|
|
||||||
// Insert "<script>...</script>" inside inline elements (they are already scripts)
|
|
||||||
Handlebars.registerHelper('javascript', function(options) {
|
|
||||||
return new Handlebars.SafeString('<script>' + options.fn(this) + '</script>');
|
|
||||||
});
|
|
||||||
|
|
||||||
// Truncate chars, like django "truncatechars" filter
|
|
||||||
Handlebars.registerHelper('truncatechars', function(len, value) {
|
|
||||||
var val = value.toString(); // For Array objects, the toString method joins the array and returns one string containing each array element separated by commas
|
|
||||||
if(val.length > len) {
|
|
||||||
return val.substring(0, len-3) + "...";
|
|
||||||
} else {
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Remove white spaces
|
|
||||||
Handlebars.registerHelper('clean_whitespace', function(value) {
|
|
||||||
var val = value.toString(); // For Array objects, the toString method joins the array and returns one string containing each array element separated by commas
|
|
||||||
return val.replace(/ /g, '');
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
api.templates = {};
|
|
||||||
// Now initialize templates api
|
|
||||||
api.templates.cache = new api.cache('tmpls'); // Will cache templates locally. If name contains
|
|
||||||
// '?', data will not be cached and always
|
|
||||||
// re-requested. We do not care about lang, because page will reload on language change
|
|
||||||
api.templates.get = function(name, success_fnc) {
|
|
||||||
var $this = this;
|
|
||||||
success_fnc = success_fnc || function(){};
|
|
||||||
api.doLog('Getting template ' + name);
|
|
||||||
if (name.indexOf('?') == -1) {
|
|
||||||
if ($this.cache.get(name+'------') ) {
|
|
||||||
success_fnc($this.cache.get(name));
|
|
||||||
return;
|
|
||||||
// Let's check if a "preloaded template" exists
|
|
||||||
} else if( document.getElementById('tmpl_' + name) ) {
|
|
||||||
$this.cache.put(name, 'tmpl_' + name); // In fact, this is not neccesary...
|
|
||||||
success_fnc('tmpl_' + name);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
api.doLog('Invoking ajax for ', api.url_for(name, 'template'));
|
|
||||||
$.ajax({
|
|
||||||
url : api.url_for(name,'template'),
|
|
||||||
type : "GET",
|
|
||||||
dataType : "text",
|
|
||||||
success : function(data) {
|
|
||||||
var cachedId = 'tmpl_' + name;
|
|
||||||
$this.cache.put('_' + cachedId, $this.evaluate(data));
|
|
||||||
$this.cache.put(name, cachedId);
|
|
||||||
api.doLog('Success getting template "' + name + '".');
|
|
||||||
success_fnc(cachedId);
|
|
||||||
},
|
|
||||||
fail: function( jqXHR, textStatus, errorThrown ) {
|
|
||||||
api.doLog(jqXHR);
|
|
||||||
api.doLog(textStatus);
|
|
||||||
apid.doLog(errorThrown);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
// Simple JavaScript Templating, using HandleBars
|
|
||||||
api.templates.evaluate = function(str, context) {
|
|
||||||
// Figure out if we're getting a template, or if we need to
|
|
||||||
// load the template - and be sure to cache the result (compiled template).
|
|
||||||
var cached;
|
|
||||||
if( !/\W/.test(str) ) {
|
|
||||||
cached = this.cache.get('_'+str);
|
|
||||||
if( cached === undefined ) {
|
|
||||||
cached = api.templates.evaluate(document.getElementById(str).innerHTML);
|
|
||||||
this.cache.put('_'+str, cached);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var template = cached || Handlebars.compile(str);
|
|
||||||
return context ? template(context) : template;
|
|
||||||
};
|
|
||||||
}(window.api = window.api || {}, jQuery));
|
|
@ -1,407 +0,0 @@
|
|||||||
/* jshint strict: true */
|
|
||||||
(function(api, $, undefined) {
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
api.tools = {
|
|
||||||
base64 : function(s) {
|
|
||||||
return window.btoa(unescape(encodeURIComponent(s)));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
}(window.api = window.api || {}, jQuery));
|
|
||||||
|
|
||||||
|
|
||||||
// Insert strftime into tools
|
|
||||||
//
|
|
||||||
//strftime
|
|
||||||
//github.com/samsonjs/strftime
|
|
||||||
//@_sjs
|
|
||||||
//
|
|
||||||
//Copyright 2010 - 2013 Sami Samhuri <sami@samhuri.net>
|
|
||||||
//
|
|
||||||
//MIT License
|
|
||||||
//http://sjs.mit-license.org
|
|
||||||
//
|
|
||||||
|
|
||||||
;(function() {
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
var namespace = api.tools;
|
|
||||||
|
|
||||||
var dayNames = [ gettext('Sunday'), gettext('Monday'), gettext('Tuesday'), gettext('Wednesday'),
|
|
||||||
gettext('Thursday'), gettext('Friday'), gettext('Saturday') ];
|
|
||||||
var monthNames = [ gettext('January'), gettext('February'), gettext('March'), gettext('April'), gettext('May'),
|
|
||||||
gettext('June'), gettext('July'), gettext('August'), gettext('September'), gettext('October'),
|
|
||||||
gettext('November'), gettext('December') ];
|
|
||||||
|
|
||||||
function initialsOf(arr) {
|
|
||||||
var res = [];
|
|
||||||
for ( var v in arr) {
|
|
||||||
res.push(arr[v].substr(0, 3));
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
var DefaultLocale = {
|
|
||||||
days : dayNames,
|
|
||||||
shortDays : initialsOf(dayNames),
|
|
||||||
months : monthNames,
|
|
||||||
shortMonths : initialsOf(monthNames),
|
|
||||||
AM : 'AM',
|
|
||||||
PM : 'PM',
|
|
||||||
am : 'am',
|
|
||||||
pm : 'pm',
|
|
||||||
};
|
|
||||||
|
|
||||||
// Added this to convert django format strings to c format string
|
|
||||||
// This is ofc, a "simplified" version, aimed to use date format used by
|
|
||||||
// DJANGO
|
|
||||||
namespace.djangoFormat = function(format) {
|
|
||||||
return format.replace(/./g, function(c) {
|
|
||||||
switch (c) {
|
|
||||||
case 'a':
|
|
||||||
case 'A':
|
|
||||||
return '%p';
|
|
||||||
case 'b':
|
|
||||||
case 'd':
|
|
||||||
case 'm':
|
|
||||||
case 'w':
|
|
||||||
case 'W':
|
|
||||||
case 'y':
|
|
||||||
case 'Y':
|
|
||||||
return '%' + c;
|
|
||||||
case 'c':
|
|
||||||
return '%FT%TZ';
|
|
||||||
case 'D':
|
|
||||||
return '%a';
|
|
||||||
case 'e':
|
|
||||||
return '%z';
|
|
||||||
case 'f':
|
|
||||||
return '%I:%M';
|
|
||||||
case 'F':
|
|
||||||
return '%F';
|
|
||||||
case 'h':
|
|
||||||
case 'g':
|
|
||||||
return '%I';
|
|
||||||
case 'H':
|
|
||||||
case 'G':
|
|
||||||
return '%H';
|
|
||||||
case 'i':
|
|
||||||
return '%M';
|
|
||||||
case 'I':
|
|
||||||
return ''; // daylight saving
|
|
||||||
case 'j':
|
|
||||||
return '%d';
|
|
||||||
case 'l':
|
|
||||||
return '%A';
|
|
||||||
case 'L':
|
|
||||||
return ''; // if it is leap year
|
|
||||||
case 'M':
|
|
||||||
return '%b';
|
|
||||||
case 'n':
|
|
||||||
return '%m';
|
|
||||||
case 'N':
|
|
||||||
return '%b';
|
|
||||||
case 'o':
|
|
||||||
return '%W'; // Not so sure, not important i thing anyway :-)
|
|
||||||
case 'O':
|
|
||||||
return '%z';
|
|
||||||
case 'P':
|
|
||||||
return '%R %p';
|
|
||||||
case 'r':
|
|
||||||
return '%a, %d %b %Y %T %z';
|
|
||||||
case 's':
|
|
||||||
return '%S';
|
|
||||||
case 'S':
|
|
||||||
return ''; // english ordinal suffix for day of month
|
|
||||||
case 't':
|
|
||||||
return ''; // number of days of specified month, not important
|
|
||||||
case 'T':
|
|
||||||
return '%Z';
|
|
||||||
case 'u':
|
|
||||||
return '0'; // microseconds
|
|
||||||
case 'U':
|
|
||||||
return ''; // Seconds since EPOCH, not used
|
|
||||||
case 'z':
|
|
||||||
return '%j';
|
|
||||||
case 'Z':
|
|
||||||
return 'z'; // Time zone offset in seconds, replaced by offset
|
|
||||||
// in ours/minutes :-)
|
|
||||||
default:
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace.strftime = strftime;
|
|
||||||
function strftime(fmt, d, locale) {
|
|
||||||
return _strftime(fmt, d, locale);
|
|
||||||
}
|
|
||||||
|
|
||||||
// locale is optional
|
|
||||||
namespace.strftimeTZ = strftime.strftimeTZ = strftimeTZ;
|
|
||||||
function strftimeTZ(fmt, d, locale, timezone) {
|
|
||||||
if (typeof locale == 'number' && timezone === null) {
|
|
||||||
timezone = locale;
|
|
||||||
locale = undefined;
|
|
||||||
}
|
|
||||||
return _strftime(fmt, d, locale, {
|
|
||||||
timezone : timezone
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace.strftimeUTC = strftime.strftimeUTC = strftimeUTC;
|
|
||||||
function strftimeUTC(fmt, d, locale) {
|
|
||||||
return _strftime(fmt, d, locale, {
|
|
||||||
utc : true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace.localizedStrftime = strftime.localizedStrftime = localizedStrftime;
|
|
||||||
function localizedStrftime(locale) {
|
|
||||||
return function(fmt, d, options) {
|
|
||||||
return strftime(fmt, d, locale, options);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// d, locale, and options are optional, but you can't leave
|
|
||||||
// holes in the argument list. If you pass options you have to pass
|
|
||||||
// in all the preceding args as well.
|
|
||||||
//
|
|
||||||
// options:
|
|
||||||
// - locale [object] an object with the same structure as DefaultLocale
|
|
||||||
// - timezone [number] timezone offset in minutes from GMT
|
|
||||||
function _strftime(fmt, d, locale, options) {
|
|
||||||
options = options || {};
|
|
||||||
|
|
||||||
// d and locale are optional so check if d is really the locale
|
|
||||||
if (d && !quacksLikeDate(d)) {
|
|
||||||
locale = d;
|
|
||||||
d = undefined;
|
|
||||||
}
|
|
||||||
d = d || new Date();
|
|
||||||
|
|
||||||
locale = locale || DefaultLocale;
|
|
||||||
locale.formats = locale.formats || {};
|
|
||||||
|
|
||||||
// Hang on to this Unix timestamp because we might mess with it directly
|
|
||||||
// below.
|
|
||||||
var timestamp = d.getTime();
|
|
||||||
|
|
||||||
if (options.utc || typeof options.timezone == 'number') {
|
|
||||||
d = dateToUTC(d);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof options.timezone == 'number') {
|
|
||||||
d = new Date(d.getTime() + (options.timezone * 60000));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Most of the specifiers supported by C's strftime, and some from Ruby.
|
|
||||||
// Some other syntax extensions from Ruby are supported: %-, %_, and %0
|
|
||||||
// to pad with nothing, space, or zero (respectively).
|
|
||||||
return fmt.replace(/%([-_0]?.)/g, function(_, c) {
|
|
||||||
var mod, padding;
|
|
||||||
if (c.length == 2) {
|
|
||||||
mod = c[0];
|
|
||||||
// omit padding
|
|
||||||
if (mod == '-') {
|
|
||||||
padding = '';
|
|
||||||
}
|
|
||||||
// pad with space
|
|
||||||
else if (mod == '_') {
|
|
||||||
padding = ' ';
|
|
||||||
}
|
|
||||||
// pad with zero
|
|
||||||
else if (mod == '0') {
|
|
||||||
padding = '0';
|
|
||||||
} else {
|
|
||||||
// unrecognized, return the format
|
|
||||||
return _;
|
|
||||||
}
|
|
||||||
c = c[1];
|
|
||||||
}
|
|
||||||
switch (c) {
|
|
||||||
case 'A':
|
|
||||||
return locale.days[d.getDay()];
|
|
||||||
case 'a':
|
|
||||||
return locale.shortDays[d.getDay()];
|
|
||||||
case 'B':
|
|
||||||
return locale.months[d.getMonth()];
|
|
||||||
case 'b':
|
|
||||||
return locale.shortMonths[d.getMonth()];
|
|
||||||
case 'C':
|
|
||||||
return pad(Math.floor(d.getFullYear() / 100), padding);
|
|
||||||
case 'D':
|
|
||||||
return _strftime(locale.formats.D || '%m/%d/%y', d, locale);
|
|
||||||
case 'd':
|
|
||||||
return pad(d.getDate(), padding);
|
|
||||||
case 'e':
|
|
||||||
return d.getDate();
|
|
||||||
case 'F':
|
|
||||||
return _strftime(locale.formats.F || '%Y-%m-%d', d, locale);
|
|
||||||
case 'H':
|
|
||||||
return pad(d.getHours(), padding);
|
|
||||||
case 'h':
|
|
||||||
return locale.shortMonths[d.getMonth()];
|
|
||||||
case 'I':
|
|
||||||
return pad(hours12(d), padding);
|
|
||||||
case 'j':
|
|
||||||
var y = new Date(d.getFullYear(), 0, 1);
|
|
||||||
var day = Math.ceil((d.getTime() - y.getTime()) / (1000 * 60 * 60 * 24));
|
|
||||||
return pad(day, 3);
|
|
||||||
case 'k':
|
|
||||||
return pad(d.getHours(), padding === null ? ' ' : padding);
|
|
||||||
case 'L':
|
|
||||||
return pad(Math.floor(timestamp % 1000), 3);
|
|
||||||
case 'l':
|
|
||||||
return pad(hours12(d), padding === null ? ' ' : padding);
|
|
||||||
case 'M':
|
|
||||||
return pad(d.getMinutes(), padding);
|
|
||||||
case 'm':
|
|
||||||
return pad(d.getMonth() + 1, padding);
|
|
||||||
case 'n':
|
|
||||||
return '\n';
|
|
||||||
case 'o':
|
|
||||||
return String(d.getDate()) + ordinal(d.getDate());
|
|
||||||
case 'P':
|
|
||||||
return d.getHours() < 12 ? locale.am : locale.pm;
|
|
||||||
case 'p':
|
|
||||||
return d.getHours() < 12 ? locale.AM : locale.PM;
|
|
||||||
case 'R':
|
|
||||||
return _strftime(locale.formats.R || '%H:%M', d, locale);
|
|
||||||
case 'r':
|
|
||||||
return _strftime(locale.formats.r || '%I:%M:%S %p', d, locale);
|
|
||||||
case 'S':
|
|
||||||
return pad(d.getSeconds(), padding);
|
|
||||||
case 's':
|
|
||||||
return Math.floor(timestamp / 1000);
|
|
||||||
case 'T':
|
|
||||||
return _strftime(locale.formats.T || '%H:%M:%S', d, locale);
|
|
||||||
case 't':
|
|
||||||
return '\t';
|
|
||||||
case 'U':
|
|
||||||
return pad(weekNumber(d, 'sunday'), padding);
|
|
||||||
case 'u':
|
|
||||||
var dayu = d.getDay();
|
|
||||||
return dayu === 0 ? 7 : dayu; // 1 - 7, Monday is first day of the
|
|
||||||
// week
|
|
||||||
case 'v':
|
|
||||||
return _strftime(locale.formats.v || '%e-%b-%Y', d, locale);
|
|
||||||
case 'W':
|
|
||||||
return pad(weekNumber(d, 'monday'), padding);
|
|
||||||
case 'w':
|
|
||||||
return d.getDay(); // 0 - 6, Sunday is first day of the
|
|
||||||
// week
|
|
||||||
case 'Y':
|
|
||||||
return d.getFullYear();
|
|
||||||
case 'y':
|
|
||||||
var yy = String(d.getFullYear());
|
|
||||||
return yy.slice(yy.length - 2);
|
|
||||||
case 'Z':
|
|
||||||
if (options.utc) {
|
|
||||||
return "GMT";
|
|
||||||
} else {
|
|
||||||
var tz = d.toString().match(/\((\w+)\)/);
|
|
||||||
return tz && tz[1] || '';
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'z':
|
|
||||||
if (options.utc) {
|
|
||||||
return "+0000";
|
|
||||||
} else {
|
|
||||||
var off = typeof options.timezone == 'number' ? options.timezone : -d.getTimezoneOffset();
|
|
||||||
return (off < 0 ? '-' : '+') + pad(Math.abs(off / 60)) + pad(off % 60);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function dateToUTC(d) {
|
|
||||||
var msDelta = (d.getTimezoneOffset() || 0) * 60000;
|
|
||||||
return new Date(d.getTime() + msDelta);
|
|
||||||
}
|
|
||||||
|
|
||||||
var RequiredDateMethods = [ 'getTime', 'getTimezoneOffset', 'getDay', 'getDate', 'getMonth', 'getFullYear',
|
|
||||||
'getYear', 'getHours', 'getMinutes', 'getSeconds' ];
|
|
||||||
function quacksLikeDate(x) {
|
|
||||||
var i = 0, n = RequiredDateMethods.length;
|
|
||||||
for (i = 0; i < n; ++i) {
|
|
||||||
if (typeof x[RequiredDateMethods[i]] != 'function') {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Default padding is '0' and default length is 2, both are optional.
|
|
||||||
function pad(n, padding, length) {
|
|
||||||
// pad(n, <length>)
|
|
||||||
if (typeof padding === 'number') {
|
|
||||||
length = padding;
|
|
||||||
padding = '0';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Defaults handle pad(n) and pad(n, <padding>)
|
|
||||||
if (padding === null) {
|
|
||||||
padding = '0';
|
|
||||||
}
|
|
||||||
length = length || 2;
|
|
||||||
|
|
||||||
var s = String(n);
|
|
||||||
// padding may be an empty string, don't loop forever if it is
|
|
||||||
if (padding) {
|
|
||||||
while (s.length < length)
|
|
||||||
s = padding + s;
|
|
||||||
}
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
function hours12(d) {
|
|
||||||
var hour = d.getHours();
|
|
||||||
if (hour === 0)
|
|
||||||
hour = 12;
|
|
||||||
else if (hour > 12)
|
|
||||||
hour -= 12;
|
|
||||||
return hour;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the ordinal suffix for a number: st, nd, rd, or th
|
|
||||||
function ordinal(n) {
|
|
||||||
var i = n % 10, ii = n % 100;
|
|
||||||
if ((ii >= 11 && ii <= 13) || i === 0 || i >= 4) {
|
|
||||||
return 'th';
|
|
||||||
}
|
|
||||||
switch (i) {
|
|
||||||
case 1:
|
|
||||||
return 'st';
|
|
||||||
case 2:
|
|
||||||
return 'nd';
|
|
||||||
case 3:
|
|
||||||
return 'rd';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// firstWeekday: 'sunday' or 'monday', default is 'sunday'
|
|
||||||
//
|
|
||||||
// Pilfered & ported from Ruby's strftime implementation.
|
|
||||||
function weekNumber(d, firstWeekday) {
|
|
||||||
firstWeekday = firstWeekday || 'sunday';
|
|
||||||
|
|
||||||
// This works by shifting the weekday back by one day if we
|
|
||||||
// are treating Monday as the first day of the week.
|
|
||||||
var wday = d.getDay();
|
|
||||||
if (firstWeekday == 'monday') {
|
|
||||||
if (wday === 0) // Sunday
|
|
||||||
wday = 6;
|
|
||||||
else
|
|
||||||
wday--;
|
|
||||||
}
|
|
||||||
var firstDayOfYear = new Date(d.getFullYear(), 0, 1), yday = (d - firstDayOfYear) / 86400000, weekNum = (yday + 7 - wday) / 7;
|
|
||||||
return Math.floor(weekNum);
|
|
||||||
}
|
|
||||||
|
|
||||||
}());
|
|
@ -1,480 +0,0 @@
|
|||||||
/* jshint strict: true */
|
|
||||||
(function(api, $, undefined) {
|
|
||||||
"use strict";
|
|
||||||
// "public" methods
|
|
||||||
api.doLog = function() {
|
|
||||||
if (api.debug) {
|
|
||||||
try {
|
|
||||||
console.log.apply(window, arguments);
|
|
||||||
} catch (e) {
|
|
||||||
// nothing can be logged
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Cache table
|
|
||||||
api.cacheTable = {};
|
|
||||||
|
|
||||||
// Returns a cache object (for easy caching requests, templates, etc...)
|
|
||||||
api.cache = function(cacheName) {
|
|
||||||
return new Cache(cacheName);
|
|
||||||
};
|
|
||||||
|
|
||||||
api.cache.clear = function(cacheName) {
|
|
||||||
if( cacheName === undefined ) {
|
|
||||||
api.cacheTable = {};
|
|
||||||
} else {
|
|
||||||
api.cacheTable[cacheName] = {};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
api.url_for = function(path, type) {
|
|
||||||
switch(type) {
|
|
||||||
case 'template':
|
|
||||||
return api.config.template_url + path;
|
|
||||||
case undefined:
|
|
||||||
case 'rest':
|
|
||||||
return api.config.base_url + path;
|
|
||||||
default:
|
|
||||||
throw new Exception('Type of url not found: ' + type);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Default fail function
|
|
||||||
api.defaultFail = function(jqXHR, textStatus, errorThrown) {
|
|
||||||
api.doLog(jqXHR, ', ', textStatus, ', ', errorThrown);
|
|
||||||
};
|
|
||||||
|
|
||||||
api.getJson = function(path, options) {
|
|
||||||
options = options || {};
|
|
||||||
var success_fnc = options.success || function(){};
|
|
||||||
var fail_fnc = options.fail || api.defaultFail;
|
|
||||||
|
|
||||||
var url = api.url_for(path);
|
|
||||||
api.doLog('Ajax GET Json for "' + url + '"');
|
|
||||||
$.ajax({
|
|
||||||
url : url,
|
|
||||||
type : options.method || "GET", // Will use GET if no method provided
|
|
||||||
dataType : "json",
|
|
||||||
success : function(data) {
|
|
||||||
api.doLog('Success on GET "' + url + '".');
|
|
||||||
api.doLog('Received ', data);
|
|
||||||
success_fnc(data);
|
|
||||||
},
|
|
||||||
error: function(jqXHR, textStatus, errorThrown) {
|
|
||||||
api.doLog('Error on GET "' + url + '". ', textStatus, ', ', errorThrown);
|
|
||||||
fail_fnc(jqXHR, textStatus, errorThrown);
|
|
||||||
},
|
|
||||||
beforeSend : function(request) {
|
|
||||||
request.setRequestHeader(api.config.auth_header, api.config.token);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
api.putJson = function(path, data, options) {
|
|
||||||
options = options || {};
|
|
||||||
var success_fnc = options.success || function(){};
|
|
||||||
var fail_fnc = options.fail || api.defaultFail;
|
|
||||||
|
|
||||||
var url = api.url_for(path);
|
|
||||||
api.doLog('Ajax PUT Json for "' + url + '"');
|
|
||||||
$.ajax({
|
|
||||||
url : url,
|
|
||||||
type : options.method || "PUT", // Will use PUT if no method provided
|
|
||||||
dataType : "json",
|
|
||||||
data: JSON.stringify(data),
|
|
||||||
success: function(data) {
|
|
||||||
api.doLog('Success on PUT "' + url + '".');
|
|
||||||
api.doLog('Received ', data);
|
|
||||||
success_fnc(data);
|
|
||||||
},
|
|
||||||
error: function(jqXHR, textStatus, errorThrown) {
|
|
||||||
api.doLog('Error on PUT "' + url + '". ', textStatus, ', ', errorThrown);
|
|
||||||
fail_fnc(jqXHR, textStatus, errorThrown);
|
|
||||||
},
|
|
||||||
beforeSend : function(request) {
|
|
||||||
request.setRequestHeader(api.config.auth_header, api.config.token);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}; // End putJson
|
|
||||||
|
|
||||||
|
|
||||||
api.deleteJson = function(path, options) {
|
|
||||||
options = options || {};
|
|
||||||
var success_fnc = options.success || function(){};
|
|
||||||
var fail_fnc = options.fail || api.defaultFail;
|
|
||||||
|
|
||||||
var url = api.url_for(path);
|
|
||||||
api.doLog('Ajax DELETE Json for "' + url + '"');
|
|
||||||
$.ajax({
|
|
||||||
url : url,
|
|
||||||
type : "DELETE",
|
|
||||||
dataType : "json",
|
|
||||||
success: function(data) {
|
|
||||||
api.doLog('Success on DELETE "' + url + '".');
|
|
||||||
api.doLog('Received ', data);
|
|
||||||
success_fnc(data);
|
|
||||||
},
|
|
||||||
error: function(jqXHR, textStatus, errorThrown) {
|
|
||||||
api.doLog('Error on DELETE "' + url + '". ', textStatus, ', ', errorThrown);
|
|
||||||
fail_fnc(jqXHR, textStatus, errorThrown);
|
|
||||||
},
|
|
||||||
beforeSend : function(request) {
|
|
||||||
request.setRequestHeader(api.config.auth_header, api.config.token);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}; // End putJson
|
|
||||||
|
|
||||||
|
|
||||||
// Public attributes
|
|
||||||
api.debug = false;
|
|
||||||
|
|
||||||
|
|
||||||
// Cache related
|
|
||||||
function Cache(cacheName) {
|
|
||||||
api.cacheTable[cacheName] = api.cacheTable[cacheName] || {};
|
|
||||||
|
|
||||||
this.name = cacheName;
|
|
||||||
this.cache = api.cacheTable[cacheName];
|
|
||||||
}
|
|
||||||
|
|
||||||
Cache.prototype = {
|
|
||||||
get: function(key, not_found_fnc){
|
|
||||||
not_found_fnc = not_found_fnc || function() { return undefined; };
|
|
||||||
|
|
||||||
if( this.cache[key] === undefined ) {
|
|
||||||
this.cache[key] = not_found_fnc();
|
|
||||||
}
|
|
||||||
return this.cache[key];
|
|
||||||
},
|
|
||||||
|
|
||||||
put: function(key, value) {
|
|
||||||
this.cache[key] = value;
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// Great part of UDS REST api provides same methods.
|
|
||||||
// We will take advantage of this and save a lot of nonsense, prone to failure
|
|
||||||
// code :-)
|
|
||||||
|
|
||||||
function BasicModelRest(path, options) {
|
|
||||||
options = options || {};
|
|
||||||
path = path || '';
|
|
||||||
// Requests paths
|
|
||||||
this.path = path;
|
|
||||||
this.getPath = options.getPath || path;
|
|
||||||
this.logPath = options.logPath || path;
|
|
||||||
this.putPath = options.putPath || path;
|
|
||||||
this.testPath = options.testPath || (path + '/test');
|
|
||||||
this.delPath = options.delPath || path;
|
|
||||||
this.typesPath = options.typesPath || (path + '/types');
|
|
||||||
this.guiPath = options.guiPath || (path + '/gui');
|
|
||||||
this.tableInfoPath = options.tableInfoPath || (path + '/tableinfo');
|
|
||||||
this.cache = api.cache('bmr'+path);
|
|
||||||
}
|
|
||||||
|
|
||||||
BasicModelRest.prototype = {
|
|
||||||
// options:
|
|
||||||
// cacheKey: '.' --> do not cache (undefined will set cacheKey to current path)
|
|
||||||
// undefined -- > use path as key
|
|
||||||
// success: success fnc to execute in case of success
|
|
||||||
_requestPath: function(path, options) {
|
|
||||||
options = options || {};
|
|
||||||
var success_fnc = options.success || function(){api.doLog('success function not provided for '+path);};
|
|
||||||
var fail_fnc = options.fail;
|
|
||||||
var cacheKey = options.cacheKey || path;
|
|
||||||
|
|
||||||
if( path == '.' ) {
|
|
||||||
success_fnc({});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cacheKey != '.' && this.cache.get(cacheKey)) {
|
|
||||||
success_fnc(this.cache.get(cacheKey));
|
|
||||||
} else {
|
|
||||||
var $this = this;
|
|
||||||
api.getJson(path, {
|
|
||||||
success: function(data) {
|
|
||||||
if( cacheKey != '.' ) {
|
|
||||||
$this.cache.put(cacheKey, data);
|
|
||||||
}
|
|
||||||
success_fnc(data);
|
|
||||||
},
|
|
||||||
fail: fail_fnc,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
get: function(options) {
|
|
||||||
options = options || {};
|
|
||||||
|
|
||||||
var path = this.getPath;
|
|
||||||
if ( options.id )
|
|
||||||
path += '/' + options.id;
|
|
||||||
return this._requestPath(path, {
|
|
||||||
cacheKey: '.', // Right now, do not cache any "get" method
|
|
||||||
success: options.success,
|
|
||||||
fail: options.fail
|
|
||||||
|
|
||||||
});
|
|
||||||
},
|
|
||||||
list: function(success_fnc, fail_fnc) { // This is "almost" an alias for get
|
|
||||||
return this.get({
|
|
||||||
id: '',
|
|
||||||
success: success_fnc,
|
|
||||||
fail: fail_fnc
|
|
||||||
});
|
|
||||||
},
|
|
||||||
overview: function(success_fnc, fail_fnc) {
|
|
||||||
return this.get({
|
|
||||||
id: 'overview',
|
|
||||||
success: success_fnc,
|
|
||||||
fail: fail_fnc
|
|
||||||
});
|
|
||||||
},
|
|
||||||
item: function(itemId, success_fnc, fail_fnc) {
|
|
||||||
return this.get({
|
|
||||||
id: itemId,
|
|
||||||
success: success_fnc,
|
|
||||||
fail: fail_fnc
|
|
||||||
});
|
|
||||||
|
|
||||||
},
|
|
||||||
// -------------
|
|
||||||
// Log methods
|
|
||||||
// -------------
|
|
||||||
getLogs: function(itemId, success_fnc, fail_fnc) {
|
|
||||||
var path = this.logPath + '/' + itemId + '/' + 'log';
|
|
||||||
return this._requestPath(path, {
|
|
||||||
cacheKey: '.',
|
|
||||||
success: success_fnc,
|
|
||||||
fail: fail_fnc
|
|
||||||
});
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
// -------------
|
|
||||||
// Put methods
|
|
||||||
// -------------
|
|
||||||
|
|
||||||
put: function(data, options) {
|
|
||||||
options = options || {};
|
|
||||||
|
|
||||||
var path = this.putPath;
|
|
||||||
if ( options.id )
|
|
||||||
path += '/' + options.id;
|
|
||||||
|
|
||||||
api.putJson(path, data, {
|
|
||||||
success: options.success,
|
|
||||||
fail: options.fail
|
|
||||||
});
|
|
||||||
},
|
|
||||||
create: function(data, success_fnc, fail_fnc) {
|
|
||||||
|
|
||||||
return this.put(data, {
|
|
||||||
success: success_fnc,
|
|
||||||
fail: fail_fnc
|
|
||||||
});
|
|
||||||
},
|
|
||||||
save: function(data, success_fnc, fail_fnc) {
|
|
||||||
|
|
||||||
return this.put(data, {
|
|
||||||
id: data.id,
|
|
||||||
success: success_fnc,
|
|
||||||
fail: fail_fnc
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
// Testing
|
|
||||||
test: function(type, data, success_fnc, fail_fnc) {
|
|
||||||
var path = this.testPath + '/' + type;
|
|
||||||
|
|
||||||
api.putJson(path, data, {
|
|
||||||
success: success_fnc,
|
|
||||||
fail: fail_fnc,
|
|
||||||
method: 'POST'
|
|
||||||
});
|
|
||||||
},
|
|
||||||
// --------------
|
|
||||||
// Delete
|
|
||||||
// --------------
|
|
||||||
del: function(id, success_fnc, fail_fnc) {
|
|
||||||
var path = this.delPath + '/' + id;
|
|
||||||
|
|
||||||
api.deleteJson(path, {
|
|
||||||
success: success_fnc,
|
|
||||||
fail: fail_fnc
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
// --------------
|
|
||||||
// Types methods
|
|
||||||
// --------------
|
|
||||||
types : function(success_fnc, fail_fnc) {
|
|
||||||
return this._requestPath(this.typesPath, {
|
|
||||||
cacheKey: this.typesPath,
|
|
||||||
success: success_fnc,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
gui: function(typeName, success_fnc, fail_fnc) {
|
|
||||||
// GUI returns a dict, that contains:
|
|
||||||
// name: Name of the field
|
|
||||||
// value: value of the field (selected element in choice, text for inputs, etc....)
|
|
||||||
// gui: Description of the field (type, value or values, defvalue, ....
|
|
||||||
|
|
||||||
var path;
|
|
||||||
if( typeName !== undefined ) {
|
|
||||||
path = [this.guiPath, typeName].join('/');
|
|
||||||
} else {
|
|
||||||
path = this.guiPath;
|
|
||||||
}
|
|
||||||
return this._requestPath(path, {
|
|
||||||
cacheKey: '.', // Gui is not cacheable, it's dynamic and can change from call to call
|
|
||||||
success: success_fnc,
|
|
||||||
fail: fail_fnc,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
tableInfo : function(success_fnc, fail_fnc) {
|
|
||||||
success_fnc = success_fnc || function(){api.doLog('success not provided for tableInfo');};
|
|
||||||
|
|
||||||
var path = this.tableInfoPath;
|
|
||||||
this._requestPath(path, {
|
|
||||||
success: success_fnc,
|
|
||||||
fail: fail_fnc,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
detail: function(id, child, options) {
|
|
||||||
options = options || {};
|
|
||||||
return new DetailModelRestApi(this, id, child, options);
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
// For REST of type /auth/[id]/users, /services/[id]/users, ...
|
|
||||||
function DetailModelRestApi(parentApi, parentId, model, options) {
|
|
||||||
this.options = options;
|
|
||||||
this.base = new BasicModelRest([parentApi.path, parentId, model].join('/'));
|
|
||||||
}
|
|
||||||
|
|
||||||
DetailModelRestApi.prototype = {
|
|
||||||
// Generates a basic model with fixed methods for "detail" models
|
|
||||||
get: function(success_fnc, fail_fnc) {
|
|
||||||
return this.base.get(success_fnc, fail_fnc);
|
|
||||||
},
|
|
||||||
list: function(success_fnc, fail_fnc) { // This is "almost" an alias for get
|
|
||||||
return this.base.list(success_fnc, fail_fnc);
|
|
||||||
},
|
|
||||||
overview: function(success_fnc, fail_fnc) {
|
|
||||||
return this.base.overview(success_fnc, fail_fnc);
|
|
||||||
},
|
|
||||||
item: function(itemId, success_fnc, fail_fnc) {
|
|
||||||
return this.base.item(itemId, success_fnc, fail_fnc);
|
|
||||||
},
|
|
||||||
// -------------
|
|
||||||
// Log methods
|
|
||||||
// -------------
|
|
||||||
getLogs: function(itemId, success_fnc, fail_fnc) {
|
|
||||||
return this.base.getLogs(itemId, success_fnc, fail_fnc);
|
|
||||||
},
|
|
||||||
// Put methods
|
|
||||||
put: function(data, options) {
|
|
||||||
return this.base.put(data, options);
|
|
||||||
},
|
|
||||||
create: function(data, success_fnc, fail_fnc) {
|
|
||||||
|
|
||||||
return this.put(data, {
|
|
||||||
success: success_fnc,
|
|
||||||
fail: fail_fnc
|
|
||||||
});
|
|
||||||
},
|
|
||||||
save: function(data, success_fnc, fail_fnc) {
|
|
||||||
return this.put(data, {
|
|
||||||
id: data.id,
|
|
||||||
success: success_fnc,
|
|
||||||
fail: fail_fnc
|
|
||||||
});
|
|
||||||
},
|
|
||||||
// Testing
|
|
||||||
test: function(type, data, success_fnc, fail_fnc) {
|
|
||||||
return this.base.test(type, data, success_fnc, fail_fnc);
|
|
||||||
},
|
|
||||||
// --------------
|
|
||||||
// Delete
|
|
||||||
// --------------
|
|
||||||
del: function(id, success_fnc, fail_fnc) {
|
|
||||||
return this.base.del(id, success_fnc, fail_fnc);
|
|
||||||
},
|
|
||||||
|
|
||||||
tableInfo: function(success_fnc, fail_fnc) {
|
|
||||||
return this.base.tableInfo(success_fnc, fail_fnc);
|
|
||||||
},
|
|
||||||
types: function(success_fnc, fail_fnc) {
|
|
||||||
if( this.options.types ) {
|
|
||||||
this.options.types(success_fnc, fail_fnc);
|
|
||||||
} else {
|
|
||||||
return this.base.types(success_fnc, fail_fnc);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
gui: function(typeName, success_fnc, fail_fnc) { // Typename can be "undefined" to request MAIN gui (it it exists ofc..)
|
|
||||||
return this.base.gui(typeName, success_fnc, fail_fnc);
|
|
||||||
},
|
|
||||||
|
|
||||||
// Generic "Invoke" method (with no args, if needed, put them on "method" after "?" as normal url would be
|
|
||||||
invoke: function(method, success_fnc, fail_fnc) {
|
|
||||||
return this.base.get({
|
|
||||||
id: method,
|
|
||||||
success: success_fnc,
|
|
||||||
fail: fail_fnc
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
// Populate api
|
|
||||||
|
|
||||||
api.providers = new BasicModelRest('providers');
|
|
||||||
// all services method used in providers
|
|
||||||
api.providers.allServices = function(success_fnc, fail_fnc) {
|
|
||||||
return this.get({
|
|
||||||
id: 'allservices',
|
|
||||||
success: success_fnc,
|
|
||||||
fail: fail_fnc
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
api.providers.service = function(id, success_fnc, fail_fnc) {
|
|
||||||
return this.get({
|
|
||||||
id: 'service/' + id,
|
|
||||||
success: success_fnc,
|
|
||||||
fail: fail_fnc
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
api.authenticators = new BasicModelRest('authenticators');
|
|
||||||
// Search method used in authenticators
|
|
||||||
api.authenticators.search = function(id, type, term, success_fnc, fail_fnc) {
|
|
||||||
return this.get({
|
|
||||||
id: id + '/search?type=' + encodeURIComponent(type) + '&term=' + encodeURIComponent(term),
|
|
||||||
success: success_fnc,
|
|
||||||
fail: fail_fnc
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
api.osmanagers = new BasicModelRest('osmanagers');
|
|
||||||
api.transports = new BasicModelRest('transports');
|
|
||||||
api.networks = new BasicModelRest('networks');
|
|
||||||
api.servicesPools = new BasicModelRest('servicespools');
|
|
||||||
|
|
||||||
api.configuration = new BasicModelRest('config');
|
|
||||||
|
|
||||||
api.system = new BasicModelRest('system');
|
|
||||||
api.system.stats = function(type, success_fnc, fail_fnc) {
|
|
||||||
return this.get({
|
|
||||||
id: 'stats/' + type,
|
|
||||||
success: success_fnc,
|
|
||||||
fail: fail_fnc
|
|
||||||
});
|
|
||||||
};
|
|
||||||
}(window.api = window.api || {}, jQuery));
|
|
@ -1,388 +0,0 @@
|
|||||||
/* jshint strict: true */
|
|
||||||
gui.authenticators = new GuiElement(api.authenticators, 'auth');
|
|
||||||
|
|
||||||
gui.authenticators.link = function(event) {
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
// Button definition to trigger "Test" action
|
|
||||||
var testButton = {
|
|
||||||
testButton: {
|
|
||||||
text: gettext('Test authenticator'),
|
|
||||||
css: 'btn-info',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
// Clears the log of the detail, in this case, the log of "users"
|
|
||||||
// Memory saver :-)
|
|
||||||
var detailLogTable = null;
|
|
||||||
var clearDetailLog = function() {
|
|
||||||
if( detailLogTable ) {
|
|
||||||
var $tbl = $(detailLogTable).dataTable();
|
|
||||||
$tbl.fnClearTable();
|
|
||||||
$tbl.fnDestroy();
|
|
||||||
$('#user-log-placeholder').empty();
|
|
||||||
detailLogTable = null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Clears the details
|
|
||||||
// Memory saver :-)
|
|
||||||
var prevTables = [];
|
|
||||||
var clearDetails = function() {
|
|
||||||
$.each(prevTables, function(undefined, tbl){
|
|
||||||
var $tbl = $(tbl).dataTable();
|
|
||||||
$tbl.fnClearTable();
|
|
||||||
$tbl.fnDestroy();
|
|
||||||
});
|
|
||||||
|
|
||||||
clearDetailLog();
|
|
||||||
|
|
||||||
$('#users-placeholder').empty();
|
|
||||||
$('#groups-placeholder').empty();
|
|
||||||
$('#logs-placeholder').empty();
|
|
||||||
|
|
||||||
$('#detail-placeholder').addClass('hidden');
|
|
||||||
|
|
||||||
prevTables = [];
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// Search button event generator for user/group
|
|
||||||
var searchForm = function(parentModalId, type, id, title, searchLabel, resultsLabel) {
|
|
||||||
var errorModal = gui.failRequestModalFnc(gettext('Search error'));
|
|
||||||
var srcSelector = parentModalId + ' input[name="name"]';
|
|
||||||
|
|
||||||
$(parentModalId + ' .button-search').on('click', function() {
|
|
||||||
api.templates.get('search', function(tmpl) { // Get form template
|
|
||||||
var modalId = gui.launchModal(title, api.templates.evaluate(tmpl, {
|
|
||||||
search_label : searchLabel,
|
|
||||||
results_label : resultsLabel,
|
|
||||||
}), { actionButton: '<button type="button" class="btn btn-success button-accept">' + gettext('Accept') + '</button>'});
|
|
||||||
|
|
||||||
var $searchInput = $(modalId + ' input[name="search"]');
|
|
||||||
var $select = $(modalId + ' select[name="results"]');
|
|
||||||
var $searchButton = $(modalId + ' .button-do-search');
|
|
||||||
var $saveButton = $(modalId + ' .button-accept');
|
|
||||||
|
|
||||||
$searchInput.val($(srcSelector).val());
|
|
||||||
|
|
||||||
$saveButton.on('click', function(){
|
|
||||||
var value = $select.val();
|
|
||||||
if( value ) {
|
|
||||||
$(srcSelector).val(value);
|
|
||||||
$(modalId).modal('hide');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
$searchButton.on('click', function() {
|
|
||||||
$searchButton.addClass('disabled');
|
|
||||||
var term = $searchInput.val();
|
|
||||||
api.authenticators.search(id, type, term, function(data) {
|
|
||||||
$searchButton.removeClass('disabled');
|
|
||||||
$select.empty();
|
|
||||||
gui.doLog(data);
|
|
||||||
$.each(data, function(undefined, value) {
|
|
||||||
$select.append('<option value="' + value.id + '">' + value.id + ' (' + value.name + ')</option>');
|
|
||||||
});
|
|
||||||
}, function(jqXHR, textStatus, errorThrown) {
|
|
||||||
$searchButton.removeClass('disabled');
|
|
||||||
errorModal(jqXHR, textStatus, errorThrown);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
$(modalId + ' form').submit(function(event){
|
|
||||||
event.preventDefault();
|
|
||||||
$searchButton.click();
|
|
||||||
});
|
|
||||||
|
|
||||||
if( $searchInput.val() !== '') {
|
|
||||||
$searchButton.click();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
api.templates.get('authenticators', function(tmpl) {
|
|
||||||
gui.clearWorkspace();
|
|
||||||
gui.appendToWorkspace(api.templates.evaluate(tmpl, {
|
|
||||||
auths : 'auths-placeholder',
|
|
||||||
users : 'users-placeholder',
|
|
||||||
users_log : 'users-log-placeholder',
|
|
||||||
groups: 'groups-placeholder',
|
|
||||||
logs: 'logs-placeholder',
|
|
||||||
}));
|
|
||||||
gui.setLinksEvents();
|
|
||||||
|
|
||||||
// Append tabs click events
|
|
||||||
$('.bottom_tabs').on('click', function(event){
|
|
||||||
gui.doLog(event.target);
|
|
||||||
setTimeout(function(){
|
|
||||||
$($(event.target).attr('href') + ' span.fa-refresh').click();
|
|
||||||
}, 10);
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
var tableId = gui.authenticators.table({
|
|
||||||
container : 'auths-placeholder',
|
|
||||||
rowSelect : 'single',
|
|
||||||
buttons : [ 'new', 'edit', 'delete', 'xls' ],
|
|
||||||
onRowDeselect: function() {
|
|
||||||
clearDetails();
|
|
||||||
},
|
|
||||||
onRowSelect : function(selected) {
|
|
||||||
|
|
||||||
// We can have lots of users, so memory can grow up rapidly if we do not keep thins clena
|
|
||||||
// To do so, we empty previous table contents before storing new table contents
|
|
||||||
// Anyway, TabletTools will keep "leaking" memory, but we can handle a little "leak" that will be fixed as soon as we change the section
|
|
||||||
clearDetails();
|
|
||||||
$('#detail-placeholder').removeClass('hidden');
|
|
||||||
|
|
||||||
gui.tools.blockUI();
|
|
||||||
var id = selected[0].id;
|
|
||||||
var type = gui.authenticators.types[selected[0].type];
|
|
||||||
gui.doLog('Type', type);
|
|
||||||
|
|
||||||
var user = new GuiElement(api.authenticators.detail(id, 'users'), 'users');
|
|
||||||
var group = new GuiElement(api.authenticators.detail(id, 'groups'), 'groups');
|
|
||||||
|
|
||||||
|
|
||||||
var grpTable = group.table({
|
|
||||||
container : 'groups-placeholder',
|
|
||||||
rowSelect : 'single',
|
|
||||||
buttons : [ 'new', 'edit', 'delete', 'xls' ],
|
|
||||||
onLoad: function(k) {
|
|
||||||
gui.tools.unblockUI();
|
|
||||||
},
|
|
||||||
onEdit: function(value, event, table, refreshFnc) {
|
|
||||||
var exec = function(groups_all) {
|
|
||||||
gui.tools.blockUI();
|
|
||||||
api.templates.get('group', function(tmpl) { // Get form template
|
|
||||||
group.rest.item(value.id, function(item){ // Get item to edit
|
|
||||||
// Creates modal
|
|
||||||
var modalId = gui.launchModal(gettext('Edit group') + ' <b>' + item.name + '</b>', api.templates.evaluate(tmpl, {
|
|
||||||
id: item.id,
|
|
||||||
type: item.type,
|
|
||||||
groupname: item.name,
|
|
||||||
groupname_label: type.groupNameLabel,
|
|
||||||
comments: item.comments,
|
|
||||||
state: item.state,
|
|
||||||
external: type.isExternal,
|
|
||||||
canSearchGroups: type.canSearchGroups,
|
|
||||||
groups: item.groups,
|
|
||||||
groups_all: groups_all
|
|
||||||
}));
|
|
||||||
|
|
||||||
gui.tools.applyCustoms(modalId);
|
|
||||||
gui.tools.unblockUI();
|
|
||||||
|
|
||||||
$(modalId + ' .button-accept').click(function(){
|
|
||||||
var fields = gui.forms.read(modalId);
|
|
||||||
gui.doLog('Fields', fields);
|
|
||||||
group.rest.save(fields, function(data) { // Success on put
|
|
||||||
$(modalId).modal('hide');
|
|
||||||
refreshFnc();
|
|
||||||
gui.notify(gettext('Group saved'), 'success');
|
|
||||||
}, gui.failRequestModalFnc("Error saving group", true));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
if( value.type == 'meta' ) {
|
|
||||||
// Meta will get all groups
|
|
||||||
group.rest.overview(function(groups) {
|
|
||||||
exec(groups);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
exec();
|
|
||||||
}
|
|
||||||
|
|
||||||
},
|
|
||||||
onNew : function(t, table, refreshFnc) {
|
|
||||||
var exec = function(groups_all) {
|
|
||||||
gui.tools.blockUI();
|
|
||||||
api.templates.get('group', function(tmpl) { // Get form template
|
|
||||||
// Creates modal
|
|
||||||
var modalId = gui.launchModal(gettext('New group'), api.templates.evaluate(tmpl, {
|
|
||||||
type: t,
|
|
||||||
groupname_label: type.groupNameLabel,
|
|
||||||
external: type.isExternal,
|
|
||||||
canSearchGroups: type.canSearchGroups,
|
|
||||||
groups: [],
|
|
||||||
groups_all: groups_all
|
|
||||||
}));
|
|
||||||
gui.tools.unblockUI();
|
|
||||||
|
|
||||||
gui.tools.applyCustoms(modalId);
|
|
||||||
|
|
||||||
searchForm(modalId, 'group', id, gettext('Search groups'), gettext('Group'), gettext('Groups found')); // Enable search button click, if it exist ofc
|
|
||||||
|
|
||||||
$(modalId + ' .button-accept').click(function(){
|
|
||||||
var fields = gui.forms.read(modalId);
|
|
||||||
gui.doLog('Fields', fields);
|
|
||||||
group.rest.create(fields, function(data) { // Success on put
|
|
||||||
$(modalId).modal('hide');
|
|
||||||
refreshFnc();
|
|
||||||
gui.notify(gettext('Group saved'), 'success');
|
|
||||||
}, gui.failRequestModalFnc(gettext("Group saving error"), true));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
if( t == 'meta' ) {
|
|
||||||
// Meta will get all groups
|
|
||||||
group.rest.overview(function(groups) {
|
|
||||||
exec(groups);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
exec();
|
|
||||||
}
|
|
||||||
|
|
||||||
},
|
|
||||||
onDelete: gui.methods.del(group, gettext('Delete group'), gettext('Group deletion error')),
|
|
||||||
|
|
||||||
});
|
|
||||||
var tmpLogTable = null;
|
|
||||||
|
|
||||||
// New button will only be shown on authenticators that can create new users
|
|
||||||
var usrButtons = ['edit', 'delete', 'xls'];
|
|
||||||
if( type.canCreateUsers ) {
|
|
||||||
usrButtons = ['new'].concat(usrButtons); // New is first button
|
|
||||||
}
|
|
||||||
|
|
||||||
var usrTable = user.table({
|
|
||||||
container : 'users-placeholder',
|
|
||||||
rowSelect : 'single',
|
|
||||||
onRowSelect: function(uselected) {
|
|
||||||
gui.tools.blockUI();
|
|
||||||
var uId = uselected[0].id;
|
|
||||||
|
|
||||||
clearDetailLog();
|
|
||||||
|
|
||||||
tmpLogTable = user.logTable(uId, {
|
|
||||||
container: 'users-log-placeholder',
|
|
||||||
onLoad: function() {
|
|
||||||
detailLogTable = tmpLogTable;
|
|
||||||
gui.tools.unblockUI();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
onRowDeselect : function() {
|
|
||||||
clearDetailLog();
|
|
||||||
},
|
|
||||||
buttons : usrButtons,
|
|
||||||
deferedRender: true, // Use defered rendering for users, this table can be "huge"
|
|
||||||
scrollToTable : false,
|
|
||||||
onLoad: function(k) {
|
|
||||||
gui.tools.unblockUI();
|
|
||||||
},
|
|
||||||
onRefresh : function() {
|
|
||||||
$('#users-log-placeholder').empty(); // Remove logs on detail refresh
|
|
||||||
},
|
|
||||||
onEdit: function(value, event, table, refreshFnc) {
|
|
||||||
var password = "#æð~¬ŋ@æß”¢€~½¬@#~þ¬@|"; // Garbage for password (to detect change)
|
|
||||||
gui.tools.blockUI();
|
|
||||||
api.templates.get('user', function(tmpl) { // Get form template
|
|
||||||
group.rest.overview(function(groups) { // Get groups
|
|
||||||
user.rest.item(value.id, function(item){ // Get item to edit
|
|
||||||
|
|
||||||
// Creates modal
|
|
||||||
var modalId = gui.launchModal(gettext('Edit user') + ' <b>' + value.name + '</b>', api.templates.evaluate(tmpl, {
|
|
||||||
id: item.id,
|
|
||||||
username: item.name,
|
|
||||||
username_label: type.userNameLabel,
|
|
||||||
realname: item.real_name,
|
|
||||||
comments: item.comments,
|
|
||||||
state: item.state,
|
|
||||||
staff_member: item.staff_member,
|
|
||||||
is_admin: item.is_admin,
|
|
||||||
needs_password: type.needsPassword,
|
|
||||||
password: type.needsPassword ? password : undefined,
|
|
||||||
password_label: type.passwordLabel,
|
|
||||||
groups_all: groups,
|
|
||||||
groups: item.groups,
|
|
||||||
external: type.isExternal,
|
|
||||||
canSearchUsers: type.canSearchUsers,
|
|
||||||
}));
|
|
||||||
|
|
||||||
gui.tools.applyCustoms(modalId);
|
|
||||||
|
|
||||||
gui.tools.unblockUI();
|
|
||||||
|
|
||||||
$(modalId + ' .button-accept').click(function(){
|
|
||||||
var fields = gui.forms.read(modalId);
|
|
||||||
// If needs password, and password has changed
|
|
||||||
gui.doLog('passwords', type.needsPassword, password, fields.password);
|
|
||||||
if( type.needsPassword ) {
|
|
||||||
if( fields.password == password)
|
|
||||||
delete fields.password;
|
|
||||||
}
|
|
||||||
gui.doLog('Fields', fields);
|
|
||||||
user.rest.save(fields, function(data) { // Success on put
|
|
||||||
$(modalId).modal('hide');
|
|
||||||
refreshFnc();
|
|
||||||
gui.notify(gettext('User saved'), 'success');
|
|
||||||
}, gui.failRequestModalFnc(gettext("User saving error"), true));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},
|
|
||||||
onNew: function(undefined, table, refreshFnc) {
|
|
||||||
gui.tools.blockUI();
|
|
||||||
api.templates.get('user', function(tmpl) { // Get form template
|
|
||||||
group.rest.overview(function(groups) { // Get groups
|
|
||||||
// Creates modal
|
|
||||||
var modalId = gui.launchModal(gettext('New user'), api.templates.evaluate(tmpl, {
|
|
||||||
username_label: type.userNameLabel,
|
|
||||||
needs_password: type.needsPassword,
|
|
||||||
password_label: type.passwordLabel,
|
|
||||||
groups_all: groups,
|
|
||||||
groups: [],
|
|
||||||
external: type.isExternal,
|
|
||||||
canSearchUsers: type.canSearchUsers,
|
|
||||||
}));
|
|
||||||
|
|
||||||
gui.tools.applyCustoms(modalId);
|
|
||||||
|
|
||||||
gui.tools.unblockUI();
|
|
||||||
|
|
||||||
searchForm(modalId, 'user', id, gettext('Search users'), gettext('User'), gettext('Users found')); // Enable search button click, if it exist ofc
|
|
||||||
|
|
||||||
$(modalId + ' .button-accept').click(function(){
|
|
||||||
var fields = gui.forms.read(modalId);
|
|
||||||
// If needs password, and password has changed
|
|
||||||
gui.doLog('Fields', fields);
|
|
||||||
user.rest.create(fields, function(data) { // Success on put
|
|
||||||
$(modalId).modal('hide');
|
|
||||||
refreshFnc();
|
|
||||||
gui.notify(gettext('User saved'), 'success');
|
|
||||||
}, gui.failRequestModalFnc(gettext("User saving error"), true));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},
|
|
||||||
onDelete: gui.methods.del(user, gettext('Delete user'), gettext('User deletion error')),
|
|
||||||
});
|
|
||||||
|
|
||||||
var logTable = gui.authenticators.logTable(id, {
|
|
||||||
container : 'logs-placeholder',
|
|
||||||
});
|
|
||||||
|
|
||||||
// So we can destroy the tables beforing adding new ones
|
|
||||||
prevTables.push(grpTable);
|
|
||||||
prevTables.push(usrTable);
|
|
||||||
prevTables.push(logTable);
|
|
||||||
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
onRefresh : function() {
|
|
||||||
$('#users-placeholder').empty(); // Remove detail on parent refresh
|
|
||||||
},
|
|
||||||
onNew : gui.methods.typedNew(gui.authenticators, gettext('New authenticator'), gettext('Authenticator creation error'),testButton),
|
|
||||||
onEdit: gui.methods.typedEdit(gui.authenticators, gettext('Edit authenticator'), gettext('Authenticator saving error'), testButton),
|
|
||||||
onDelete: gui.methods.del(gui.authenticators, gettext('Delete authenticator'), gettext('Authenticator deletion error')),
|
|
||||||
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
return false;
|
|
||||||
};
|
|
@ -1,48 +0,0 @@
|
|||||||
// Tools
|
|
||||||
gui.configuration = new BasicGuiElement('Clear cache');
|
|
||||||
gui.configuration.link = function() {
|
|
||||||
"use strict";
|
|
||||||
api.templates.get('configuration', function(tmpl) {
|
|
||||||
api.configuration.overview(function(data){
|
|
||||||
gui.doLog(data);
|
|
||||||
gui.clearWorkspace();
|
|
||||||
gui.appendToWorkspace(api.templates.evaluate(tmpl, {
|
|
||||||
config: data,
|
|
||||||
}));
|
|
||||||
gui.setLinksEvents();
|
|
||||||
|
|
||||||
$('#form_config .form-control').each(function(i, element){
|
|
||||||
$(element).attr('data-val', $(element).val());
|
|
||||||
});
|
|
||||||
|
|
||||||
// Add handlers to buttons
|
|
||||||
$('#form_config .button-undo').on('click', function(event){
|
|
||||||
var fld = $(this).attr('data-fld');
|
|
||||||
gui.doLog(fld,$('#'+fld).val());
|
|
||||||
$('#'+fld).val($('#'+fld).attr('data-val'));
|
|
||||||
});
|
|
||||||
|
|
||||||
$('#form_config .button-save').on('click', function(event){
|
|
||||||
var cfg = {};
|
|
||||||
$('#form_config .form-control').each(function(i, element){
|
|
||||||
var $element = $(element);
|
|
||||||
if( $element.attr('data-val') != $element.val()) {
|
|
||||||
var section = $element.attr('data-section');
|
|
||||||
var key = $element.attr('data-key');
|
|
||||||
if( cfg[section] === undefined ) {
|
|
||||||
cfg[section] = {};
|
|
||||||
}
|
|
||||||
cfg[section][key] = { value: $element.val() };
|
|
||||||
}
|
|
||||||
});
|
|
||||||
gui.doLog(cfg);
|
|
||||||
if( !$.isEmptyObject(cfg) ) {
|
|
||||||
api.configuration.save(cfg, function(){
|
|
||||||
gui.showDashboard();
|
|
||||||
gui.notify(gettext('Configuration saved'), 'success');
|
|
||||||
}, gui.failRequestModalFnc);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}, gui.failRequestModalFnc);
|
|
||||||
});
|
|
||||||
};
|
|
@ -1,34 +0,0 @@
|
|||||||
/* jshint strict: true */
|
|
||||||
gui.connectivity = {
|
|
||||||
transports : new GuiElement(api.transports, 'trans'),
|
|
||||||
networks : new GuiElement(api.networks, 'nets'),
|
|
||||||
};
|
|
||||||
|
|
||||||
gui.connectivity.link = function(event) {
|
|
||||||
"use strict";
|
|
||||||
api.templates.get('connectivity', function(tmpl) {
|
|
||||||
gui.clearWorkspace();
|
|
||||||
gui.appendToWorkspace(api.templates.evaluate(tmpl, {
|
|
||||||
transports : 'transports-placeholder',
|
|
||||||
networks : 'networks-placeholder'
|
|
||||||
}));
|
|
||||||
|
|
||||||
gui.connectivity.transports.table({
|
|
||||||
rowSelect : 'single',
|
|
||||||
container : 'transports-placeholder',
|
|
||||||
buttons : [ 'new', 'edit', 'delete', 'xls' ],
|
|
||||||
onNew : gui.methods.typedNew(gui.connectivity.transports, gettext('New transport'), gettext('Transport creation error')),
|
|
||||||
onEdit: gui.methods.typedEdit(gui.connectivity.transports, gettext('Edit transport'), gettext('Transport saving error')),
|
|
||||||
onDelete: gui.methods.del(gui.connectivity.transports, gettext('Delete transport'), gettext('Transport deletion error')),
|
|
||||||
});
|
|
||||||
gui.connectivity.networks.table({
|
|
||||||
rowSelect : 'single',
|
|
||||||
container : 'networks-placeholder',
|
|
||||||
buttons : [ 'new', 'edit', 'delete', 'xls' ],
|
|
||||||
onNew : gui.methods.typedNew(gui.connectivity.networks, gettext('New network'), gettext('Network creation error')),
|
|
||||||
onEdit: gui.methods.typedEdit(gui.connectivity.networks, gettext('Edit network'), gettext('Network saving error')),
|
|
||||||
onDelete: gui.methods.del(gui.connectivity.networks, gettext('Delete network'), gettext('Network deletion error')),
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
};
|
|
@ -1,37 +0,0 @@
|
|||||||
gui.dashboard = new BasicGuiElement('Dashboard');
|
|
||||||
gui.dashboard.link = function(event) {
|
|
||||||
"use strict";
|
|
||||||
gui.clearWorkspace();
|
|
||||||
api.templates.get('dashboard', function(tmpl) {
|
|
||||||
api.system.overview(function(data){
|
|
||||||
|
|
||||||
gui.doLog('enter dashboard');
|
|
||||||
gui.appendToWorkspace(api.templates.evaluate(tmpl, {
|
|
||||||
users: data.users,
|
|
||||||
services: data.services,
|
|
||||||
user_services: data.user_services,
|
|
||||||
restrained_services_pools: data.restrained_services_pools,
|
|
||||||
}));
|
|
||||||
gui.setLinksEvents();
|
|
||||||
|
|
||||||
$.each(['assigned', 'inuse'], function(index, stat){
|
|
||||||
api.system.stats(stat, function(data) {
|
|
||||||
var d = [];
|
|
||||||
$.each(data, function(index, value){
|
|
||||||
d.push([value.stamp * 1000, value.value]);
|
|
||||||
});
|
|
||||||
gui.doLog('Data', d);
|
|
||||||
|
|
||||||
$.plot('#placeholder-' + stat + '-chart', [d], {
|
|
||||||
xaxis: {
|
|
||||||
mode: "time",
|
|
||||||
timeformat: api.tools.djangoFormat(django.formats.SHORT_DATE_FORMAT)
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
};
|
|
@ -1,23 +0,0 @@
|
|||||||
//------------------------
|
|
||||||
// Os managers
|
|
||||||
//------------------------
|
|
||||||
gui.osmanagers = new GuiElement(api.osmanagers, 'osm');
|
|
||||||
gui.osmanagers.link = function(event) {
|
|
||||||
"use strict";
|
|
||||||
api.templates.get('osmanagers', function(tmpl) {
|
|
||||||
gui.clearWorkspace();
|
|
||||||
gui.appendToWorkspace(api.templates.evaluate(tmpl, {
|
|
||||||
osmanagers: 'osmanagers-placeholder',
|
|
||||||
}));
|
|
||||||
|
|
||||||
|
|
||||||
gui.osmanagers.table({
|
|
||||||
container : 'osmanagers-placeholder',
|
|
||||||
rowSelect : 'single',
|
|
||||||
buttons : [ 'new', 'edit', 'delete', 'xls' ],
|
|
||||||
onNew : gui.methods.typedNew(gui.osmanagers, gettext('New OSManager'), gettext('OSManager creation error')),
|
|
||||||
onEdit: gui.methods.typedEdit(gui.osmanagers, gettext('Edit OSManager'), gettext('OSManager saving error')),
|
|
||||||
onDelete: gui.methods.del(gui.osmanagers, gettext('Delete OSManager'), gettext('OSManager deletion error')),
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
@ -1,144 +0,0 @@
|
|||||||
/* jshint strict: true */
|
|
||||||
gui.providers = new GuiElement(api.providers, 'provi');
|
|
||||||
gui.providers.link = function(event) {
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
// Button definition to trigger "Test" action
|
|
||||||
var testButton = {
|
|
||||||
testButton: {
|
|
||||||
text: gettext('Test'),
|
|
||||||
css: 'btn-info',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
var detailLogTable = null;
|
|
||||||
var clearDetailLog = function() {
|
|
||||||
if( detailLogTable ) {
|
|
||||||
var $tbl = $(detailLogTable).dataTable();
|
|
||||||
$tbl.fnClearTable();
|
|
||||||
$tbl.fnDestroy();
|
|
||||||
$('#services-log-placeholder').empty();
|
|
||||||
detailLogTable = undefined;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var prevTables = [];
|
|
||||||
var clearDetails = function() {
|
|
||||||
gui.doLog('Clearing details');
|
|
||||||
$.each(prevTables, function(undefined, tbl){
|
|
||||||
var $tbl = $(tbl).dataTable();
|
|
||||||
$tbl.fnClearTable();
|
|
||||||
$tbl.fnDestroy();
|
|
||||||
});
|
|
||||||
|
|
||||||
clearDetailLog();
|
|
||||||
|
|
||||||
prevTables = [];
|
|
||||||
$('#services-placeholder').empty();
|
|
||||||
$('#logs-placeholder').empty();
|
|
||||||
|
|
||||||
$('#detail-placeholder').addClass('hidden');
|
|
||||||
};
|
|
||||||
|
|
||||||
api.templates.get('providers', function(tmpl) {
|
|
||||||
gui.clearWorkspace();
|
|
||||||
gui.appendToWorkspace(api.templates.evaluate(tmpl, {
|
|
||||||
providers : 'providers-placeholder',
|
|
||||||
services : 'services-placeholder',
|
|
||||||
services_log : 'services-log-placeholder',
|
|
||||||
logs: 'logs-placeholder',
|
|
||||||
}));
|
|
||||||
gui.setLinksEvents();
|
|
||||||
|
|
||||||
// Append tabs click events
|
|
||||||
$('.bottom_tabs').on('click', function(event){
|
|
||||||
gui.doLog(event.target);
|
|
||||||
setTimeout(function(){
|
|
||||||
$($(event.target).attr('href') + ' span.fa-refresh').click();
|
|
||||||
}, 10);
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
var tableId = gui.providers.table({
|
|
||||||
container : 'providers-placeholder',
|
|
||||||
rowSelect : 'single',
|
|
||||||
onCheck : function(check, items) { // Check if item can be deleted
|
|
||||||
/*if( check == 'delete' ) {
|
|
||||||
for( var i in items ) {
|
|
||||||
if( items[i].services_count > 0)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}*/
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
onRowDeselect: function() {
|
|
||||||
clearDetails();
|
|
||||||
},
|
|
||||||
onRowSelect : function(selected) {
|
|
||||||
gui.tools.blockUI();
|
|
||||||
|
|
||||||
clearDetails();
|
|
||||||
$('#detail-placeholder').removeClass('hidden');
|
|
||||||
|
|
||||||
var id = selected[0].id;
|
|
||||||
// Giving the name compossed with type, will ensure that only styles will be reattached once
|
|
||||||
var services = new GuiElement(api.providers.detail(id, 'services'), 'services-'+selected[0].type);
|
|
||||||
|
|
||||||
var tmpLogTable = null;
|
|
||||||
var servicesTable = services.table({
|
|
||||||
container : 'services-placeholder',
|
|
||||||
rowSelect : 'single',
|
|
||||||
onRowSelect: function(sselected) {
|
|
||||||
gui.tools.blockUI();
|
|
||||||
var sId = sselected[0].id;
|
|
||||||
|
|
||||||
clearDetailLog();
|
|
||||||
|
|
||||||
tmpLogTable = services.logTable(sId, {
|
|
||||||
container: 'services-log-placeholder',
|
|
||||||
onLoad: function() {
|
|
||||||
detailLogTable = tmpLogTable;
|
|
||||||
gui.tools.unblockUI();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
onRowDeselect : function() {
|
|
||||||
clearDetailLog();
|
|
||||||
},
|
|
||||||
onCheck: function(check, items) {
|
|
||||||
if( check == 'delete' ) {
|
|
||||||
for( var i in items ) {
|
|
||||||
if( items[i].deployed_services_count > 0)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
buttons : [ 'new', 'edit', 'delete', 'xls' ],
|
|
||||||
onEdit : gui.methods.typedEdit(services, gettext('Edit service'), gettext('Service creation error'), testButton),
|
|
||||||
onNew : gui.methods.typedNew(services, gettext('New service'), gettext('Service saving error'), testButton),
|
|
||||||
onDelete: gui.methods.del(services, gettext('Delete service'), gettext('Service deletion error'), testButton),
|
|
||||||
scrollToTable : false,
|
|
||||||
onLoad: function(k) {
|
|
||||||
gui.tools.unblockUI();
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
var logTable = gui.providers.logTable(id, {
|
|
||||||
container : 'logs-placeholder',
|
|
||||||
});
|
|
||||||
|
|
||||||
prevTables.push(servicesTable);
|
|
||||||
prevTables.push(logTable);
|
|
||||||
},
|
|
||||||
buttons : [ 'new', 'edit', 'delete', 'xls' ],
|
|
||||||
onNew : gui.methods.typedNew(gui.providers, gettext('New services provider'), gettext('Services provider creation error'), testButton),
|
|
||||||
onEdit: gui.methods.typedEdit(gui.providers, gettext('Edit services provider'), gettext('Services Provider saving error'), testButton),
|
|
||||||
onDelete: gui.methods.del(gui.providers, gettext('Delete services provider'), gettext('Services Provider deletion error')),
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
return false;
|
|
||||||
};
|
|
@ -1,472 +0,0 @@
|
|||||||
/* jshint strict: true */
|
|
||||||
gui.servicesPools = new GuiElement(api.servicesPools, 'servicespools');
|
|
||||||
|
|
||||||
|
|
||||||
gui.servicesPools.link = function(event) {
|
|
||||||
"use strict";
|
|
||||||
gui.clearWorkspace();
|
|
||||||
|
|
||||||
// Clears the details
|
|
||||||
// Memory saver :-)
|
|
||||||
var prevTables = [];
|
|
||||||
var clearDetails = function() {
|
|
||||||
$.each(prevTables, function(undefined, tbl){
|
|
||||||
var $tbl = $(tbl).dataTable();
|
|
||||||
$tbl.fnClearTable();
|
|
||||||
$tbl.fnDestroy();
|
|
||||||
});
|
|
||||||
|
|
||||||
$('#assigned-services-placeholder_tbl').empty();
|
|
||||||
$('#assigned-services-placeholder_log').empty();
|
|
||||||
$('#cache-placeholder_tbl').empty();
|
|
||||||
$('#cache-placeholder_log').empty();
|
|
||||||
$('#transports-placeholder').empty();
|
|
||||||
$('#groups-placeholder').empty();
|
|
||||||
$('#logs-placeholder').empty();
|
|
||||||
|
|
||||||
$('#detail-placeholder').addClass('hidden');
|
|
||||||
|
|
||||||
prevTables = [];
|
|
||||||
};
|
|
||||||
|
|
||||||
// On change base service
|
|
||||||
var preFnc = function(formId) {
|
|
||||||
var $fld = $(formId + ' [name="service_id"]');
|
|
||||||
var $osmFld = $(formId + ' [name="osmanager_id"]');
|
|
||||||
var selectors = [];
|
|
||||||
$.each(['initial_srvs', 'cache_l1_srvs', 'cache_l2_srvs', 'max_srvs'], function(index, value){
|
|
||||||
selectors.push(formId + ' [name="' + value + '"]');
|
|
||||||
});
|
|
||||||
var $cacheFlds = $(selectors.join(','));
|
|
||||||
var $cacheL2Fld = $(formId + ' [name="cache_l2_srvs"]');
|
|
||||||
var $publishOnSaveFld = $(formId + ' [name="publish_on_save"]');
|
|
||||||
$fld.on('change', function(event){
|
|
||||||
if($fld.val() != -1 ) {
|
|
||||||
api.providers.service($fld.val(), function(data){
|
|
||||||
gui.doLog('Onchange', data);
|
|
||||||
if( data.info.needs_manager === false ) {
|
|
||||||
$osmFld.prop('disabled', 'disabled');
|
|
||||||
} else {
|
|
||||||
$osmFld.prop('disabled', false);
|
|
||||||
}
|
|
||||||
|
|
||||||
if( data.info.uses_cache === false ) {
|
|
||||||
$cacheFlds.prop('disabled', 'disabled');
|
|
||||||
} else {
|
|
||||||
$cacheFlds.prop('disabled', false);
|
|
||||||
if( data.info.uses_cache_l2 === false ) {
|
|
||||||
$cacheL2Fld.prop('disabled', 'disabled');
|
|
||||||
} else {
|
|
||||||
$cacheL2Fld.prop('disabled', false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if( data.info.needs_publication === false ) {
|
|
||||||
$publishOnSaveFld.bootstrapSwitch('setDisabled', true);
|
|
||||||
} else {
|
|
||||||
$publishOnSaveFld.bootstrapSwitch('setDisabled', false);
|
|
||||||
}
|
|
||||||
|
|
||||||
if($osmFld.hasClass('selectpicker'))
|
|
||||||
$osmFld.selectpicker('refresh');
|
|
||||||
|
|
||||||
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
// Fill "State" for cached and assigned services
|
|
||||||
var fillState = function(data) {
|
|
||||||
$.each(data, function(index, value){
|
|
||||||
if(value.state == 'U') {
|
|
||||||
if( value.os_state != '' && value.os_state != 'U')
|
|
||||||
value.state = gettext('Waiting OS');
|
|
||||||
else
|
|
||||||
value.state = gettext('Ready');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if(value.state == 'R'){
|
|
||||||
value.state = gettext('Waiting for removal');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if(value.state == 'M'){
|
|
||||||
value.state = gettext('Removing');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if(value.state == 'S'){
|
|
||||||
value.state = gettext('Removed');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if(value.state == 'E'){
|
|
||||||
value.state = gettext('Error');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if(value.state == 'P'){
|
|
||||||
value.state = gettext('Generating');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
value.state = gettext('Unknown');
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
// Fills up the list of available services
|
|
||||||
api.providers.allServices(function(services){
|
|
||||||
var availableServices = {};
|
|
||||||
|
|
||||||
$.each(services, function(undefined, service){
|
|
||||||
availableServices[service.id] = service;
|
|
||||||
});
|
|
||||||
|
|
||||||
gui.doLog('Available services', availableServices);
|
|
||||||
api.templates.get('services_pool', function(tmpl) {
|
|
||||||
gui.appendToWorkspace(api.templates.evaluate(tmpl, {
|
|
||||||
deployed_services : 'deployed-services-placeholder',
|
|
||||||
assigned_services : 'assigned-services-placeholder',
|
|
||||||
cache : 'cache-placeholder',
|
|
||||||
groups : 'groups-placeholder',
|
|
||||||
transports : 'transports-placeholder',
|
|
||||||
publications: 'publications-placeholder',
|
|
||||||
logs : 'logs-placeholder',
|
|
||||||
}));
|
|
||||||
gui.setLinksEvents();
|
|
||||||
|
|
||||||
// Append tabs click events
|
|
||||||
$('.bottom_tabs').on('click', function(event){
|
|
||||||
gui.doLog(event.target);
|
|
||||||
setTimeout(function(){
|
|
||||||
$($(event.target).attr('href') + ' span.fa-refresh').click();
|
|
||||||
}, 10);
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Services pools part
|
|
||||||
*/
|
|
||||||
var servicesPoolsTable = gui.servicesPools.table({
|
|
||||||
container : 'deployed-services-placeholder',
|
|
||||||
rowSelect : 'single',
|
|
||||||
buttons : [ 'new', 'edit', 'delete', 'xls' ],
|
|
||||||
onRowDeselect: function() {
|
|
||||||
clearDetails();
|
|
||||||
},
|
|
||||||
onRowSelect : function(selected) {
|
|
||||||
var servPool = selected[0];
|
|
||||||
gui.doLog('Selected services pool', servPool);
|
|
||||||
|
|
||||||
clearDetails();
|
|
||||||
|
|
||||||
var service = null;
|
|
||||||
try {
|
|
||||||
service = availableServices[servPool.service_id];
|
|
||||||
|
|
||||||
} catch (e) {
|
|
||||||
gui.doLog('Exception on rowSelect', e);
|
|
||||||
gui.notify('Service pool ' + gettext('error'), 'danger');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( service !== null )
|
|
||||||
$('#detail-placeholder').removeClass('hidden');
|
|
||||||
else {
|
|
||||||
$('#detail-placeholder').addClass('hidden');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Cache Part
|
|
||||||
*/
|
|
||||||
|
|
||||||
var cachedItems = null;
|
|
||||||
// If service does not supports cache, do not show it
|
|
||||||
// Shows/hides cache
|
|
||||||
if( service.info.uses_cache || service.info.uses_cache_l2 ) {
|
|
||||||
$('#cache-placeholder_tab').removeClass('hidden');
|
|
||||||
cachedItems = new GuiElement(api.servicesPools.detail(servPool.id, 'cache'), 'cache');
|
|
||||||
// Cached items table
|
|
||||||
var prevCacheLogTbl = null;
|
|
||||||
var cachedItemsTable = cachedItems.table({
|
|
||||||
container : 'cache-placeholder_tbl',
|
|
||||||
buttons : [ 'delete', 'xls' ],
|
|
||||||
rowSelect : 'single',
|
|
||||||
onData: function(data) {
|
|
||||||
fillState(data);
|
|
||||||
},
|
|
||||||
onRowSelect : function(selected) {
|
|
||||||
var cached = selected[0];
|
|
||||||
if( prevCacheLogTbl ) {
|
|
||||||
var $tbl = $(prevCacheLogTbl).dataTable();
|
|
||||||
$tbl.fnClearTable();
|
|
||||||
$tbl.fnDestroy();
|
|
||||||
}
|
|
||||||
prevCacheLogTbl = cachedItems.logTable(cached.id, {
|
|
||||||
container : 'cache-placeholder_log',
|
|
||||||
});
|
|
||||||
},
|
|
||||||
onDelete: gui.methods.del(cachedItems, gettext('Remove Cache element'), gettext('Deletion error')),
|
|
||||||
});
|
|
||||||
prevTables.push(cachedItemsTable);
|
|
||||||
} else {
|
|
||||||
$('#cache-placeholder_tab').addClass('hidden');
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Groups part
|
|
||||||
*/
|
|
||||||
|
|
||||||
var groups = null;
|
|
||||||
// Shows/hides groups
|
|
||||||
if( service.info.must_assign_manually === false ) {
|
|
||||||
$('#groups-placeholder_tab').removeClass('hidden');
|
|
||||||
groups = new GuiElement(api.servicesPools.detail(servPool.id, 'groups'), 'groups');
|
|
||||||
// Groups items table
|
|
||||||
var groupsTable = groups.table({
|
|
||||||
container : 'groups-placeholder',
|
|
||||||
rowSelect : 'single',
|
|
||||||
buttons : [ 'new', 'delete', 'xls' ],
|
|
||||||
onNew: function(value, table, refreshFnc) {
|
|
||||||
|
|
||||||
api.templates.get('pool_add_group', function(tmpl){
|
|
||||||
api.authenticators.overview(function(data){
|
|
||||||
var modalId = gui.launchModal(gettext('Add group'),api.templates.evaluate(tmpl, {
|
|
||||||
auths: data,
|
|
||||||
}));
|
|
||||||
|
|
||||||
$(modalId + ' #id_auth_select').on('change', function(event){
|
|
||||||
var auth = $(modalId + ' #id_auth_select').val();
|
|
||||||
|
|
||||||
api.authenticators.detail(auth, 'groups').overview(function(data){
|
|
||||||
var $select = $(modalId + ' #id_group_select');
|
|
||||||
$select.empty();
|
|
||||||
|
|
||||||
$.each(data, function(undefined, value){
|
|
||||||
$select.append('<option value="' + value.id + '">' + value.name + '</option>');
|
|
||||||
});
|
|
||||||
// Refresh selectpicker if item is such
|
|
||||||
if($select.hasClass('selectpicker'))
|
|
||||||
$select.selectpicker('refresh');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
$(modalId + ' .button-accept').on('click', function(event) {
|
|
||||||
var auth = $(modalId + ' #id_auth_select').val();
|
|
||||||
var group = $(modalId + ' #id_group_select').val();
|
|
||||||
if( auth == -1 || group == -1 ) {
|
|
||||||
gui.notify(gettext('You must provide authenticator and group'), 'danger');
|
|
||||||
} else { // Save & close modal
|
|
||||||
groups.rest.create({id: group}, function(data){
|
|
||||||
$(modalId).modal('hide');
|
|
||||||
refreshFnc();
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// Makes form "beautyfull" :-)
|
|
||||||
gui.tools.applyCustoms(modalId);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
},
|
|
||||||
onDelete: gui.methods.del(groups, gettext('Remove group'), gettext('Group removal error')),
|
|
||||||
onData : function(data) {
|
|
||||||
$.each(data, function(undefined, value){
|
|
||||||
value.group_name = '<b>' + value.auth_name + '</b>\\' + value.name;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
});
|
|
||||||
prevTables.push(groupsTable);
|
|
||||||
} else {
|
|
||||||
$('#groups-placeholder_tab').addClass('hidden');
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Assigned services part
|
|
||||||
*/
|
|
||||||
var prevAssignedLogTbl = null;
|
|
||||||
var assignedServices = new GuiElement(api.servicesPools.detail(servPool.id, 'services'), 'services');
|
|
||||||
var assignedServicesTable = assignedServices.table({
|
|
||||||
container: 'assigned-services-placeholder_tbl',
|
|
||||||
rowSelect: 'single',
|
|
||||||
buttons: service.info.must_assign_manually ? ['new', 'delete', 'xls'] : ['delete', 'xls'],
|
|
||||||
onRowSelect: function(selected) {
|
|
||||||
var service = selected[0];
|
|
||||||
if( prevAssignedLogTbl ) {
|
|
||||||
var $tbl = $(prevAssignedLogTbl).dataTable();
|
|
||||||
$tbl.fnClearTable();
|
|
||||||
$tbl.fnDestroy();
|
|
||||||
}
|
|
||||||
prevAssignedLogTbl = assignedServices.logTable(service.id, {
|
|
||||||
container : 'assigned-services-placeholder_log',
|
|
||||||
});
|
|
||||||
},
|
|
||||||
onDelete: gui.methods.del(assignedServices, gettext('Remove Assigned service'), gettext('Deletion error')),
|
|
||||||
});
|
|
||||||
// Log of assigned services (right under assigned services)
|
|
||||||
|
|
||||||
prevTables.push(assignedServicesTable);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Transports part
|
|
||||||
*/
|
|
||||||
|
|
||||||
var transports = new GuiElement(api.servicesPools.detail(servPool.id, 'transports'), 'transports');
|
|
||||||
// Transports items table
|
|
||||||
var transportsTable = transports.table({
|
|
||||||
container: 'transports-placeholder',
|
|
||||||
rowSelect: 'single',
|
|
||||||
buttons : [ 'new', 'delete', 'xls' ],
|
|
||||||
onNew: function(value, table, refreshFnc) {
|
|
||||||
|
|
||||||
api.templates.get('pool_add_transport', function(tmpl){
|
|
||||||
api.transports.overview(function(data){
|
|
||||||
var modalId = gui.launchModal(gettext('Add transport'),api.templates.evaluate(tmpl, {
|
|
||||||
transports: data,
|
|
||||||
}));
|
|
||||||
|
|
||||||
$(modalId + ' .button-accept').on('click', function(event) {
|
|
||||||
var transport = $(modalId + ' #id_transport_select').val();
|
|
||||||
if( transport == -1 ) {
|
|
||||||
gui.notify(gettext('You must provide a transport'), 'danger');
|
|
||||||
} else { // Save & close modal
|
|
||||||
transports.rest.create({id: transport}, function(data){
|
|
||||||
$(modalId).modal('hide');
|
|
||||||
refreshFnc();
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// Makes form "beautyfull" :-)
|
|
||||||
gui.tools.applyCustoms(modalId);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
},
|
|
||||||
onDelete: gui.methods.del(transports, gettext('Remove transport'), gettext('Transport removal error')),
|
|
||||||
onData: function(data) {
|
|
||||||
$.each(data, function(undefined, value){
|
|
||||||
var style = 'display:inline-block; background: url(data:image/png;base64,' +
|
|
||||||
value.type.icon + '); ' + 'width: 16px; height: 16px; vertical-align: middle;';
|
|
||||||
value.trans_type = value.type.name;
|
|
||||||
value.name = '<span style="' + style + '"></span> ' + value.name;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
prevTables.push(transportsTable);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Publications part
|
|
||||||
*/
|
|
||||||
var publications = null;
|
|
||||||
if( service.info.needs_publication ) {
|
|
||||||
$('#publications-placeholder_tab').removeClass('hidden');
|
|
||||||
var pubApi = api.servicesPools.detail(servPool.id, 'publications');
|
|
||||||
publications = new GuiElement(pubApi, 'publications');
|
|
||||||
// Publications table
|
|
||||||
var publicationsTable = publications.table({
|
|
||||||
container : 'publications-placeholder',
|
|
||||||
rowSelect : 'single',
|
|
||||||
buttons : [ 'new', {
|
|
||||||
text: gettext('Cancel'),
|
|
||||||
css: 'disabled',
|
|
||||||
click: function(val, value, btn, tbl, refreshFnc) {
|
|
||||||
gui.promptModal(gettext('Publish'), gettext('Cancel publication'),{
|
|
||||||
onYes: function() {
|
|
||||||
pubApi.invoke( val.id + '/cancel', function(){
|
|
||||||
refreshFnc();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
select: function(val, value, btn, tbl, refreshFnc) {
|
|
||||||
if( !val ) {
|
|
||||||
$(btn).removeClass('btn3d-info').addClass('disabled');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if( ['P','W','L'].indexOf(val.state) > 0 ) { // Waiting for publication, Preparing or running
|
|
||||||
$(btn).removeClass('disabled').addClass('btn3d-info');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
'xls' ],
|
|
||||||
onNew: function(action, tbl, refreshFnc) {
|
|
||||||
gui.promptModal(gettext('Publish'), gettext('Launch new publication?'), {
|
|
||||||
onYes: function() {
|
|
||||||
pubApi.invoke('publish', function(){
|
|
||||||
refreshFnc();
|
|
||||||
}, gui.failRequestModalFnc(gettext('Failed creating publication')) );
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
});
|
|
||||||
prevTables.push(publicationsTable);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
$('#publications-placeholder_tab').addClass('hidden');
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Log table
|
|
||||||
*/
|
|
||||||
|
|
||||||
var logTable = gui.servicesPools.logTable(servPool.id, {
|
|
||||||
container : 'logs-placeholder',
|
|
||||||
});
|
|
||||||
|
|
||||||
prevTables.push(logTable);
|
|
||||||
|
|
||||||
},
|
|
||||||
// Pre-process data received to add "icon" to deployed service
|
|
||||||
onData: function(data) {
|
|
||||||
gui.doLog('onData', data);
|
|
||||||
$.each(data, function(index, value){
|
|
||||||
try {
|
|
||||||
var service = availableServices[value.service_id];
|
|
||||||
if( service === undefined ) {
|
|
||||||
value.parent = gettext('undefined');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var style = 'display:inline-block; background: url(data:image/png;base64,' +
|
|
||||||
service.info.icon + '); ' + 'width: 16px; height: 16px; vertical-align: middle;';
|
|
||||||
|
|
||||||
if( value.restrained ) {
|
|
||||||
value.name = '<span class="fa fa-exclamation text-danger"></span> ' + value.name;
|
|
||||||
value.state = gettext('Restrained');
|
|
||||||
}
|
|
||||||
|
|
||||||
value.name = '<span style="' + style + '"></span> ' + value.name;
|
|
||||||
|
|
||||||
value.parent = service.name;
|
|
||||||
} catch (e) {
|
|
||||||
value.name = '<span class="fa fa-asterisk text-alert"></span> ' + value.name;
|
|
||||||
value.parent = gettext('unknown (needs reload)');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
onNew: gui.methods.typedNew(gui.servicesPools, gettext('New service pool'), 'Service pool ' + gettext('creation error'), {
|
|
||||||
guiProcessor: function(guiDef) { // Create has "save on publish" field
|
|
||||||
gui.doLog(guiDef);
|
|
||||||
var newDef = [].concat(guiDef).concat([{
|
|
||||||
'name': 'publish_on_save',
|
|
||||||
'value': true,
|
|
||||||
'gui': {
|
|
||||||
'label': gettext('Publish on creation'),
|
|
||||||
'tooltip': gettext('If selected, will initiate the publication inmediatly after creation'),
|
|
||||||
'type': 'checkbox',
|
|
||||||
'order': 150,
|
|
||||||
'defvalue': true,
|
|
||||||
},
|
|
||||||
}]);
|
|
||||||
gui.doLog(newDef);
|
|
||||||
return newDef;
|
|
||||||
},
|
|
||||||
preprocessor: preFnc,
|
|
||||||
}),
|
|
||||||
onEdit: gui.methods.typedEdit(gui.servicesPools, gettext('Edit') + ' service pool', 'Service pool ' + gettext('saving error')),
|
|
||||||
onDelete: gui.methods.del(gui.servicesPools, gettext('Delete') + ' service pool', 'Service pool ' + gettext('deletion error')),
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
};
|
|
@ -1,15 +0,0 @@
|
|||||||
/* jshint strict: true */
|
|
||||||
|
|
||||||
// Basic GUI components
|
|
||||||
|
|
||||||
// Tools
|
|
||||||
gui.clear_cache = new BasicGuiElement('Flush cache');
|
|
||||||
gui.clear_cache.link = function() {
|
|
||||||
"use strict";
|
|
||||||
api.getJson('cache/flush', {
|
|
||||||
success: function() {
|
|
||||||
gui.launchModal(gettext('Cache'), gettext('Cache has been flushed'), { actionButton: ' ' } );
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
};
|
|
@ -1,633 +0,0 @@
|
|||||||
/* jshint strict: true */
|
|
||||||
// Operations commmon to most elements
|
|
||||||
function BasicGuiElement(name) {
|
|
||||||
"use strict";
|
|
||||||
this.name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
function GuiElement(restItem, name, typesFunction) {
|
|
||||||
"use strict";
|
|
||||||
this.rest = restItem;
|
|
||||||
this.name = name;
|
|
||||||
this.types = {};
|
|
||||||
this.init();
|
|
||||||
}
|
|
||||||
|
|
||||||
// all gui elements has, at least, name && type
|
|
||||||
// Types must include, at least: type, icon
|
|
||||||
GuiElement.prototype = {
|
|
||||||
init : function() {
|
|
||||||
"use strict";
|
|
||||||
gui.doLog('Initializing ' + this.name);
|
|
||||||
var self = this;
|
|
||||||
this.rest.types(function(data) {
|
|
||||||
var styles = '';
|
|
||||||
var alreadyAttached = $('#gui-style-'+self.name).length !== 0;
|
|
||||||
$.each(data, function(index, value) {
|
|
||||||
var className = self.name + '-' + value.type;
|
|
||||||
self.types[value.type] = value;
|
|
||||||
self.types[value.type].css = className;
|
|
||||||
gui.doLog('Creating style for ' + className);
|
|
||||||
if( !alreadyAttached ) {
|
|
||||||
var style = '.' + className + ' { display:inline-block; background: url(data:image/png;base64,' +
|
|
||||||
value.icon + '); ' + 'width: 16px; height: 16px; vertical-align: middle; } ';
|
|
||||||
styles += style;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (styles !== '') {
|
|
||||||
// If style already attached, do not re-attach it
|
|
||||||
styles = '<style id="gui-style-' + self.name + '" media="screen">' + styles + '</style>';
|
|
||||||
$(styles).appendTo('head');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
// Options: dictionary
|
|
||||||
// container: container ID of parent for the table. If undefined, table will be appended to workspace
|
|
||||||
// buttons: array of visible buttons (strings), valid are [ 'new', 'edit', 'refresh', 'delete', 'xls' ],
|
|
||||||
// Can contain also objects with {'text': ..., 'fnc': ...}
|
|
||||||
// rowSelect: type of allowed row selection, valid values are 'single' and 'multi'
|
|
||||||
// scrollToTable: if True, will scroll page to show table
|
|
||||||
// deferedRender: if True, datatable will be created with "bDeferRender": true, that will improve a lot creation of huge tables
|
|
||||||
//
|
|
||||||
// onData: Event (function). If defined, will be invoked on data load (to allow preprocess of data)
|
|
||||||
// onLoad: Event (function). If defined, will be invoked when table is fully loaded.
|
|
||||||
// Receives 1 parameter, that is the gui element (GuiElement) used to render table
|
|
||||||
// onRowSelect: Event (function). If defined, will be invoked when a row of table is selected
|
|
||||||
// Receives 3 parameters:
|
|
||||||
// 1.- the array of selected items data (objects, as got from api...get)
|
|
||||||
// 2.- the DataTable that raised the event
|
|
||||||
// 3.- the DataTableTools that raised the event
|
|
||||||
// onRowDeselect: Event (function). If defined, will be invoked when a row of table is deselected
|
|
||||||
// Receives 3 parameters:
|
|
||||||
// 1.- the array of selected items data (objects, as got from api...get)
|
|
||||||
// 2.- the DataTable that raised the event
|
|
||||||
// onCheck: Event (function),
|
|
||||||
// It determines the state of buttons on selection: if returns "true", the indicated button will be enabled, and disabled if returns "false"
|
|
||||||
// Receives 2 parameters:
|
|
||||||
// 1.- the event fired, that can be "edit" or "delete"
|
|
||||||
// 2.- the selected items data (array of selected elements, as got from api...get. In case of edit, array length will be 1)
|
|
||||||
// onNew: Event (function). If defined, will be invoked when "new" button is pressed
|
|
||||||
// Receives 4 parameters:
|
|
||||||
// 1.- the selected item data (single object, as got from api...get)
|
|
||||||
// 2.- the event that fired this (new, delete, edit, ..)
|
|
||||||
// 3.- the DataTable that raised the event
|
|
||||||
// onEdit: Event (function). If defined, will be invoked when "edit" button is pressed
|
|
||||||
// Receives 4 parameters:
|
|
||||||
// 1.- the selected item data (single object, as got from api...get)
|
|
||||||
// 2.- the event that fired this (new, delete, edit, ..)
|
|
||||||
// 3.- the DataTable that raised the event
|
|
||||||
// onDelete: Event (function). If defined, will be invoked when "delete" button is pressed
|
|
||||||
// Receives 4 parameters:
|
|
||||||
// 1.- the selected item data (single object, as got from api...get)
|
|
||||||
// 2.- the event that fired this (new, delete, edit, ..)
|
|
||||||
// 4.- the DataTable that raised the event
|
|
||||||
table : function(tblParams) {
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
tblParams = tblParams || {};
|
|
||||||
gui.doLog('Composing table for ' + this.name);
|
|
||||||
var tableId = this.name + '-table';
|
|
||||||
var self = this; // Store this for child functions
|
|
||||||
|
|
||||||
// ---------------
|
|
||||||
// Cells renderers
|
|
||||||
// ---------------
|
|
||||||
|
|
||||||
// Empty cells transform
|
|
||||||
var renderEmptyCell = function(data) {
|
|
||||||
if( data === '' )
|
|
||||||
return '-';
|
|
||||||
return data;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Icon renderer, based on type (created on init methods in styles)
|
|
||||||
var renderTypeIcon = function(data, type, value){
|
|
||||||
if( type == 'display' ) {
|
|
||||||
self.types[value.type] = self.types[value.type] || {};
|
|
||||||
var css = self.types[value.type].css || 'fa fa-asterisk';
|
|
||||||
return '<span class="' + css + '"></span> ' + renderEmptyCell(data);
|
|
||||||
} else {
|
|
||||||
return renderEmptyCell(data);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Custom icon renderer, in fact span with defined class
|
|
||||||
var renderIcon = function(icon) {
|
|
||||||
return function(data, type, full) {
|
|
||||||
if( type == 'display' ) {
|
|
||||||
return '<span class="' + icon + '"></span> ' + renderEmptyCell(data);
|
|
||||||
} else {
|
|
||||||
return renderEmptyCell(data);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
||||||
// Custom icon based on type
|
|
||||||
var renderIconDict = function(iconDict) {
|
|
||||||
return function(data, type, value) {
|
|
||||||
if( type == 'display' ) {
|
|
||||||
return '<span class="' + iconDict[value.type] + '"></span> ' + renderEmptyCell(data);
|
|
||||||
} else {
|
|
||||||
return renderEmptyCell(data);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
// Text transformation, dictionary based
|
|
||||||
var renderTextTransform = function(dict) {
|
|
||||||
return function(data, type, full) {
|
|
||||||
return dict[data] || renderEmptyCell(data);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
this.rest.tableInfo(function(data) { // Gets tableinfo data (columns, title, visibility of fields, etc...
|
|
||||||
var row_style = data['row-style'];
|
|
||||||
gui.doLog(row_style);
|
|
||||||
var title = data.title;
|
|
||||||
var columns = [];
|
|
||||||
$.each(data.fields, function(index, value) {
|
|
||||||
for ( var v in value) {
|
|
||||||
var opts = value[v];
|
|
||||||
var column = {
|
|
||||||
mData : v,
|
|
||||||
};
|
|
||||||
column.sTitle = opts.title;
|
|
||||||
column.mRender = renderEmptyCell;
|
|
||||||
if (opts.width)
|
|
||||||
column.sWidth = opts.width;
|
|
||||||
column.bVisible = opts.visible === undefined ? true : opts.visible;
|
|
||||||
if (opts.sortable !== undefined)
|
|
||||||
column.bSortable = opts.sortable;
|
|
||||||
if (opts.searchable !== undefined)
|
|
||||||
column.bSearchable = opts.searchable;
|
|
||||||
|
|
||||||
if (opts.type && column.bVisible ) {
|
|
||||||
switch(opts.type) {
|
|
||||||
case 'date':
|
|
||||||
column.sType = 'uds-date';
|
|
||||||
column.mRender = gui.tools.renderDate(api.tools.djangoFormat(get_format('SHORT_DATE_FORMAT')));
|
|
||||||
break;
|
|
||||||
case 'datetime':
|
|
||||||
column.sType = 'uds-date';
|
|
||||||
column.mRender = gui.tools.renderDate(api.tools.djangoFormat(get_format('SHORT_DATETIME_FORMAT')));
|
|
||||||
break;
|
|
||||||
case 'time':
|
|
||||||
column.sType = 'uds-date';
|
|
||||||
column.mRender = gui.tools.renderDate(api.tools.djangoFormat(get_format('TIME_FORMAT')));
|
|
||||||
break;
|
|
||||||
case 'iconType':
|
|
||||||
//columnt.sType = 'html'; // html is default, so this is not needed
|
|
||||||
column.mRender = renderTypeIcon;
|
|
||||||
break;
|
|
||||||
case 'icon':
|
|
||||||
if( opts.icon !== undefined ) {
|
|
||||||
column.mRender = renderIcon(opts.icon);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'icon_dict':
|
|
||||||
if( opts.icon_dict !== undefined ) {
|
|
||||||
column.mRender = renderIconDict(opts.icon_dict);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'dict':
|
|
||||||
if( opts.dict !== undefined ) {
|
|
||||||
column.mRender = renderTextTransform(opts.dict);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
column.sType = opts.type;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
columns.push(column);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// Responsive style for tables, using tables.css and this code generates the "titles" for vertical display on small sizes
|
|
||||||
$('#style-' + tableId).remove(); // Remove existing style for table before adding new one
|
|
||||||
$(api.templates.evaluate('tmpl_comp_responsive_table', {
|
|
||||||
tableId: tableId,
|
|
||||||
columns: columns,
|
|
||||||
})).appendTo('head');
|
|
||||||
|
|
||||||
self.rest.overview(function(data) { // Gets "overview" data for table (table contents, but resume form)
|
|
||||||
if( tblParams.onData ) {
|
|
||||||
tblParams.onData(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
var table = gui.table(title, tableId);
|
|
||||||
if (tblParams.container === undefined) {
|
|
||||||
gui.appendToWorkspace('<div class="row"><div class="col-lg-12">' + table.text + '</div></div>');
|
|
||||||
} else {
|
|
||||||
$('#' + tblParams.container).empty();
|
|
||||||
$('#' + tblParams.container).append(table.text);
|
|
||||||
}
|
|
||||||
|
|
||||||
// What execute on refresh button push
|
|
||||||
var onRefresh = tblParams.onRefresh || function(){};
|
|
||||||
|
|
||||||
var refreshFnc = function() {
|
|
||||||
// Refreshes table content
|
|
||||||
var tbl = $('#' + tableId).dataTable();
|
|
||||||
// Clears selection first
|
|
||||||
TableTools.fnGetInstance(tableId).fnSelectNone();
|
|
||||||
//if( data.length > 1000 )
|
|
||||||
gui.tools.blockUI();
|
|
||||||
|
|
||||||
self.rest.overview(function(data) { // Restore overview
|
|
||||||
if( tblParams.onData ) {
|
|
||||||
tblParams.onData(data);
|
|
||||||
}
|
|
||||||
setTimeout( function() {
|
|
||||||
tbl.fnClearTable();
|
|
||||||
tbl.fnAddData(data);
|
|
||||||
onRefresh(self);
|
|
||||||
gui.tools.unblockUI();
|
|
||||||
}, 0);
|
|
||||||
}); // End restore overview
|
|
||||||
return false; // This may be used on button or href, better disable execution of it
|
|
||||||
};
|
|
||||||
|
|
||||||
var btns = [];
|
|
||||||
|
|
||||||
if (tblParams.buttons) {
|
|
||||||
// Generic click handler generator for this table
|
|
||||||
var clickHandlerFor = function(handler, action, newHandler) {
|
|
||||||
var handleFnc = handler || function(val, action, tbl) {gui.doLog('Default handler called for ', action);};
|
|
||||||
return function(btn) {
|
|
||||||
var tbl = $('#' + tableId).dataTable();
|
|
||||||
var val = this.fnGetSelectedData()[0];
|
|
||||||
setTimeout(function() {
|
|
||||||
if( newHandler ) {
|
|
||||||
handleFnc(action, tbl, refreshFnc);
|
|
||||||
} else {
|
|
||||||
handleFnc(val, action, tbl, refreshFnc);
|
|
||||||
}
|
|
||||||
}, 0);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
var onCheck = tblParams.onCheck || function(){ return true; }; // Default oncheck always returns true
|
|
||||||
|
|
||||||
// methods for buttons on row select
|
|
||||||
var editSelected = function(btn, obj, node) {
|
|
||||||
var sel = this.fnGetSelectedData();
|
|
||||||
var enable = sel.length == 1 ? onCheck("edit", sel) : false;
|
|
||||||
|
|
||||||
if ( enable) {
|
|
||||||
$(btn).removeClass('disabled').addClass('btn3d-success');
|
|
||||||
} else {
|
|
||||||
$(btn).removeClass('btn3d-success').addClass('disabled');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
var deleteSelected = function(btn, obj, node) {
|
|
||||||
var sel = this.fnGetSelectedData();
|
|
||||||
var enable = sel.length == 1 ? onCheck("delete", sel) : false;
|
|
||||||
|
|
||||||
if (enable) {
|
|
||||||
$(btn).removeClass('disabled').addClass('btn3d-warning');
|
|
||||||
} else {
|
|
||||||
$(btn).removeClass('btn3d-warning').addClass('disabled');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
$.each(tblParams.buttons, function(index, value) { // Iterate through button definition
|
|
||||||
var btn = null;
|
|
||||||
switch (value) {
|
|
||||||
case 'new':
|
|
||||||
if(Object.keys(self.types).length !== 0) {
|
|
||||||
var menuId = gui.genRamdonId('dd-');
|
|
||||||
var ordered = [];
|
|
||||||
$.each(self.types, function(k, v){
|
|
||||||
ordered.push({
|
|
||||||
type: k,
|
|
||||||
css: v.css,
|
|
||||||
name: v.name,
|
|
||||||
description: v.description,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
ordered = ordered.sort(function(a,b){return a.name.localeCompare(b.name);});
|
|
||||||
|
|
||||||
btn = {
|
|
||||||
"sExtends" : "div",
|
|
||||||
"sButtonText" : api.templates.evaluate('tmpl_comp_dropdown', {
|
|
||||||
label: gui.config.dataTableButtons['new'].text,
|
|
||||||
css: gui.config.dataTableButtons['new'].css,
|
|
||||||
id: menuId,
|
|
||||||
tableId: tableId,
|
|
||||||
columns: columns,
|
|
||||||
menu: ordered,
|
|
||||||
}),
|
|
||||||
};
|
|
||||||
|
|
||||||
} else {
|
|
||||||
btn = {
|
|
||||||
"sExtends" : "text",
|
|
||||||
"sButtonText" : gui.config.dataTableButtons['new'].text,
|
|
||||||
"sButtonClass" : gui.config.dataTableButtons['new'].css,
|
|
||||||
"fnClick" : clickHandlerFor(tblParams.onNew, 'new', true),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'edit':
|
|
||||||
btn = {
|
|
||||||
"sExtends" : "text",
|
|
||||||
"sButtonText" : gui.config.dataTableButtons.edit.text,
|
|
||||||
"fnSelect" : editSelected,
|
|
||||||
"fnClick" : clickHandlerFor(tblParams.onEdit, 'edit'),
|
|
||||||
"sButtonClass" : gui.config.dataTableButtons.edit.css,
|
|
||||||
};
|
|
||||||
break;
|
|
||||||
case 'delete':
|
|
||||||
btn = {
|
|
||||||
"sExtends" : "text",
|
|
||||||
"sButtonText" : gui.config.dataTableButtons['delete'].text,
|
|
||||||
"fnSelect" : deleteSelected,
|
|
||||||
"fnClick" : clickHandlerFor(tblParams.onDelete, 'delete'),
|
|
||||||
"sButtonClass" : gui.config.dataTableButtons['delete'].css,
|
|
||||||
};
|
|
||||||
break;
|
|
||||||
case 'refresh':
|
|
||||||
btn = {
|
|
||||||
"sExtends" : "text",
|
|
||||||
"sButtonText" : gui.config.dataTableButtons.refresh.text,
|
|
||||||
"fnClick" : refreshFnc,
|
|
||||||
"sButtonClass" : gui.config.dataTableButtons.refresh.css,
|
|
||||||
};
|
|
||||||
break;
|
|
||||||
case 'xls':
|
|
||||||
btn = {
|
|
||||||
"sExtends" : "text",
|
|
||||||
"sButtonText" : gui.config.dataTableButtons.xls.text,
|
|
||||||
"fnClick" : function() { // Export to excel
|
|
||||||
api.templates.get('spreadsheet', function(tmpl) {
|
|
||||||
var styles = { 'bold': 's21', };
|
|
||||||
|
|
||||||
var headings = [], rows = [];
|
|
||||||
$.each(columns, function(index, heading){
|
|
||||||
if( heading.bVisible === false ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
headings.push(api.spreadsheet.cell(heading.sTitle, 'String', styles.bold));
|
|
||||||
});
|
|
||||||
rows.push(api.spreadsheet.row(headings));
|
|
||||||
$.each(data, function(index1, row) {
|
|
||||||
var cells = [];
|
|
||||||
$.each(columns, function(index2, col){
|
|
||||||
if( col.bVisible === false ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var type = col.sType == 'numeric' ? 'Number':'String';
|
|
||||||
cells.push(api.spreadsheet.cell(row[col.mData], type));
|
|
||||||
});
|
|
||||||
rows.push(api.spreadsheet.row(cells));
|
|
||||||
});
|
|
||||||
var ctx = {
|
|
||||||
creation_date: (new Date()).toISOString(),
|
|
||||||
worksheet: title,
|
|
||||||
columns_count: headings.length,
|
|
||||||
rows_count: rows.length,
|
|
||||||
rows: rows.join('\n')
|
|
||||||
};
|
|
||||||
gui.doLog(ctx);
|
|
||||||
setTimeout( function() {
|
|
||||||
saveAs(new Blob([api.templates.evaluate(tmpl, ctx)],
|
|
||||||
{type: 'application/vnd.ms-excel'} ), title + '.xls');
|
|
||||||
}, 20);
|
|
||||||
});
|
|
||||||
}, // End export to excell
|
|
||||||
"sButtonClass" : gui.config.dataTableButtons.xls.css,
|
|
||||||
};
|
|
||||||
break;
|
|
||||||
|
|
||||||
default: // Custom button, this has to be
|
|
||||||
try {
|
|
||||||
var css = (value.css ? value.css + ' ' : '') + gui.config.dataTableButtons.custom.css;
|
|
||||||
btn = {
|
|
||||||
"sExtends" : "text",
|
|
||||||
"sButtonText" : value.text,
|
|
||||||
"sButtonClass" : css,
|
|
||||||
};
|
|
||||||
if( value.click ) {
|
|
||||||
btn.fnClick = function(btn) {
|
|
||||||
var tbl = $('#' + tableId).dataTable();
|
|
||||||
var val = this.fnGetSelectedData()[0];
|
|
||||||
setTimeout(function() {
|
|
||||||
value.click(val, value, btn, tbl, refreshFnc);
|
|
||||||
}, 0);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
if( value.select ){
|
|
||||||
btn.fnSelect = function(btn) {
|
|
||||||
var tbl = $('#' + tableId).dataTable();
|
|
||||||
var val = this.fnGetSelectedData()[0];
|
|
||||||
setTimeout(function() {
|
|
||||||
value.select(val, value, btn, tbl, refreshFnc);
|
|
||||||
}, 0);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (e) {
|
|
||||||
gui.doLog('Button', value, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(btn) {
|
|
||||||
btns.push(btn);
|
|
||||||
}
|
|
||||||
}); // End buttoon iteration
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initializes oTableTools
|
|
||||||
var oTableTools = {
|
|
||||||
"aButtons" : btns,
|
|
||||||
"sRowSelect": tblParams.rowSelect || 'none',
|
|
||||||
};
|
|
||||||
|
|
||||||
if (tblParams.onRowSelect) {
|
|
||||||
var rowSelectedFnc = tblParams.onRowSelect;
|
|
||||||
oTableTools.fnRowSelected = function() {
|
|
||||||
rowSelectedFnc(this.fnGetSelectedData(), $('#' + tableId).dataTable(), self);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
if (tblParams.onRowDeselect) {
|
|
||||||
var rowDeselectedFnc = tblParams.onRowDeselect;
|
|
||||||
oTableTools.fnRowDeselected = function() {
|
|
||||||
rowDeselectedFnc(this.fnGetSelectedData(), $('#' + tableId).dataTable(), self);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
var dataTableOptions = {
|
|
||||||
"aaData" : data,
|
|
||||||
"aaSorting": [[0, 'asc']],
|
|
||||||
"aoColumns" : columns,
|
|
||||||
"oLanguage" : gui.config.dataTablesLanguage,
|
|
||||||
"oTableTools" : oTableTools,
|
|
||||||
"sPaginationType": "bootstrap",
|
|
||||||
// First is upper row,
|
|
||||||
// second row is lower
|
|
||||||
// (pagination) row
|
|
||||||
"sDom" : "<'row'<'col-xs-8'T><'col-xs-4'f>r>t<'row'<'col-xs-5'i><'col-xs-7'p>>",
|
|
||||||
"bDeferRender": tblParams.deferedRender || false,
|
|
||||||
};
|
|
||||||
|
|
||||||
// If row is "styled"
|
|
||||||
if( row_style.field ) {
|
|
||||||
var field = row_style.field;
|
|
||||||
var dct = row_style.dict;
|
|
||||||
var prefix = row_style.prefix;
|
|
||||||
dataTableOptions.fnCreatedRow = function( nRow, aData, iDataIndex ) {
|
|
||||||
var v = dct !== undefined ? dct[this.fnGetData(iDataIndex)[field]] : this.fnGetData(iDataIndex)[field];
|
|
||||||
$(nRow).addClass(prefix + v);
|
|
||||||
gui.doLog(prefix + v);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
$('#' + tableId).dataTable(dataTableOptions);
|
|
||||||
// Fix 3dbuttons
|
|
||||||
gui.tools.fix3dButtons('#' + tableId + '_wrapper .btn-group-3d');
|
|
||||||
// Fix form
|
|
||||||
$('#' + tableId + '_filter input').addClass('form-control');
|
|
||||||
// Add refresh action to panel
|
|
||||||
$(table.refreshSelector).click(refreshFnc);
|
|
||||||
|
|
||||||
// Add tooltips to "new" buttons
|
|
||||||
$('#' + table.panelId + ' [data-toggle="tooltip"]').tooltip({
|
|
||||||
container:'body',
|
|
||||||
delay: { show: 1000, hide: 100},
|
|
||||||
placement: 'auto right',
|
|
||||||
});
|
|
||||||
// And the handler of the new "dropdown" button links
|
|
||||||
if( tblParams.onNew ) { // If onNew, set the handlers for dropdown
|
|
||||||
$('#' + table.panelId + ' [data-type]').on('click', function(event){
|
|
||||||
event.preventDefault();
|
|
||||||
var tbl = $('#' + tableId).dataTable();
|
|
||||||
// Executes "onNew" outside click event
|
|
||||||
var type = $(this).attr('data-type');
|
|
||||||
setTimeout(function() {
|
|
||||||
tblParams.onNew(type, tbl, refreshFnc);
|
|
||||||
}, 0);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tblParams.scrollToTable === true ) {
|
|
||||||
var tableTop = $('#' + tableId).offset().top;
|
|
||||||
$('html, body').scrollTop(tableTop);
|
|
||||||
}
|
|
||||||
// if table rendered event
|
|
||||||
if( tblParams.onLoad ) {
|
|
||||||
tblParams.onLoad(self);
|
|
||||||
}
|
|
||||||
}); // End Overview data
|
|
||||||
}); // End Tableinfo data
|
|
||||||
|
|
||||||
return '#' + tableId;
|
|
||||||
},
|
|
||||||
logTable: function(itemId, tblParams) {
|
|
||||||
"use strict";
|
|
||||||
tblParams = tblParams || {};
|
|
||||||
gui.doLog('Composing log for ' + this.name);
|
|
||||||
var tableId = this.name + '-table-log';
|
|
||||||
var self = this; // Store this for child functions
|
|
||||||
|
|
||||||
// Renderers for columns
|
|
||||||
|
|
||||||
var refreshFnc = function() {
|
|
||||||
// Refreshes table content
|
|
||||||
var tbl = $('#' + tableId).dataTable();
|
|
||||||
|
|
||||||
gui.tools.blockUI();
|
|
||||||
|
|
||||||
self.rest.getLogs(itemId, function(data) {
|
|
||||||
setTimeout( function() {
|
|
||||||
tbl.fnClearTable();
|
|
||||||
tbl.fnAddData(data);
|
|
||||||
gui.tools.unblockUI();
|
|
||||||
}, 0);
|
|
||||||
}); // End restore overview
|
|
||||||
return false; // This may be used on button or href, better disable execution of it
|
|
||||||
};
|
|
||||||
|
|
||||||
// Log level "translator" (renderer)
|
|
||||||
var logRenderer = gui.tools.renderLogLovel();
|
|
||||||
|
|
||||||
// Columns description
|
|
||||||
var columns = [
|
|
||||||
{
|
|
||||||
"mData" : 'date',
|
|
||||||
"sTitle" : gettext('Date'),
|
|
||||||
"sType": "uds-date",
|
|
||||||
"asSorting": [ 'desc', 'asc' ],
|
|
||||||
"mRender" : gui.tools.renderDate(api.tools.djangoFormat(get_format('SHORT_DATE_FORMAT') + ' ' + get_format('TIME_FORMAT'))),
|
|
||||||
"bSortable" : true,
|
|
||||||
"bSearchable" : true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"mData" : 'level',
|
|
||||||
"sTitle" : gettext('level'),
|
|
||||||
"mRender" : logRenderer,
|
|
||||||
"sWidth" : "5em",
|
|
||||||
"bSortable" : true,
|
|
||||||
"bSearchable" : true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"mData" : 'source',
|
|
||||||
"sTitle" : gettext('source'),
|
|
||||||
"sWidth" : "5em",
|
|
||||||
"bSortable" : true,
|
|
||||||
"bSearchable" : true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"mData" : 'message',
|
|
||||||
"sTitle" : gettext('message'),
|
|
||||||
"bSortable" : true,
|
|
||||||
"bSearchable" : true,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
var table = gui.table(tblParams.title || gettext('Logs'), tableId);
|
|
||||||
if (tblParams.container === undefined) {
|
|
||||||
gui.appendToWorkspace('<div class="row"><div class="col-lg-12">' + table.text + '</div></div>');
|
|
||||||
} else {
|
|
||||||
$('#' + tblParams.container).empty();
|
|
||||||
$('#' + tblParams.container).append(table.text);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Responsive style for tables, using tables.css and this code generates the "titles" for vertical display on small sizes
|
|
||||||
$('#style-' + tableId).remove(); // Remove existing style for table before adding new one
|
|
||||||
$(api.templates.evaluate('tmpl_comp_responsive_table', {
|
|
||||||
tableId: tableId,
|
|
||||||
columns: columns,
|
|
||||||
})).appendTo('head');
|
|
||||||
|
|
||||||
self.rest.getLogs(itemId, function(data){
|
|
||||||
gui.doLog(data);
|
|
||||||
|
|
||||||
$('#' + tableId).dataTable({
|
|
||||||
"aaData" : data,
|
|
||||||
"aaSorting": [[0, 'desc']],
|
|
||||||
"oTableTools" : {"aButtons" : [],},
|
|
||||||
"aoColumns" : columns,
|
|
||||||
"oLanguage" : gui.config.dataTablesLanguage,
|
|
||||||
"sDom" : "<'row'<'col-xs-8'T><'col-xs-4'f>r>t<'row'<'col-xs-5'i><'col-xs-7'p>>",
|
|
||||||
"bDeferRender": tblParams.deferedRender || false,
|
|
||||||
"fnCreatedRow": function( nRow, aData, iDataIndex ) {
|
|
||||||
var v = 'log-' + logRenderer(this.fnGetData(iDataIndex).level);
|
|
||||||
$(nRow).addClass(v);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
// Fix form
|
|
||||||
$('#' + tableId + '_filter input').addClass('form-control');
|
|
||||||
|
|
||||||
// Add refresh action to panel
|
|
||||||
$(table.refreshSelector).click(refreshFnc);
|
|
||||||
|
|
||||||
// if table rendered event
|
|
||||||
if( tblParams.onLoad ) {
|
|
||||||
tblParams.onLoad(self);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return '#' + tableId;
|
|
||||||
},
|
|
||||||
};
|
|
@ -1,286 +0,0 @@
|
|||||||
/* jshint strict: true */
|
|
||||||
(function(gui, $, undefined) {
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
gui.forms = {};
|
|
||||||
|
|
||||||
gui.forms.callback = function(formSelector, method, params, success_fnc) {
|
|
||||||
var path = 'gui/callback/' + method;
|
|
||||||
var p = [];
|
|
||||||
$.each(params, function(index, val) {
|
|
||||||
p.push(val.name + '=' + encodeURIComponent(val.value));
|
|
||||||
});
|
|
||||||
path = path + '?' + p.join('&');
|
|
||||||
api.getJson(path, {
|
|
||||||
success: success_fnc,
|
|
||||||
});
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
// Returns form fields that will manage a gui description (new or edit)
|
|
||||||
gui.forms.fieldsToHtml = function(itemGui, item, editing) {
|
|
||||||
var html = '';
|
|
||||||
var fillers = []; // Fillers (callbacks)
|
|
||||||
var originalValues = {}; // Initial stored values (defaults to "reset" form and also used on fillers callback to try to restore previous value)
|
|
||||||
// itemGui is expected to have fields sorted by .gui.order (REST api returns them sorted)
|
|
||||||
$.each(itemGui, function(index, f){
|
|
||||||
if( f.gui === undefined ) { // Not exactly a field, maybe some other info...
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Fix multiline text fields to textbox
|
|
||||||
if( f.gui.type == 'text' && f.gui.multiline ) {
|
|
||||||
f.gui.type = 'textbox';
|
|
||||||
}
|
|
||||||
var value = item[f.name] || f.gui.value || f.gui.defvalue;
|
|
||||||
// We need to convert "array" values for multichoices to single list of ids (much more usable right here)
|
|
||||||
if( f.gui.type == 'multichoice') {
|
|
||||||
var newValue = [];
|
|
||||||
$.each(value, function(undefined, val) {
|
|
||||||
newValue.push(val.id);
|
|
||||||
});
|
|
||||||
value = newValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
originalValues[f.name] = value; // Store original value
|
|
||||||
html += api.templates.evaluate('tmpl_fld_'+f.gui.type, {
|
|
||||||
value: value, // If no value present, use default value
|
|
||||||
values: f.gui.values,
|
|
||||||
label: f.gui.label,
|
|
||||||
length: f.gui.length,
|
|
||||||
multiline: f.gui.multiline,
|
|
||||||
readonly: editing ? f.gui.rdonly : false, // rdonly applies just to editing
|
|
||||||
required: f.gui.required,
|
|
||||||
tooltip: f.gui.tooltip,
|
|
||||||
type: f.gui.type,
|
|
||||||
name: f.name,
|
|
||||||
css: 'modal_field_data',
|
|
||||||
});
|
|
||||||
|
|
||||||
// if this field has a filler (callback to get data)
|
|
||||||
if( f.gui.fills ) {
|
|
||||||
gui.doLog('This field has a filler');
|
|
||||||
fillers.push({ name: f.name, callbackName: f.gui.fills.callbackName, parameters: f.gui.fills.parameters });
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
return { html: html, fillers: fillers, originalValues: originalValues };
|
|
||||||
};
|
|
||||||
|
|
||||||
gui.forms.fromFields = function(fields, item) {
|
|
||||||
var editing = item !== undefined; // Locate real Editing
|
|
||||||
item = item || {id:''};
|
|
||||||
|
|
||||||
var form = '<form class="form-horizontal" role="form">' +
|
|
||||||
'<input type="hidden" name="id" class="modal_field_data" value="' + item.id + '">';
|
|
||||||
var fillers = [];
|
|
||||||
var originalValues = {};
|
|
||||||
|
|
||||||
if( fields.tabs ) {
|
|
||||||
var id = 'tab-' + Math.random().toString().split('.')[1]; // Get a random base ID for tab entries
|
|
||||||
var tabs = [];
|
|
||||||
var tabsContent = [];
|
|
||||||
var active = ' active in' ;
|
|
||||||
$.each(fields.tabs, function(index, tab){
|
|
||||||
var h = gui.forms.fieldsToHtml(tab.fields, item);
|
|
||||||
tabsContent.push('<div class="tab-pane fade' + active + '" id="' + id + index + '">' + h.html + '</div>' );
|
|
||||||
tabs.push('<li><a href="#' + id + index + '" data-toggle="tab">' + tab.title + '</a></li>' );
|
|
||||||
active = '';
|
|
||||||
fillers = fillers.concat(h.fillers); // Fillers (callback based)
|
|
||||||
$.extend(originalValues, h.originalValues); // Original values
|
|
||||||
gui.doLog('Fillers:', h.fillers);
|
|
||||||
});
|
|
||||||
form += '<ul class="nav nav-tabs">' + tabs.join('\n') + '</ul><div class="tab-content">' + tabsContent.join('\n') + '</div>';
|
|
||||||
} else {
|
|
||||||
var h = gui.forms.fieldsToHtml(fields, item, editing);
|
|
||||||
form += h.html;
|
|
||||||
fillers = fillers.concat(h.fillers);
|
|
||||||
$.extend(originalValues, h.originalValues);
|
|
||||||
}
|
|
||||||
form += '</form>';
|
|
||||||
|
|
||||||
gui.doLog('Original values: ', originalValues);
|
|
||||||
|
|
||||||
// Init function for callbacks.
|
|
||||||
// Callbacks can only be attached to "Selects", but it's parameters can be got from any field
|
|
||||||
// This needs the "form selector" as base for setting callbacks, etc..
|
|
||||||
var init = function(formSelector) {
|
|
||||||
gui.doLog(formSelector, fillers);
|
|
||||||
|
|
||||||
var onChange = function(filler) {
|
|
||||||
return function() {
|
|
||||||
gui.doLog('Onchange invoked for ', filler);
|
|
||||||
// Attach on change method to each filler, and after that, all
|
|
||||||
var params = [];
|
|
||||||
$.each(filler.parameters, function(undefined, p){
|
|
||||||
var val = $(formSelector + ' [name="' + p + '"]').val();
|
|
||||||
params.push({name: p, value: val});
|
|
||||||
});
|
|
||||||
gui.forms.callback(formSelector, filler.callbackName, params, function(data){
|
|
||||||
$.each(data, function(undefined, sel){
|
|
||||||
// Update select contents with returned values
|
|
||||||
var $select = $(formSelector + ' [name="' + sel.name + '"]');
|
|
||||||
|
|
||||||
$select.empty();
|
|
||||||
$.each(sel.values, function(undefined, value){
|
|
||||||
$select.append('<option value="' + value.id + '">' + value.text + '</option>');
|
|
||||||
});
|
|
||||||
$select.val(originalValues[sel.name]);
|
|
||||||
// Refresh selectpicker if item is such
|
|
||||||
if($select.hasClass('selectpicker'))
|
|
||||||
$select.selectpicker('refresh');
|
|
||||||
// Trigger change for the changed item
|
|
||||||
$select.trigger('change');
|
|
||||||
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
// Sets the "on change" event for select with fillers (callbacks that fills other fields)
|
|
||||||
$.each(fillers, function(undefined, f) {
|
|
||||||
$(formSelector + ' [name="' + f.name + '"]').on('change', onChange(f));
|
|
||||||
});
|
|
||||||
|
|
||||||
// Trigger first filler if it exists, this will cascade rest of "changes" if they exists
|
|
||||||
if( fillers.length )
|
|
||||||
$(formSelector + ' [name="' + fillers[0].name + '"]').trigger('change');
|
|
||||||
};
|
|
||||||
|
|
||||||
return { 'html': form, 'init': init }; // Returns the form and a initialization function for the form, that must be invoked to start it
|
|
||||||
};
|
|
||||||
|
|
||||||
// Reads fields from a form
|
|
||||||
gui.forms.read = function(formSelector) {
|
|
||||||
var res = {};
|
|
||||||
$(formSelector + ' .modal_field_data').each(function(i, field) {
|
|
||||||
var $field = $(field);
|
|
||||||
if( $field.attr('name') ) { // Is a valid field
|
|
||||||
var name = $field.attr('name');
|
|
||||||
if( $field.attr('type') == 'checkbox') {
|
|
||||||
res[name] = $field.is(':checked');
|
|
||||||
} else {
|
|
||||||
res[name] = $field.val();
|
|
||||||
if( res[name] === null && $field.is('select') )
|
|
||||||
res[name] = [];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
gui.doLog(res);
|
|
||||||
return res;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Options has this keys:
|
|
||||||
// title
|
|
||||||
// fields
|
|
||||||
// item
|
|
||||||
// success
|
|
||||||
// buttons: Array of buttons to be added to footer, with:
|
|
||||||
// text --> text of button
|
|
||||||
// css --> button style (btn-default, btn-warning, ...). If not defined, 'btn-default' will be used
|
|
||||||
// action --> function to be executed. Will be passed 3 parameters: event, formSelector and closeFnc
|
|
||||||
// (use gui.forms.read(form selector) to get fields, closeFnc() to close form if desired)
|
|
||||||
// Failed operations will show a modal with server error
|
|
||||||
gui.forms.launchModal = function(options, onSuccess) {
|
|
||||||
options = options || {};
|
|
||||||
|
|
||||||
var id = 'modal-' + Math.random().toString().split('.')[1]; // Get a random ID for this modal
|
|
||||||
var ff = gui.forms.fromFields(options.fields, options.item);
|
|
||||||
var footer = '';
|
|
||||||
var clickEventHandlers = [];
|
|
||||||
|
|
||||||
if( options.buttons ) {
|
|
||||||
$.each(options.buttons, function(index, value){
|
|
||||||
var _id = id + '-footer-' + index;
|
|
||||||
var css = value.css || 'btn-default';
|
|
||||||
clickEventHandlers.push({id: '#' + _id, action: value.action });
|
|
||||||
footer += '<button id="' + _id + '" type="button" class="pull-left btn ' + css + '">' + value.text + '</button>';
|
|
||||||
});
|
|
||||||
}
|
|
||||||
gui.appendToWorkspace(gui.modal(id, options.title, ff.html, { footer: footer }));
|
|
||||||
id = '#' + id; // for jQuery
|
|
||||||
|
|
||||||
var formSelector = id + ' form';
|
|
||||||
var closeFnc = function(){$(id).modal('hide');};
|
|
||||||
|
|
||||||
if( ff.init )
|
|
||||||
ff.init(id);
|
|
||||||
|
|
||||||
// Append click events for custom buttons on footer
|
|
||||||
$.each(clickEventHandlers, function(undefined, value){
|
|
||||||
if( value.action ) {
|
|
||||||
$(value.id).on('click', function(event){
|
|
||||||
value.action(event, formSelector, closeFnc);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Get form
|
|
||||||
var $form = $(id + ' form');
|
|
||||||
|
|
||||||
gui.tools.applyCustoms(id);
|
|
||||||
|
|
||||||
// Validation
|
|
||||||
$form.validate({
|
|
||||||
debug: true,
|
|
||||||
errorClass: 'text-danger',
|
|
||||||
validClass: 'has-success',
|
|
||||||
highlight: function(element) {
|
|
||||||
$(element).closest('.form-group').addClass('has-error');
|
|
||||||
},
|
|
||||||
success: function(element) {
|
|
||||||
$(element).closest('.form-group').removeClass('has-error');
|
|
||||||
$(element).remove();
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
// And catch "accept" (default is "Save" in fact) button click
|
|
||||||
$(id + ' .button-accept').click(function(){
|
|
||||||
if( !$form.valid() )
|
|
||||||
return;
|
|
||||||
if( options.success ) {
|
|
||||||
options.success(formSelector, closeFnc); // Delegate close to to onSuccess
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
closeFnc();
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
// If preprocessors of modal (maybe custom event handlers)
|
|
||||||
if( options.preprocessor ) {
|
|
||||||
options.preprocessor(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Launch modal
|
|
||||||
$(id).modal({keyboard: false})
|
|
||||||
.on('hidden.bs.modal', function () {
|
|
||||||
$(id).remove();
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
// simple gui generators
|
|
||||||
gui.forms.guiField = function(name, type, label, tooltip, value, values, length, multiline, readonly, required) {
|
|
||||||
length = length || 128;
|
|
||||||
multiline = multiline !== undefined ? multiline : 0;
|
|
||||||
readonly = readonly || false;
|
|
||||||
required = required || false;
|
|
||||||
return {
|
|
||||||
name: name,
|
|
||||||
gui: {
|
|
||||||
defvalue: value,
|
|
||||||
value: value,
|
|
||||||
values: values,
|
|
||||||
label: label,
|
|
||||||
length: length,
|
|
||||||
multiline: multiline,
|
|
||||||
rdonly: readonly, // rdonly applies just to editing
|
|
||||||
required: required,
|
|
||||||
tooltip: tooltip,
|
|
||||||
type: type,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
}(window.gui = window.gui || {}, jQuery));
|
|
||||||
|
|
@ -1,92 +0,0 @@
|
|||||||
/* jshint strict: true */
|
|
||||||
(function(gui, $, undefined) {
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
gui.tools = {
|
|
||||||
blockUI : function(message) {
|
|
||||||
message = message || '<h1><span class="fa fa-spinner fa-spin"></span> ' + gettext('Just a moment...') + '</h1>';
|
|
||||||
$.blockUI({ message: message });
|
|
||||||
},
|
|
||||||
unblockUI : function() {
|
|
||||||
$.unblockUI();
|
|
||||||
$('.DTTT_collection_background').remove();
|
|
||||||
},
|
|
||||||
fix3dButtons : function(selector) {
|
|
||||||
selector = selector || '';
|
|
||||||
selector += ' .btn3d';
|
|
||||||
console.log(selector);
|
|
||||||
$.each($(selector), function(index, value) {
|
|
||||||
// If no events associated, return
|
|
||||||
if( $._data(value, 'events') === undefined )
|
|
||||||
return;
|
|
||||||
|
|
||||||
var $this = $(this);
|
|
||||||
|
|
||||||
var clkEvents = [];
|
|
||||||
// Store old click events, so we can reconstruct click chain later
|
|
||||||
$.each($._data(value, 'events').click, function(index, fnc) {
|
|
||||||
clkEvents.push(fnc);
|
|
||||||
});
|
|
||||||
$this.unbind('click');
|
|
||||||
|
|
||||||
/* If Mousedown registers a temporal mouseUp event on parent, to lauch button click */
|
|
||||||
$this.mousedown(function(event){
|
|
||||||
$('body').mouseup(function(e){
|
|
||||||
// Remove temporal mouseup handler
|
|
||||||
$(this).unbind('mouseup');
|
|
||||||
|
|
||||||
// If movement of mouse is not too far... (16 px maybe well for 3d buttons?)
|
|
||||||
var x = event.pageX - e.pageX, y = event.pageY - e.pageY;
|
|
||||||
var dist_square = x*x + y*y;
|
|
||||||
if( dist_square < 16*16 ) {
|
|
||||||
// Register again old event handlers
|
|
||||||
$.each(clkEvents, function(index, fnc){
|
|
||||||
$this.click(fnc.handler);
|
|
||||||
});
|
|
||||||
$this.click();
|
|
||||||
$this.unbind('click');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},
|
|
||||||
applyCustoms: function(selector) {
|
|
||||||
// Activate "custom" styles
|
|
||||||
$(selector + ' input:checkbox').bootstrapSwitch();
|
|
||||||
// Activate "cool" selects
|
|
||||||
$(selector + ' .selectpicker').selectpicker();
|
|
||||||
// TEST: cooler on mobile devices
|
|
||||||
if( /Android|webOS|iPhone|iPad|iPod|BlackBerry/i.test(navigator.userAgent) ) {
|
|
||||||
$(selector + ' .selectpicker').selectpicker('mobile');
|
|
||||||
}
|
|
||||||
// Activate tooltips
|
|
||||||
$(selector + ' [data-toggle="tooltip"]').tooltip({delay: {show: 1000, hide: 100}, placement: 'auto right'});
|
|
||||||
|
|
||||||
// Fix 3d buttons
|
|
||||||
gui.tools.fix3dButtons(selector);
|
|
||||||
},
|
|
||||||
// Datetime renderer (with specified format)
|
|
||||||
renderDate : function(format) {
|
|
||||||
return function(data, type, full) {
|
|
||||||
return '<span data-date="' + data + '">' + api.tools.strftime(format, new Date(data*1000)) + '</span>';
|
|
||||||
};
|
|
||||||
},
|
|
||||||
// Log level rendererer
|
|
||||||
renderLogLovel : function() {
|
|
||||||
var levels = {
|
|
||||||
10000 : 'OTHER',
|
|
||||||
20000 : 'DEBUG',
|
|
||||||
30000 : 'INFO',
|
|
||||||
40000 : 'WARN',
|
|
||||||
50000 : 'ERROR',
|
|
||||||
60000 : 'FATAL'
|
|
||||||
};
|
|
||||||
|
|
||||||
return function(data, type, full) {
|
|
||||||
return levels[data] || 'OTHER';
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
}(window.gui = window.gui || {}, jQuery));
|
|
@ -1,391 +0,0 @@
|
|||||||
/* jshint strict: true */
|
|
||||||
(function(gui, $, undefined) {
|
|
||||||
"use strict";
|
|
||||||
// "public" methods
|
|
||||||
gui.doLog = function() {
|
|
||||||
if (gui.debug) {
|
|
||||||
try {
|
|
||||||
console.log.apply(window, arguments);
|
|
||||||
} catch (e) {
|
|
||||||
// nothing can be logged
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
gui.config = gui.config || {};
|
|
||||||
|
|
||||||
// Several convenience "constants" for tables
|
|
||||||
gui.config.dataTablesLanguage = {
|
|
||||||
'sLengthMenu' : gettext('_MENU_ records per page'),
|
|
||||||
'sZeroRecords' : gettext('Empty'),
|
|
||||||
'sInfo' : gettext('Records _START_ to _END_ of _TOTAL_'),
|
|
||||||
'sInfoEmpty' : gettext('No records'),
|
|
||||||
'sInfoFiltered' : gettext('(filtered from _MAX_ total records)'),
|
|
||||||
'sProcessing' : gettext('Please wait, processing'),
|
|
||||||
'sSearch' : gettext('Filter'),
|
|
||||||
'sInfoThousands' : django.formats.THOUSAND_SEPARATOR,
|
|
||||||
'oPaginate' : {
|
|
||||||
'sFirst' : '<span class="fa fa-fast-backward "></span> ',
|
|
||||||
'sLast' : '<span class="fa fa-fast-forward"></span> ',
|
|
||||||
'sNext' : '<span class="fa fa-forward"></span> ',
|
|
||||||
'sPrevious' : '<span class="fa fa-backward"></span> ',
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
gui.config.dataTableButtons = {
|
|
||||||
'new': {
|
|
||||||
text: '<span class="fa fa-pencil"></span> <span class="label-tbl-button">' + gettext('New') + '</span>',
|
|
||||||
css: 'btn btn3d btn3d-primary btn3d-tables',
|
|
||||||
},
|
|
||||||
'edit': {
|
|
||||||
text: '<span class="fa fa-edit"></span> <span class="label-tbl-button">' + gettext('Edit') + '</span>',
|
|
||||||
css: 'btn disabled btn3d-default btn3d btn3d-tables',
|
|
||||||
},
|
|
||||||
'delete': {
|
|
||||||
text: '<span class="fa fa-trash-o"></span> <span class="label-tbl-button">' + gettext('Delete') + '</span>',
|
|
||||||
css: 'btn disabled btn3d-default btn3d btn3d-tables',
|
|
||||||
},
|
|
||||||
'xls': {
|
|
||||||
text: '<span class="fa fa-save"></span> <span class="label-tbl-button">' + gettext('Xls') + '</span>',
|
|
||||||
css: 'btn btn3d-info btn3d btn3d-tables',
|
|
||||||
},
|
|
||||||
'custom': {
|
|
||||||
text: null,
|
|
||||||
css: 'btn btn3d-default btn3d btn3d-tables',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
gui.genRamdonId = function(prefix) {
|
|
||||||
prefix = prefix || '';
|
|
||||||
return prefix + Math.random().toString().split('.')[1];
|
|
||||||
};
|
|
||||||
|
|
||||||
gui.table = function(title, table_id, options) {
|
|
||||||
options = options || {};
|
|
||||||
var panelId = 'panel-' + table_id;
|
|
||||||
|
|
||||||
return {
|
|
||||||
text: api.templates.evaluate('tmpl_comp_table', {
|
|
||||||
panelId: panelId,
|
|
||||||
icon: options.icon || 'table',
|
|
||||||
size: options.size || 12,
|
|
||||||
title: title,
|
|
||||||
table_id: table_id
|
|
||||||
}),
|
|
||||||
panelId: panelId,
|
|
||||||
refreshSelector: '#' + panelId + ' span.fa-refresh'
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
gui.breadcrumbs = function(path) {
|
|
||||||
var items = path.split('/');
|
|
||||||
var active = items.pop();
|
|
||||||
var list = '';
|
|
||||||
$.each(items, function(index, value) {
|
|
||||||
list += '<li><a href="#">' + value + '</a></li>';
|
|
||||||
});
|
|
||||||
list += '<li class="active">' + active + '</li>';
|
|
||||||
|
|
||||||
return '<div class="row"><div class="col-lg-12"><ol class="breadcrumb">' + list + "</ol></div></div>";
|
|
||||||
};
|
|
||||||
|
|
||||||
// By default, actionButton has class "button-accept", so you can use returned id + this class to select it
|
|
||||||
// and do whatever is needed (for example, insert an "on click" event (this method returns id without '#'
|
|
||||||
// Example: $('#' + id + ' .button-accept').on('click', ...
|
|
||||||
gui.modal = function(id, title, content, options) {
|
|
||||||
options = options || {};
|
|
||||||
return api.templates.evaluate('tmpl_comp_modal', {
|
|
||||||
id: id,
|
|
||||||
title: title,
|
|
||||||
content: content,
|
|
||||||
footer: options.footer,
|
|
||||||
button1: options.closeButton,
|
|
||||||
button2: options.actionButton,
|
|
||||||
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
// As previous, this creates the modal and shows it. in this case, the id of the modal returned already has '#'
|
|
||||||
gui.launchModal = function(title, content, options) {
|
|
||||||
options = options || {};
|
|
||||||
var id = gui.genRamdonId('modal-'); // Get a random ID for this modal
|
|
||||||
gui.appendToWorkspace(gui.modal(id, title, content, options));
|
|
||||||
id = '#' + id; // for jQuery
|
|
||||||
|
|
||||||
$(id).modal()
|
|
||||||
.on('hidden.bs.modal', function () {
|
|
||||||
$(id).remove();
|
|
||||||
});
|
|
||||||
return id;
|
|
||||||
};
|
|
||||||
|
|
||||||
gui.notify = function(message, type) {
|
|
||||||
gui.launchModal('<b class="text-'+ type + '">' + gettext('Message') + '</b>', '<span class="text-' + type + '">' + message + '</span>', {actionButton: ' '});
|
|
||||||
};
|
|
||||||
|
|
||||||
gui.failRequestModalFnc = function(title) {
|
|
||||||
return function(jqXHR, textStatus, errorThrown) { // fail on put
|
|
||||||
gui.tools.unblockUI();
|
|
||||||
gui.launchModal('<b class="text-danger">' + title + '</b>', jqXHR.responseText, { actionButton: ' '});
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
gui.promptModal = function(title, question, options) {
|
|
||||||
options = options || {};
|
|
||||||
options.actionButton = '<button type="button" class="btn btn-primary button-yes">' + (options.yesButton || gettext('yes')) + '</button>';
|
|
||||||
options.closeButton = '<button type="button" class="btn btn-danger button-no">' + (options.yesButton || gettext('no')) + '</button>';
|
|
||||||
var onYes = options.onYes || function(){};
|
|
||||||
var onNo = options.onNo || function(){};
|
|
||||||
|
|
||||||
var modalId = gui.launchModal(title, question, options);
|
|
||||||
$(modalId + ' .button-yes').on('click', function(event){
|
|
||||||
$(modalId).modal('hide');
|
|
||||||
onYes();
|
|
||||||
});
|
|
||||||
$(modalId + ' .button-no').on('click', function(event){
|
|
||||||
$(modalId).modal('hide');
|
|
||||||
onNo();
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
gui.clearWorkspace = function() {
|
|
||||||
$('#content').empty();
|
|
||||||
$('#minimized').empty();
|
|
||||||
};
|
|
||||||
|
|
||||||
gui.appendToWorkspace = function(data) {
|
|
||||||
$(data).appendTo('#content');
|
|
||||||
};
|
|
||||||
|
|
||||||
// Clean up several "internal" data
|
|
||||||
// I have discovered some "items" that are keep in memory, or that adds garbage to body (datatable && tabletools mainly)
|
|
||||||
// Whenever we change "section", we clean up as much as we can, so we can keep things as clean as possible
|
|
||||||
// Main problem where comming with "tabletools" and keeping references to all instances created
|
|
||||||
gui.cleanup = function() {
|
|
||||||
gui.doLog('Cleaning up things');
|
|
||||||
// Tabletools creates divs at end that do not get removed, here is a good place to ensure there is no garbage left behind
|
|
||||||
// And anyway, if this div does not exists, it creates a new one...
|
|
||||||
$('.DTTT_dropdown').remove(); // Tabletools keep adding garbage to end of body on each new table creation, so we simply remove it on each new creation
|
|
||||||
TableTools._aInstances = []; // Same for internal references
|
|
||||||
TableTools._aListeners = [];
|
|
||||||
|
|
||||||
// Destroy any created datatable
|
|
||||||
$.each($.fn.dataTable.fnTables(), function(undefined, tbl){
|
|
||||||
var $tbl = $(tbl).dataTable();
|
|
||||||
$tbl.fnClearTable(); // Removing data first makes things much faster
|
|
||||||
$tbl.fnDestroy();
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
gui.setLinksEvents = function() {
|
|
||||||
var sidebarLinks = [
|
|
||||||
{
|
|
||||||
id : 'lnk-dashboard',
|
|
||||||
exec : gui.dashboard.link,
|
|
||||||
cleanup: true,
|
|
||||||
}, {
|
|
||||||
id : 'lnk-service_providers',
|
|
||||||
exec : gui.providers.link,
|
|
||||||
cleanup: true,
|
|
||||||
}, {
|
|
||||||
id : 'lnk-authenticators',
|
|
||||||
exec : gui.authenticators.link,
|
|
||||||
cleanup: true,
|
|
||||||
}, {
|
|
||||||
id : 'lnk-osmanagers',
|
|
||||||
exec : gui.osmanagers.link,
|
|
||||||
cleanup: true,
|
|
||||||
}, {
|
|
||||||
id : 'lnk-connectivity',
|
|
||||||
exec : gui.connectivity.link,
|
|
||||||
cleanup: true,
|
|
||||||
}, {
|
|
||||||
id : 'lnk-deployed_services',
|
|
||||||
exec : gui.servicesPools.link,
|
|
||||||
cleanup: true,
|
|
||||||
}, {
|
|
||||||
id : 'lnk-clear_cache',
|
|
||||||
exec : gui.clear_cache.link,
|
|
||||||
cleanup: false,
|
|
||||||
}, {
|
|
||||||
id : 'lnk-configuration',
|
|
||||||
exec : gui.configuration.link,
|
|
||||||
cleanup: false,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
$.each(sidebarLinks, function(index, value) {
|
|
||||||
gui.doLog('Adding ' + value.id);
|
|
||||||
$('.' + value.id).unbind('click').click(function(event) {
|
|
||||||
event.preventDefault();
|
|
||||||
if ($('.navbar-toggle').css('display') != 'none') {
|
|
||||||
$(".navbar-toggle").trigger("click");
|
|
||||||
}
|
|
||||||
if( value.cleanup ) {
|
|
||||||
gui.cleanup();
|
|
||||||
}
|
|
||||||
$('html, body').scrollTop(0);
|
|
||||||
value.exec(event);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
gui.init = function() {
|
|
||||||
// Load jquery validator strings
|
|
||||||
$.extend($.validator.messages, {
|
|
||||||
required: gettext("This field is required."),
|
|
||||||
remote: gettext("Please fix this field."),
|
|
||||||
email: gettext("Please enter a valid email address."),
|
|
||||||
url: gettext("Please enter a valid URL."),
|
|
||||||
date: gettext("Please enter a valid date."),
|
|
||||||
dateISO: gettext("Please enter a valid date (ISO)."),
|
|
||||||
number: gettext("Please enter a valid number."),
|
|
||||||
digits: gettext("Please enter only digits."),
|
|
||||||
creditcard: gettext("Please enter a valid credit card number."),
|
|
||||||
equalTo: gettext("Please enter the same value again."),
|
|
||||||
maxlength: $.validator.format(gettext("Please enter no more than {0} characters.")),
|
|
||||||
minlength: $.validator.format(gettext("Please enter at least {0} characters.")),
|
|
||||||
rangelength: $.validator.format(gettext("Please enter a value between {0} and {1} characters long.")),
|
|
||||||
range: $.validator.format(gettext("Please enter a value between {0} and {1}.")),
|
|
||||||
max: $.validator.format(gettext("Please enter a value less than or equal to {0}.")),
|
|
||||||
min: $.validator.format(gettext("Please enter a value greater than or equal to {0}."))
|
|
||||||
});
|
|
||||||
// Set blockui params
|
|
||||||
$.blockUI.defaults.baseZ = 2000;
|
|
||||||
|
|
||||||
$.fn.dataTableExt.oSort['uds-date-pre'] = function( s ) {
|
|
||||||
return parseInt(s.split('"')[1], 10);
|
|
||||||
};
|
|
||||||
// Sort for "date" columns (our "dates" are in fact postfix dates rendered as dates with locale format
|
|
||||||
$.fn.dataTableExt.oSort['uds-date-asc'] = function(x,y) {
|
|
||||||
var val = ((x < y) ? -1 : ((x > y) ? 1 : 0));
|
|
||||||
return val;
|
|
||||||
};
|
|
||||||
|
|
||||||
$.fn.dataTableExt.oSort['uds-date-desc'] = function(x,y) {
|
|
||||||
var val = ((x < y) ? 1 : ((x > y) ? -1 : 0));
|
|
||||||
return val;
|
|
||||||
};
|
|
||||||
// Wait a bit before activating links to give tome tine to initializations
|
|
||||||
setTimeout(function(){
|
|
||||||
gui.setLinksEvents();
|
|
||||||
gui.dashboard.link();
|
|
||||||
}, 500);
|
|
||||||
};
|
|
||||||
|
|
||||||
gui.showDashboard = function() {
|
|
||||||
gui.dashboard.link();
|
|
||||||
};
|
|
||||||
|
|
||||||
// Generic "methods" for editing, creating, etc...
|
|
||||||
|
|
||||||
gui.methods = {};
|
|
||||||
|
|
||||||
gui.methods.typedTestButton = function(rest, text, css, type) {
|
|
||||||
return [
|
|
||||||
{
|
|
||||||
text: text,
|
|
||||||
css: css,
|
|
||||||
action: function(event, form_selector, closeFnc) {
|
|
||||||
var fields = gui.forms.read(form_selector);
|
|
||||||
gui.doLog('Fields: ', fields);
|
|
||||||
rest.test(type, fields, function(data){
|
|
||||||
gui.launchModal(gettext('Test result'), data, { actionButton: ' '});
|
|
||||||
}, gui.failRequestModalFnc(gettext('Test error')));
|
|
||||||
},
|
|
||||||
},
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
// "Generic" edit method to set onEdit table
|
|
||||||
gui.methods.typedEdit = function(parent, modalTitle, modalErrorMsg, options) {
|
|
||||||
options = options || {};
|
|
||||||
return function(value, event, table, refreshFnc) {
|
|
||||||
gui.tools.blockUI();
|
|
||||||
parent.rest.gui(value.type, function(guiDefinition) {
|
|
||||||
var buttons = null;
|
|
||||||
if( options.testButton ) {
|
|
||||||
buttons = gui.methods.typedTestButton(parent.rest, options.testButton.text, options.testButton.css, value.type);
|
|
||||||
}
|
|
||||||
var tabs = options.guiProcessor ? options.guiProcessor(guiDefinition) : guiDefinition; // Preprocess fields (probably generate tabs...)
|
|
||||||
parent.rest.item(value.id, function(item) {
|
|
||||||
gui.tools.unblockUI();
|
|
||||||
gui.forms.launchModal({
|
|
||||||
title: modalTitle+' <b>'+value.name+'</b>',
|
|
||||||
fields: tabs,
|
|
||||||
item: item,
|
|
||||||
preprocessor: options.preprocessor,
|
|
||||||
buttons: buttons,
|
|
||||||
success: function(form_selector, closeFnc) {
|
|
||||||
var fields = gui.forms.read(form_selector);
|
|
||||||
fields.data_type = value.type;
|
|
||||||
fields = options.fieldsProcessor ? options.fieldsProcessor(fields) : fields;
|
|
||||||
parent.rest.save(fields, function(data) { // Success on put
|
|
||||||
closeFnc();
|
|
||||||
refreshFnc();
|
|
||||||
gui.notify(gettext('Edition successfully done'), 'success');
|
|
||||||
}, gui.failRequestModalFnc(modalErrorMsg, true)); // Fail on put, show modal message
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}, gui.failRequestModalFnc(modalErrorMsg, true));
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
// "Generic" new method to set onNew table
|
|
||||||
gui.methods.typedNew = function(parent, modalTitle, modalErrorMsg, options) {
|
|
||||||
options = options || {};
|
|
||||||
return function(type, table, refreshFnc) {
|
|
||||||
gui.tools.blockUI();
|
|
||||||
parent.rest.gui(type, function(guiDefinition) {
|
|
||||||
gui.tools.unblockUI();
|
|
||||||
var buttons = null;
|
|
||||||
if( options.testButton ) {
|
|
||||||
buttons = gui.methods.typedTestButton(parent.rest, options.testButton.text, options.testButton.css, type);
|
|
||||||
}
|
|
||||||
var tabs = options.guiProcessor ? options.guiProcessor(guiDefinition) : guiDefinition; // Preprocess fields (probably generate tabs...)
|
|
||||||
var title = modalTitle;
|
|
||||||
if( parent.types[type] !== undefined ) {
|
|
||||||
title += ' ' + gettext('of type') +' <b>' + parent.types[type].name + '</b>';
|
|
||||||
}
|
|
||||||
gui.forms.launchModal({
|
|
||||||
title: title,
|
|
||||||
fields: tabs,
|
|
||||||
item: undefined,
|
|
||||||
preprocessor: options.preprocessor,
|
|
||||||
buttons: buttons,
|
|
||||||
success: function(form_selector, closeFnc) {
|
|
||||||
var fields = gui.forms.read(form_selector);
|
|
||||||
if( parent.types[type] !== undefined ) {
|
|
||||||
fields.data_type = type;
|
|
||||||
}
|
|
||||||
fields = options.fieldsProcessor ? options.fieldsProcessor(fields) : fields; // Process fields before creating?
|
|
||||||
parent.rest.create(fields, function(data) { // Success on put
|
|
||||||
closeFnc();
|
|
||||||
refreshFnc();
|
|
||||||
gui.notify(gettext('Creation successfully done'), 'success');
|
|
||||||
}, gui.failRequestModalFnc(modalErrorMsg, true)); // Fail on put, show modal message
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}, gui.failRequestModalFnc(modalErrorMsg, true));
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
gui.methods.del = function(parent, modalTitle, modalErrorMsg) {
|
|
||||||
return function(value, event, table, refreshFnc) {
|
|
||||||
gui.doLog(value);
|
|
||||||
name = value.name || value.friendly_name;
|
|
||||||
var content = gettext('Are you sure do you want to delete ') + '<b>' + name + '</b>';
|
|
||||||
var modalId = gui.launchModal(modalTitle, content, { actionButton: '<button type="button" class="btn btn-danger button-accept">' + gettext('Delete') + '</button>'});
|
|
||||||
$(modalId + ' .button-accept').click(function(){
|
|
||||||
$(modalId).modal('hide');
|
|
||||||
parent.rest.del(value.id, function(){
|
|
||||||
refreshFnc();
|
|
||||||
gui.notify(gettext('Item deleted'), 'success');
|
|
||||||
}, gui.failRequestModalFnc(modalErrorMsg) );
|
|
||||||
});
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
// Public attributes
|
|
||||||
gui.debug = true;
|
|
||||||
}(window.gui = window.gui || {}, jQuery));
|
|
Loading…
Reference in New Issue
Block a user