forked from shaba/openuds
Updated admin script to use coffescript instead of directly javascript
This commit is contained in:
parent
a1e5a1357a
commit
7a0465fca5
17
server/src/uds/static/adm/js/api-spreadsheet.coffee
Normal file
17
server/src/uds/static/adm/js/api-spreadsheet.coffee
Normal file
@ -0,0 +1,17 @@
|
||||
"use strict"
|
||||
@api = @api ? {}
|
||||
@api.spreadsheet = @api.spreadsheet ? {}
|
||||
$ = jQuery
|
||||
|
||||
@api.spreadsheet.cell = (data, type, style) ->
|
||||
type = type or "String"
|
||||
if style isnt `undefined`
|
||||
style = " ss:StyleID=\"" + style + "\""
|
||||
else
|
||||
style = ""
|
||||
"<Cell" + style + "><Data ss:Type=\"" + type + "\">" + data + "</Data></Cell>"
|
||||
|
||||
@api.spreadsheet.row = (cell) ->
|
||||
"<Row>" + cell + "</Row>"
|
||||
|
||||
return
|
143
server/src/uds/static/adm/js/api-templates.coffee
Normal file
143
server/src/uds/static/adm/js/api-templates.coffee
Normal file
@ -0,0 +1,143 @@
|
||||
# jshint strict: true
|
||||
|
||||
# -------------------------------
|
||||
# Templates related
|
||||
# Inserted into api
|
||||
# for the admin app
|
||||
# -------------------------------
|
||||
"use strict"
|
||||
@api = @api ? {}
|
||||
$ = jQuery
|
||||
api = @api
|
||||
|
||||
# Registers Handlebar useful helpers
|
||||
|
||||
# Iterate thought dictionary
|
||||
Handlebars.registerHelper "eachKey", (context, options) ->
|
||||
ret = ""
|
||||
first = true
|
||||
for prop of context
|
||||
ret = ret + options.fn(
|
||||
key: prop
|
||||
value: context[prop]
|
||||
first: first
|
||||
)
|
||||
first = false
|
||||
ret
|
||||
|
||||
|
||||
# Equal comparision (like if helper, but with comparation)
|
||||
# Use as block as {{#ifequals [element] [element]}}....{{/ifequals}}
|
||||
Handlebars.registerHelper "ifequals", (context1, context2, options) ->
|
||||
if context1 is context2
|
||||
options.fn this
|
||||
else
|
||||
options.inverse this
|
||||
|
||||
|
||||
# Belongs comparision (similar to "if xxx in yyyyy")
|
||||
# Use as block as {{#ifbelong [element] [group]}}....{{/ifbelongs}}
|
||||
Handlebars.registerHelper "ifbelongs", (context1, context2, options) ->
|
||||
gui.doLog "belongs", context1, context2
|
||||
unless $.inArray(context1, context2) is -1
|
||||
gui.doLog "belongs is true"
|
||||
options.fn this
|
||||
else
|
||||
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", (id, value, options) ->
|
||||
options.data["_counter_" + id] = value
|
||||
return
|
||||
|
||||
Handlebars.registerHelper "get_counter", (id, options) ->
|
||||
options.data["_counter_" + id]
|
||||
|
||||
Handlebars.registerHelper "inc_counter", (id, options) ->
|
||||
options.data["_counter_" + id] += 1
|
||||
return
|
||||
|
||||
|
||||
# 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", (options) ->
|
||||
new Handlebars.SafeString("<script>" + options.fn(this) + "</script>")
|
||||
|
||||
|
||||
# Truncate chars, like django "truncatechars" filter
|
||||
Handlebars.registerHelper "truncatechars", (len, value) ->
|
||||
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
|
||||
val.substring(0, len - 3) + "..."
|
||||
else
|
||||
val
|
||||
|
||||
|
||||
# Remove white spaces
|
||||
Handlebars.registerHelper "clean_whitespace", (value) ->
|
||||
val = value.toString() # For Array objects, the toString method joins the array and returns one string containing each array element separated by commas
|
||||
val.replace RegExp(" ", "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 = (name, success_fnc) ->
|
||||
$this = this
|
||||
success_fnc = success_fnc or ->
|
||||
|
||||
api.doLog "Getting template " + name
|
||||
if name.indexOf("?") is -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: (data) ->
|
||||
cachedId = "tmpl_" + name
|
||||
$this.cache.put "_" + cachedId, $this.evaluate(data)
|
||||
$this.cache.put name, cachedId
|
||||
api.doLog "Success getting template \"" + name + "\"."
|
||||
success_fnc cachedId
|
||||
return
|
||||
|
||||
fail: (jqXHR, textStatus, errorThrown) ->
|
||||
api.doLog jqXHR
|
||||
api.doLog textStatus
|
||||
apid.doLog errorThrown
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
|
||||
# Simple JavaScript Templating, using HandleBars
|
||||
api.templates.evaluate = (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).
|
||||
cached = undefined
|
||||
unless /\W/.test(str)
|
||||
cached = @cache.get("_" + str)
|
||||
if cached is `undefined`
|
||||
cached = api.templates.evaluate(document.getElementById(str).innerHTML)
|
||||
@cache.put "_" + str, cached
|
||||
template = cached or Handlebars.compile(str)
|
||||
(if context then template(context) else template)
|
||||
|
||||
return
|
@ -101,6 +101,7 @@
|
||||
return;
|
||||
}
|
||||
}
|
||||
api.doLog('Invoking ajax for ', api.url_for(name, 'template'));
|
||||
$.ajax({
|
||||
url : api.url_for(name,'template'),
|
||||
type : "GET",
|
||||
|
381
server/src/uds/static/adm/js/api-tools.coffee
Normal file
381
server/src/uds/static/adm/js/api-tools.coffee
Normal file
@ -0,0 +1,381 @@
|
||||
# jshint strict: true
|
||||
((api, $, undefined_) ->
|
||||
"use strict"
|
||||
api.tools = base64: (s) ->
|
||||
window.btoa unescape(encodeURIComponent(s))
|
||||
|
||||
return
|
||||
) window.api = window.api or {}, 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
|
||||
#
|
||||
initialsOf = (arr) ->
|
||||
res = []
|
||||
for v of arr
|
||||
res.push arr[v].substr(0, 3)
|
||||
res
|
||||
|
||||
# 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
|
||||
# daylight saving
|
||||
# if it is leap year
|
||||
# Not so sure, not important i thing anyway :-)
|
||||
# english ordinal suffix for day of month
|
||||
# number of days of specified month, not important
|
||||
# microseconds
|
||||
# Seconds since EPOCH, not used
|
||||
# Time zone offset in seconds, replaced by offset
|
||||
# in ours/minutes :-)
|
||||
strftime = (fmt, d, locale) ->
|
||||
_strftime fmt, d, locale
|
||||
|
||||
# locale is optional
|
||||
strftimeTZ = (fmt, d, locale, timezone) ->
|
||||
if typeof locale is "number" and timezone is null
|
||||
timezone = locale
|
||||
locale = `undefined`
|
||||
_strftime fmt, d, locale,
|
||||
timezone: timezone
|
||||
|
||||
strftimeUTC = (fmt, d, locale) ->
|
||||
_strftime fmt, d, locale,
|
||||
utc: true
|
||||
|
||||
localizedStrftime = (locale) ->
|
||||
(fmt, d, options) ->
|
||||
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
|
||||
_strftime = (fmt, d, locale, options) ->
|
||||
options = options or {}
|
||||
|
||||
# d and locale are optional so check if d is really the locale
|
||||
if d and not quacksLikeDate(d)
|
||||
locale = d
|
||||
d = `undefined`
|
||||
d = d or new Date()
|
||||
locale = locale or DefaultLocale
|
||||
locale.formats = locale.formats or {}
|
||||
|
||||
# Hang on to this Unix timestamp because we might mess with it directly
|
||||
# below.
|
||||
timestamp = d.getTime()
|
||||
d = dateToUTC(d) if options.utc or typeof options.timezone is "number"
|
||||
d = new Date(d.getTime() + (options.timezone * 60000)) if typeof options.timezone is "number"
|
||||
|
||||
# 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).
|
||||
fmt.replace /%([-_0]?.)/g, (_, c) ->
|
||||
mod = undefined
|
||||
padding = undefined
|
||||
if c.length is 2
|
||||
mod = c[0]
|
||||
|
||||
# omit padding
|
||||
if mod is "-"
|
||||
padding = ""
|
||||
|
||||
# pad with space
|
||||
else if mod is "_"
|
||||
padding = " "
|
||||
|
||||
# pad with zero
|
||||
else if mod is "0"
|
||||
padding = "0"
|
||||
else
|
||||
|
||||
# unrecognized, return the format
|
||||
return _
|
||||
c = c[1]
|
||||
switch c
|
||||
when "A"
|
||||
locale.days[d.getDay()]
|
||||
when "a"
|
||||
locale.shortDays[d.getDay()]
|
||||
when "B"
|
||||
locale.months[d.getMonth()]
|
||||
when "b"
|
||||
locale.shortMonths[d.getMonth()]
|
||||
when "C"
|
||||
pad Math.floor(d.getFullYear() / 100), padding
|
||||
when "D"
|
||||
_strftime locale.formats.D or "%m/%d/%y", d, locale
|
||||
when "d"
|
||||
pad d.getDate(), padding
|
||||
when "e"
|
||||
d.getDate()
|
||||
when "F"
|
||||
_strftime locale.formats.F or "%Y-%m-%d", d, locale
|
||||
when "H"
|
||||
pad d.getHours(), padding
|
||||
when "h"
|
||||
locale.shortMonths[d.getMonth()]
|
||||
when "I"
|
||||
pad hours12(d), padding
|
||||
when "j"
|
||||
y = new Date(d.getFullYear(), 0, 1)
|
||||
day = Math.ceil((d.getTime() - y.getTime()) / (1000 * 60 * 60 * 24))
|
||||
pad day, 3
|
||||
when "k"
|
||||
pad d.getHours(), (if padding is null then " " else padding)
|
||||
when "L"
|
||||
pad Math.floor(timestamp % 1000), 3
|
||||
when "l"
|
||||
pad hours12(d), (if padding is null then " " else padding)
|
||||
when "M"
|
||||
pad d.getMinutes(), padding
|
||||
when "m"
|
||||
pad d.getMonth() + 1, padding
|
||||
when "n"
|
||||
"\n"
|
||||
when "o"
|
||||
String(d.getDate()) + ordinal(d.getDate())
|
||||
when "P"
|
||||
(if d.getHours() < 12 then locale.am else locale.pm)
|
||||
when "p"
|
||||
(if d.getHours() < 12 then locale.AM else locale.PM)
|
||||
when "R"
|
||||
_strftime locale.formats.R or "%H:%M", d, locale
|
||||
when "r"
|
||||
_strftime locale.formats.r or "%I:%M:%S %p", d, locale
|
||||
when "S"
|
||||
pad d.getSeconds(), padding
|
||||
when "s"
|
||||
Math.floor timestamp / 1000
|
||||
when "T"
|
||||
_strftime locale.formats.T or "%H:%M:%S", d, locale
|
||||
when "t"
|
||||
"\t"
|
||||
when "U"
|
||||
pad weekNumber(d, "sunday"), padding
|
||||
when "u"
|
||||
dayu = d.getDay()
|
||||
(if dayu is 0 then 7 else dayu) # 1 - 7, Monday is first day of the
|
||||
# week
|
||||
when "v"
|
||||
_strftime locale.formats.v or "%e-%b-%Y", d, locale
|
||||
when "W"
|
||||
pad weekNumber(d, "monday"), padding
|
||||
when "w"
|
||||
d.getDay() # 0 - 6, Sunday is first day of the
|
||||
# week
|
||||
when "Y"
|
||||
d.getFullYear()
|
||||
when "y"
|
||||
yy = String(d.getFullYear())
|
||||
yy.slice yy.length - 2
|
||||
when "Z"
|
||||
if options.utc
|
||||
return "GMT"
|
||||
else
|
||||
tz = d.toString().match(/\((\w+)\)/)
|
||||
return tz and tz[1] or ""
|
||||
when "z"
|
||||
if options.utc
|
||||
return "+0000"
|
||||
else
|
||||
off_ = (if typeof options.timezone is "number" then options.timezone else -d.getTimezoneOffset())
|
||||
return ((if off_ < 0 then "-" else "+")) + pad(Math.abs(off_ / 60)) + pad(off_ % 60)
|
||||
else
|
||||
c
|
||||
|
||||
dateToUTC = (d) ->
|
||||
msDelta = (d.getTimezoneOffset() or 0) * 60000
|
||||
new Date(d.getTime() + msDelta)
|
||||
quacksLikeDate = (x) ->
|
||||
i = 0
|
||||
n = RequiredDateMethods.length
|
||||
i = 0
|
||||
while i < n
|
||||
return false unless typeof x[RequiredDateMethods[i]] is "function"
|
||||
++i
|
||||
true
|
||||
|
||||
# Default padding is '0' and default length is 2, both are optional.
|
||||
pad = (n, padding, length) ->
|
||||
|
||||
# pad(n, <length>)
|
||||
if typeof padding is "number"
|
||||
length = padding
|
||||
padding = "0"
|
||||
|
||||
# Defaults handle pad(n) and pad(n, <padding>)
|
||||
padding = "0" if padding is null
|
||||
length = length or 2
|
||||
s = String(n)
|
||||
|
||||
# padding may be an empty string, don't loop forever if it is
|
||||
s = padding + s while s.length < length if padding
|
||||
s
|
||||
hours12 = (d) ->
|
||||
hour = d.getHours()
|
||||
if hour is 0
|
||||
hour = 12
|
||||
else hour -= 12 if hour > 12
|
||||
hour
|
||||
|
||||
# Get the ordinal suffix for a number: st, nd, rd, or th
|
||||
ordinal = (n) ->
|
||||
i = n % 10
|
||||
ii = n % 100
|
||||
return "th" if (ii >= 11 and ii <= 13) or i is 0 or i >= 4
|
||||
switch i
|
||||
when 1
|
||||
"st"
|
||||
when 2
|
||||
"nd"
|
||||
when 3
|
||||
"rd"
|
||||
|
||||
# firstWeekday: 'sunday' or 'monday', default is 'sunday'
|
||||
#
|
||||
# Pilfered & ported from Ruby's strftime implementation.
|
||||
weekNumber = (d, firstWeekday) ->
|
||||
firstWeekday = firstWeekday or "sunday"
|
||||
|
||||
# This works by shifting the weekday back by one day if we
|
||||
# are treating Monday as the first day of the week.
|
||||
wday = d.getDay()
|
||||
if firstWeekday is "monday"
|
||||
if wday is 0 # Sunday
|
||||
wday = 6
|
||||
else
|
||||
wday--
|
||||
firstDayOfYear = new Date(d.getFullYear(), 0, 1)
|
||||
yday = (d - firstDayOfYear) / 86400000
|
||||
weekNum = (yday + 7 - wday) / 7
|
||||
Math.floor weekNum
|
||||
"use strict"
|
||||
namespace = api.tools
|
||||
dayNames = [
|
||||
gettext("Sunday")
|
||||
gettext("Monday")
|
||||
gettext("Tuesday")
|
||||
gettext("Wednesday")
|
||||
gettext("Thursday")
|
||||
gettext("Friday")
|
||||
gettext("Saturday")
|
||||
]
|
||||
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")
|
||||
]
|
||||
DefaultLocale =
|
||||
days: dayNames
|
||||
shortDays: initialsOf(dayNames)
|
||||
months: monthNames
|
||||
shortMonths: initialsOf(monthNames)
|
||||
AM: "AM"
|
||||
PM: "PM"
|
||||
am: "am"
|
||||
pm: "pm"
|
||||
|
||||
namespace.djangoFormat = (format) ->
|
||||
format.replace /./g, (c) ->
|
||||
switch c
|
||||
when "a", "A"
|
||||
"%p"
|
||||
when "b", "d", "m", "w", "W", "y", "Y"
|
||||
"%" + c
|
||||
when "c"
|
||||
"%FT%TZ"
|
||||
when "D"
|
||||
"%a"
|
||||
when "e"
|
||||
"%z"
|
||||
when "f"
|
||||
"%I:%M"
|
||||
when "F"
|
||||
"%F"
|
||||
when "h", "g"
|
||||
"%I"
|
||||
when "H", "G"
|
||||
"%H"
|
||||
when "i"
|
||||
"%M"
|
||||
when "I"
|
||||
""
|
||||
when "j"
|
||||
"%d"
|
||||
when "l"
|
||||
"%A"
|
||||
when "L"
|
||||
""
|
||||
when "M"
|
||||
"%b"
|
||||
when "n"
|
||||
"%m"
|
||||
when "N"
|
||||
"%b"
|
||||
when "o"
|
||||
"%W"
|
||||
when "O"
|
||||
"%z"
|
||||
when "P"
|
||||
"%R %p"
|
||||
when "r"
|
||||
"%a, %d %b %Y %T %z"
|
||||
when "s"
|
||||
"%S"
|
||||
when "S"
|
||||
""
|
||||
when "t"
|
||||
""
|
||||
when "T"
|
||||
"%Z"
|
||||
when "u"
|
||||
"0"
|
||||
when "U"
|
||||
""
|
||||
when "z"
|
||||
"%j"
|
||||
when "Z"
|
||||
"z"
|
||||
else
|
||||
c
|
||||
|
||||
|
||||
namespace.strftime = strftime
|
||||
namespace.strftimeTZ = strftime.strftimeTZ = strftimeTZ
|
||||
namespace.strftimeUTC = strftime.strftimeUTC = strftimeUTC
|
||||
namespace.localizedStrftime = strftime.localizedStrftime = localizedStrftime
|
||||
RequiredDateMethods = [
|
||||
"getTime"
|
||||
"getTimezoneOffset"
|
||||
"getDay"
|
||||
"getDate"
|
||||
"getMonth"
|
||||
"getFullYear"
|
||||
"getYear"
|
||||
"getHours"
|
||||
"getMinutes"
|
||||
"getSeconds"
|
||||
]
|
||||
return
|
383
server/src/uds/static/adm/js/api.coffee
Normal file
383
server/src/uds/static/adm/js/api.coffee
Normal file
@ -0,0 +1,383 @@
|
||||
# jshint strict: true
|
||||
"use strict"
|
||||
@api = @api ? {}
|
||||
$ = jQuery
|
||||
api = @api
|
||||
|
||||
api.debug = off
|
||||
|
||||
api.doLog = (args...) ->
|
||||
if api.debug
|
||||
try
|
||||
console.log.apply window, args
|
||||
return
|
||||
|
||||
api.cacheTable = {}
|
||||
api.cache = (cacheName) ->
|
||||
new Cache(cacheName)
|
||||
|
||||
api.cache.clear = (cacheName) ->
|
||||
if cacheName is `undefined`
|
||||
api.cacheTable = {}
|
||||
else
|
||||
api.cacheTable[cacheName] = {}
|
||||
return
|
||||
|
||||
api.url_for = (path, type='rest') ->
|
||||
api.doLog 'Url for: ', path, ', ', type
|
||||
switch type
|
||||
when "template"
|
||||
api.config.template_url + path
|
||||
when "rest"
|
||||
api.config.base_url + path
|
||||
else
|
||||
api.doLog 'Type of url not found: ' + type
|
||||
throw "Type of url not found: " + type
|
||||
|
||||
api.defaultFail = (jqXHR, textStatus, errorThrown) ->
|
||||
api.doLog jqXHR, ", ", textStatus, ", ", errorThrown
|
||||
return
|
||||
|
||||
api.getJson = (path, options) ->
|
||||
options = options or {}
|
||||
success_fnc = options.success or ->
|
||||
|
||||
fail_fnc = options.fail or api.defaultFail
|
||||
url = api.url_for(path)
|
||||
api.doLog "Ajax GET Json for \"" + url + "\""
|
||||
$.ajax
|
||||
url: url
|
||||
type: options.method or "GET"
|
||||
dataType: "json"
|
||||
success: (data) ->
|
||||
api.doLog "Success on GET \"" + url + "\"."
|
||||
api.doLog "Received ", data
|
||||
success_fnc data
|
||||
return
|
||||
|
||||
error: (jqXHR, textStatus, errorThrown) ->
|
||||
api.doLog "Error on GET \"" + url + "\". ", textStatus, ", ", errorThrown
|
||||
fail_fnc jqXHR, textStatus, errorThrown
|
||||
return
|
||||
|
||||
beforeSend: (request) ->
|
||||
request.setRequestHeader api.config.auth_header, api.config.token
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
api.putJson = (path, data, options) ->
|
||||
options = options or {}
|
||||
success_fnc = options.success or ->
|
||||
|
||||
fail_fnc = options.fail or api.defaultFail
|
||||
url = api.url_for(path)
|
||||
api.doLog "Ajax PUT Json for \"" + url + "\""
|
||||
$.ajax
|
||||
url: url
|
||||
type: options.method or "PUT"
|
||||
dataType: "json"
|
||||
data: JSON.stringify(data)
|
||||
success: (data) ->
|
||||
api.doLog "Success on PUT \"" + url + "\"."
|
||||
api.doLog "Received ", data
|
||||
success_fnc data
|
||||
return
|
||||
|
||||
error: (jqXHR, textStatus, errorThrown) ->
|
||||
api.doLog "Error on PUT \"" + url + "\". ", textStatus, ", ", errorThrown
|
||||
fail_fnc jqXHR, textStatus, errorThrown
|
||||
return
|
||||
|
||||
beforeSend: (request) ->
|
||||
request.setRequestHeader api.config.auth_header, api.config.token
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
api.deleteJson = (path, options) ->
|
||||
options = options or {}
|
||||
success_fnc = options.success or ->
|
||||
|
||||
fail_fnc = options.fail or api.defaultFail
|
||||
url = api.url_for(path)
|
||||
api.doLog "Ajax DELETE Json for \"" + url + "\""
|
||||
$.ajax
|
||||
url: url
|
||||
type: "DELETE"
|
||||
dataType: "json"
|
||||
success: (data) ->
|
||||
api.doLog "Success on DELETE \"" + url + "\"."
|
||||
api.doLog "Received ", data
|
||||
success_fnc data
|
||||
return
|
||||
|
||||
error: (jqXHR, textStatus, errorThrown) ->
|
||||
api.doLog "Error on DELETE \"" + url + "\". ", textStatus, ", ", errorThrown
|
||||
fail_fnc jqXHR, textStatus, errorThrown
|
||||
return
|
||||
|
||||
beforeSend: (request) ->
|
||||
request.setRequestHeader api.config.auth_header, api.config.token
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
class Cache
|
||||
constructor: (cacheName) ->
|
||||
api.cacheTable[cacheName] = api.cacheTable[cacheName] or {}
|
||||
@name = cacheName
|
||||
@cache = api.cacheTable[cacheName]
|
||||
|
||||
get: (key, not_found_fnc) ->
|
||||
not_found_fnc = not_found_fnc or ->
|
||||
null
|
||||
|
||||
@cache[key] = not_found_fnc() if @cache[key] is null
|
||||
@cache[key]
|
||||
|
||||
put: (key, value) ->
|
||||
@cache[key] = value
|
||||
return
|
||||
|
||||
|
||||
class BasicModelRest
|
||||
constructor: (path, options) ->
|
||||
options = options or {}
|
||||
path = path or ""
|
||||
|
||||
# Requests paths
|
||||
@path = path
|
||||
@getPath = options.getPath or path
|
||||
@logPath = options.logPath or path
|
||||
@putPath = options.putPath or path
|
||||
@testPath = options.testPath or (path + "/test")
|
||||
@delPath = options.delPath or path
|
||||
@typesPath = options.typesPath or (path + "/types")
|
||||
@guiPath = options.guiPath or (path + "/gui")
|
||||
@tableInfoPath = options.tableInfoPath or (path + "/tableinfo")
|
||||
@cache = api.cache("bmr" + path)
|
||||
|
||||
_requestPath: (path, options) ->
|
||||
api.doLog "Requesting ", path, options
|
||||
options = options or {}
|
||||
success_fnc = options.success or ->
|
||||
api.doLog "success function not provided for " + path
|
||||
return
|
||||
|
||||
fail_fnc = options.fail or ->
|
||||
api.doLog "failFnc not provided for " + path
|
||||
cacheKey = options.cacheKey or path
|
||||
api.doLog 'CacheKey ', cacheKey
|
||||
if path is "."
|
||||
success_fnc {}
|
||||
return
|
||||
if cacheKey isnt "." and @cache.get(cacheKey)
|
||||
success_fnc @cache.get(cacheKey)
|
||||
else
|
||||
$this = @
|
||||
api.doLog 'Obtaining json for ', path
|
||||
api.getJson path,
|
||||
success: (data) ->
|
||||
$this.cache.put cacheKey, data unless cacheKey is "."
|
||||
success_fnc data
|
||||
return
|
||||
|
||||
fail: fail_fnc
|
||||
|
||||
return
|
||||
|
||||
get: (options) ->
|
||||
options = options or {}
|
||||
path = @getPath
|
||||
path += "/" + options.id if options.id
|
||||
api.doLog "get Options: ", options, path
|
||||
@_requestPath path,
|
||||
cacheKey: "."
|
||||
success: options.success
|
||||
fail: options.fail
|
||||
|
||||
|
||||
list: (success_fnc, fail_fnc) ->
|
||||
@get
|
||||
id: ""
|
||||
success: success_fnc
|
||||
fail: fail_fnc
|
||||
|
||||
|
||||
overview: (success_fnc, fail_fnc) ->
|
||||
@get
|
||||
id: "overview"
|
||||
success: success_fnc
|
||||
fail: fail_fnc
|
||||
|
||||
|
||||
item: (itemId, success_fnc, fail_fnc) ->
|
||||
@get
|
||||
id: itemId
|
||||
success: success_fnc
|
||||
fail: fail_fnc
|
||||
|
||||
|
||||
getLogs: (itemId, success_fnc, fail_fnc) ->
|
||||
path = @logPath + "/" + itemId + "/" + "log"
|
||||
@_requestPath path,
|
||||
cacheKey: "."
|
||||
success: success_fnc
|
||||
fail: fail_fnc
|
||||
|
||||
|
||||
put: (data, options) ->
|
||||
options = options or {}
|
||||
path = @putPath
|
||||
path += "/" + options.id if options.id
|
||||
api.putJson path, data,
|
||||
success: options.success
|
||||
fail: options.fail
|
||||
|
||||
return
|
||||
|
||||
create: (data, success_fnc, fail_fnc) ->
|
||||
@put data,
|
||||
success: success_fnc
|
||||
fail: fail_fnc
|
||||
|
||||
|
||||
save: (data, success_fnc, fail_fnc) ->
|
||||
@put data,
|
||||
id: data.id
|
||||
success: success_fnc
|
||||
fail: fail_fnc
|
||||
|
||||
|
||||
test: (type, data, success_fnc, fail_fnc) ->
|
||||
path = @testPath + "/" + type
|
||||
api.putJson path, data,
|
||||
success: success_fnc
|
||||
fail: fail_fnc
|
||||
method: "POST"
|
||||
|
||||
return
|
||||
|
||||
del: (id, success_fnc, fail_fnc) ->
|
||||
path = @delPath + "/" + id
|
||||
api.deleteJson path,
|
||||
success: success_fnc
|
||||
fail: fail_fnc
|
||||
|
||||
return
|
||||
|
||||
types: (success_fnc, fail_fnc) ->
|
||||
@_requestPath @typesPath,
|
||||
cacheKey: @typesPath
|
||||
success: success_fnc
|
||||
|
||||
|
||||
gui: (typeName, success_fnc, fail_fnc) ->
|
||||
path = undefined
|
||||
if typeName isnt `undefined`
|
||||
path = [
|
||||
this.guiPath
|
||||
typeName
|
||||
].join("/")
|
||||
else
|
||||
path = @guiPath
|
||||
@_requestPath path,
|
||||
cacheKey: "."
|
||||
success: success_fnc
|
||||
fail: fail_fnc
|
||||
|
||||
|
||||
tableInfo: (success_fnc, fail_fnc) ->
|
||||
success_fnc = success_fnc or ->
|
||||
api.doLog "success not provided for tableInfo"
|
||||
return
|
||||
|
||||
path = @tableInfoPath
|
||||
@_requestPath path,
|
||||
success: success_fnc
|
||||
fail: fail_fnc
|
||||
|
||||
return
|
||||
|
||||
detail: (id, child, options) ->
|
||||
options = options or {}
|
||||
new DetailModelRestApi(this, id, child, options)
|
||||
|
||||
class DetailModelRestApi extends BasicModelRest
|
||||
constructor: (parentApi, parentId, model, options) ->
|
||||
super [
|
||||
parentApi.path
|
||||
parentId
|
||||
model
|
||||
].join("/")
|
||||
@moptions = options
|
||||
|
||||
create: (data, success_fnc, fail_fnc) ->
|
||||
@put data,
|
||||
success: success_fnc
|
||||
fail: fail_fnc
|
||||
|
||||
|
||||
save: (data, success_fnc, fail_fnc) ->
|
||||
@put data,
|
||||
id: data.id
|
||||
success: success_fnc
|
||||
fail: fail_fnc
|
||||
|
||||
types: (success_fnc, fail_fnc) ->
|
||||
if @moptions.types
|
||||
@moptions.types success_fnc, fail_fnc
|
||||
else
|
||||
super success_fnc, fail_fnc
|
||||
return
|
||||
|
||||
# Generic "Invoke" method (with no args, if needed, put them on "method" after "?" as normal url would be
|
||||
invoke: (method, success_fnc, fail_fnc) ->
|
||||
@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 = (success_fnc, fail_fnc) ->
|
||||
@get
|
||||
id: "allservices"
|
||||
success: success_fnc
|
||||
fail: fail_fnc
|
||||
|
||||
|
||||
api.providers.service = (id, success_fnc, fail_fnc) ->
|
||||
@get
|
||||
id: "service/" + id
|
||||
success: success_fnc
|
||||
fail: fail_fnc
|
||||
|
||||
|
||||
api.authenticators = new BasicModelRest("authenticators")
|
||||
|
||||
# Search method used in authenticators
|
||||
api.authenticators.search = (id, type, term, success_fnc, fail_fnc) ->
|
||||
@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 = (type, success_fnc, fail_fnc) ->
|
||||
@get
|
||||
id: "stats/" + type
|
||||
success: success_fnc
|
||||
fail: fail_fnc
|
||||
|
||||
|
||||
return
|
@ -128,21 +128,18 @@
|
||||
|
||||
// Public attributes
|
||||
api.debug = false;
|
||||
}(window.api = window.api || {}, jQuery));
|
||||
|
||||
|
||||
// Cache related
|
||||
function Cache(cacheName) {
|
||||
"use strict";
|
||||
// Cache related
|
||||
function Cache(cacheName) {
|
||||
api.cacheTable[cacheName] = api.cacheTable[cacheName] || {};
|
||||
|
||||
this.name = cacheName;
|
||||
this.cache = api.cacheTable[cacheName];
|
||||
}
|
||||
}
|
||||
|
||||
Cache.prototype = {
|
||||
Cache.prototype = {
|
||||
get: function(key, not_found_fnc){
|
||||
"use strict";
|
||||
not_found_fnc = not_found_fnc || function() { return undefined; };
|
||||
|
||||
if( this.cache[key] === undefined ) {
|
||||
@ -152,18 +149,16 @@ Cache.prototype = {
|
||||
},
|
||||
|
||||
put: function(key, value) {
|
||||
"use strict";
|
||||
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 :-)
|
||||
// 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) {
|
||||
"use strict";
|
||||
function BasicModelRest(path, options) {
|
||||
options = options || {};
|
||||
path = path || '';
|
||||
// Requests paths
|
||||
@ -177,15 +172,14 @@ function BasicModelRest(path, options) {
|
||||
this.guiPath = options.guiPath || (path + '/gui');
|
||||
this.tableInfoPath = options.tableInfoPath || (path + '/tableinfo');
|
||||
this.cache = api.cache('bmr'+path);
|
||||
}
|
||||
}
|
||||
|
||||
BasicModelRest.prototype = {
|
||||
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) {
|
||||
"use strict";
|
||||
options = options || {};
|
||||
var success_fnc = options.success || function(){api.doLog('success function not provided for '+path);};
|
||||
var fail_fnc = options.fail;
|
||||
@ -212,7 +206,6 @@ BasicModelRest.prototype = {
|
||||
}
|
||||
},
|
||||
get: function(options) {
|
||||
"use strict";
|
||||
options = options || {};
|
||||
|
||||
var path = this.getPath;
|
||||
@ -226,7 +219,6 @@ BasicModelRest.prototype = {
|
||||
});
|
||||
},
|
||||
list: function(success_fnc, fail_fnc) { // This is "almost" an alias for get
|
||||
"use strict";
|
||||
return this.get({
|
||||
id: '',
|
||||
success: success_fnc,
|
||||
@ -234,7 +226,6 @@ BasicModelRest.prototype = {
|
||||
});
|
||||
},
|
||||
overview: function(success_fnc, fail_fnc) {
|
||||
"use strict";
|
||||
return this.get({
|
||||
id: 'overview',
|
||||
success: success_fnc,
|
||||
@ -242,7 +233,6 @@ BasicModelRest.prototype = {
|
||||
});
|
||||
},
|
||||
item: function(itemId, success_fnc, fail_fnc) {
|
||||
"use strict";
|
||||
return this.get({
|
||||
id: itemId,
|
||||
success: success_fnc,
|
||||
@ -254,7 +244,6 @@ BasicModelRest.prototype = {
|
||||
// Log methods
|
||||
// -------------
|
||||
getLogs: function(itemId, success_fnc, fail_fnc) {
|
||||
"use strict";
|
||||
var path = this.logPath + '/' + itemId + '/' + 'log';
|
||||
return this._requestPath(path, {
|
||||
cacheKey: '.',
|
||||
@ -269,7 +258,6 @@ BasicModelRest.prototype = {
|
||||
// -------------
|
||||
|
||||
put: function(data, options) {
|
||||
"use strict";
|
||||
options = options || {};
|
||||
|
||||
var path = this.putPath;
|
||||
@ -282,7 +270,6 @@ BasicModelRest.prototype = {
|
||||
});
|
||||
},
|
||||
create: function(data, success_fnc, fail_fnc) {
|
||||
"use strict";
|
||||
|
||||
return this.put(data, {
|
||||
success: success_fnc,
|
||||
@ -290,7 +277,6 @@ BasicModelRest.prototype = {
|
||||
});
|
||||
},
|
||||
save: function(data, success_fnc, fail_fnc) {
|
||||
"use strict";
|
||||
|
||||
return this.put(data, {
|
||||
id: data.id,
|
||||
@ -301,8 +287,6 @@ BasicModelRest.prototype = {
|
||||
|
||||
// Testing
|
||||
test: function(type, data, success_fnc, fail_fnc) {
|
||||
"use strict";
|
||||
|
||||
var path = this.testPath + '/' + type;
|
||||
|
||||
api.putJson(path, data, {
|
||||
@ -315,8 +299,6 @@ BasicModelRest.prototype = {
|
||||
// Delete
|
||||
// --------------
|
||||
del: function(id, success_fnc, fail_fnc) {
|
||||
"use strict";
|
||||
|
||||
var path = this.delPath + '/' + id;
|
||||
|
||||
api.deleteJson(path, {
|
||||
@ -329,7 +311,6 @@ BasicModelRest.prototype = {
|
||||
// Types methods
|
||||
// --------------
|
||||
types : function(success_fnc, fail_fnc) {
|
||||
"use strict";
|
||||
return this._requestPath(this.typesPath, {
|
||||
cacheKey: this.typesPath,
|
||||
success: success_fnc,
|
||||
@ -340,7 +321,6 @@ BasicModelRest.prototype = {
|
||||
// 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, ....
|
||||
"use strict";
|
||||
|
||||
var path;
|
||||
if( typeName !== undefined ) {
|
||||
@ -355,7 +335,6 @@ BasicModelRest.prototype = {
|
||||
});
|
||||
},
|
||||
tableInfo : function(success_fnc, fail_fnc) {
|
||||
"use strict";
|
||||
success_fnc = success_fnc || function(){api.doLog('success not provided for tableInfo');};
|
||||
|
||||
var path = this.tableInfoPath;
|
||||
@ -366,52 +345,43 @@ BasicModelRest.prototype = {
|
||||
},
|
||||
|
||||
detail: function(id, child, options) {
|
||||
"use strict";
|
||||
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) {
|
||||
"use strict";
|
||||
// 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 = {
|
||||
DetailModelRestApi.prototype = {
|
||||
// Generates a basic model with fixed methods for "detail" models
|
||||
get: function(success_fnc, fail_fnc) {
|
||||
"use strict";
|
||||
return this.base.get(success_fnc, fail_fnc);
|
||||
},
|
||||
list: function(success_fnc, fail_fnc) { // This is "almost" an alias for get
|
||||
"use strict";
|
||||
return this.base.list(success_fnc, fail_fnc);
|
||||
},
|
||||
overview: function(success_fnc, fail_fnc) {
|
||||
"use strict";
|
||||
return this.base.overview(success_fnc, fail_fnc);
|
||||
},
|
||||
item: function(itemId, success_fnc, fail_fnc) {
|
||||
"use strict";
|
||||
return this.base.item(itemId, success_fnc, fail_fnc);
|
||||
},
|
||||
// -------------
|
||||
// Log methods
|
||||
// -------------
|
||||
getLogs: function(itemId, success_fnc, fail_fnc) {
|
||||
"use strict";
|
||||
return this.base.getLogs(itemId, success_fnc, fail_fnc);
|
||||
},
|
||||
// Put methods
|
||||
put: function(data, options) {
|
||||
"use strict";
|
||||
return this.base.put(data, options);
|
||||
},
|
||||
create: function(data, success_fnc, fail_fnc) {
|
||||
"use strict";
|
||||
|
||||
return this.put(data, {
|
||||
success: success_fnc,
|
||||
@ -419,8 +389,6 @@ DetailModelRestApi.prototype = {
|
||||
});
|
||||
},
|
||||
save: function(data, success_fnc, fail_fnc) {
|
||||
"use strict";
|
||||
|
||||
return this.put(data, {
|
||||
id: data.id,
|
||||
success: success_fnc,
|
||||
@ -429,24 +397,19 @@ DetailModelRestApi.prototype = {
|
||||
},
|
||||
// Testing
|
||||
test: function(type, data, success_fnc, fail_fnc) {
|
||||
"use strict";
|
||||
|
||||
return this.base.test(type, data, success_fnc, fail_fnc);
|
||||
},
|
||||
// --------------
|
||||
// Delete
|
||||
// --------------
|
||||
del: function(id, success_fnc, fail_fnc) {
|
||||
"use strict";
|
||||
return this.base.del(id, success_fnc, fail_fnc);
|
||||
},
|
||||
|
||||
tableInfo: function(success_fnc, fail_fnc) {
|
||||
"use strict";
|
||||
return this.base.tableInfo(success_fnc, fail_fnc);
|
||||
},
|
||||
types: function(success_fnc, fail_fnc) {
|
||||
"use strict";
|
||||
if( this.options.types ) {
|
||||
this.options.types(success_fnc, fail_fnc);
|
||||
} else {
|
||||
@ -454,13 +417,11 @@ DetailModelRestApi.prototype = {
|
||||
}
|
||||
},
|
||||
gui: function(typeName, success_fnc, fail_fnc) { // Typename can be "undefined" to request MAIN gui (it it exists ofc..)
|
||||
"use strict";
|
||||
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) {
|
||||
"use strict";
|
||||
return this.base.get({
|
||||
id: method,
|
||||
success: success_fnc,
|
||||
@ -468,57 +429,52 @@ DetailModelRestApi.prototype = {
|
||||
});
|
||||
},
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
// Populate api
|
||||
// Populate api
|
||||
|
||||
api.providers = new BasicModelRest('providers');
|
||||
// all services method used in providers
|
||||
api.providers.allServices = function(success_fnc, fail_fnc) {
|
||||
"use strict";
|
||||
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) {
|
||||
"use strict";
|
||||
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) {
|
||||
"use strict";
|
||||
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.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.configuration = new BasicModelRest('config');
|
||||
|
||||
api.system = new BasicModelRest('system');
|
||||
api.system.stats = function(type, success_fnc, fail_fnc) {
|
||||
"use strict";
|
||||
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));
|
||||
|
398
server/src/uds/static/adm/js/gui-d-authenticators.coffee
Normal file
398
server/src/uds/static/adm/js/gui-d-authenticators.coffee
Normal file
@ -0,0 +1,398 @@
|
||||
# jshint strict: true
|
||||
gui.authenticators = new GuiElement(api.authenticators, "auth")
|
||||
gui.authenticators.link = (event) ->
|
||||
"use strict"
|
||||
|
||||
# Button definition to trigger "Test" action
|
||||
testButton = testButton:
|
||||
text: gettext("Test authenticator")
|
||||
css: "btn-info"
|
||||
|
||||
|
||||
# Clears the log of the detail, in this case, the log of "users"
|
||||
# Memory saver :-)
|
||||
detailLogTable = null
|
||||
clearDetailLog = ->
|
||||
if detailLogTable
|
||||
$tbl = $(detailLogTable).dataTable()
|
||||
$tbl.fnClearTable()
|
||||
$tbl.fnDestroy()
|
||||
$("#user-log-placeholder").empty()
|
||||
detailLogTable = null
|
||||
return
|
||||
|
||||
|
||||
# Clears the details
|
||||
# Memory saver :-)
|
||||
prevTables = []
|
||||
clearDetails = ->
|
||||
$.each prevTables, (undefined_, tbl) ->
|
||||
$tbl = $(tbl).dataTable()
|
||||
$tbl.fnClearTable()
|
||||
$tbl.fnDestroy()
|
||||
return
|
||||
|
||||
clearDetailLog()
|
||||
$("#users-placeholder").empty()
|
||||
$("#groups-placeholder").empty()
|
||||
$("#logs-placeholder").empty()
|
||||
$("#detail-placeholder").addClass "hidden"
|
||||
prevTables = []
|
||||
return
|
||||
|
||||
|
||||
# Search button event generator for user/group
|
||||
searchForm = (parentModalId, type, id, title, searchLabel, resultsLabel) ->
|
||||
errorModal = gui.failRequestModalFnc(gettext("Search error"))
|
||||
srcSelector = parentModalId + " input[name=\"name\"]"
|
||||
$(parentModalId + " .button-search").on "click", ->
|
||||
api.templates.get "search", (tmpl) -> # Get form template
|
||||
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>"
|
||||
)
|
||||
$searchInput = $(modalId + " input[name=\"search\"]")
|
||||
$select = $(modalId + " select[name=\"results\"]")
|
||||
$searchButton = $(modalId + " .button-do-search")
|
||||
$saveButton = $(modalId + " .button-accept")
|
||||
$searchInput.val $(srcSelector).val()
|
||||
$saveButton.on "click", ->
|
||||
value = $select.val()
|
||||
if value
|
||||
$(srcSelector).val value
|
||||
$(modalId).modal "hide"
|
||||
return
|
||||
|
||||
$searchButton.on "click", ->
|
||||
$searchButton.addClass "disabled"
|
||||
term = $searchInput.val()
|
||||
api.authenticators.search id, type, term, ((data) ->
|
||||
$searchButton.removeClass "disabled"
|
||||
$select.empty()
|
||||
gui.doLog data
|
||||
$.each data, (undefined_, value) ->
|
||||
$select.append "<option value=\"" + value.id + "\">" + value.id + " (" + value.name + ")</option>"
|
||||
return
|
||||
|
||||
return
|
||||
), (jqXHR, textStatus, errorThrown) ->
|
||||
$searchButton.removeClass "disabled"
|
||||
errorModal jqXHR, textStatus, errorThrown
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
$(modalId + " form").submit (event) ->
|
||||
event.preventDefault()
|
||||
$searchButton.click()
|
||||
return
|
||||
|
||||
$searchButton.click() if $searchInput.val() isnt ""
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
api.templates.get "authenticators", (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", (event) ->
|
||||
gui.doLog event.target
|
||||
setTimeout (->
|
||||
$($(event.target).attr("href") + " span.fa-refresh").click()
|
||||
return
|
||||
), 10
|
||||
return
|
||||
|
||||
tableId = gui.authenticators.table(
|
||||
container: "auths-placeholder"
|
||||
rowSelect: "single"
|
||||
buttons: [
|
||||
"new"
|
||||
"edit"
|
||||
"delete"
|
||||
"xls"
|
||||
]
|
||||
onRowDeselect: ->
|
||||
clearDetails()
|
||||
return
|
||||
|
||||
onRowSelect: (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()
|
||||
id = selected[0].id
|
||||
type = gui.authenticators.types[selected[0].type]
|
||||
gui.doLog "Type", type
|
||||
user = new GuiElement(api.authenticators.detail(id, "users"), "users")
|
||||
group = new GuiElement(api.authenticators.detail(id, "groups"), "groups")
|
||||
grpTable = group.table(
|
||||
container: "groups-placeholder"
|
||||
rowSelect: "single"
|
||||
buttons: [
|
||||
"new"
|
||||
"edit"
|
||||
"delete"
|
||||
"xls"
|
||||
]
|
||||
onLoad: (k) ->
|
||||
gui.tools.unblockUI()
|
||||
return
|
||||
|
||||
onEdit: (value, event, table, refreshFnc) ->
|
||||
exec = (groups_all) ->
|
||||
gui.tools.blockUI()
|
||||
api.templates.get "group", (tmpl) -> # Get form template
|
||||
group.rest.item value.id, (item) -> # Get item to edit
|
||||
# Creates modal
|
||||
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 ->
|
||||
fields = gui.forms.read(modalId)
|
||||
gui.doLog "Fields", fields
|
||||
group.rest.save fields, ((data) -> # Success on put
|
||||
$(modalId).modal "hide"
|
||||
refreshFnc()
|
||||
gui.notify gettext("Group saved"), "success"
|
||||
return
|
||||
), gui.failRequestModalFnc("Error saving group", true)
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
if value.type is "meta"
|
||||
|
||||
# Meta will get all groups
|
||||
group.rest.overview (groups) ->
|
||||
exec groups
|
||||
return
|
||||
|
||||
else
|
||||
exec()
|
||||
return
|
||||
|
||||
onNew: (t, table, refreshFnc) ->
|
||||
exec = (groups_all) ->
|
||||
gui.tools.blockUI()
|
||||
api.templates.get "group", (tmpl) -> # Get form template
|
||||
# Creates modal
|
||||
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 ->
|
||||
fields = gui.forms.read(modalId)
|
||||
gui.doLog "Fields", fields
|
||||
group.rest.create fields, ((data) -> # Success on put
|
||||
$(modalId).modal "hide"
|
||||
refreshFnc()
|
||||
gui.notify gettext("Group saved"), "success"
|
||||
return
|
||||
), gui.failRequestModalFnc(gettext("Group saving error"), true)
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
if t is "meta"
|
||||
|
||||
# Meta will get all groups
|
||||
group.rest.overview (groups) ->
|
||||
exec groups
|
||||
return
|
||||
|
||||
else
|
||||
exec()
|
||||
return
|
||||
|
||||
onDelete: gui.methods.del(group, gettext("Delete group"), gettext("Group deletion error"))
|
||||
)
|
||||
tmpLogTable = null
|
||||
|
||||
# New button will only be shown on authenticators that can create new users
|
||||
usrButtons = [
|
||||
"edit"
|
||||
"delete"
|
||||
"xls"
|
||||
]
|
||||
usrButtons = ["new"].concat(usrButtons) if type.canCreateUsers # New is first button
|
||||
usrTable = user.table(
|
||||
container: "users-placeholder"
|
||||
rowSelect: "single"
|
||||
onRowSelect: (uselected) ->
|
||||
gui.tools.blockUI()
|
||||
uId = uselected[0].id
|
||||
clearDetailLog()
|
||||
tmpLogTable = user.logTable(uId,
|
||||
container: "users-log-placeholder"
|
||||
onLoad: ->
|
||||
detailLogTable = tmpLogTable
|
||||
gui.tools.unblockUI()
|
||||
return
|
||||
)
|
||||
return
|
||||
|
||||
onRowDeselect: ->
|
||||
clearDetailLog()
|
||||
return
|
||||
|
||||
buttons: usrButtons
|
||||
deferedRender: true # Use defered rendering for users, this table can be "huge"
|
||||
scrollToTable: false
|
||||
onLoad: (k) ->
|
||||
gui.tools.unblockUI()
|
||||
return
|
||||
|
||||
onRefresh: ->
|
||||
$("#users-log-placeholder").empty() # Remove logs on detail refresh
|
||||
return
|
||||
|
||||
onEdit: (value, event, table, refreshFnc) ->
|
||||
password = "#æð~¬ŋ@æß”¢€~½¬@#~þ¬@|" # Garbage for password (to detect change)
|
||||
gui.tools.blockUI()
|
||||
api.templates.get "user", (tmpl) -> # Get form template
|
||||
group.rest.overview (groups) -> # Get groups
|
||||
user.rest.item value.id, (item) -> # Get item to edit
|
||||
|
||||
# Creates modal
|
||||
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: (if type.needsPassword then password else `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 ->
|
||||
fields = gui.forms.read(modalId)
|
||||
|
||||
# If needs password, and password has changed
|
||||
gui.doLog "passwords", type.needsPassword, password, fields.password
|
||||
delete fields.password if fields.password is password if type.needsPassword
|
||||
gui.doLog "Fields", fields
|
||||
user.rest.save fields, ((data) -> # Success on put
|
||||
$(modalId).modal "hide"
|
||||
refreshFnc()
|
||||
gui.notify gettext("User saved"), "success"
|
||||
return
|
||||
), gui.failRequestModalFnc(gettext("User saving error"), true)
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
onNew: (undefined_, table, refreshFnc) ->
|
||||
gui.tools.blockUI()
|
||||
api.templates.get "user", (tmpl) -> # Get form template
|
||||
group.rest.overview (groups) -> # Get groups
|
||||
# Creates modal
|
||||
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 ->
|
||||
fields = gui.forms.read(modalId)
|
||||
|
||||
# If needs password, and password has changed
|
||||
gui.doLog "Fields", fields
|
||||
user.rest.create fields, ((data) -> # Success on put
|
||||
$(modalId).modal "hide"
|
||||
refreshFnc()
|
||||
gui.notify gettext("User saved"), "success"
|
||||
return
|
||||
), gui.failRequestModalFnc(gettext("User saving error"), true)
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
onDelete: gui.methods.del(user, gettext("Delete user"), gettext("User deletion error"))
|
||||
)
|
||||
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
|
||||
false
|
||||
|
||||
onRefresh: ->
|
||||
$("#users-placeholder").empty() # Remove detail on parent refresh
|
||||
return
|
||||
|
||||
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
|
48
server/src/uds/static/adm/js/gui-d-config.coffee
Normal file
48
server/src/uds/static/adm/js/gui-d-config.coffee
Normal file
@ -0,0 +1,48 @@
|
||||
gui.configuration = new BasicGuiElement("Clear cache")
|
||||
gui.configuration.link = ->
|
||||
"use strict"
|
||||
api.templates.get "configuration", (tmpl) ->
|
||||
api.configuration.overview ((data) ->
|
||||
gui.doLog data
|
||||
gui.clearWorkspace()
|
||||
gui.appendToWorkspace api.templates.evaluate(tmpl,
|
||||
config: data
|
||||
)
|
||||
gui.setLinksEvents()
|
||||
$("#form_config .form-control").each (i, element) ->
|
||||
$(element).attr "data-val", $(element).val()
|
||||
return
|
||||
|
||||
|
||||
# Add handlers to buttons
|
||||
$("#form_config .button-undo").on "click", (event) ->
|
||||
fld = $(this).attr("data-fld")
|
||||
gui.doLog fld, $("#" + fld).val()
|
||||
$("#" + fld).val $("#" + fld).attr("data-val")
|
||||
return
|
||||
|
||||
$("#form_config .button-save").on "click", (event) ->
|
||||
cfg = {}
|
||||
$("#form_config .form-control").each (i, element) ->
|
||||
$element = $(element)
|
||||
unless $element.attr("data-val") is $element.val()
|
||||
section = $element.attr("data-section")
|
||||
key = $element.attr("data-key")
|
||||
cfg[section] = {} if cfg[section] is `undefined`
|
||||
cfg[section][key] = value: $element.val()
|
||||
return
|
||||
|
||||
gui.doLog cfg
|
||||
unless $.isEmptyObject(cfg)
|
||||
api.configuration.save cfg, (->
|
||||
gui.showDashboard()
|
||||
gui.notify gettext("Configuration saved"), "success"
|
||||
return
|
||||
), gui.failRequestModalFnc
|
||||
return
|
||||
|
||||
return
|
||||
), gui.failRequestModalFnc
|
||||
return
|
||||
|
||||
return
|
42
server/src/uds/static/adm/js/gui-d-connectivity.coffee
Normal file
42
server/src/uds/static/adm/js/gui-d-connectivity.coffee
Normal file
@ -0,0 +1,42 @@
|
||||
# jshint strict: true
|
||||
gui.connectivity =
|
||||
transports: new GuiElement(api.transports, "trans")
|
||||
networks: new GuiElement(api.networks, "nets")
|
||||
|
||||
gui.connectivity.link = (event) ->
|
||||
"use strict"
|
||||
api.templates.get "connectivity", (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"))
|
||||
|
||||
return
|
||||
|
||||
return
|
42
server/src/uds/static/adm/js/gui-d-dashboard.coffee
Normal file
42
server/src/uds/static/adm/js/gui-d-dashboard.coffee
Normal file
@ -0,0 +1,42 @@
|
||||
gui.dashboard = new BasicGuiElement("Dashboard")
|
||||
gui.dashboard.link = (event) ->
|
||||
"use strict"
|
||||
gui.clearWorkspace()
|
||||
api.templates.get "dashboard", (tmpl) ->
|
||||
api.system.overview (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"
|
||||
], (index, stat) ->
|
||||
api.system.stats stat, (data) ->
|
||||
d = []
|
||||
$.each data, (index, value) ->
|
||||
d.push [
|
||||
value.stamp * 1000
|
||||
value.value
|
||||
]
|
||||
return
|
||||
|
||||
gui.doLog "Data", d
|
||||
$.plot "#placeholder-" + stat + "-chart", [d],
|
||||
xaxis:
|
||||
mode: "time"
|
||||
timeformat: api.tools.djangoFormat(django.formats.SHORT_DATE_FORMAT)
|
||||
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
return
|
27
server/src/uds/static/adm/js/gui-d-osmanagers.coffee
Normal file
27
server/src/uds/static/adm/js/gui-d-osmanagers.coffee
Normal file
@ -0,0 +1,27 @@
|
||||
#------------------------
|
||||
# Os managers
|
||||
#------------------------
|
||||
gui.osmanagers = new GuiElement(api.osmanagers, "osm")
|
||||
gui.osmanagers.link = (event) ->
|
||||
"use strict"
|
||||
api.templates.get "osmanagers", (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"))
|
||||
|
||||
return
|
||||
|
||||
return
|
142
server/src/uds/static/adm/js/gui-d-services.coffee
Normal file
142
server/src/uds/static/adm/js/gui-d-services.coffee
Normal file
@ -0,0 +1,142 @@
|
||||
# jshint strict: true
|
||||
gui.providers = new GuiElement(api.providers, "provi")
|
||||
gui.providers.link = (event) ->
|
||||
"use strict"
|
||||
|
||||
# Button definition to trigger "Test" action
|
||||
testButton = testButton:
|
||||
text: gettext("Test")
|
||||
css: "btn-info"
|
||||
|
||||
detailLogTable = null
|
||||
clearDetailLog = ->
|
||||
if detailLogTable
|
||||
$tbl = $(detailLogTable).dataTable()
|
||||
$tbl.fnClearTable()
|
||||
$tbl.fnDestroy()
|
||||
$("#services-log-placeholder").empty()
|
||||
detailLogTable = `undefined`
|
||||
return
|
||||
|
||||
prevTables = []
|
||||
clearDetails = ->
|
||||
gui.doLog "Clearing details"
|
||||
$.each prevTables, (undefined_, tbl) ->
|
||||
$tbl = $(tbl).dataTable()
|
||||
$tbl.fnClearTable()
|
||||
$tbl.fnDestroy()
|
||||
return
|
||||
|
||||
clearDetailLog()
|
||||
prevTables = []
|
||||
$("#services-placeholder").empty()
|
||||
$("#logs-placeholder").empty()
|
||||
$("#detail-placeholder").addClass "hidden"
|
||||
return
|
||||
|
||||
api.templates.get "providers", (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", (event) ->
|
||||
gui.doLog event.target
|
||||
setTimeout (->
|
||||
$($(event.target).attr("href") + " span.fa-refresh").click()
|
||||
return
|
||||
), 10
|
||||
return
|
||||
|
||||
tableId = gui.providers.table(
|
||||
container: "providers-placeholder"
|
||||
rowSelect: "single"
|
||||
onCheck: (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;
|
||||
# }
|
||||
true
|
||||
|
||||
onRowDeselect: ->
|
||||
clearDetails()
|
||||
return
|
||||
|
||||
onRowSelect: (selected) ->
|
||||
gui.tools.blockUI()
|
||||
clearDetails()
|
||||
$("#detail-placeholder").removeClass "hidden"
|
||||
id = selected[0].id
|
||||
|
||||
# Giving the name compossed with type, will ensure that only styles will be reattached once
|
||||
services = new GuiElement(api.providers.detail(id, "services"), "services-" + selected[0].type)
|
||||
tmpLogTable = null
|
||||
servicesTable = services.table(
|
||||
container: "services-placeholder"
|
||||
rowSelect: "single"
|
||||
onRowSelect: (sselected) ->
|
||||
gui.tools.blockUI()
|
||||
sId = sselected[0].id
|
||||
clearDetailLog()
|
||||
tmpLogTable = services.logTable(sId,
|
||||
container: "services-log-placeholder"
|
||||
onLoad: ->
|
||||
detailLogTable = tmpLogTable
|
||||
gui.tools.unblockUI()
|
||||
return
|
||||
)
|
||||
return
|
||||
|
||||
onRowDeselect: ->
|
||||
clearDetailLog()
|
||||
return
|
||||
|
||||
onCheck: (check, items) ->
|
||||
if check is "delete"
|
||||
for i of items
|
||||
return false if items[i].deployed_services_count > 0
|
||||
return true
|
||||
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: (k) ->
|
||||
gui.tools.unblockUI()
|
||||
return
|
||||
)
|
||||
logTable = gui.providers.logTable(id,
|
||||
container: "logs-placeholder"
|
||||
)
|
||||
prevTables.push servicesTable
|
||||
prevTables.push logTable
|
||||
return
|
||||
|
||||
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
|
488
server/src/uds/static/adm/js/gui-d-servicespools.coffee
Normal file
488
server/src/uds/static/adm/js/gui-d-servicespools.coffee
Normal file
@ -0,0 +1,488 @@
|
||||
# jshint strict: true
|
||||
gui.servicesPools = new GuiElement(api.servicesPools, "servicespools")
|
||||
gui.servicesPools.link = (event) ->
|
||||
"use strict"
|
||||
gui.clearWorkspace()
|
||||
|
||||
# Clears the details
|
||||
# Memory saver :-)
|
||||
prevTables = []
|
||||
clearDetails = ->
|
||||
$.each prevTables, (undefined_, tbl) ->
|
||||
$tbl = $(tbl).dataTable()
|
||||
$tbl.fnClearTable()
|
||||
$tbl.fnDestroy()
|
||||
return
|
||||
|
||||
$("#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 = []
|
||||
return
|
||||
|
||||
|
||||
# On change base service
|
||||
preFnc = (formId) ->
|
||||
$fld = $(formId + " [name=\"service_id\"]")
|
||||
$osmFld = $(formId + " [name=\"osmanager_id\"]")
|
||||
selectors = []
|
||||
$.each [
|
||||
"initial_srvs"
|
||||
"cache_l1_srvs"
|
||||
"cache_l2_srvs"
|
||||
"max_srvs"
|
||||
], (index, value) ->
|
||||
selectors.push formId + " [name=\"" + value + "\"]"
|
||||
return
|
||||
|
||||
$cacheFlds = $(selectors.join(","))
|
||||
$cacheL2Fld = $(formId + " [name=\"cache_l2_srvs\"]")
|
||||
$publishOnSaveFld = $(formId + " [name=\"publish_on_save\"]")
|
||||
$fld.on "change", (event) ->
|
||||
unless $fld.val() is -1
|
||||
api.providers.service $fld.val(), (data) ->
|
||||
gui.doLog "Onchange", data
|
||||
if data.info.needs_manager is false
|
||||
$osmFld.prop "disabled", "disabled"
|
||||
else
|
||||
$osmFld.prop "disabled", false
|
||||
if data.info.uses_cache is false
|
||||
$cacheFlds.prop "disabled", "disabled"
|
||||
else
|
||||
$cacheFlds.prop "disabled", false
|
||||
if data.info.uses_cache_l2 is false
|
||||
$cacheL2Fld.prop "disabled", "disabled"
|
||||
else
|
||||
$cacheL2Fld.prop "disabled", false
|
||||
if data.info.needs_publication is false
|
||||
$publishOnSaveFld.bootstrapSwitch "setDisabled", true
|
||||
else
|
||||
$publishOnSaveFld.bootstrapSwitch "setDisabled", false
|
||||
$osmFld.selectpicker "refresh" if $osmFld.hasClass("selectpicker")
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
|
||||
# Fill "State" for cached and assigned services
|
||||
fillState = (data) ->
|
||||
$.each data, (index, value) ->
|
||||
if value.state is "U"
|
||||
if value.os_state isnt "" and value.os_state isnt "U"
|
||||
value.state = gettext("Waiting OS")
|
||||
else
|
||||
value.state = gettext("Ready")
|
||||
return
|
||||
if value.state is "R"
|
||||
value.state = gettext("Waiting for removal")
|
||||
return
|
||||
if value.state is "M"
|
||||
value.state = gettext("Removing")
|
||||
return
|
||||
if value.state is "S"
|
||||
value.state = gettext("Removed")
|
||||
return
|
||||
if value.state is "E"
|
||||
value.state = gettext("Error")
|
||||
return
|
||||
if value.state is "P"
|
||||
value.state = gettext("Generating")
|
||||
return
|
||||
value.state = gettext("Unknown")
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
|
||||
# Fills up the list of available services
|
||||
api.providers.allServices (services) ->
|
||||
availableServices = {}
|
||||
$.each services, (undefined_, service) ->
|
||||
availableServices[service.id] = service
|
||||
return
|
||||
|
||||
gui.doLog "Available services", availableServices
|
||||
api.templates.get "services_pool", (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", (event) ->
|
||||
gui.doLog event.target
|
||||
setTimeout (->
|
||||
$($(event.target).attr("href") + " span.fa-refresh").click()
|
||||
return
|
||||
), 10
|
||||
return
|
||||
|
||||
|
||||
#
|
||||
# * Services pools part
|
||||
#
|
||||
servicesPoolsTable = gui.servicesPools.table(
|
||||
container: "deployed-services-placeholder"
|
||||
rowSelect: "single"
|
||||
buttons: [
|
||||
"new"
|
||||
"edit"
|
||||
"delete"
|
||||
"xls"
|
||||
]
|
||||
onRowDeselect: ->
|
||||
clearDetails()
|
||||
return
|
||||
|
||||
onRowSelect: (selected) ->
|
||||
servPool = selected[0]
|
||||
gui.doLog "Selected services pool", servPool
|
||||
clearDetails()
|
||||
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 isnt null
|
||||
$("#detail-placeholder").removeClass "hidden"
|
||||
else
|
||||
$("#detail-placeholder").addClass "hidden"
|
||||
return
|
||||
|
||||
#
|
||||
# * Cache Part
|
||||
#
|
||||
cachedItems = null
|
||||
|
||||
# If service does not supports cache, do not show it
|
||||
# Shows/hides cache
|
||||
if service.info.uses_cache or service.info.uses_cache_l2
|
||||
$("#cache-placeholder_tab").removeClass "hidden"
|
||||
cachedItems = new GuiElement(api.servicesPools.detail(servPool.id, "cache"), "cache")
|
||||
|
||||
# Cached items table
|
||||
prevCacheLogTbl = null
|
||||
cachedItemsTable = cachedItems.table(
|
||||
container: "cache-placeholder_tbl"
|
||||
buttons: [
|
||||
"delete"
|
||||
"xls"
|
||||
]
|
||||
rowSelect: "single"
|
||||
onData: (data) ->
|
||||
fillState data
|
||||
return
|
||||
|
||||
onRowSelect: (selected) ->
|
||||
cached = selected[0]
|
||||
if prevCacheLogTbl
|
||||
$tbl = $(prevCacheLogTbl).dataTable()
|
||||
$tbl.fnClearTable()
|
||||
$tbl.fnDestroy()
|
||||
prevCacheLogTbl = cachedItems.logTable(cached.id,
|
||||
container: "cache-placeholder_log"
|
||||
)
|
||||
return
|
||||
|
||||
onDelete: gui.methods.del(cachedItems, gettext("Remove Cache element"), gettext("Deletion error"))
|
||||
)
|
||||
prevTables.push cachedItemsTable
|
||||
else
|
||||
$("#cache-placeholder_tab").addClass "hidden"
|
||||
|
||||
#
|
||||
# * Groups part
|
||||
#
|
||||
groups = null
|
||||
|
||||
# Shows/hides groups
|
||||
if service.info.must_assign_manually is false
|
||||
$("#groups-placeholder_tab").removeClass "hidden"
|
||||
groups = new GuiElement(api.servicesPools.detail(servPool.id, "groups"), "groups")
|
||||
|
||||
# Groups items table
|
||||
groupsTable = groups.table(
|
||||
container: "groups-placeholder"
|
||||
rowSelect: "single"
|
||||
buttons: [
|
||||
"new"
|
||||
"delete"
|
||||
"xls"
|
||||
]
|
||||
onNew: (value, table, refreshFnc) ->
|
||||
api.templates.get "pool_add_group", (tmpl) ->
|
||||
api.authenticators.overview (data) ->
|
||||
modalId = gui.launchModal(gettext("Add group"), api.templates.evaluate(tmpl,
|
||||
auths: data
|
||||
))
|
||||
$(modalId + " #id_auth_select").on "change", (event) ->
|
||||
auth = $(modalId + " #id_auth_select").val()
|
||||
api.authenticators.detail(auth, "groups").overview (data) ->
|
||||
$select = $(modalId + " #id_group_select")
|
||||
$select.empty()
|
||||
$.each data, (undefined_, value) ->
|
||||
$select.append "<option value=\"" + value.id + "\">" + value.name + "</option>"
|
||||
return
|
||||
|
||||
|
||||
# Refresh selectpicker if item is such
|
||||
$select.selectpicker "refresh" if $select.hasClass("selectpicker")
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
$(modalId + " .button-accept").on "click", (event) ->
|
||||
auth = $(modalId + " #id_auth_select").val()
|
||||
group = $(modalId + " #id_group_select").val()
|
||||
if auth is -1 or group is -1
|
||||
gui.notify gettext("You must provide authenticator and group"), "danger"
|
||||
else # Save & close modal
|
||||
groups.rest.create
|
||||
id: group
|
||||
, (data) ->
|
||||
$(modalId).modal "hide"
|
||||
refreshFnc()
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
|
||||
# Makes form "beautyfull" :-)
|
||||
gui.tools.applyCustoms modalId
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
onDelete: gui.methods.del(groups, gettext("Remove group"), gettext("Group removal error"))
|
||||
onData: (data) ->
|
||||
$.each data, (undefined_, value) ->
|
||||
value.group_name = "<b>" + value.auth_name + "</b>\\" + value.name
|
||||
return
|
||||
|
||||
return
|
||||
)
|
||||
prevTables.push groupsTable
|
||||
else
|
||||
$("#groups-placeholder_tab").addClass "hidden"
|
||||
|
||||
#
|
||||
# * Assigned services part
|
||||
#
|
||||
prevAssignedLogTbl = null
|
||||
assignedServices = new GuiElement(api.servicesPools.detail(servPool.id, "services"), "services")
|
||||
assignedServicesTable = assignedServices.table(
|
||||
container: "assigned-services-placeholder_tbl"
|
||||
rowSelect: "single"
|
||||
buttons: (if service.info.must_assign_manually then [
|
||||
"new"
|
||||
"delete"
|
||||
"xls"
|
||||
] else [
|
||||
"delete"
|
||||
"xls"
|
||||
])
|
||||
onRowSelect: (selected) ->
|
||||
service = selected[0]
|
||||
if prevAssignedLogTbl
|
||||
$tbl = $(prevAssignedLogTbl).dataTable()
|
||||
$tbl.fnClearTable()
|
||||
$tbl.fnDestroy()
|
||||
prevAssignedLogTbl = assignedServices.logTable(service.id,
|
||||
container: "assigned-services-placeholder_log"
|
||||
)
|
||||
return
|
||||
|
||||
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
|
||||
#
|
||||
transports = new GuiElement(api.servicesPools.detail(servPool.id, "transports"), "transports")
|
||||
|
||||
# Transports items table
|
||||
transportsTable = transports.table(
|
||||
container: "transports-placeholder"
|
||||
rowSelect: "single"
|
||||
buttons: [
|
||||
"new"
|
||||
"delete"
|
||||
"xls"
|
||||
]
|
||||
onNew: (value, table, refreshFnc) ->
|
||||
api.templates.get "pool_add_transport", (tmpl) ->
|
||||
api.transports.overview (data) ->
|
||||
modalId = gui.launchModal(gettext("Add transport"), api.templates.evaluate(tmpl,
|
||||
transports: data
|
||||
))
|
||||
$(modalId + " .button-accept").on "click", (event) ->
|
||||
transport = $(modalId + " #id_transport_select").val()
|
||||
if transport is -1
|
||||
gui.notify gettext("You must provide a transport"), "danger"
|
||||
else # Save & close modal
|
||||
transports.rest.create
|
||||
id: transport
|
||||
, (data) ->
|
||||
$(modalId).modal "hide"
|
||||
refreshFnc()
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
|
||||
# Makes form "beautyfull" :-)
|
||||
gui.tools.applyCustoms modalId
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
onDelete: gui.methods.del(transports, gettext("Remove transport"), gettext("Transport removal error"))
|
||||
onData: (data) ->
|
||||
$.each data, (undefined_, value) ->
|
||||
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
|
||||
return
|
||||
|
||||
return
|
||||
)
|
||||
prevTables.push transportsTable
|
||||
|
||||
#
|
||||
# * Publications part
|
||||
#
|
||||
publications = null
|
||||
if service.info.needs_publication
|
||||
$("#publications-placeholder_tab").removeClass "hidden"
|
||||
pubApi = api.servicesPools.detail(servPool.id, "publications")
|
||||
publications = new GuiElement(pubApi, "publications")
|
||||
|
||||
# Publications table
|
||||
publicationsTable = publications.table(
|
||||
container: "publications-placeholder"
|
||||
rowSelect: "single"
|
||||
buttons: [
|
||||
"new"
|
||||
{
|
||||
text: gettext("Cancel")
|
||||
css: "disabled"
|
||||
click: (val, value, btn, tbl, refreshFnc) ->
|
||||
gui.promptModal gettext("Publish"), gettext("Cancel publication"),
|
||||
onYes: ->
|
||||
pubApi.invoke val.id + "/cancel", ->
|
||||
refreshFnc()
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
select: (val, value, btn, tbl, refreshFnc) ->
|
||||
unless val
|
||||
$(btn).removeClass("btn3d-info").addClass "disabled"
|
||||
return
|
||||
# Waiting for publication, Preparing or running
|
||||
$(btn).removeClass("disabled").addClass "btn3d-info" if [
|
||||
"P"
|
||||
"W"
|
||||
"L"
|
||||
].indexOf(val.state) > 0
|
||||
return
|
||||
}
|
||||
"xls"
|
||||
]
|
||||
onNew: (action, tbl, refreshFnc) ->
|
||||
gui.promptModal gettext("Publish"), gettext("Launch new publication?"),
|
||||
onYes: ->
|
||||
pubApi.invoke "publish", (->
|
||||
refreshFnc()
|
||||
return
|
||||
), gui.failRequestModalFnc(gettext("Failed creating publication"))
|
||||
return
|
||||
|
||||
return
|
||||
)
|
||||
prevTables.push publicationsTable
|
||||
else
|
||||
$("#publications-placeholder_tab").addClass "hidden"
|
||||
|
||||
#
|
||||
# * Log table
|
||||
#
|
||||
logTable = gui.servicesPools.logTable(servPool.id,
|
||||
container: "logs-placeholder"
|
||||
)
|
||||
prevTables.push logTable
|
||||
return
|
||||
|
||||
|
||||
# Pre-process data received to add "icon" to deployed service
|
||||
onData: (data) ->
|
||||
gui.doLog "onData", data
|
||||
$.each data, (index, value) ->
|
||||
try
|
||||
service = availableServices[value.service_id]
|
||||
if service is `undefined`
|
||||
value.parent = gettext("undefined")
|
||||
return
|
||||
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)")
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
onNew: gui.methods.typedNew(gui.servicesPools, gettext("New service pool"), "Service pool " + gettext("creation error"),
|
||||
guiProcessor: (guiDef) -> # Create has "save on publish" field
|
||||
gui.doLog guiDef
|
||||
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
|
||||
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"))
|
||||
)
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
return
|
16
server/src/uds/static/adm/js/gui-definition.coffee
Normal file
16
server/src/uds/static/adm/js/gui-definition.coffee
Normal file
@ -0,0 +1,16 @@
|
||||
# jshint strict: true
|
||||
|
||||
# Basic GUI components
|
||||
|
||||
# Tools
|
||||
gui.clear_cache = new BasicGuiElement("Flush cache")
|
||||
gui.clear_cache.link = ->
|
||||
"use strict"
|
||||
api.getJson "cache/flush",
|
||||
success: ->
|
||||
gui.launchModal gettext("Cache"), gettext("Cache has been flushed"),
|
||||
actionButton: " "
|
||||
|
||||
return
|
||||
|
||||
return
|
599
server/src/uds/static/adm/js/gui-element.coffee
Normal file
599
server/src/uds/static/adm/js/gui-element.coffee
Normal file
@ -0,0 +1,599 @@
|
||||
# jshint strict: true
|
||||
|
||||
# Operations commmon to most elements
|
||||
@BasicGuiElement = (name) ->
|
||||
"use strict"
|
||||
@name = name
|
||||
return
|
||||
@GuiElement = (restItem, name, typesFunction) ->
|
||||
"use strict"
|
||||
@rest = restItem
|
||||
@name = name
|
||||
@types = {}
|
||||
@init()
|
||||
return
|
||||
|
||||
# all gui elements has, at least, name && type
|
||||
# Types must include, at least: type, icon
|
||||
@GuiElement:: =
|
||||
init: ->
|
||||
"use strict"
|
||||
gui.doLog "Initializing " + @name
|
||||
self = this
|
||||
@rest.types (data) ->
|
||||
styles = ""
|
||||
alreadyAttached = $("#gui-style-" + self.name).length isnt 0
|
||||
$.each data, (index, value) ->
|
||||
className = self.name + "-" + value.type
|
||||
self.types[value.type] = value
|
||||
self.types[value.type].css = className
|
||||
gui.doLog "Creating style for " + className
|
||||
unless alreadyAttached
|
||||
style = "." + className + " { display:inline-block; background: url(data:image/png;base64," + value.icon + "); " + "width: 16px; height: 16px; vertical-align: middle; } "
|
||||
styles += style
|
||||
return
|
||||
|
||||
if styles isnt ""
|
||||
|
||||
# If style already attached, do not re-attach it
|
||||
styles = "<style id=\"gui-style-" + self.name + "\" media=\"screen\">" + styles + "</style>"
|
||||
$(styles).appendTo "head"
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
|
||||
# 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: (tblParams) ->
|
||||
"use strict"
|
||||
tblParams = tblParams or {}
|
||||
gui.doLog "Composing table for " + @name
|
||||
tableId = @name + "-table"
|
||||
self = this # Store this for child functions
|
||||
|
||||
# ---------------
|
||||
# Cells renderers
|
||||
# ---------------
|
||||
|
||||
# Empty cells transform
|
||||
renderEmptyCell = (data) ->
|
||||
return "-" if data is ""
|
||||
data
|
||||
|
||||
|
||||
# Icon renderer, based on type (created on init methods in styles)
|
||||
renderTypeIcon = (data, type, value) ->
|
||||
if type is "display"
|
||||
self.types[value.type] = self.types[value.type] or {}
|
||||
css = self.types[value.type].css or "fa fa-asterisk"
|
||||
"<span class=\"" + css + "\"></span> " + renderEmptyCell(data)
|
||||
else
|
||||
renderEmptyCell data
|
||||
|
||||
|
||||
# Custom icon renderer, in fact span with defined class
|
||||
renderIcon = (icon) ->
|
||||
(data, type, full) ->
|
||||
if type is "display"
|
||||
"<span class=\"" + icon + "\"></span> " + renderEmptyCell(data)
|
||||
else
|
||||
renderEmptyCell data
|
||||
|
||||
|
||||
# Custom icon based on type
|
||||
renderIconDict = (iconDict) ->
|
||||
(data, type, value) ->
|
||||
if type is "display"
|
||||
"<span class=\"" + iconDict[value.type] + "\"></span> " + renderEmptyCell(data)
|
||||
else
|
||||
renderEmptyCell data
|
||||
|
||||
|
||||
# Text transformation, dictionary based
|
||||
renderTextTransform = (dict) ->
|
||||
(data, type, full) ->
|
||||
dict[data] or renderEmptyCell(data)
|
||||
|
||||
@rest.tableInfo (data) -> # Gets tableinfo data (columns, title, visibility of fields, etc...
|
||||
row_style = data["row-style"]
|
||||
gui.doLog row_style
|
||||
title = data.title
|
||||
columns = []
|
||||
$.each data.fields, (index, value) ->
|
||||
for v of value
|
||||
opts = value[v]
|
||||
column = mData: v
|
||||
column.sTitle = opts.title
|
||||
column.mRender = renderEmptyCell
|
||||
column.sWidth = opts.width if opts.width
|
||||
column.bVisible = (if opts.visible is `undefined` then true else opts.visible)
|
||||
column.bSortable = opts.sortable if opts.sortable isnt `undefined`
|
||||
column.bSearchable = opts.searchable if opts.searchable isnt `undefined`
|
||||
if opts.type and column.bVisible
|
||||
switch opts.type
|
||||
when "date"
|
||||
column.sType = "uds-date"
|
||||
column.mRender = gui.tools.renderDate(api.tools.djangoFormat(get_format("SHORT_DATE_FORMAT")))
|
||||
when "datetime"
|
||||
column.sType = "uds-date"
|
||||
column.mRender = gui.tools.renderDate(api.tools.djangoFormat(get_format("SHORT_DATETIME_FORMAT")))
|
||||
when "time"
|
||||
column.sType = "uds-date"
|
||||
column.mRender = gui.tools.renderDate(api.tools.djangoFormat(get_format("TIME_FORMAT")))
|
||||
when "iconType"
|
||||
|
||||
#columnt.sType = 'html'; // html is default, so this is not needed
|
||||
column.mRender = renderTypeIcon
|
||||
when "icon"
|
||||
column.mRender = renderIcon(opts.icon) if opts.icon isnt `undefined`
|
||||
when "icon_dict"
|
||||
column.mRender = renderIconDict(opts.icon_dict) if opts.icon_dict isnt `undefined`
|
||||
when "dict"
|
||||
column.mRender = renderTextTransform(opts.dict) if opts.dict isnt `undefined`
|
||||
else
|
||||
column.sType = opts.type
|
||||
columns.push column
|
||||
return
|
||||
|
||||
|
||||
# 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 (data) -> # Gets "overview" data for table (table contents, but resume form)
|
||||
tblParams.onData data if tblParams.onData
|
||||
table = gui.table(title, tableId)
|
||||
if tblParams.container is `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
|
||||
onRefresh = tblParams.onRefresh or ->
|
||||
|
||||
refreshFnc = ->
|
||||
|
||||
# Refreshes table content
|
||||
tbl = $("#" + tableId).dataTable()
|
||||
|
||||
# Clears selection first
|
||||
TableTools.fnGetInstance(tableId).fnSelectNone()
|
||||
|
||||
#if( data.length > 1000 )
|
||||
gui.tools.blockUI()
|
||||
self.rest.overview (data) -> # Restore overview
|
||||
tblParams.onData data if tblParams.onData
|
||||
setTimeout (->
|
||||
tbl.fnClearTable()
|
||||
tbl.fnAddData data
|
||||
onRefresh self
|
||||
gui.tools.unblockUI()
|
||||
return
|
||||
), 0
|
||||
return
|
||||
|
||||
# End restore overview
|
||||
false # This may be used on button or href, better disable execution of it
|
||||
|
||||
btns = []
|
||||
if tblParams.buttons
|
||||
|
||||
# Generic click handler generator for this table
|
||||
clickHandlerFor = (handler, action, newHandler) ->
|
||||
handleFnc = handler or (val, action, tbl) ->
|
||||
gui.doLog "Default handler called for ", action
|
||||
return
|
||||
|
||||
(btn) ->
|
||||
tbl = $("#" + tableId).dataTable()
|
||||
val = @fnGetSelectedData()[0]
|
||||
setTimeout (->
|
||||
if newHandler
|
||||
handleFnc action, tbl, refreshFnc
|
||||
else
|
||||
handleFnc val, action, tbl, refreshFnc
|
||||
return
|
||||
), 0
|
||||
return
|
||||
|
||||
onCheck = tblParams.onCheck or -> # Default oncheck always returns true
|
||||
true
|
||||
|
||||
|
||||
# methods for buttons on row select
|
||||
editSelected = (btn, obj, node) ->
|
||||
sel = @fnGetSelectedData()
|
||||
enable = (if sel.length is 1 then onCheck("edit", sel) else false)
|
||||
if enable
|
||||
$(btn).removeClass("disabled").addClass "btn3d-success"
|
||||
else
|
||||
$(btn).removeClass("btn3d-success").addClass "disabled"
|
||||
return
|
||||
|
||||
deleteSelected = (btn, obj, node) ->
|
||||
sel = @fnGetSelectedData()
|
||||
enable = (if sel.length is 1 then onCheck("delete", sel) else false)
|
||||
if enable
|
||||
$(btn).removeClass("disabled").addClass "btn3d-warning"
|
||||
else
|
||||
$(btn).removeClass("btn3d-warning").addClass "disabled"
|
||||
return
|
||||
|
||||
$.each tblParams.buttons, (index, value) -> # Iterate through button definition
|
||||
btn = null
|
||||
switch value
|
||||
when "new"
|
||||
if Object.keys(self.types).length isnt 0
|
||||
menuId = gui.genRamdonId("dd-")
|
||||
ordered = []
|
||||
$.each self.types, (k, v) ->
|
||||
ordered.push
|
||||
type: k
|
||||
css: v.css
|
||||
name: v.name
|
||||
description: v.description
|
||||
|
||||
return
|
||||
|
||||
ordered = ordered.sort((a, b) ->
|
||||
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)
|
||||
when "edit"
|
||||
btn =
|
||||
sExtends: "text"
|
||||
sButtonText: gui.config.dataTableButtons.edit.text
|
||||
fnSelect: editSelected
|
||||
fnClick: clickHandlerFor(tblParams.onEdit, "edit")
|
||||
sButtonClass: gui.config.dataTableButtons.edit.css
|
||||
when "delete"
|
||||
btn =
|
||||
sExtends: "text"
|
||||
sButtonText: gui.config.dataTableButtons["delete"].text
|
||||
fnSelect: deleteSelected
|
||||
fnClick: clickHandlerFor(tblParams.onDelete, "delete")
|
||||
sButtonClass: gui.config.dataTableButtons["delete"].css
|
||||
when "refresh"
|
||||
btn =
|
||||
sExtends: "text"
|
||||
sButtonText: gui.config.dataTableButtons.refresh.text
|
||||
fnClick: refreshFnc
|
||||
sButtonClass: gui.config.dataTableButtons.refresh.css
|
||||
when "xls"
|
||||
btn =
|
||||
sExtends: "text"
|
||||
sButtonText: gui.config.dataTableButtons.xls.text
|
||||
fnClick: -> # Export to excel
|
||||
api.templates.get "spreadsheet", (tmpl) ->
|
||||
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
|
||||
|
||||
# End export to excell
|
||||
sButtonClass: gui.config.dataTableButtons.xls.css
|
||||
else # Custom button, this has to be
|
||||
try
|
||||
css = ((if value.css then value.css + " " else "")) + gui.config.dataTableButtons.custom.css
|
||||
btn =
|
||||
sExtends: "text"
|
||||
sButtonText: value.text
|
||||
sButtonClass: css
|
||||
|
||||
if value.click
|
||||
btn.fnClick = (btn) ->
|
||||
tbl = $("#" + tableId).dataTable()
|
||||
val = @fnGetSelectedData()[0]
|
||||
setTimeout (->
|
||||
value.click val, value, btn, tbl, refreshFnc
|
||||
return
|
||||
), 0
|
||||
return
|
||||
if value.select
|
||||
btn.fnSelect = (btn) ->
|
||||
tbl = $("#" + tableId).dataTable()
|
||||
val = @fnGetSelectedData()[0]
|
||||
setTimeout (->
|
||||
value.select val, value, btn, tbl, refreshFnc
|
||||
return
|
||||
), 0
|
||||
return
|
||||
catch e
|
||||
gui.doLog "Button", value, e
|
||||
btns.push btn if btn
|
||||
return
|
||||
|
||||
# End buttoon iteration
|
||||
|
||||
# Initializes oTableTools
|
||||
oTableTools =
|
||||
aButtons: btns
|
||||
sRowSelect: tblParams.rowSelect or "none"
|
||||
|
||||
if tblParams.onRowSelect
|
||||
rowSelectedFnc = tblParams.onRowSelect
|
||||
oTableTools.fnRowSelected = ->
|
||||
rowSelectedFnc @fnGetSelectedData(), $("#" + tableId).dataTable(), self
|
||||
return
|
||||
if tblParams.onRowDeselect
|
||||
rowDeselectedFnc = tblParams.onRowDeselect
|
||||
oTableTools.fnRowDeselected = ->
|
||||
rowDeselectedFnc @fnGetSelectedData(), $("#" + tableId).dataTable(), self
|
||||
return
|
||||
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 or false
|
||||
|
||||
|
||||
# If row is "styled"
|
||||
if row_style.field
|
||||
field = row_style.field
|
||||
dct = row_style.dict
|
||||
prefix = row_style.prefix
|
||||
dataTableOptions.fnCreatedRow = (nRow, aData, iDataIndex) ->
|
||||
v = (if dct isnt `undefined` then dct[@fnGetData(iDataIndex)[field]] else @fnGetData(iDataIndex)[field])
|
||||
$(nRow).addClass prefix + v
|
||||
gui.doLog prefix + v
|
||||
return
|
||||
$("#" + 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", (event) ->
|
||||
event.preventDefault()
|
||||
tbl = $("#" + tableId).dataTable()
|
||||
|
||||
# Executes "onNew" outside click event
|
||||
type = $(this).attr("data-type")
|
||||
setTimeout (->
|
||||
tblParams.onNew type, tbl, refreshFnc
|
||||
return
|
||||
), 0
|
||||
return
|
||||
|
||||
if tblParams.scrollToTable is true
|
||||
tableTop = $("#" + tableId).offset().top
|
||||
$("html, body").scrollTop tableTop
|
||||
|
||||
# if table rendered event
|
||||
tblParams.onLoad self if tblParams.onLoad
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
# End Overview data
|
||||
# End Tableinfo data
|
||||
"#" + tableId
|
||||
|
||||
logTable: (itemId, tblParams) ->
|
||||
"use strict"
|
||||
tblParams = tblParams or {}
|
||||
gui.doLog "Composing log for " + @name
|
||||
tableId = @name + "-table-log"
|
||||
self = this # Store this for child functions
|
||||
|
||||
# Renderers for columns
|
||||
refreshFnc = ->
|
||||
|
||||
# Refreshes table content
|
||||
tbl = $("#" + tableId).dataTable()
|
||||
gui.tools.blockUI()
|
||||
self.rest.getLogs itemId, (data) ->
|
||||
setTimeout (->
|
||||
tbl.fnClearTable()
|
||||
tbl.fnAddData data
|
||||
gui.tools.unblockUI()
|
||||
return
|
||||
), 0
|
||||
return
|
||||
|
||||
# End restore overview
|
||||
false # This may be used on button or href, better disable execution of it
|
||||
|
||||
|
||||
# Log level "translator" (renderer)
|
||||
logRenderer = gui.tools.renderLogLovel()
|
||||
|
||||
# Columns description
|
||||
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
|
||||
}
|
||||
]
|
||||
table = gui.table(tblParams.title or gettext("Logs"), tableId)
|
||||
if tblParams.container is `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, (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 or false
|
||||
fnCreatedRow: (nRow, aData, iDataIndex) ->
|
||||
v = "log-" + logRenderer(@fnGetData(iDataIndex).level)
|
||||
$(nRow).addClass v
|
||||
return
|
||||
|
||||
|
||||
# Fix form
|
||||
$("#" + tableId + "_filter input").addClass "form-control"
|
||||
|
||||
# Add refresh action to panel
|
||||
$(table.refreshSelector).click refreshFnc
|
||||
|
||||
# if table rendered event
|
||||
tblParams.onLoad self if tblParams.onLoad
|
||||
return
|
||||
|
||||
"#" + tableId
|
285
server/src/uds/static/adm/js/gui-form.coffee
Normal file
285
server/src/uds/static/adm/js/gui-form.coffee
Normal file
@ -0,0 +1,285 @@
|
||||
# jshint strict: true
|
||||
((gui, $, undefined_) ->
|
||||
"use strict"
|
||||
gui.forms = {}
|
||||
gui.forms.callback = (formSelector, method, params, success_fnc) ->
|
||||
path = "gui/callback/" + method
|
||||
p = []
|
||||
$.each params, (index, val) ->
|
||||
p.push val.name + "=" + encodeURIComponent(val.value)
|
||||
return
|
||||
|
||||
path = path + "?" + p.join("&")
|
||||
api.getJson path,
|
||||
success: success_fnc
|
||||
|
||||
return
|
||||
|
||||
|
||||
# Returns form fields that will manage a gui description (new or edit)
|
||||
gui.forms.fieldsToHtml = (itemGui, item, editing) ->
|
||||
html = ""
|
||||
fillers = [] # Fillers (callbacks)
|
||||
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, (index, f) ->
|
||||
# Not exactly a field, maybe some other info...
|
||||
return if f.gui is `undefined`
|
||||
|
||||
# Fix multiline text fields to textbox
|
||||
f.gui.type = "textbox" if f.gui.type is "text" and f.gui.multiline
|
||||
value = item[f.name] or f.gui.value or 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 is "multichoice"
|
||||
newValue = []
|
||||
$.each value, (undefined_, val) ->
|
||||
newValue.push val.id
|
||||
return
|
||||
|
||||
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: (if editing then f.gui.rdonly else 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 = (fields, item) ->
|
||||
editing = item isnt `undefined` # Locate real Editing
|
||||
item = item or id: ""
|
||||
form = "<form class=\"form-horizontal\" role=\"form\">" + "<input type=\"hidden\" name=\"id\" class=\"modal_field_data\" value=\"" + item.id + "\">"
|
||||
fillers = []
|
||||
originalValues = {}
|
||||
if fields.tabs
|
||||
id = "tab-" + Math.random().toString().split(".")[1] # Get a random base ID for tab entries
|
||||
tabs = []
|
||||
tabsContent = []
|
||||
active = " active in"
|
||||
$.each fields.tabs, (index, tab) ->
|
||||
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
|
||||
return
|
||||
|
||||
form += "<ul class=\"nav nav-tabs\">" + tabs.join("\n") + "</ul><div class=\"tab-content\">" + tabsContent.join("\n") + "</div>"
|
||||
else
|
||||
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..
|
||||
init = (formSelector) ->
|
||||
gui.doLog formSelector, fillers
|
||||
onChange = (filler) ->
|
||||
->
|
||||
gui.doLog "Onchange invoked for ", filler
|
||||
|
||||
# Attach on change method to each filler, and after that, all
|
||||
params = []
|
||||
$.each filler.parameters, (undefined_, p) ->
|
||||
val = $(formSelector + " [name=\"" + p + "\"]").val()
|
||||
params.push
|
||||
name: p
|
||||
value: val
|
||||
|
||||
return
|
||||
|
||||
gui.forms.callback formSelector, filler.callbackName, params, (data) ->
|
||||
$.each data, (undefined_, sel) ->
|
||||
|
||||
# Update select contents with returned values
|
||||
$select = $(formSelector + " [name=\"" + sel.name + "\"]")
|
||||
$select.empty()
|
||||
$.each sel.values, (undefined_, value) ->
|
||||
$select.append "<option value=\"" + value.id + "\">" + value.text + "</option>"
|
||||
return
|
||||
|
||||
$select.val originalValues[sel.name]
|
||||
|
||||
# Refresh selectpicker if item is such
|
||||
$select.selectpicker "refresh" if $select.hasClass("selectpicker")
|
||||
|
||||
# Trigger change for the changed item
|
||||
$select.trigger "change"
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
|
||||
# Sets the "on change" event for select with fillers (callbacks that fills other fields)
|
||||
$.each fillers, (undefined_, f) ->
|
||||
$(formSelector + " [name=\"" + f.name + "\"]").on "change", onChange(f)
|
||||
return
|
||||
|
||||
|
||||
# Trigger first filler if it exists, this will cascade rest of "changes" if they exists
|
||||
$(formSelector + " [name=\"" + fillers[0].name + "\"]").trigger "change" if fillers.length
|
||||
return
|
||||
|
||||
html: form # Returns the form and a initialization function for the form, that must be invoked to start it
|
||||
init: init
|
||||
|
||||
|
||||
# Reads fields from a form
|
||||
gui.forms.read = (formSelector) ->
|
||||
res = {}
|
||||
$(formSelector + " .modal_field_data").each (i, field) ->
|
||||
$field = $(field)
|
||||
if $field.attr("name") # Is a valid field
|
||||
name = $field.attr("name")
|
||||
if $field.attr("type") is "checkbox"
|
||||
res[name] = $field.is(":checked")
|
||||
else
|
||||
res[name] = $field.val()
|
||||
res[name] = [] if res[name] is null and $field.is("select")
|
||||
return
|
||||
|
||||
gui.doLog res
|
||||
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 = (options, onSuccess) ->
|
||||
options = options or {}
|
||||
id = "modal-" + Math.random().toString().split(".")[1] # Get a random ID for this modal
|
||||
ff = gui.forms.fromFields(options.fields, options.item)
|
||||
footer = ""
|
||||
clickEventHandlers = []
|
||||
if options.buttons
|
||||
$.each options.buttons, (index, value) ->
|
||||
_id = id + "-footer-" + index
|
||||
css = value.css or "btn-default"
|
||||
clickEventHandlers.push
|
||||
id: "#" + _id
|
||||
action: value.action
|
||||
|
||||
footer += "<button id=\"" + _id + "\" type=\"button\" class=\"pull-left btn " + css + "\">" + value.text + "</button>"
|
||||
return
|
||||
|
||||
gui.appendToWorkspace gui.modal(id, options.title, ff.html,
|
||||
footer: footer
|
||||
)
|
||||
id = "#" + id # for jQuery
|
||||
formSelector = id + " form"
|
||||
closeFnc = ->
|
||||
$(id).modal "hide"
|
||||
return
|
||||
|
||||
ff.init id if ff.init
|
||||
|
||||
# Append click events for custom buttons on footer
|
||||
$.each clickEventHandlers, (undefined_, value) ->
|
||||
if value.action
|
||||
$(value.id).on "click", (event) ->
|
||||
value.action event, formSelector, closeFnc
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
|
||||
# Get form
|
||||
$form = $(id + " form")
|
||||
gui.tools.applyCustoms id
|
||||
|
||||
# Validation
|
||||
$form.validate
|
||||
debug: true
|
||||
errorClass: "text-danger"
|
||||
validClass: "has-success"
|
||||
highlight: (element) ->
|
||||
$(element).closest(".form-group").addClass "has-error"
|
||||
return
|
||||
|
||||
success: (element) ->
|
||||
$(element).closest(".form-group").removeClass "has-error"
|
||||
$(element).remove()
|
||||
return
|
||||
|
||||
|
||||
# And catch "accept" (default is "Save" in fact) button click
|
||||
$("#{id} .button-accept").click ->
|
||||
return unless $form.valid()
|
||||
if options.success
|
||||
options.success formSelector, closeFnc # Delegate close to to onSuccess
|
||||
return
|
||||
else
|
||||
closeFnc()
|
||||
return
|
||||
|
||||
|
||||
# If preprocessors of modal (maybe custom event handlers)
|
||||
options.preprocessor id if options.preprocessor
|
||||
|
||||
# Launch modal
|
||||
$(id).modal(keyboard: false).on "hidden.bs.modal", ->
|
||||
$(id).remove()
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
|
||||
# simple gui generators
|
||||
gui.forms.guiField = (name, type, label, tooltip, value, values, length, multiline, readonly, required) ->
|
||||
length = length or 128
|
||||
multiline = (if multiline isnt `undefined` then multiline else 0)
|
||||
readonly = readonly or false
|
||||
required = required or false
|
||||
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
|
||||
|
||||
return
|
||||
) window.gui = window.gui or {}, jQuery
|
106
server/src/uds/static/adm/js/gui-tools.coffee
Normal file
106
server/src/uds/static/adm/js/gui-tools.coffee
Normal file
@ -0,0 +1,106 @@
|
||||
# jshint strict: true
|
||||
((gui, $, undefined_) ->
|
||||
"use strict"
|
||||
gui.tools =
|
||||
blockUI: (message) ->
|
||||
message = message or "<h1><span class=\"fa fa-spinner fa-spin\"></span> " + gettext("Just a moment...") + "</h1>"
|
||||
$.blockUI message: message
|
||||
return
|
||||
|
||||
unblockUI: ->
|
||||
$.unblockUI()
|
||||
$(".DTTT_collection_background").remove()
|
||||
return
|
||||
|
||||
fix3dButtons: (selector) ->
|
||||
selector = selector or ""
|
||||
selector += " .btn3d"
|
||||
console.log selector
|
||||
$.each $(selector), (index, value) ->
|
||||
|
||||
# If no events associated, return
|
||||
return if $._data(value, "events") is `undefined`
|
||||
$this = $(this)
|
||||
clkEvents = []
|
||||
|
||||
# Store old click events, so we can reconstruct click chain later
|
||||
$.each $._data(value, "events").click, (index, fnc) ->
|
||||
clkEvents.push fnc
|
||||
return
|
||||
|
||||
$this.unbind "click"
|
||||
|
||||
# If Mousedown registers a temporal mouseUp event on parent, to lauch button click
|
||||
$this.mousedown (event) ->
|
||||
$("body").mouseup (e) ->
|
||||
|
||||
# Remove temporal mouseup handler
|
||||
$(this).unbind "mouseup"
|
||||
|
||||
# If movement of mouse is not too far... (16 px maybe well for 3d buttons?)
|
||||
x = event.pageX - e.pageX
|
||||
y = event.pageY - e.pageY
|
||||
dist_square = x * x + y * y
|
||||
if dist_square < 16 * 16
|
||||
|
||||
# Register again old event handlers
|
||||
$.each clkEvents, (index, fnc) ->
|
||||
$this.click fnc.handler
|
||||
return
|
||||
|
||||
$this.click()
|
||||
$this.unbind "click"
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
applyCustoms: (selector) ->
|
||||
|
||||
# Activate "custom" styles
|
||||
$(selector + " input:checkbox").bootstrapSwitch()
|
||||
|
||||
# Activate "cool" selects
|
||||
$(selector + " .selectpicker").selectpicker()
|
||||
|
||||
# TEST: cooler on mobile devices
|
||||
$(selector + " .selectpicker").selectpicker "mobile" if /Android|webOS|iPhone|iPad|iPod|BlackBerry/i.test(navigator.userAgent)
|
||||
|
||||
# Activate tooltips
|
||||
$(selector + " [data-toggle=\"tooltip\"]").tooltip
|
||||
delay:
|
||||
show: 1000
|
||||
hide: 100
|
||||
|
||||
placement: "auto right"
|
||||
|
||||
|
||||
# Fix 3d buttons
|
||||
gui.tools.fix3dButtons selector
|
||||
return
|
||||
|
||||
|
||||
# Datetime renderer (with specified format)
|
||||
renderDate: (format) ->
|
||||
(data, type, full) ->
|
||||
"<span data-date=\"" + data + "\">" + api.tools.strftime(format, new Date(data * 1000)) + "</span>"
|
||||
|
||||
|
||||
# Log level rendererer
|
||||
renderLogLovel: ->
|
||||
levels =
|
||||
10000: "OTHER"
|
||||
20000: "DEBUG"
|
||||
30000: "INFO"
|
||||
40000: "WARN"
|
||||
50000: "ERROR"
|
||||
60000: "FATAL"
|
||||
|
||||
(data, type, full) ->
|
||||
levels[data] or "OTHER"
|
||||
|
||||
return
|
||||
) window.gui = window.gui or {}, jQuery
|
396
server/src/uds/static/adm/js/gui.coffee
Normal file
396
server/src/uds/static/adm/js/gui.coffee
Normal file
@ -0,0 +1,396 @@
|
||||
# jshint strict: true
|
||||
((gui, $, undefined_) ->
|
||||
"use strict"
|
||||
|
||||
# "public" methods
|
||||
gui.doLog = (args...)->
|
||||
if gui.debug
|
||||
try
|
||||
console.log.apply window, args
|
||||
return
|
||||
|
||||
|
||||
# nothing can be logged
|
||||
gui.config = gui.config or {}
|
||||
|
||||
# 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 = (prefix) ->
|
||||
prefix = prefix or ""
|
||||
prefix + Math.random().toString().split(".")[1]
|
||||
|
||||
gui.table = (title, table_id, options) ->
|
||||
options = options or {}
|
||||
panelId = "panel-" + table_id
|
||||
text: api.templates.evaluate("tmpl_comp_table",
|
||||
panelId: panelId
|
||||
icon: options.icon or "table"
|
||||
size: options.size or 12
|
||||
title: title
|
||||
table_id: table_id
|
||||
)
|
||||
panelId: panelId
|
||||
refreshSelector: "#" + panelId + " span.fa-refresh"
|
||||
|
||||
gui.breadcrumbs = (path) ->
|
||||
items = path.split("/")
|
||||
active = items.pop()
|
||||
list = ""
|
||||
$.each items, (index, value) ->
|
||||
list += "<li><a href=\"#\">" + value + "</a></li>"
|
||||
return
|
||||
|
||||
list += "<li class=\"active\">" + active + "</li>"
|
||||
"<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 = (id, title, content, options) ->
|
||||
options = options or {}
|
||||
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 = (title, content, options) ->
|
||||
options = options or {}
|
||||
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", ->
|
||||
$(id).remove()
|
||||
return
|
||||
|
||||
id
|
||||
|
||||
gui.notify = (message, type) ->
|
||||
gui.launchModal "<b class=\"text-" + type + "\">" + gettext("Message") + "</b>", "<span class=\"text-" + type + "\">" + message + "</span>",
|
||||
actionButton: " "
|
||||
|
||||
return
|
||||
|
||||
gui.failRequestModalFnc = (title) ->
|
||||
(jqXHR, textStatus, errorThrown) -> # fail on put
|
||||
gui.tools.unblockUI()
|
||||
gui.launchModal "<b class=\"text-danger\">" + title + "</b>", jqXHR.responseText,
|
||||
actionButton: " "
|
||||
|
||||
return
|
||||
|
||||
gui.promptModal = (title, question, options) ->
|
||||
options = options or {}
|
||||
options.actionButton = "<button type=\"button\" class=\"btn btn-primary button-yes\">" + (options.yesButton or gettext("yes")) + "</button>"
|
||||
options.closeButton = "<button type=\"button\" class=\"btn btn-danger button-no\">" + (options.yesButton or gettext("no")) + "</button>"
|
||||
onYes = options.onYes or ->
|
||||
|
||||
onNo = options.onNo or ->
|
||||
|
||||
modalId = gui.launchModal(title, question, options)
|
||||
$(modalId + " .button-yes").on "click", (event) ->
|
||||
$(modalId).modal "hide"
|
||||
onYes()
|
||||
return
|
||||
|
||||
$(modalId + " .button-no").on "click", (event) ->
|
||||
$(modalId).modal "hide"
|
||||
onNo()
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
gui.clearWorkspace = ->
|
||||
$("#content").empty()
|
||||
$("#minimized").empty()
|
||||
return
|
||||
|
||||
gui.appendToWorkspace = (data) ->
|
||||
$(data).appendTo "#content"
|
||||
return
|
||||
|
||||
|
||||
# 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 = ->
|
||||
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(), (undefined_, tbl) ->
|
||||
$tbl = $(tbl).dataTable()
|
||||
$tbl.fnClearTable() # Removing data first makes things much faster
|
||||
$tbl.fnDestroy()
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
gui.setLinksEvents = ->
|
||||
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, (index, value) ->
|
||||
gui.doLog "Adding " + value.id
|
||||
$("." + value.id).unbind("click").click (event) ->
|
||||
event.preventDefault()
|
||||
$(".navbar-toggle").trigger "click" unless $(".navbar-toggle").css("display") is "none"
|
||||
gui.cleanup() if value.cleanup
|
||||
$("html, body").scrollTop 0
|
||||
value.exec event
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
gui.init = ->
|
||||
|
||||
# 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"] = (s) ->
|
||||
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"] = (x, y) ->
|
||||
val = ((if (x < y) then -1 else ((if (x > y) then 1 else 0))))
|
||||
val
|
||||
|
||||
$.fn.dataTableExt.oSort["uds-date-desc"] = (x, y) ->
|
||||
val = ((if (x < y) then 1 else ((if (x > y) then -1 else 0))))
|
||||
val
|
||||
|
||||
|
||||
# Wait a bit before activating links to give tome tine to initializations
|
||||
setTimeout (->
|
||||
gui.setLinksEvents()
|
||||
gui.dashboard.link()
|
||||
return
|
||||
), 500
|
||||
return
|
||||
|
||||
gui.showDashboard = ->
|
||||
gui.dashboard.link()
|
||||
return
|
||||
|
||||
|
||||
# Generic "methods" for editing, creating, etc...
|
||||
gui.methods = {}
|
||||
gui.methods.typedTestButton = (rest, text, css, type) ->
|
||||
[
|
||||
text: text
|
||||
css: css
|
||||
action: (event, form_selector, closeFnc) ->
|
||||
fields = gui.forms.read(form_selector)
|
||||
gui.doLog "Fields: ", fields
|
||||
rest.test type, fields, ((data) ->
|
||||
gui.launchModal gettext("Test result"), data,
|
||||
actionButton: " "
|
||||
|
||||
return
|
||||
), gui.failRequestModalFnc(gettext("Test error"))
|
||||
return
|
||||
]
|
||||
|
||||
|
||||
# "Generic" edit method to set onEdit table
|
||||
gui.methods.typedEdit = (parent, modalTitle, modalErrorMsg, options) ->
|
||||
options = options or {}
|
||||
(value, event, table, refreshFnc) ->
|
||||
gui.tools.blockUI()
|
||||
parent.rest.gui value.type, ((guiDefinition) ->
|
||||
buttons = null
|
||||
buttons = gui.methods.typedTestButton(parent.rest, options.testButton.text, options.testButton.css, value.type) if options.testButton
|
||||
tabs = (if options.guiProcessor then options.guiProcessor(guiDefinition) else guiDefinition) # Preprocess fields (probably generate tabs...)
|
||||
parent.rest.item value.id, (item) ->
|
||||
gui.tools.unblockUI()
|
||||
gui.forms.launchModal
|
||||
title: modalTitle + " <b>" + value.name + "</b>"
|
||||
fields: tabs
|
||||
item: item
|
||||
preprocessor: options.preprocessor
|
||||
buttons: buttons
|
||||
success: (form_selector, closeFnc) ->
|
||||
fields = gui.forms.read(form_selector)
|
||||
fields.data_type = value.type
|
||||
fields = (if options.fieldsProcessor then options.fieldsProcessor(fields) else fields)
|
||||
parent.rest.save fields, ((data) -> # Success on put
|
||||
closeFnc()
|
||||
refreshFnc()
|
||||
gui.notify gettext("Edition successfully done"), "success"
|
||||
return
|
||||
), gui.failRequestModalFnc(modalErrorMsg, true) # Fail on put, show modal message
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
return
|
||||
), gui.failRequestModalFnc(modalErrorMsg, true)
|
||||
return
|
||||
|
||||
|
||||
# "Generic" new method to set onNew table
|
||||
gui.methods.typedNew = (parent, modalTitle, modalErrorMsg, options) ->
|
||||
options = options or {}
|
||||
(type, table, refreshFnc) ->
|
||||
gui.tools.blockUI()
|
||||
parent.rest.gui type, ((guiDefinition) ->
|
||||
gui.tools.unblockUI()
|
||||
buttons = null
|
||||
buttons = gui.methods.typedTestButton(parent.rest, options.testButton.text, options.testButton.css, type) if options.testButton
|
||||
tabs = (if options.guiProcessor then options.guiProcessor(guiDefinition) else guiDefinition) # Preprocess fields (probably generate tabs...)
|
||||
title = modalTitle
|
||||
title += " " + gettext("of type") + " <b>" + parent.types[type].name + "</b>" if parent.types[type] isnt `undefined`
|
||||
gui.forms.launchModal
|
||||
title: title
|
||||
fields: tabs
|
||||
item: `undefined`
|
||||
preprocessor: options.preprocessor
|
||||
buttons: buttons
|
||||
success: (form_selector, closeFnc) ->
|
||||
fields = gui.forms.read(form_selector)
|
||||
fields.data_type = type if parent.types[type] isnt `undefined`
|
||||
fields = (if options.fieldsProcessor then options.fieldsProcessor(fields) else fields) # Process fields before creating?
|
||||
parent.rest.create fields, ((data) -> # Success on put
|
||||
closeFnc()
|
||||
refreshFnc()
|
||||
gui.notify gettext("Creation successfully done"), "success"
|
||||
return
|
||||
), gui.failRequestModalFnc(modalErrorMsg, true) # Fail on put, show modal message
|
||||
return
|
||||
|
||||
return
|
||||
), gui.failRequestModalFnc(modalErrorMsg, true)
|
||||
return
|
||||
|
||||
gui.methods.del = (parent, modalTitle, modalErrorMsg) ->
|
||||
(value, event, table, refreshFnc) ->
|
||||
gui.doLog value
|
||||
name = value.name or value.friendly_name
|
||||
content = gettext("Are you sure do you want to delete ") + "<b>" + name + "</b>"
|
||||
modalId = gui.launchModal(modalTitle, content,
|
||||
actionButton: "<button type=\"button\" class=\"btn btn-danger button-accept\">" + gettext("Delete") + "</button>"
|
||||
)
|
||||
$(modalId + " .button-accept").click ->
|
||||
$(modalId).modal "hide"
|
||||
parent.rest.del value.id, (->
|
||||
refreshFnc()
|
||||
gui.notify gettext("Item deleted"), "success"
|
||||
return
|
||||
), gui.failRequestModalFnc(modalErrorMsg)
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
|
||||
# Public attributes
|
||||
gui.debug = true
|
||||
return
|
||||
) window.gui = window.gui or {}, jQuery
|
@ -92,31 +92,31 @@
|
||||
<script src="{% get_static_prefix %}adm/js/handlebars-v1.3.0.js"></script>
|
||||
|
||||
<!-- First all api related stuff -->
|
||||
<script src="{% get_static_prefix %}adm/js/api.js"></script>
|
||||
<script type="text/coffeescript" charset="utf-8" src="{% get_static_prefix %}adm/js/api.coffee"></script>
|
||||
|
||||
<!-- utilities attached to api -->
|
||||
<script src="{% get_static_prefix %}adm/js/api-tools.js"></script>
|
||||
<script type="text/coffeescript" charset="utf-8" src="{% get_static_prefix %}adm/js/api-tools.coffee"></script>
|
||||
|
||||
<!-- templates related, inserts itself into api -->
|
||||
<script src="{% get_static_prefix %}adm/js/api-templates.js"></script>
|
||||
<script type="text/coffeescript" charset="utf-8" src="{% get_static_prefix %}adm/js/api-templates.coffee"></script>
|
||||
|
||||
<!-- export to xls, inserts itself into api -->
|
||||
<script src="{% get_static_prefix %}adm/js/api-spreadsheet.js"></script>
|
||||
<script type="text/coffeescript" charset="utf-8" src="{% get_static_prefix %}adm/js/api-spreadsheet.coffee"></script>
|
||||
|
||||
<script src="{% get_static_prefix %}adm/js/gui.js"></script>
|
||||
<script src="{% get_static_prefix %}adm/js/gui-tools.js"></script>
|
||||
<script src="{% get_static_prefix %}adm/js/gui-form.js"></script>
|
||||
<script src="{% get_static_prefix %}adm/js/gui-element.js"></script>
|
||||
<script type="text/coffeescript" charset="utf-8" src="{% get_static_prefix %}adm/js/gui.coffee"></script>
|
||||
<script type="text/coffeescript" charset="utf-8" src="{% get_static_prefix %}adm/js/gui-tools.coffee"></script>
|
||||
<script type="text/coffeescript" charset="utf-8" src="{% get_static_prefix %}adm/js/gui-form.coffee"></script>
|
||||
<script type="text/coffeescript" charset="utf-8" src="{% get_static_prefix %}adm/js/gui-element.coffee"></script>
|
||||
|
||||
<!-- user interface management -->
|
||||
<script src="{% get_static_prefix %}adm/js/gui-definition.js"></script>
|
||||
<script src="{% get_static_prefix %}adm/js/gui-d-dashboard.js"></script>
|
||||
<script src="{% get_static_prefix %}adm/js/gui-d-services.js"></script>
|
||||
<script src="{% get_static_prefix %}adm/js/gui-d-authenticators.js"></script>
|
||||
<script src="{% get_static_prefix %}adm/js/gui-d-osmanagers.js"></script>
|
||||
<script src="{% get_static_prefix %}adm/js/gui-d-connectivity.js"></script>
|
||||
<script src="{% get_static_prefix %}adm/js/gui-d-servicespools.js"></script>
|
||||
<script src="{% get_static_prefix %}adm/js/gui-d-config.js"></script>
|
||||
<script type="text/coffeescript" charset="utf-8" src="{% get_static_prefix %}adm/js/gui-definition.coffee"></script>
|
||||
<script type="text/coffeescript" charset="utf-8" src="{% get_static_prefix %}adm/js/gui-d-dashboard.coffee"></script>
|
||||
<script type="text/coffeescript" charset="utf-8" src="{% get_static_prefix %}adm/js/gui-d-services.coffee"></script>
|
||||
<script type="text/coffeescript" charset="utf-8" src="{% get_static_prefix %}adm/js/gui-d-authenticators.coffee"></script>
|
||||
<script type="text/coffeescript" charset="utf-8" src="{% get_static_prefix %}adm/js/gui-d-osmanagers.coffee"></script>
|
||||
<script type="text/coffeescript" charset="utf-8" src="{% get_static_prefix %}adm/js/gui-d-connectivity.coffee"></script>
|
||||
<script type="text/coffeescript" charset="utf-8" src="{% get_static_prefix %}adm/js/gui-d-servicespools.coffee"></script>
|
||||
<script type="text/coffeescript" charset="utf-8" src="{% get_static_prefix %}adm/js/gui-d-config.coffee"></script>
|
||||
|
||||
<script>
|
||||
$(function() {
|
||||
|
7
server/src/uds/templates/uds/pruebas/about.html
Normal file
7
server/src/uds/templates/uds/pruebas/about.html
Normal file
@ -0,0 +1,7 @@
|
||||
{% extends "uds/html5/templates/base.html" %}
|
||||
{% load i18n %}
|
||||
|
||||
|
||||
|
||||
{% block body %}
|
||||
{% endblock %}
|
29
server/src/uds/templates/uds/pruebas/detectJava.html
Normal file
29
server/src/uds/templates/uds/pruebas/detectJava.html
Normal file
@ -0,0 +1,29 @@
|
||||
{% extends "uds/html5/templates/base.html" %}
|
||||
{% load i18n static %}
|
||||
|
||||
{% block title %}{% trans "Login redirection to UDS" %}{% endblock %}
|
||||
|
||||
{% block script %}
|
||||
<script src="{% get_static_prefix %}js/PluginDetect_Java.js" type="text/javascript" ></script>
|
||||
<script type="text/javascript">
|
||||
function isJavaAvailable() {
|
||||
if( PluginDetect.isMinVersion('Java', '1,6,0,0','{% get_static_prefix %}/other/getJavaInfo.jar') == 1 )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
var java = isJavaAvailable() ? "y" : "n";
|
||||
window.location.replace("{% url "uds.web.views.authJava" idAuth=idAuth hasJava='' %}" + java);
|
||||
});
|
||||
|
||||
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<!--<div>
|
||||
<a href="<a href="{% url "uds.web.views.index" %}">{% trans "Go to main page" %}
|
||||
</div>-->
|
||||
{% endblock %}
|
21
server/src/uds/templates/uds/pruebas/downloads.html
Normal file
21
server/src/uds/templates/uds/pruebas/downloads.html
Normal file
@ -0,0 +1,21 @@
|
||||
{% extends "uds/html5/templates/base.html" %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block body %}
|
||||
<div class="panel panel-info">
|
||||
<div class="panel-heading">
|
||||
{% trans "Downloads" %}
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<p>{% trans "This page contains a list of downloadables provided by different modules" %}</p>
|
||||
<div class="list-group">
|
||||
{% for f in files %}
|
||||
<a class="list-group-item" href="{% url "uds.web.views.download" idDownload=f.id %}">
|
||||
<h4 class="list-group-item-heading">{{ f.name }}</h4>
|
||||
<p class="list-group-item-text">{{ f.comment|safe }}</p>
|
||||
</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
14
server/src/uds/templates/uds/pruebas/downloads.jade
Normal file
14
server/src/uds/templates/uds/pruebas/downloads.jade
Normal file
@ -0,0 +1,14 @@
|
||||
extends "uds/html5/templates/base.html"
|
||||
- load i18n
|
||||
block body
|
||||
div.panel.panel-info
|
||||
div.panel-heading
|
||||
- trans "Downloads"
|
||||
div.panel-body
|
||||
p
|
||||
- trans "This page contains a list of downloadables provided by different modules"
|
||||
div.list-group
|
||||
for f in files
|
||||
a.list-group-item(href!="{% url "uds.web.views.download" idDownload=f.id %}")
|
||||
h4.list-group-item-heading: f.name
|
||||
p.list-group-item-text: {{ f.comment|safe }}
|
18
server/src/uds/templates/uds/pruebas/error.html
Normal file
18
server/src/uds/templates/uds/pruebas/error.html
Normal file
@ -0,0 +1,18 @@
|
||||
{% extends "uds/html5/templates/base.html" %}
|
||||
{% load i18n static %}
|
||||
|
||||
{% block title %}{% trans 'Error' %}{% endblock %}
|
||||
{% block css %}
|
||||
<style>
|
||||
.center {text-align: center; margin-left: auto; margin-right: auto; margin-bottom: auto; margin-top: auto;}
|
||||
</style>
|
||||
{% endblock %}
|
||||
{% block body %}
|
||||
<div class="jumbotron center">
|
||||
<h1>{% trans 'An error occurred' %}</h1>
|
||||
<br />
|
||||
<p>{% trans "Error" %}: <b class="text-danger">{{ errorString }}</b></p>
|
||||
<br />
|
||||
<a href="{% url 'uds.web.views.index' %}" class="btn btn-lg btn-info"><i class="fa fa-home"></i> {% trans "Back to services list" %}</a>
|
||||
</div>
|
||||
{% endblock %}
|
131
server/src/uds/templates/uds/pruebas/index.html
Normal file
131
server/src/uds/templates/uds/pruebas/index.html
Normal file
@ -0,0 +1,131 @@
|
||||
{% extends "uds/html5/templates/base.html" %}
|
||||
{% load i18n html5 %}
|
||||
|
||||
{% block title %}{% trans 'Available services list' %}{% endblock %}
|
||||
|
||||
{% block css %}
|
||||
<style media="screen">
|
||||
.list-btn-group {
|
||||
margin-bottom: 24px;
|
||||
margin-right: 24px;
|
||||
}
|
||||
.list-btn {
|
||||
padding-top: 24px;
|
||||
height: 96px;
|
||||
overflow: hidden;
|
||||
}
|
||||
.list-btn-reduced {
|
||||
width: 96px;
|
||||
}
|
||||
.list-btn-normal {
|
||||
width: 112px;
|
||||
}
|
||||
|
||||
.list-dropdown-toggle {
|
||||
width: 16px;
|
||||
}
|
||||
|
||||
.transport {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
}
|
||||
|
||||
/* We need to write under button */
|
||||
.btn-group {
|
||||
max-width: 114px;
|
||||
}
|
||||
|
||||
{% ifbrowser firefox %}
|
||||
{% else %}
|
||||
.btn .caret {
|
||||
margin-left: -4px;
|
||||
}
|
||||
{% endifbrowser %}
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
{% block js %}
|
||||
<script>
|
||||
$(function() {
|
||||
{% if not java %}
|
||||
$("a.nojava").click( function() {
|
||||
$('#no-java-dialog').modal({
|
||||
keyboard: false
|
||||
})
|
||||
return false;
|
||||
});
|
||||
|
||||
{% endif %}
|
||||
$('.transport-caption-small').popover({container: 'body', trigger: 'hover', delay: { show: 500, hide: 100 }, placement: 'auto bottom'});
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<h2>{% trans "Services" %}</h2>
|
||||
<div class="clearfix">
|
||||
{% for ser in services %}
|
||||
{% if ser.transports %}
|
||||
{% with trans=ser.transports|first numTransports=ser.transports|length %}
|
||||
<div class="btn-group list-btn-group">
|
||||
<a class="{% if not java and trans.needsJava %} nojava{% endif %} btn list-btn btn-default list-btn-{% if numTransports > 1 %}reduced{% else %}normal{% endif %}"
|
||||
href="{% url "uds.web.views.service" idService=ser.id idTransport=trans.id %}"
|
||||
title="{{ ser.name }}"
|
||||
data-toggle="tooltip">
|
||||
<img src="{% url "uds.web.views.serviceImage" idImage=ser.imageId %}" class="transport" alt="{{ ser.name }}" />
|
||||
</a>
|
||||
{% if numTransports > 1 %}
|
||||
<button type="button" class="btn list-btn btn-default dropdown-toggle list-dropdown-toggle" data-toggle="dropdown">
|
||||
<span class="caret"></span>
|
||||
<span class="sr-only">{% trans 'transports' %}</span>
|
||||
</button>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
{% for trans in ser.transports %}
|
||||
{% if not forloop.first %}
|
||||
<li><a{% if not java and trans.needsJava %} class="nojava"{% endif %} href="{% url "uds.web.views.service" idService=ser.id idTransport=trans.id %}"><img src="{% url "uds.web.views.transportIcon" idTrans=trans.id %}" alt="{{ trans.name }}" />{{ trans.name }}</a></li>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
<div class="transport-caption{% if ser.name|length > 16 %}-small{% endif %} text-center" data-content="{{ser.name|capfirst}}">{{ ser.name|capfirst|truncatechars:16 }}</div>
|
||||
</div>
|
||||
{% endwith %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
{% if not java %}
|
||||
<div class="modal fade" id="no-java-dialog">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
<h4 class="modal-title">{% trans "Java not found" %}</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>{% trans "Java is not available on your browser, and the selected transport needs it." %}</p>
|
||||
<p>{% trans "Please, install latest version from" %} <a href="http://www.java.com" target="_blank">{% trans "Java website" %}</a> {% trans "and restart browser" %}</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
|
||||
</div>
|
||||
</div><!-- /.modal-content -->
|
||||
</div><!-- /.modal-dialog -->
|
||||
</div><!-- /.modal -->
|
||||
{% endif %}
|
||||
|
||||
{% if user.isStaff %}
|
||||
<div class="panel panel-warning">
|
||||
<div class="panel-heading">
|
||||
{% trans "Administrator info panel" %}
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<p>{% trans "Ip" %}: {{ ip }}</p>
|
||||
<p>{% trans "Networks" %}: {{ nets }}</p>
|
||||
<p>{% trans "Transports" %}: {{ transports }}</p>
|
||||
<p>{% trans "User Agent" %}: {{ request.META.HTTP_USER_AGENT }}</p>
|
||||
<p>{% trans "OS" %}: {{ request.session.OS.OS }}</p>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endblock %}
|
107
server/src/uds/templates/uds/pruebas/login.html
Normal file
107
server/src/uds/templates/uds/pruebas/login.html
Normal file
@ -0,0 +1,107 @@
|
||||
{% extends "uds/html5/templates/base.html" %}
|
||||
{% load i18n static html5 %}
|
||||
|
||||
{% block title %}{% trans 'Welcome to UDS' %}{% endblock %}
|
||||
|
||||
{% block js %}
|
||||
<script src="{% get_static_prefix %}js/PluginDetect_Java.js" type="text/javascript" ></script>
|
||||
<script type="text/javascript">
|
||||
function isJavaAvailable() {
|
||||
if( PluginDetect.isMinVersion('Java', '1,6,0,0','{% get_static_prefix %}/other/getJavaInfo.jar') == 1 )
|
||||
return true;
|
||||
|
||||
//PluginDetect.getVersion('Java', '{% get_static_prefix %}/other/getJavaInfo.jar')
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function chkNonStandardAuth(val, nonStandard) {
|
||||
if( $.inArray(val, nonStandard) >= 0) {
|
||||
var vv = val;
|
||||
$("#login").hide(300, function() {
|
||||
$.get('{%url "uds.web.views.customAuth" idAuth=''%}' + vv, function(data) {
|
||||
$('#nonStandardLogin').html(data);
|
||||
$('#nonStandard').show(300);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
$('#id_java').val(isJavaAvailable() ? "y" : "n");
|
||||
var nonStandard = $('#id_nonStandard').val();
|
||||
|
||||
if( nonStandard.length == 0 )
|
||||
nonStandard = [];
|
||||
else
|
||||
nonStandard = nonStandard.split(',');
|
||||
var standard = $('#id_standard').val();
|
||||
if( standard.length == 0 )
|
||||
standard = [];
|
||||
else
|
||||
standard = standard.split(',');
|
||||
|
||||
$('#id_authenticator').change(function() { chkNonStandardAuth($(this).val(), nonStandard) });
|
||||
if( standard.length > 0 ) {
|
||||
$('#backToLogin').click(function() {
|
||||
$('#id_authenticator').val(standard[0]);
|
||||
$('#nonStandard').hide(300, function() {
|
||||
$('#nonStandardLogin').html('');
|
||||
$("#login").show(300);
|
||||
});
|
||||
return false;
|
||||
});
|
||||
} else {
|
||||
$('#divBackToLogin').html('');
|
||||
}
|
||||
// Check initial value (may default auth is non Standard)
|
||||
chkNonStandardAuth($('#id_authenticator').val(), nonStandard);
|
||||
});
|
||||
|
||||
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<div class="container">
|
||||
<div class="row" id="login">
|
||||
<div class="col-md-4 col-md-offset-4">
|
||||
<h1 class="text-center login-title">{% trans 'Welcome to UDS' %}</h1>
|
||||
<div class="account-wall">
|
||||
<img class="profile-img" src="{% get_static_prefix %}img/login-img.png" alt="">
|
||||
<form id="loginform" class="form-signin" name="loginform" method="post">
|
||||
{% if form.errors %}
|
||||
<div class="alert alert-dismissable alert-danger">
|
||||
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
|
||||
{% trans 'invalid credentials'|capfirst %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% csrf_token %}
|
||||
{% for hidden in form.hidden_fields %}
|
||||
{{ hidden }}
|
||||
{% endfor %}
|
||||
<div class="form-group">
|
||||
<input id="id_{{form.user.name}}" name="{{form.user.name}}" type="text" class="form-control" placeholder="{% trans 'username'|capfirst %}" autofocus required>
|
||||
<input id="id_{{form.password.name}}" name="{{form.password.name}}" type="password" class="form-control" placeholder="{% trans 'password'|capfirst %}">
|
||||
{{ form.authenticator }}
|
||||
</div>
|
||||
<button class="btn btn-lg btn-primary btn-block" type="submit"><span class="fa fa-sign-in"></span> {% trans 'Sign in' %}</button>
|
||||
<div id="nonStandard" style="display: none">
|
||||
<div id="nonStandardLogin" class="form">
|
||||
non standard logins
|
||||
</div>
|
||||
<div id="divBackToLogin">
|
||||
<a href="#" id="backToLogin" title="{% trans "Back to login" %}">{% trans "Back to login" %}</a>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row" id="customHtml">
|
||||
{% autoescape off %}
|
||||
{{ customHtml }}
|
||||
{% endautoescape %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
14
server/src/uds/templates/uds/pruebas/prefs.html
Normal file
14
server/src/uds/templates/uds/pruebas/prefs.html
Normal file
@ -0,0 +1,14 @@
|
||||
{% extends "uds/html5/templates/base.html" %}
|
||||
{% load i18n %}
|
||||
{% load static %}
|
||||
|
||||
{% block title %}{% trans "UDS User Preferences" %}{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<form name="form1" method="post" class="form-preferences">
|
||||
{% csrf_token %}
|
||||
{% autoescape off %}{{ prefs_form }}{% endautoescape %}
|
||||
<a href="{% url "uds.web.views.index" %}" class="btn btn-warning">{% trans "Cancel" %}</a>
|
||||
<button type="submit" class="btn btn-success pull-right">{% trans "Save Preferences" %}</button>
|
||||
</form>
|
||||
{% endblock %}
|
19
server/src/uds/templates/uds/pruebas/service_not_ready.html
Normal file
19
server/src/uds/templates/uds/pruebas/service_not_ready.html
Normal file
@ -0,0 +1,19 @@
|
||||
{% extends "uds/html5/templates/base.html" %}
|
||||
{% load i18n static %}
|
||||
|
||||
{% block title %}{% trans 'The service is not ready' %}{% endblock %}
|
||||
{% block css %}
|
||||
<style>
|
||||
.center {text-align: center; margin-left: auto; margin-right: auto; margin-bottom: auto; margin-top: auto;}
|
||||
</style>
|
||||
{% endblock %}
|
||||
{% block body %}
|
||||
<div class="jumbotron center">
|
||||
<h1> {% trans 'The service is not ready' %}</h1>
|
||||
<br />
|
||||
<p>{% trans 'The service is not ready at this moment. Please, try it again after a few seconds.' %}</p>
|
||||
<h5>{% trans 'The service you has requested was not ready, and is being created right now. It will be availabe shortly' %}</h5>
|
||||
<br />
|
||||
<a href="{% url 'uds.web.views.index' %}" class="btn btn-lg btn-info"><i class="fa fa-home"></i> {% trans "Back" %}</a>
|
||||
</div>
|
||||
{% endblock %}
|
20
server/src/uds/templates/uds/pruebas/show_transport.html
Normal file
20
server/src/uds/templates/uds/pruebas/show_transport.html
Normal file
@ -0,0 +1,20 @@
|
||||
{% extends "uds/html5/templates/base.html" %}
|
||||
{% load i18n static %}
|
||||
|
||||
{% block body %}
|
||||
<div class="panel panel-default text-center">
|
||||
<div id="transport">
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-center">
|
||||
<a href="{% url 'uds.web.views.index' %}" class="btn btn-info"><i class="fa fa-home"></i> {% trans "Back to services list" %}</a>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block js %}
|
||||
<script>
|
||||
$(document).ready(function(){
|
||||
$('#transport').append("{{ transport|escapejs }}");
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
57
server/src/uds/templates/uds/pruebas/snippets/navbar.html
Normal file
57
server/src/uds/templates/uds/pruebas/snippets/navbar.html
Normal file
@ -0,0 +1,57 @@
|
||||
{% load i18n html5 static %}
|
||||
<nav class="navbar navbar-default navbar-fixed-top" role="navigation">
|
||||
<!-- Brand and toggle get grouped for better mobile display -->
|
||||
<div class="navbar-header">
|
||||
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-ex1-collapse">
|
||||
<span class="sr-only">{% trans 'toggle navigation'|capfirst %}</span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
<a href="{% url 'uds.web.views.index' %}"><span class="navbar-brand">Universal Desktop Services</span></a>
|
||||
</div>
|
||||
<div class="collapse navbar-collapse navbar-ex1-collapse">
|
||||
<ul class="nav navbar-nav">
|
||||
</ul>
|
||||
<form id="form_language" action="{% url "django.views.i18n.set_language" %}" method="post">
|
||||
{% csrf_token %}
|
||||
<input id="id_language" type="hidden" name="language" value=""/>
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
<li><a href="#">{% trans 'About' %}</a></li>
|
||||
<li class="dropdown">
|
||||
{% for lang in LANGUAGES %}
|
||||
{% if lang.0 == LANGUAGE_CODE %}
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown"><i class="glyphicon bfh-flag-{{ lang.0|country }}"></i>{% trans lang.1|capfirst %}<b class="caret"></b></a>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
<ul class="dropdown-menu">
|
||||
{% for lang in LANGUAGES %}
|
||||
{% if lang.0 != LANGUAGE_CODE %}
|
||||
<li><a href="#" onclick='$("#id_language").val("{{ lang.0 }}"); $("#form_language").submit()'><i class="glyphicon bfh-flag-{{ lang.0|country }}"></i>{% trans lang.1|capfirst %}</a></li>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</li>
|
||||
{% if user and not user.is_anonymous %}
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown"><i class="fa fa-user"></i> {{ user.real_name }} <b class="caret"></b></a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a href="{% url "uds.web.views.prefs" %}"><span class="fa fa-edit"></span> {% trans 'Preferences' %}</a></li>
|
||||
{% if user.staff_member or user.is_admin %}
|
||||
<li><a href="{% url "uds.web.views.download" idDownload='' %}"><span class="fa fa-download"></span> {% trans "Downloads" %}</a></li>
|
||||
{% ifbrowser ie<8 %}
|
||||
{% else %}
|
||||
<li><a href="{% url "uds.admin.views.index" %}"><span class="fa fa-dashboard"></span> Dashboard</a></li>
|
||||
{% endifbrowser %}
|
||||
{% endif %}
|
||||
<li><a href="{% url 'uds.web.views.logout' %}"><span class="fa fa-power-off text-danger"></span> {% trans 'Logout' %}</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
</ul>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
|
||||
</nav>
|
102
server/src/uds/templates/uds/pruebas/templates/base.html
Normal file
102
server/src/uds/templates/uds/pruebas/templates/base.html
Normal file
@ -0,0 +1,102 @@
|
||||
{% load l10n i18n static html5 compress %}{% spaceless %}
|
||||
{% get_current_language as LANGUAGE_CODE %}
|
||||
{% get_available_languages as LANGUAGES %}
|
||||
<!DOCTYPE html>{% endspaceless %}
|
||||
<html lang='{{LANGUAGE_CODE}}'>
|
||||
<head>
|
||||
<title>{% block title %}{% endblock %}</title>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="robots" content="noindex, nofollow" />
|
||||
{% block meta %}{% endblock %}
|
||||
|
||||
{% block icon %}<link href="{% get_static_prefix %}img/favicon.png" rel="icon" type="image/x-icon" />{% endblock %}
|
||||
|
||||
<!-- Bootstrap -->
|
||||
{% compress css %}
|
||||
<link href="{% get_static_prefix %}css/bootstrap.min.css" rel="stylesheet" media="screen">
|
||||
<link href="{% get_static_prefix %}css/font-awesome.min.css" rel="stylesheet" media="screen">
|
||||
{% endcompress %}
|
||||
|
||||
{% ifbrowser ie<9 %}
|
||||
<script src="{% get_static_prefix %}/js/respond.min.js"></script>
|
||||
{% endifbrowser %}
|
||||
|
||||
{% compress css %}
|
||||
<link href="{% get_static_prefix %}css/bootstrap-theme.min.css" rel="stylesheet" media="screen">
|
||||
<link href="{% get_static_prefix %}css/bootstrap-formhelpers.min.css" rel="stylesheet" media="screen">
|
||||
<link href="{% get_static_prefix %}css/bootstrap-select.min.css" rel="stylesheet" media="screen">
|
||||
|
||||
{% ifbrowser ie<10 %}
|
||||
<link href="{% get_static_prefix %}css/fix.css" rel="stylesheet" media="screen">
|
||||
{% endifbrowser %}
|
||||
|
||||
<link href="{% get_static_prefix %}css/bootstrap-responsive.min.css" rel="stylesheet" media="screen">
|
||||
<link href="{% get_static_prefix %}css/bootstrap-switch.css" rel="stylesheet" media="screen">
|
||||
<link href="{% get_static_prefix %}css/uds-html5.css" rel="stylesheet" media="screen">
|
||||
|
||||
{% endcompress %}
|
||||
|
||||
{% compress css %}
|
||||
{% ifbrowser ie<9 %}
|
||||
<script src="{% get_static_prefix %}/js/html5shiv.js"></script>
|
||||
{% endifbrowser %}
|
||||
|
||||
{% block css %}{% endblock %}
|
||||
{% endcompress %}
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<!-- Navigation bar -->
|
||||
{% block menu %}{% include 'uds/html5/snippets/navbar.html' %}{% endblock %}
|
||||
<!-- End of menu -->
|
||||
<div class="st-sticky-wrap">
|
||||
<div class="container">
|
||||
{% ifbrowser ie<10 %}
|
||||
<div class="alert alert-dismissable alert-danger">
|
||||
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
|
||||
{% trans 'Your browser is supported only partially. Please, upgrade it to a modern html5 browser like Firefox, Chrome, Opera, ... (IE must be 10 or better)' %}
|
||||
</div>
|
||||
{% endifbrowser %}
|
||||
{% block messages %}
|
||||
{% if messages %}
|
||||
{% for message in messages %}
|
||||
<div class="alert alert-dismissable {{ message.tags }}">
|
||||
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
|
||||
{{ message }}
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
<!-- Content -->
|
||||
{% block body %}{% endblock %}
|
||||
<!-- End of content -->
|
||||
</div> <!-- End of container -->
|
||||
<div class="st-sticky-push"></div>
|
||||
</div>
|
||||
<footer>
|
||||
{% block footer %}
|
||||
<a href="http://www.udsenterprise.com">© 2012-2014 Virtual Cable S.L.U.</a>
|
||||
{% endblock %}
|
||||
</footer>
|
||||
|
||||
<script src="{% url 'uds.web.views.jsCatalog' LANGUAGE_CODE %}"></script>
|
||||
{% compress js %}
|
||||
<script src="{% get_static_prefix %}js/jquery-1.10.2.min.js"></script>
|
||||
<script src="{% get_static_prefix %}js/jquery.cookie.js"></script>
|
||||
<script src="{% get_static_prefix %}js/bootstrap.min.js"></script>
|
||||
<script src="{% get_static_prefix %}js/bootstrap-switch.min.js"></script>
|
||||
<script src="{% get_static_prefix %}js/bootstrap-select.min.js"></script>
|
||||
|
||||
<script>
|
||||
$(function(){
|
||||
$('.selectpicker').selectpicker();
|
||||
});
|
||||
</script>
|
||||
|
||||
{% block js %}{% endblock %}
|
||||
{% endcompress %}
|
||||
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in New Issue
Block a user