Revision 4e03ba30
b/snf-astakos-app/astakos/api/urls.py | ||
---|---|---|
35 | 35 |
|
36 | 36 |
urlpatterns = patterns( |
37 | 37 |
'astakos.api.quotas', |
38 |
url(r'^quotas/?$', 'quotas'), |
|
38 |
url(r'^quotas/?$', 'quotas', name="astakos-api-quotas"),
|
|
39 | 39 |
url(r'^service_quotas/?$', 'service_quotas'), |
40 | 40 |
url(r'^resources/?$', 'resources'), |
41 | 41 |
url(r'^commissions/?$', 'commissions'), |
b/snf-astakos-app/astakos/im/static/im/js/jquery.cookie.js | ||
---|---|---|
1 |
/*! |
|
2 |
* jQuery Cookie Plugin v1.3.1 |
|
3 |
* https://github.com/carhartl/jquery-cookie |
|
4 |
* |
|
5 |
* Copyright 2013 Klaus Hartl |
|
6 |
* Released under the MIT license |
|
7 |
*/ |
|
8 |
(function (factory) { |
|
9 |
if (typeof define === 'function' && define.amd) { |
|
10 |
// AMD. Register as anonymous module. |
|
11 |
define(['jquery'], factory); |
|
12 |
} else { |
|
13 |
// Browser globals. |
|
14 |
factory(jQuery); |
|
15 |
} |
|
16 |
}(function ($) { |
|
17 |
|
|
18 |
var pluses = /\+/g; |
|
19 |
|
|
20 |
function raw(s) { |
|
21 |
return s; |
|
22 |
} |
|
23 |
|
|
24 |
function decoded(s) { |
|
25 |
return decodeURIComponent(s.replace(pluses, ' ')); |
|
26 |
} |
|
27 |
|
|
28 |
function converted(s) { |
|
29 |
if (s.indexOf('"') === 0) { |
|
30 |
// This is a quoted cookie as according to RFC2068, unescape |
|
31 |
s = s.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, '\\'); |
|
32 |
} |
|
33 |
try { |
|
34 |
return config.json ? JSON.parse(s) : s; |
|
35 |
} catch(er) {} |
|
36 |
} |
|
37 |
|
|
38 |
var config = $.cookie = function (key, value, options) { |
|
39 |
|
|
40 |
// write |
|
41 |
if (value !== undefined) { |
|
42 |
options = $.extend({}, config.defaults, options); |
|
43 |
|
|
44 |
if (typeof options.expires === 'number') { |
|
45 |
var days = options.expires, t = options.expires = new Date(); |
|
46 |
t.setDate(t.getDate() + days); |
|
47 |
} |
|
48 |
|
|
49 |
value = config.json ? JSON.stringify(value) : String(value); |
|
50 |
|
|
51 |
return (document.cookie = [ |
|
52 |
config.raw ? key : encodeURIComponent(key), |
|
53 |
'=', |
|
54 |
config.raw ? value : encodeURIComponent(value), |
|
55 |
options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE |
|
56 |
options.path ? '; path=' + options.path : '', |
|
57 |
options.domain ? '; domain=' + options.domain : '', |
|
58 |
options.secure ? '; secure' : '' |
|
59 |
].join('')); |
|
60 |
} |
|
61 |
|
|
62 |
// read |
|
63 |
var decode = config.raw ? raw : decoded; |
|
64 |
var cookies = document.cookie.split('; '); |
|
65 |
var result = key ? undefined : {}; |
|
66 |
for (var i = 0, l = cookies.length; i < l; i++) { |
|
67 |
var parts = cookies[i].split('='); |
|
68 |
var name = decode(parts.shift()); |
|
69 |
var cookie = decode(parts.join('=')); |
|
70 |
|
|
71 |
if (key && key === name) { |
|
72 |
result = converted(cookie); |
|
73 |
break; |
|
74 |
} |
|
75 |
|
|
76 |
if (!key) { |
|
77 |
result[name] = converted(cookie); |
|
78 |
} |
|
79 |
} |
|
80 |
|
|
81 |
return result; |
|
82 |
}; |
|
83 |
|
|
84 |
config.defaults = {}; |
|
85 |
|
|
86 |
$.removeCookie = function (key, options) { |
|
87 |
if ($.cookie(key) !== undefined) { |
|
88 |
// Must not alter options, thus extending a fresh object... |
|
89 |
$.cookie(key, '', $.extend({}, options, { expires: -1 })); |
|
90 |
return true; |
|
91 |
} |
|
92 |
return false; |
|
93 |
}; |
|
94 |
|
|
95 |
})); |
b/snf-astakos-app/astakos/im/static/im/js/mustache.js | ||
---|---|---|
1 |
/*! |
|
2 |
* mustache.js - Logic-less {{mustache}} templates with JavaScript |
|
3 |
* http://github.com/janl/mustache.js |
|
4 |
*/ |
|
5 |
|
|
6 |
/*global define: false*/ |
|
7 |
|
|
8 |
(function (root, mustache) { |
|
9 |
if (typeof exports === "object" && exports) { |
|
10 |
module.exports = mustache; // CommonJS |
|
11 |
} else if (typeof define === "function" && define.amd) { |
|
12 |
define(mustache); // AMD |
|
13 |
} else { |
|
14 |
root.Mustache = mustache; // <script> |
|
15 |
} |
|
16 |
}(this, (function () { |
|
17 |
|
|
18 |
var whiteRe = /\s*/; |
|
19 |
var spaceRe = /\s+/; |
|
20 |
var nonSpaceRe = /\S/; |
|
21 |
var eqRe = /\s*=/; |
|
22 |
var curlyRe = /\s*\}/; |
|
23 |
var tagRe = /#|\^|\/|>|\{|&|=|!/; |
|
24 |
|
|
25 |
var _test = RegExp.prototype.test; |
|
26 |
var _toString = Object.prototype.toString; |
|
27 |
|
|
28 |
// Workaround for https://issues.apache.org/jira/browse/COUCHDB-577 |
|
29 |
// See https://github.com/janl/mustache.js/issues/189 |
|
30 |
function testRe(re, string) { |
|
31 |
return _test.call(re, string); |
|
32 |
} |
|
33 |
|
|
34 |
function isWhitespace(string) { |
|
35 |
return !testRe(nonSpaceRe, string); |
|
36 |
} |
|
37 |
|
|
38 |
var isArray = Array.isArray || function (obj) { |
|
39 |
return _toString.call(obj) === '[object Array]'; |
|
40 |
}; |
|
41 |
|
|
42 |
function escapeRe(string) { |
|
43 |
return string.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&"); |
|
44 |
} |
|
45 |
|
|
46 |
var entityMap = { |
|
47 |
"&": "&", |
|
48 |
"<": "<", |
|
49 |
">": ">", |
|
50 |
'"': '"', |
|
51 |
"'": ''', |
|
52 |
"/": '/' |
|
53 |
}; |
|
54 |
|
|
55 |
function escapeHtml(string) { |
|
56 |
return String(string).replace(/[&<>"'\/]/g, function (s) { |
|
57 |
return entityMap[s]; |
|
58 |
}); |
|
59 |
} |
|
60 |
|
|
61 |
function Scanner(string) { |
|
62 |
this.string = string; |
|
63 |
this.tail = string; |
|
64 |
this.pos = 0; |
|
65 |
} |
|
66 |
|
|
67 |
/** |
|
68 |
* Returns `true` if the tail is empty (end of string). |
|
69 |
*/ |
|
70 |
Scanner.prototype.eos = function () { |
|
71 |
return this.tail === ""; |
|
72 |
}; |
|
73 |
|
|
74 |
/** |
|
75 |
* Tries to match the given regular expression at the current position. |
|
76 |
* Returns the matched text if it can match, the empty string otherwise. |
|
77 |
*/ |
|
78 |
Scanner.prototype.scan = function (re) { |
|
79 |
var match = this.tail.match(re); |
|
80 |
|
|
81 |
if (match && match.index === 0) { |
|
82 |
this.tail = this.tail.substring(match[0].length); |
|
83 |
this.pos += match[0].length; |
|
84 |
return match[0]; |
|
85 |
} |
|
86 |
|
|
87 |
return ""; |
|
88 |
}; |
|
89 |
|
|
90 |
/** |
|
91 |
* Skips all text until the given regular expression can be matched. Returns |
|
92 |
* the skipped string, which is the entire tail if no match can be made. |
|
93 |
*/ |
|
94 |
Scanner.prototype.scanUntil = function (re) { |
|
95 |
var match, pos = this.tail.search(re); |
|
96 |
|
|
97 |
switch (pos) { |
|
98 |
case -1: |
|
99 |
match = this.tail; |
|
100 |
this.pos += this.tail.length; |
|
101 |
this.tail = ""; |
|
102 |
break; |
|
103 |
case 0: |
|
104 |
match = ""; |
|
105 |
break; |
|
106 |
default: |
|
107 |
match = this.tail.substring(0, pos); |
|
108 |
this.tail = this.tail.substring(pos); |
|
109 |
this.pos += pos; |
|
110 |
} |
|
111 |
|
|
112 |
return match; |
|
113 |
}; |
|
114 |
|
|
115 |
function Context(view, parent) { |
|
116 |
this.view = view || {}; |
|
117 |
this.parent = parent; |
|
118 |
this._cache = {}; |
|
119 |
} |
|
120 |
|
|
121 |
Context.make = function (view) { |
|
122 |
return (view instanceof Context) ? view : new Context(view); |
|
123 |
}; |
|
124 |
|
|
125 |
Context.prototype.push = function (view) { |
|
126 |
return new Context(view, this); |
|
127 |
}; |
|
128 |
|
|
129 |
Context.prototype.lookup = function (name) { |
|
130 |
var value = this._cache[name]; |
|
131 |
|
|
132 |
if (!value) { |
|
133 |
if (name == '.') { |
|
134 |
value = this.view; |
|
135 |
} else { |
|
136 |
var context = this; |
|
137 |
|
|
138 |
while (context) { |
|
139 |
if (name.indexOf('.') > 0) { |
|
140 |
value = context.view; |
|
141 |
var names = name.split('.'), i = 0; |
|
142 |
while (value && i < names.length) { |
|
143 |
value = value[names[i++]]; |
|
144 |
} |
|
145 |
} else { |
|
146 |
value = context.view[name]; |
|
147 |
} |
|
148 |
|
|
149 |
if (value != null) break; |
|
150 |
|
|
151 |
context = context.parent; |
|
152 |
} |
|
153 |
} |
|
154 |
|
|
155 |
this._cache[name] = value; |
|
156 |
} |
|
157 |
|
|
158 |
if (typeof value === 'function') value = value.call(this.view); |
|
159 |
|
|
160 |
return value; |
|
161 |
}; |
|
162 |
|
|
163 |
function Writer() { |
|
164 |
this.clearCache(); |
|
165 |
} |
|
166 |
|
|
167 |
Writer.prototype.clearCache = function () { |
|
168 |
this._cache = {}; |
|
169 |
this._partialCache = {}; |
|
170 |
}; |
|
171 |
|
|
172 |
Writer.prototype.compile = function (template, tags) { |
|
173 |
var fn = this._cache[template]; |
|
174 |
|
|
175 |
if (!fn) { |
|
176 |
var tokens = mustache.parse(template, tags); |
|
177 |
fn = this._cache[template] = this.compileTokens(tokens, template); |
|
178 |
} |
|
179 |
|
|
180 |
return fn; |
|
181 |
}; |
|
182 |
|
|
183 |
Writer.prototype.compilePartial = function (name, template, tags) { |
|
184 |
var fn = this.compile(template, tags); |
|
185 |
this._partialCache[name] = fn; |
|
186 |
return fn; |
|
187 |
}; |
|
188 |
|
|
189 |
Writer.prototype.getPartial = function (name) { |
|
190 |
if (!(name in this._partialCache) && this._loadPartial) { |
|
191 |
this.compilePartial(name, this._loadPartial(name)); |
|
192 |
} |
|
193 |
|
|
194 |
return this._partialCache[name]; |
|
195 |
}; |
|
196 |
|
|
197 |
Writer.prototype.compileTokens = function (tokens, template) { |
|
198 |
var self = this; |
|
199 |
return function (view, partials) { |
|
200 |
if (partials) { |
|
201 |
if (typeof partials === 'function') { |
|
202 |
self._loadPartial = partials; |
|
203 |
} else { |
|
204 |
for (var name in partials) { |
|
205 |
self.compilePartial(name, partials[name]); |
|
206 |
} |
|
207 |
} |
|
208 |
} |
|
209 |
|
|
210 |
return renderTokens(tokens, self, Context.make(view), template); |
|
211 |
}; |
|
212 |
}; |
|
213 |
|
|
214 |
Writer.prototype.render = function (template, view, partials) { |
|
215 |
return this.compile(template)(view, partials); |
|
216 |
}; |
|
217 |
|
|
218 |
/** |
|
219 |
* Low-level function that renders the given `tokens` using the given `writer` |
|
220 |
* and `context`. The `template` string is only needed for templates that use |
|
221 |
* higher-order sections to extract the portion of the original template that |
|
222 |
* was contained in that section. |
|
223 |
*/ |
|
224 |
function renderTokens(tokens, writer, context, template) { |
|
225 |
var buffer = ''; |
|
226 |
|
|
227 |
var token, tokenValue, value; |
|
228 |
for (var i = 0, len = tokens.length; i < len; ++i) { |
|
229 |
token = tokens[i]; |
|
230 |
tokenValue = token[1]; |
|
231 |
|
|
232 |
switch (token[0]) { |
|
233 |
case '#': |
|
234 |
value = context.lookup(tokenValue); |
|
235 |
|
|
236 |
if (typeof value === 'object') { |
|
237 |
if (isArray(value)) { |
|
238 |
for (var j = 0, jlen = value.length; j < jlen; ++j) { |
|
239 |
buffer += renderTokens(token[4], writer, context.push(value[j]), template); |
|
240 |
} |
|
241 |
} else if (value) { |
|
242 |
buffer += renderTokens(token[4], writer, context.push(value), template); |
|
243 |
} |
|
244 |
} else if (typeof value === 'function') { |
|
245 |
var text = template == null ? null : template.slice(token[3], token[5]); |
|
246 |
value = value.call(context.view, text, function (template) { |
|
247 |
return writer.render(template, context); |
|
248 |
}); |
|
249 |
if (value != null) buffer += value; |
|
250 |
} else if (value) { |
|
251 |
buffer += renderTokens(token[4], writer, context, template); |
|
252 |
} |
|
253 |
|
|
254 |
break; |
|
255 |
case '^': |
|
256 |
value = context.lookup(tokenValue); |
|
257 |
|
|
258 |
// Use JavaScript's definition of falsy. Include empty arrays. |
|
259 |
// See https://github.com/janl/mustache.js/issues/186 |
|
260 |
if (!value || (isArray(value) && value.length === 0)) { |
|
261 |
buffer += renderTokens(token[4], writer, context, template); |
|
262 |
} |
|
263 |
|
|
264 |
break; |
|
265 |
case '>': |
|
266 |
value = writer.getPartial(tokenValue); |
|
267 |
if (typeof value === 'function') buffer += value(context); |
|
268 |
break; |
|
269 |
case '&': |
|
270 |
value = context.lookup(tokenValue); |
|
271 |
if (value != null) buffer += value; |
|
272 |
break; |
|
273 |
case 'name': |
|
274 |
value = context.lookup(tokenValue); |
|
275 |
if (value != null) buffer += mustache.escape(value); |
|
276 |
break; |
|
277 |
case 'text': |
|
278 |
buffer += tokenValue; |
|
279 |
break; |
|
280 |
} |
|
281 |
} |
|
282 |
|
|
283 |
return buffer; |
|
284 |
} |
|
285 |
|
|
286 |
/** |
|
287 |
* Forms the given array of `tokens` into a nested tree structure where |
|
288 |
* tokens that represent a section have two additional items: 1) an array of |
|
289 |
* all tokens that appear in that section and 2) the index in the original |
|
290 |
* template that represents the end of that section. |
|
291 |
*/ |
|
292 |
function nestTokens(tokens) { |
|
293 |
var tree = []; |
|
294 |
var collector = tree; |
|
295 |
var sections = []; |
|
296 |
|
|
297 |
var token; |
|
298 |
for (var i = 0, len = tokens.length; i < len; ++i) { |
|
299 |
token = tokens[i]; |
|
300 |
switch (token[0]) { |
|
301 |
case '#': |
|
302 |
case '^': |
|
303 |
sections.push(token); |
|
304 |
collector.push(token); |
|
305 |
collector = token[4] = []; |
|
306 |
break; |
|
307 |
case '/': |
|
308 |
var section = sections.pop(); |
|
309 |
section[5] = token[2]; |
|
310 |
collector = sections.length > 0 ? sections[sections.length - 1][4] : tree; |
|
311 |
break; |
|
312 |
default: |
|
313 |
collector.push(token); |
|
314 |
} |
|
315 |
} |
|
316 |
|
|
317 |
return tree; |
|
318 |
} |
|
319 |
|
|
320 |
/** |
|
321 |
* Combines the values of consecutive text tokens in the given `tokens` array |
|
322 |
* to a single token. |
|
323 |
*/ |
|
324 |
function squashTokens(tokens) { |
|
325 |
var squashedTokens = []; |
|
326 |
|
|
327 |
var token, lastToken; |
|
328 |
for (var i = 0, len = tokens.length; i < len; ++i) { |
|
329 |
token = tokens[i]; |
|
330 |
if (token) { |
|
331 |
if (token[0] === 'text' && lastToken && lastToken[0] === 'text') { |
|
332 |
lastToken[1] += token[1]; |
|
333 |
lastToken[3] = token[3]; |
|
334 |
} else { |
|
335 |
lastToken = token; |
|
336 |
squashedTokens.push(token); |
|
337 |
} |
|
338 |
} |
|
339 |
} |
|
340 |
|
|
341 |
return squashedTokens; |
|
342 |
} |
|
343 |
|
|
344 |
function escapeTags(tags) { |
|
345 |
return [ |
|
346 |
new RegExp(escapeRe(tags[0]) + "\\s*"), |
|
347 |
new RegExp("\\s*" + escapeRe(tags[1])) |
|
348 |
]; |
|
349 |
} |
|
350 |
|
|
351 |
/** |
|
352 |
* Breaks up the given `template` string into a tree of token objects. If |
|
353 |
* `tags` is given here it must be an array with two string values: the |
|
354 |
* opening and closing tags used in the template (e.g. ["<%", "%>"]). Of |
|
355 |
* course, the default is to use mustaches (i.e. Mustache.tags). |
|
356 |
*/ |
|
357 |
function parseTemplate(template, tags) { |
|
358 |
template = template || ''; |
|
359 |
tags = tags || mustache.tags; |
|
360 |
|
|
361 |
if (typeof tags === 'string') tags = tags.split(spaceRe); |
|
362 |
if (tags.length !== 2) throw new Error('Invalid tags: ' + tags.join(', ')); |
|
363 |
|
|
364 |
var tagRes = escapeTags(tags); |
|
365 |
var scanner = new Scanner(template); |
|
366 |
|
|
367 |
var sections = []; // Stack to hold section tokens |
|
368 |
var tokens = []; // Buffer to hold the tokens |
|
369 |
var spaces = []; // Indices of whitespace tokens on the current line |
|
370 |
var hasTag = false; // Is there a {{tag}} on the current line? |
|
371 |
var nonSpace = false; // Is there a non-space char on the current line? |
|
372 |
|
|
373 |
// Strips all whitespace tokens array for the current line |
|
374 |
// if there was a {{#tag}} on it and otherwise only space. |
|
375 |
function stripSpace() { |
|
376 |
if (hasTag && !nonSpace) { |
|
377 |
while (spaces.length) { |
|
378 |
delete tokens[spaces.pop()]; |
|
379 |
} |
|
380 |
} else { |
|
381 |
spaces = []; |
|
382 |
} |
|
383 |
|
|
384 |
hasTag = false; |
|
385 |
nonSpace = false; |
|
386 |
} |
|
387 |
|
|
388 |
var start, type, value, chr, token; |
|
389 |
while (!scanner.eos()) { |
|
390 |
start = scanner.pos; |
|
391 |
|
|
392 |
// Match any text between tags. |
|
393 |
value = scanner.scanUntil(tagRes[0]); |
|
394 |
if (value) { |
|
395 |
for (var i = 0, len = value.length; i < len; ++i) { |
|
396 |
chr = value.charAt(i); |
|
397 |
|
|
398 |
if (isWhitespace(chr)) { |
|
399 |
spaces.push(tokens.length); |
|
400 |
} else { |
|
401 |
nonSpace = true; |
|
402 |
} |
|
403 |
|
|
404 |
tokens.push(['text', chr, start, start + 1]); |
|
405 |
start += 1; |
|
406 |
|
|
407 |
// Check for whitespace on the current line. |
|
408 |
if (chr == '\n') stripSpace(); |
|
409 |
} |
|
410 |
} |
|
411 |
|
|
412 |
// Match the opening tag. |
|
413 |
if (!scanner.scan(tagRes[0])) break; |
|
414 |
hasTag = true; |
|
415 |
|
|
416 |
// Get the tag type. |
|
417 |
type = scanner.scan(tagRe) || 'name'; |
|
418 |
scanner.scan(whiteRe); |
|
419 |
|
|
420 |
// Get the tag value. |
|
421 |
if (type === '=') { |
|
422 |
value = scanner.scanUntil(eqRe); |
|
423 |
scanner.scan(eqRe); |
|
424 |
scanner.scanUntil(tagRes[1]); |
|
425 |
} else if (type === '{') { |
|
426 |
value = scanner.scanUntil(new RegExp('\\s*' + escapeRe('}' + tags[1]))); |
|
427 |
scanner.scan(curlyRe); |
|
428 |
scanner.scanUntil(tagRes[1]); |
|
429 |
type = '&'; |
|
430 |
} else { |
|
431 |
value = scanner.scanUntil(tagRes[1]); |
|
432 |
} |
|
433 |
|
|
434 |
// Match the closing tag. |
|
435 |
if (!scanner.scan(tagRes[1])) throw new Error('Unclosed tag at ' + scanner.pos); |
|
436 |
|
|
437 |
token = [type, value, start, scanner.pos]; |
|
438 |
tokens.push(token); |
|
439 |
|
|
440 |
if (type === '#' || type === '^') { |
|
441 |
sections.push(token); |
|
442 |
} else if (type === '/') { |
|
443 |
// Check section nesting. |
|
444 |
if (sections.length === 0) throw new Error('Unopened section "' + value + '" at ' + start); |
|
445 |
var openSection = sections.pop(); |
|
446 |
if (openSection[1] !== value) throw new Error('Unclosed section "' + openSection[1] + '" at ' + start); |
|
447 |
} else if (type === 'name' || type === '{' || type === '&') { |
|
448 |
nonSpace = true; |
|
449 |
} else if (type === '=') { |
|
450 |
// Set the tags for the next time around. |
|
451 |
tags = value.split(spaceRe); |
|
452 |
if (tags.length !== 2) throw new Error('Invalid tags at ' + start + ': ' + tags.join(', ')); |
|
453 |
tagRes = escapeTags(tags); |
|
454 |
} |
|
455 |
} |
|
456 |
|
|
457 |
// Make sure there are no open sections when we're done. |
|
458 |
var openSection = sections.pop(); |
|
459 |
if (openSection) throw new Error('Unclosed section "' + openSection[1] + '" at ' + scanner.pos); |
|
460 |
|
|
461 |
tokens = squashTokens(tokens); |
|
462 |
|
|
463 |
return nestTokens(tokens); |
|
464 |
} |
|
465 |
|
|
466 |
var mustache = {}; |
|
467 |
|
|
468 |
mustache.name = "mustache.js"; |
|
469 |
mustache.version = "0.7.2"; |
|
470 |
mustache.tags = ["{{", "}}"]; |
|
471 |
|
|
472 |
mustache.Scanner = Scanner; |
|
473 |
mustache.Context = Context; |
|
474 |
mustache.Writer = Writer; |
|
475 |
|
|
476 |
mustache.parse = parseTemplate; |
|
477 |
|
|
478 |
// Export the escaping function so that the user may override it. |
|
479 |
// See https://github.com/janl/mustache.js/issues/244 |
|
480 |
mustache.escape = escapeHtml; |
|
481 |
|
|
482 |
// All Mustache.* functions use this writer. |
|
483 |
var _writer = new Writer(); |
|
484 |
|
|
485 |
/** |
|
486 |
* Clears all cached templates and partials in the default writer. |
|
487 |
*/ |
|
488 |
mustache.clearCache = function () { |
|
489 |
return _writer.clearCache(); |
|
490 |
}; |
|
491 |
|
|
492 |
/** |
|
493 |
* Compiles the given `template` to a reusable function using the default |
|
494 |
* writer. |
|
495 |
*/ |
|
496 |
mustache.compile = function (template, tags) { |
|
497 |
return _writer.compile(template, tags); |
|
498 |
}; |
|
499 |
|
|
500 |
/** |
|
501 |
* Compiles the partial with the given `name` and `template` to a reusable |
|
502 |
* function using the default writer. |
|
503 |
*/ |
|
504 |
mustache.compilePartial = function (name, template, tags) { |
|
505 |
return _writer.compilePartial(name, template, tags); |
|
506 |
}; |
|
507 |
|
|
508 |
/** |
|
509 |
* Compiles the given array of tokens (the output of a parse) to a reusable |
|
510 |
* function using the default writer. |
|
511 |
*/ |
|
512 |
mustache.compileTokens = function (tokens, template) { |
|
513 |
return _writer.compileTokens(tokens, template); |
|
514 |
}; |
|
515 |
|
|
516 |
/** |
|
517 |
* Renders the `template` with the given `view` and `partials` using the |
|
518 |
* default writer. |
|
519 |
*/ |
|
520 |
mustache.render = function (template, view, partials) { |
|
521 |
return _writer.render(template, view, partials); |
|
522 |
}; |
|
523 |
|
|
524 |
// This is here for backwards compatibility with 0.4.x. |
|
525 |
mustache.to_html = function (template, view, partials, send) { |
|
526 |
var result = mustache.render(template, view, partials); |
|
527 |
|
|
528 |
if (typeof send === "function") { |
|
529 |
send(result); |
|
530 |
} else { |
|
531 |
return result; |
|
532 |
} |
|
533 |
}; |
|
534 |
|
|
535 |
return mustache; |
|
536 |
|
|
537 |
}()))); |
b/snf-astakos-app/astakos/im/static/im/js/usage.js | ||
---|---|---|
39 | 39 |
return sign + (j ? intPart.substr(0, j) + thousandsSep : '') + intPart.substr(j).replace(/(\d{3})(?=\d)/g, '$1' + thousandsSep) + (decimals ? decPoint + Math.abs(number - intPart).toFixed(decimals).slice(2) : ''); |
40 | 40 |
}; |
41 | 41 |
|
42 |
function UsageClient(settings) { |
|
42 |
|
|
43 |
DO_LOG = false |
|
44 |
|
|
45 |
LOG = DO_LOG ? _.bind(console.log, console) : function() {}; |
|
46 |
WARN = DO_LOG ? _.bind(console.warn, console) : function() {}; |
|
47 |
|
|
48 |
var default_usage_cls_map = { |
|
49 |
0: 'green', |
|
50 |
33: 'yellow', |
|
51 |
66: 'red' |
|
52 |
} |
|
53 |
|
|
54 |
function UsageView(settings) { |
|
43 | 55 |
this.settings = settings; |
44 | 56 |
this.url = this.settings.url; |
45 | 57 |
this.container = $(this.settings.container); |
58 |
this.meta = this.settings.meta; |
|
59 |
this.groups = this.settings.groups; |
|
60 |
this.el = {}; |
|
61 |
this.usage_cls_map = this.settings.usage_cls_map || default_usage_cls_map; |
|
62 |
this.initialize(); |
|
46 | 63 |
} |
47 | 64 |
|
48 |
UsageClient.prototype.load = function() { |
|
49 |
var self = this; |
|
50 |
$.ajax(this.url, { |
|
51 |
'success': function(data) { |
|
52 |
self.update(data); |
|
53 |
} |
|
54 |
}) |
|
55 |
} |
|
56 | 65 |
|
57 |
function setText(el, valueFrom, valueTo, direction, modifier) { |
|
58 |
//valueTo = parseInt(valueTo); |
|
59 |
//text = valueFrom; |
|
66 |
_.extend(UsageView.prototype, { |
|
67 |
tpls: { |
|
68 |
'main': '<div class="stats clearfix"><ul></ul></div>', |
|
69 |
'quotas': "#quotaTpl" |
|
70 |
}, |
|
60 | 71 |
|
61 |
//if (valueFrom >= valueTo) { |
|
62 |
//valueFrom = valueTo; |
|
63 |
//} |
|
64 |
|
|
65 |
var text = valueTo; |
|
66 |
if (modifier) { |
|
67 |
text = modifier(text); |
|
68 |
} |
|
69 |
el.html(text); |
|
72 |
initialize: function() { |
|
73 |
LOG("Initializing UsageView", this.settings); |
|
74 |
this.initResources(); |
|
70 | 75 |
|
71 |
//if (valueTo > valueFrom) { |
|
72 |
//window.setTimeout(function() { |
|
73 |
//setText(el, parseInt(valueFrom) + step, parseInt(valueTo)); |
|
74 |
//}, 10) |
|
75 |
//} |
|
76 |
} |
|
76 |
// initial usage set ???? |
|
77 |
this.quotas = {}; |
|
78 |
if (this.settings.quotas && _.keys(this.settings.quotas).length > 0) { |
|
79 |
this.setQuotas(this.settings.quotas); |
|
80 |
} |
|
81 |
this.initLayout(); |
|
82 |
this.updateQuotas(); |
|
83 |
}, |
|
84 |
|
|
85 |
$: function(selector) { |
|
86 |
return this.container; |
|
87 |
}, |
|
88 |
|
|
89 |
render: function(tpl, params) { |
|
90 |
LOG("Rendering", tpl, params); |
|
91 |
var tpl = this.tpls[tpl]; |
|
92 |
if (/^[#\.]/.exec(tpl)) { |
|
93 |
tpl = $(tpl).html(); |
|
94 |
} |
|
95 |
var rendered = Mustache.render(tpl, params); |
|
96 |
return $(rendered); |
|
97 |
}, |
|
98 |
|
|
99 |
initLayout: function() { |
|
100 |
LOG("Initializing layout"); |
|
101 |
this.el.main = this.render('main'); |
|
102 |
this.container.append(this.el.main); |
|
103 |
var ul = this.container.find("ul"); |
|
104 |
this.el.list = this.render('quotas', { |
|
105 |
'resources':this.resources_ordered |
|
106 |
}); |
|
107 |
ul.append(this.el.list); |
|
108 |
}, |
|
109 |
|
|
110 |
initResources: function() { |
|
111 |
var ordered = this.meta.resources_order; |
|
112 |
var resources = {}; |
|
113 |
var resources_ordered = []; |
|
114 |
|
|
115 |
_.each(this.meta.resources, function(group, index) { |
|
116 |
_.each(group[1], function(resource, rindex) { |
|
117 |
var resource_index = ordered.length; |
|
118 |
if (!_.contains(ordered, resource.name)) { |
|
119 |
ordered.push(resource.name); |
|
120 |
} else { |
|
121 |
resource_index = ordered.indexOf(resource.name); |
|
122 |
} |
|
123 |
resource.index = resource_index; |
|
124 |
resource.resource_name = resource.name.split(".")[1]; |
|
125 |
resources[resource.name] = resource; |
|
126 |
}) |
|
127 |
}); |
|
128 |
|
|
129 |
resources_ordered = _.map(ordered, function(rk) { return resources[rk] }); |
|
130 |
this.resources = resources; |
|
131 |
this.resources_ordered = resources_ordered; |
|
132 |
|
|
133 |
LOG("Resources initialized", this.resources_ordered, this.resources); |
|
134 |
}, |
|
135 |
|
|
136 |
updateLayout: function() { |
|
137 |
LOG("Updating layout", this.quotas); |
|
138 |
var self = this; |
|
139 |
_.each(this.quotas, function(value, key) { |
|
140 |
var usage = self.getUsage(key); |
|
141 |
var el = self.$().find("li[data-resource='"+key+"']"); |
|
142 |
self.updateResourceElement(el, usage); |
|
143 |
}) |
|
144 |
}, |
|
145 |
|
|
146 |
updateResourceElement: function(el, usage) { |
|
147 |
el.find(".currValue").text(usage.curr); |
|
148 |
el.find(".maxValue").text(usage.max); |
|
149 |
el.find(".bar span").css({width:usage.perc+"%"}); |
|
150 |
el.find(".bar .value").text(usage.perc+"%"); |
|
151 |
var left = usage.label_left == 'auto' ? |
|
152 |
usage.label_left : usage.label_left + "%"; |
|
153 |
el.find(".bar .value").css({left:left}); |
|
154 |
el.find(".bar .value").css({color:usage.label_color}); |
|
155 |
el.removeClass("green yellow red"); |
|
156 |
el.addClass(usage.cls); |
|
157 |
}, |
|
158 |
|
|
159 |
getUsage: function(resource_name) { |
|
160 |
var resource = this.quotas[resource_name]; |
|
161 |
var resource_meta = this.resources[resource_name]; |
|
162 |
var value, limit, percentage; |
|
163 |
|
|
164 |
limit = resource.limit; |
|
165 |
value = resource.limit - resource.available; |
|
166 |
if (value < 0 ) { value = 0 } |
|
167 |
|
|
168 |
percentage = (value/limit) * 100; |
|
169 |
if (value == 0) { percentage = 0 } |
|
170 |
if (resource.available <= 0) { |
|
171 |
percentage = 100; |
|
172 |
} |
|
77 | 173 |
|
78 |
UsageClient.prototype.updateEntry = function(key, data) { |
|
174 |
if (resource_meta.unit == 'bytes') { |
|
175 |
value = humanize.filesize(value); |
|
176 |
limit = humanize.filesize(limit); |
|
177 |
} |
|
79 | 178 |
|
80 |
var entry = $('li[data-resourcekey=\''+key+'\']'); |
|
81 |
var currentEl = entry.find("span.currValue"); |
|
82 |
var maxEl = entry.find("span.maxValue"); |
|
83 |
var ratioEl = entry.find("div.bar"); |
|
84 |
var barEl = entry.find("div.bar span"); |
|
85 |
var percentageEl = ratioEl.find("em"); |
|
86 |
var units = entry.data("units"); |
|
87 |
var infoEl = entry.find(".info"); |
|
179 |
var cls = 'green'; |
|
180 |
_.each(this.usage_cls_map, function(ucls, u){ |
|
181 |
if (percentage >= u) { |
|
182 |
cls = ucls |
|
183 |
} |
|
184 |
}) |
|
88 | 185 |
|
89 |
var current = data.currValue; |
|
90 |
var max = data.maxValue; |
|
186 |
var label_left = percentage >= 30 ? percentage - 17 : 'auto'; |
|
187 |
var label_col = label_left == 'auto' ? 'inherit' : '#fff'; |
|
188 |
percentage = humanize.numberFormat(percentage, 0); |
|
189 |
qdata = {'curr': value, 'max': limit, 'perc': percentage, 'cls': cls, |
|
190 |
'label_left': label_left, 'label_color': label_col} |
|
191 |
_.extend(qdata, resource); |
|
192 |
console.log(resource_name, value, resource); |
|
193 |
return qdata |
|
194 |
}, |
|
195 |
|
|
196 |
setQuotas: function(data) { |
|
197 |
LOG("Set quotas", data); |
|
198 |
var self = this; |
|
199 |
this.quotas = data; |
|
200 |
_.each(this.quotas, function(v, k) { |
|
201 |
var r = self.resources[k]; |
|
202 |
var usage = self.getUsage(k); |
|
203 |
r.usage = usage; |
|
204 |
self.resources[k].usage = usage; |
|
205 |
self.resources_ordered[r.index].usage = usage; |
|
206 |
}); |
|
207 |
}, |
|
208 |
|
|
209 |
_ajaxOptions: function() { |
|
210 |
var token = $.cookie(this.settings.cookie_name).split("|")[1]; |
|
211 |
return { |
|
212 |
'url': this.url, |
|
213 |
'headers': { |
|
214 |
'X-Auth-Token': token |
|
215 |
}, |
|
216 |
} |
|
217 |
}, |
|
91 | 218 |
|
92 |
modifier = function(v) { return v; } |
|
93 |
if (units == 'bytes') { |
|
94 |
modifier = humanize.filesize; |
|
219 |
updateQuotas: function() { |
|
220 |
LOG("Updating quotas"); |
|
221 |
var self = this; |
|
222 |
this.getQuotas(function(data){ |
|
223 |
self.setQuotas(data.system); |
|
224 |
self.updateLayout(); |
|
225 |
}) |
|
226 |
}, |
|
227 |
|
|
228 |
getQuotas: function(callback) { |
|
229 |
var options = this._ajaxOptions(); |
|
230 |
options.success = callback; |
|
231 |
LOG("Calling quotas API", options); |
|
232 |
$.ajax(options); |
|
95 | 233 |
} |
96 |
|
|
97 |
setText(maxEl, infoEl.data('maxvalue'), max, infoEl.data('maxvalue') > max, |
|
98 |
modifier); |
|
99 |
setText(currentEl, infoEl.data('currvalue'), current, |
|
100 |
infoEl.data('currvalue') > current, modifier); |
|
101 | 234 |
|
102 |
var percentage = humanize.numberFormat(data.ratio, 1); |
|
103 |
setText(percentageEl, percentageEl.data('value'), |
|
104 |
percentage, percentageEl.data('value') > percentage, |
|
105 |
function(v) { return v + '% '}); |
|
106 |
|
|
107 |
var width = data.ratio; |
|
108 |
if (width > 100) { width = 100; } |
|
109 |
if (width < 0) { width = 0; } |
|
110 |
|
|
111 |
width = humanize.numberFormat(width, 1); |
|
112 |
barEl.css({'width': width + '%'}); |
|
113 |
width = width*342/100; |
|
114 |
|
|
115 |
if (percentage > 22) { |
|
116 |
percentageEl.addClass("hovered"); |
|
117 |
var left = width-percentageEl.width() -10; |
|
118 |
percentageEl.css({'left': left+"px", 'color':'#fff'}); |
|
119 |
} else { |
|
120 |
percentageEl.removeClass("hovered"); |
|
121 |
percentageEl.css({'left': width+"px", 'color':'#222'}); |
|
122 |
} |
|
123 |
percentageEl.data('value', percentage); |
|
124 |
|
|
125 |
entry.removeClass("red green yellow"); |
|
126 |
entry.addClass(data.load_class); |
|
127 |
|
|
128 |
entry.find(".info").data("currvalue", data.currValue); |
|
129 |
entry.find(".info").data("maxvalue", data.maxValue); |
|
130 |
} |
|
131 |
|
|
132 |
UsageClient.prototype.update = function(data) { |
|
133 |
var usage = {}, self = this; |
|
134 |
_.each(data, function(e) { usage[e.name] = e}); |
|
135 |
|
|
136 |
_.each(usage, function(data, key) { |
|
137 |
self.updateEntry(key, data); |
|
138 |
}); |
|
139 |
} |
|
235 |
}); |
|
140 | 236 |
|
141 |
window.UsageClient = UsageClient;
|
|
237 |
window.UsageView = UsageView;
|
|
142 | 238 |
})(); |
b/snf-astakos-app/astakos/im/templates/im/base.html | ||
---|---|---|
52 | 52 |
<script src="{{ IM_STATIC_URL }}js/jquery.dropkick-1.0.0.js"></script> |
53 | 53 |
<script src="{{ IM_STATIC_URL }}js/jquery-ui-1.8.21.custom.min.js"></script> |
54 | 54 |
<script src="{{ IM_STATIC_URL }}js/jquery.tablesorter.js"></script> |
55 |
<script src="{{ IM_STATIC_URL }}js/jquery.cookie.js"></script> |
|
56 |
<script src="{{ IM_STATIC_URL }}js/mustache.js"></script> |
|
55 | 57 |
<script src="{{ IM_STATIC_URL }}js/common.js"></script> |
56 | 58 |
{% endblock headjs %} |
57 | 59 |
{% block endhead %}{% endblock endhead %} |
b/snf-astakos-app/astakos/im/templates/im/resource_usage.html | ||
---|---|---|
1 | 1 |
{% extends "im/account_base.html" %} |
2 | 2 |
|
3 |
{% load filters %} |
|
3 |
{% load filters astakos_tags %}
|
|
4 | 4 |
|
5 | 5 |
{% block headjs %} |
6 | 6 |
{{ block.super }} |
... | ... | |
8 | 8 |
{% endblock %} |
9 | 9 |
|
10 | 10 |
{% block page.body %} |
11 |
<div class="maincol {% block innerpage.class %}{% endblock %}"> |
|
12 | 11 |
|
13 |
<h2>RESOURCE USAGE</h2> |
|
14 |
<div class="stats clearfix"> |
|
15 |
<ul> |
|
16 |
{% for rdata in resource_usage %} |
|
17 |
<li class="clearfix {{ rdata.load_class }} {{ rdata.name|get_value_after_dot }}" |
|
18 |
data-resourcekey="{{ rdata.name }}" data-units="{{ rdata.unit }}"> |
|
19 |
<div class="img-wrap"> </div> |
|
20 |
<div class="info" data-currvalue="{{ rdata.currValue }}" |
|
21 |
data-maxvalue="{{ rdata.maxValue }}"> |
|
22 |
<h3>{{ rdata.report_desc }}</h3> |
|
23 |
<p> |
|
24 |
{% if rdata.unit == 'bytes' %} |
|
25 |
<span class="currValue"> |
|
26 |
{{ rdata.currValue }} |
|
27 |
</span> out of |
|
28 |
<span class="maxValue"> |
|
29 |
{{ rdata.maxValue }} |
|
30 |
</span> |
|
31 |
{% else %} |
|
32 |
<span class="currValue"> |
|
33 |
<span class="value">{{ rdata.currValue }}</span> |
|
34 |
</span> |
|
35 |
out of |
|
36 |
<span class="maxValue"> |
|
37 |
<span class="value">{{ rdata.maxValue }}</span> |
|
38 |
<span class="unit">{{ rdata.unit }}</span> |
|
39 |
</span> |
|
40 |
{% endif %} |
|
41 |
{{rdata.pluralized_display_name}} |
|
42 |
</p> |
|
43 |
</div> |
|
44 |
<div class="bar" data-steps=""> |
|
45 |
<div> |
|
46 |
|
|
47 |
<span style="width:{{ rdata.ratio_limited|floatformat }}%;" {% if rdata.ratio > 22 %}class="hovered"{% endif %}> |
|
48 |
|
|
49 |
</span> |
|
50 |
<em data-value="{{ rdata.ratio }}" class="value">{{ rdata.ratio|floatformat }}% </em> |
|
51 |
</div> |
|
52 |
</div> |
|
53 |
</li> |
|
54 |
{% endfor%} |
|
55 |
</ul> |
|
56 |
|
|
57 |
</div> |
|
12 |
<script id="quotaTpl" type="text/template"> |
|
13 |
{% verbatim %} |
|
14 |
{{#resources}} |
|
15 |
<li class="clearfix {{ resource_name }} {{ usage.cls }}" |
|
16 |
data-resource="{{ name }}"> |
|
17 |
<div class="img-wrap"> </div> |
|
18 |
<div class="info" data-currvalue="" data-maxvalue=""> |
|
19 |
<h3>{{ report_desc }}</h3> |
|
20 |
<p> |
|
21 |
<span class="currValue">{{ usage.curr }}</span> out of |
|
22 |
<span class="maxValue">{{ usage.max }}</span> {{ report_desc }} |
|
23 |
</p> |
|
24 |
</div> |
|
25 |
<div class="bar"> |
|
26 |
<div> |
|
27 |
<span style="width:{{ usage.perc }}%"></span> |
|
28 |
<em |
|
29 |
class="value" |
|
30 |
style="left: {{ usage.label_left }}%; color: {{ usage.label_color }}"> |
|
31 |
{{ usage.perc }} % |
|
32 |
</em> |
|
33 |
</div> |
|
34 |
</div> |
|
35 |
</li> |
|
36 |
{{/resources}} |
|
37 |
{% endverbatim %} |
|
38 |
</script> |
|
39 |
|
|
40 |
<div class="maincol {% block innerpage.class %}{% endblock %}"> |
|
41 |
<h2>RESOURCE USAGE</h2> |
|
42 |
<div id="quota-container"> |
|
43 |
</div> |
|
58 | 44 |
</div> |
59 | 45 |
<script> |
60 |
$(document).ready(function(){ |
|
61 |
var usageClient = new UsageClient({ |
|
62 |
'url': '{% url resource_usage %}?json=1', |
|
63 |
'dataType': 'json', |
|
64 |
'container': 'div.stats' |
|
65 |
}); |
|
66 |
|
|
67 |
window.setInterval(function() { |
|
68 |
usageClient.load(); |
|
69 |
}, {{ usage_update_interval }}); |
|
70 |
usageClient.load(); |
|
71 |
}) |
|
46 |
$(document).ready(function(){ |
|
47 |
var usageView = new UsageView({ |
|
48 |
'url': '{% url astakos-api-quotas %}', |
|
49 |
'cookie_name': '{{ token_cookie_name|safe }}', |
|
50 |
'dataType': 'json', |
|
51 |
'container': '#quota-container', |
|
52 |
'quotas': {{ current_usage|safe }}, |
|
53 |
'meta': { |
|
54 |
'resources': {{ resource_catalog|safe }}, |
|
55 |
'groups': {{ resource_groups|safe }}, |
|
56 |
'resources_order': {{ resources_order|safe }} |
|
57 |
} |
|
58 |
}); |
|
59 |
window.usageView = usageView; |
|
60 |
|
|
61 |
window.setInterval(function(){ |
|
62 |
window.usageView.updateQuotas(); |
|
63 |
}, {{ usage_update_interval }}); |
|
72 | 64 |
|
65 |
}) |
|
73 | 66 |
</script> |
74 | 67 |
{% endblock %} |
b/snf-astakos-app/astakos/im/templatetags/astakos_tags.py | ||
---|---|---|
268 | 268 |
|
269 | 269 |
content = render_to_string(template, tpl_context) |
270 | 270 |
return content |
271 |
|
|
272 |
|
|
273 |
class VerbatimNode(template.Node): |
|
274 |
|
|
275 |
def __init__(self, text): |
|
276 |
self.text = text |
|
277 |
|
|
278 |
def render(self, context): |
|
279 |
return self.text |
|
280 |
|
|
281 |
|
|
282 |
@register.tag |
|
283 |
def verbatim(parser, token): |
|
284 |
text = [] |
|
285 |
while 1: |
|
286 |
token = parser.tokens.pop(0) |
|
287 |
if token.contents == 'endverbatim': |
|
288 |
break |
|
289 |
if token.token_type == template.TOKEN_VAR: |
|
290 |
text.append('{{') |
|
291 |
elif token.token_type == template.TOKEN_BLOCK: |
|
292 |
text.append('{%') |
|
293 |
text.append(token.contents) |
|
294 |
if token.token_type == template.TOKEN_VAR: |
|
295 |
text.append('}}') |
|
296 |
elif token.token_type == template.TOKEN_BLOCK: |
|
297 |
text.append('%}') |
|
298 |
return VerbatimNode(''.join(text)) |
b/snf-astakos-app/astakos/im/views.py | ||
---|---|---|
116 | 116 |
from astakos.im import auth_providers as auth |
117 | 117 |
from snf_django.lib.db.transaction import commit_on_success_strict |
118 | 118 |
from astakos.im.ctx import ExceptionHandler |
119 |
from astakos.im import quotas |
|
119 | 120 |
|
120 | 121 |
logger = logging.getLogger(__name__) |
121 | 122 |
|
... | ... | |
862 | 863 |
@valid_astakos_user_required |
863 | 864 |
def resource_usage(request): |
864 | 865 |
|
865 |
def with_class(entry): |
|
866 |
entry['load_class'] = 'red' |
|
867 |
max_value = float(entry['maxValue']) |
|
868 |
curr_value = float(entry['currValue']) |
|
869 |
entry['ratio_limited']= 0 |
|
870 |
if max_value > 0 : |
|
871 |
entry['ratio'] = (curr_value / max_value) * 100 |
|
872 |
else: |
|
873 |
entry['ratio'] = 0 |
|
874 |
if entry['ratio'] < 66: |
|
875 |
entry['load_class'] = 'yellow' |
|
876 |
if entry['ratio'] < 33: |
|
877 |
entry['load_class'] = 'green' |
|
878 |
if entry['ratio']<0: |
|
879 |
entry['ratio'] = 0 |
|
880 |
if entry['ratio']>100: |
|
881 |
entry['ratio_limited'] = 100 |
|
882 |
else: |
|
883 |
entry['ratio_limited'] = entry['ratio'] |
|
884 |
return entry |
|
885 |
|
|
886 |
def pluralize(entry): |
|
887 |
entry['plural'] = engine.plural(entry.get('name')) |
|
888 |
return entry |
|
889 |
|
|
890 |
resource_usage = None |
|
891 |
result = callpoint.get_user_usage(request.user.id) |
|
892 |
if result.is_success: |
|
893 |
resource_usage = result.data |
|
894 |
backenddata = map(with_class, result.data) |
|
895 |
backenddata = map(pluralize , backenddata) |
|
896 |
else: |
|
897 |
messages.error(request, result.reason) |
|
898 |
backenddata = [] |
|
899 |
resource_usage = [] |
|
900 |
|
|
901 |
if request.REQUEST.get('json', None): |
|
902 |
return HttpResponse(json.dumps(backenddata), |
|
903 |
mimetype="application/json") |
|
866 |
current_usage = quotas.get_user_quotas(request.user) |
|
867 |
current_usage = json.dumps(current_usage['system']) |
|
868 |
resource_catalog, resource_groups = _resources_catalog(request) |
|
869 |
resource_catalog = json.dumps(resource_catalog) |
|
870 |
resource_groups = json.dumps(resource_groups) |
|
871 |
resources_order = json.dumps(presentation.RESOURCES.get('resources_order')) |
|
904 | 872 |
|
905 | 873 |
return render_response('im/resource_usage.html', |
906 | 874 |
context_instance=get_context(request), |
907 |
resource_usage=backenddata, |
|
908 |
usage_update_interval=astakos_settings.USAGE_UPDATE_INTERVAL, |
|
909 |
result=result) |
|
875 |
resource_catalog=resource_catalog, |
|
876 |
resource_groups=resource_groups, |
|
877 |
resources_order=resources_order, |
|
878 |
current_usage=current_usage, |
|
879 |
token_cookie_name=astakos_settings.COOKIE_NAME, |
|
880 |
usage_update_interval= |
|
881 |
astakos_settings.USAGE_UPDATE_INTERVAL) |
|
882 |
|
|
910 | 883 |
|
911 | 884 |
# TODO: action only on POST and user should confirm the removal |
912 | 885 |
@require_http_methods(["GET", "POST"]) |
Also available in: Unified diff