]>
git.proxmox.com Git - proxmox-widget-toolkit.git/blob - Utils.js
2 Ext
.ns('Proxmox.Setup');
4 // TODO: implement gettext
5 function gettext(buf
) { return buf
; }
8 if (!Ext
.isDefined(Proxmox
.Setup
.auth_cookie_name
)) {
9 throw "Proxmox library not initialized";
12 // avoid errors related to Accessible Rich Internet Applications
13 // (access for people with disabilities)
14 // TODO reenable after all components are upgraded
15 Ext
.enableAria
= false;
16 Ext
.enableAriaButtons
= false;
17 Ext
.enableAriaPanels
= false;
19 // avoid errors when running without development tools
20 if (!Ext
.isDefined(Ext
.global
.console
)) {
27 Ext
.Ajax
.defaultHeaders
= {
28 'Accept': 'application/json'
31 Ext
.Ajax
.on('beforerequest', function(conn
, options
) {
32 if (Proxmox
.CSRFPreventionToken
) {
33 if (!options
.headers
) {
36 options
.headers
.CSRFPreventionToken
= Proxmox
.CSRFPreventionToken
;
40 Ext
.define('Proxmox.Utils', { utilities
: {
42 // this singleton contains miscellaneous utilities
44 yesText
: gettext('Yes'),
45 noText
: gettext('No'),
46 enabledText
: gettext('Enabled'),
47 disabledText
: gettext('Disabled'),
48 noneText
: gettext('none'),
49 errorText
: gettext('Error'),
50 unknownText
: gettext('Unknown'),
51 defaultText
: gettext('Default'),
52 daysText
: gettext('days'),
53 dayText
: gettext('day'),
54 runningText
: gettext('running'),
55 stoppedText
: gettext('stopped'),
56 neverText
: gettext('never'),
57 totalText
: gettext('Total'),
58 usedText
: gettext('Used'),
59 directoryText
: gettext('Directory'),
60 stateText
: gettext('State'),
61 groupText
: gettext('Group'),
63 format_boolean_with_default: function(value
) {
64 if (Ext
.isDefined(value
) && value
!== '__default__') {
65 return value
? Proxmox
.Utils
.yesText
: Proxmox
.Utils
.noText
;
67 return Proxmox
.Utils
.defaultText
;
70 format_boolean: function(value
) {
71 return value
? Proxmox
.Utils
.yesText
: Proxmox
.Utils
.noText
;
74 format_neg_boolean: function(value
) {
75 return !value
? Proxmox
.Utils
.yesText
: Proxmox
.Utils
.noText
;
78 format_enabled_toggle: function(value
) {
79 return value
? Proxmox
.Utils
.enabledText
: Proxmox
.Utils
.disabledText
;
82 format_expire: function(date
) {
84 return Proxmox
.Utils
.neverText
;
86 return Ext
.Date
.format(date
, "Y-m-d");
89 format_duration_long: function(ut
) {
91 var days
= Math
.floor(ut
/ 86400);
93 var hours
= Math
.floor(ut
/ 3600);
95 var mins
= Math
.floor(ut
/ 60);
98 var hours_str
= '00' + hours
.toString();
99 hours_str
= hours_str
.substr(hours_str
.length
- 2);
100 var mins_str
= "00" + mins
.toString();
101 mins_str
= mins_str
.substr(mins_str
.length
- 2);
102 var ut_str
= "00" + ut
.toString();
103 ut_str
= ut_str
.substr(ut_str
.length
- 2);
106 var ds
= days
> 1 ? Proxmox
.Utils
.daysText
: Proxmox
.Utils
.dayText
;
107 return days
.toString() + ' ' + ds
+ ' ' +
108 hours_str
+ ':' + mins_str
+ ':' + ut_str
;
110 return hours_str
+ ':' + mins_str
+ ':' + ut_str
;
114 format_duration_short: function(ut
) {
117 return ut
.toString() + 's';
122 return mins
.toFixed(0) + 'm';
126 var hours
= ut
/ 3600;
127 return hours
.toFixed(0) + 'h';
130 var days
= ut
/ 86400;
131 return days
.toFixed(0) + 'd';
134 compute_min_label_width: function(text
, width
) {
136 if (width
=== undefined) { width
= 100; }
138 var tm
= new Ext
.util
.TextMetrics();
139 var min
= tm
.getWidth(text
+ ':');
141 return min
< width
? width
: min
;
145 return (Proxmox
.UserName
!== '') && Ext
.util
.Cookies
.get(Proxmox
.Setup
.auth_cookie_name
);
148 authClear: function() {
149 Ext
.util
.Cookies
.clear(Proxmox
.Setup
.auth_cookie_name
);
152 // comp.setLoading() is buggy in ExtJS 4.0.7, so we
153 // use el.mask() instead
154 setErrorMask: function(comp
, msg
) {
163 el
.mask(gettext("Loading..."));
170 monStoreErrors: function(me
, store
, clearMaskBeforeLoad
) {
171 if (clearMaskBeforeLoad
) {
172 me
.mon(store
, 'beforeload', function(s
, operation
, eOpts
) {
173 Proxmox
.Utils
.setErrorMask(me
, false);
176 me
.mon(store
, 'beforeload', function(s
, operation
, eOpts
) {
178 me
.loadCount
= 0; // make sure it is numeric
179 Proxmox
.Utils
.setErrorMask(me
, true);
184 // only works with 'proxmox' proxy
185 me
.mon(store
.proxy
, 'afterload', function(proxy
, request
, success
) {
189 Proxmox
.Utils
.setErrorMask(me
, false);
194 /*jslint nomen: true */
195 var operation
= request
._operation
;
196 var error
= operation
.getError();
197 if (error
.statusText
) {
198 msg
= error
.statusText
+ ' (' + error
.status
+ ')';
200 msg
= gettext('Connection error');
202 Proxmox
.Utils
.setErrorMask(me
, msg
);
206 extractRequestError: function(result
, verbose
) {
207 var msg
= gettext('Successful');
209 if (!result
.success
) {
210 msg
= gettext("Unknown error");
211 if (result
.message
) {
212 msg
= result
.message
;
214 msg
+= ' (' + result
.status
+ ')';
217 if (verbose
&& Ext
.isObject(result
.errors
)) {
219 Ext
.Object
.each(result
.errors
, function(prop
, desc
) {
220 msg
+= "<br><b>" + Ext
.htmlEncode(prop
) + "</b>: " +
221 Ext
.htmlEncode(desc
);
230 API2Request: function(reqOpts
) {
232 var newopts
= Ext
.apply({
233 waitMsg
: gettext('Please wait...')
236 if (!newopts
.url
.match(/^\/api2/)) {
237 newopts
.url
= '/api2/extjs' + newopts
.url
;
239 delete newopts
.callback
;
241 var createWrapper = function(successFn
, callbackFn
, failureFn
) {
243 success: function(response
, options
) {
244 if (options
.waitMsgTarget
) {
245 options
.waitMsgTarget
.setLoading(false);
247 var result
= Ext
.decode(response
.responseText
);
248 response
.result
= result
;
249 if (!result
.success
) {
250 response
.htmlStatus
= Proxmox
.Utils
.extractRequestError(result
, true);
251 Ext
.callback(callbackFn
, options
.scope
, [options
, false, response
]);
252 Ext
.callback(failureFn
, options
.scope
, [response
, options
]);
255 Ext
.callback(callbackFn
, options
.scope
, [options
, true, response
]);
256 Ext
.callback(successFn
, options
.scope
, [response
, options
]);
258 failure: function(response
, options
) {
259 if (options
.waitMsgTarget
) {
260 options
.waitMsgTarget
.setLoading(false);
262 response
.result
= {};
264 response
.result
= Ext
.decode(response
.responseText
);
266 var msg
= gettext('Connection error') + ' - server offline?';
267 if (response
.aborted
) {
268 msg
= gettext('Connection error') + ' - aborted.';
269 } else if (response
.timedout
) {
270 msg
= gettext('Connection error') + ' - Timeout.';
271 } else if (response
.status
&& response
.statusText
) {
272 msg
= gettext('Connection error') + ' ' + response
.status
+ ': ' + response
.statusText
;
274 response
.htmlStatus
= msg
;
275 Ext
.callback(callbackFn
, options
.scope
, [options
, false, response
]);
276 Ext
.callback(failureFn
, options
.scope
, [response
, options
]);
281 createWrapper(reqOpts
.success
, reqOpts
.callback
, reqOpts
.failure
);
283 var target
= newopts
.waitMsgTarget
;
285 // Note: ExtJS bug - this does not work when component is not rendered
286 target
.setLoading(newopts
.waitMsg
);
288 Ext
.Ajax
.request(newopts
);
291 assemble_field_data: function(values
, data
) {
292 if (Ext
.isObject(data
)) {
293 Ext
.Object
.each(data
, function(name
, val
) {
294 if (values
.hasOwnProperty(name
)) {
295 var bucket
= values
[name
];
296 if (!Ext
.isArray(bucket
)) {
297 bucket
= values
[name
] = [bucket
];
299 if (Ext
.isArray(val
)) {
300 values
[name
] = bucket
.concat(val
);
311 dialog_title: function(subject
, create
, isAdd
) {
314 return gettext('Add') + ': ' + subject
;
316 return gettext('Create') + ': ' + subject
;
319 return gettext('Edit') + ': ' + subject
;
323 network_iface_types
: {
324 eth
: gettext("Network Device"),
325 bridge
: 'Linux Bridge',
327 OVSBridge
: 'OVS Bridge',
330 OVSIntPort
: 'OVS IntPort'
333 render_network_iface_type: function(value
) {
334 return Proxmox
.Utils
.network_iface_types
[value
] ||
335 Proxmox
.Utils
.unknownText
;
338 // you can override this to provide nicer task descriptions
339 format_task_description: function(type
, id
) {
340 return type
+ ' ' + id
;
343 render_upid: function(value
, metaData
, record
) {
344 var type
= record
.data
.type
;
345 var id
= record
.data
.id
;
347 return Proxmox
.Utils
.format_task_description(type
, id
);
350 render_uptime: function(value
) {
354 if (uptime
=== undefined) {
362 return Proxmox
.Utils
.format_duration_long(uptime
);
365 parse_task_upid: function(upid
) {
368 var res
= upid
.match(/^UPID:(\S+):([0-9A-Fa-f]{8}):([0-9A-Fa-f]{8,9}):([0-9A-Fa-f]{8}):([^:\s]+):([^:\s]*):([^:\s]+):$/);
370 throw "unable to parse upid '" + upid
+ "'";
373 task
.pid
= parseInt(res
[2], 16);
374 task
.pstart
= parseInt(res
[3], 16);
375 task
.starttime
= parseInt(res
[4], 16);
380 task
.desc
= Proxmox
.Utils
.format_task_description(task
.type
, task
.id
);
385 render_timestamp: function(value
, metaData
, record
, rowIndex
, colIndex
, store
) {
386 var servertime
= new Date(value
* 1000);
387 return Ext
.Date
.format(servertime
, 'Y-m-d H:i:s');
393 constructor: function() {
395 Ext
.apply(me
, me
.utilities
);
397 var IPV4_OCTET
= "(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])";
398 var IPV4_REGEXP
= "(?:(?:" + IPV4_OCTET
+ "\\.){3}" + IPV4_OCTET
+ ")";
399 var IPV6_H16
= "(?:[0-9a-fA-F]{1,4})";
400 var IPV6_LS32
= "(?:(?:" + IPV6_H16
+ ":" + IPV6_H16
+ ")|" + IPV4_REGEXP
+ ")";
403 me
.IP4_match
= new RegExp("^(?:" + IPV4_REGEXP
+ ")$");
404 me
.IP4_cidr_match
= new RegExp("^(?:" + IPV4_REGEXP
+ ")\/([0-9]{1,2})$");
406 var IPV6_REGEXP
= "(?:" +
407 "(?:(?:" + "(?:" + IPV6_H16
+ ":){6})" + IPV6_LS32
+ ")|" +
408 "(?:(?:" + "::" + "(?:" + IPV6_H16
+ ":){5})" + IPV6_LS32
+ ")|" +
409 "(?:(?:(?:" + IPV6_H16
+ ")?::" + "(?:" + IPV6_H16
+ ":){4})" + IPV6_LS32
+ ")|" +
410 "(?:(?:(?:(?:" + IPV6_H16
+ ":){0,1}" + IPV6_H16
+ ")?::" + "(?:" + IPV6_H16
+ ":){3})" + IPV6_LS32
+ ")|" +
411 "(?:(?:(?:(?:" + IPV6_H16
+ ":){0,2}" + IPV6_H16
+ ")?::" + "(?:" + IPV6_H16
+ ":){2})" + IPV6_LS32
+ ")|" +
412 "(?:(?:(?:(?:" + IPV6_H16
+ ":){0,3}" + IPV6_H16
+ ")?::" + "(?:" + IPV6_H16
+ ":){1})" + IPV6_LS32
+ ")|" +
413 "(?:(?:(?:(?:" + IPV6_H16
+ ":){0,4}" + IPV6_H16
+ ")?::" + ")" + IPV6_LS32
+ ")|" +
414 "(?:(?:(?:(?:" + IPV6_H16
+ ":){0,5}" + IPV6_H16
+ ")?::" + ")" + IPV6_H16
+ ")|" +
415 "(?:(?:(?:(?:" + IPV6_H16
+ ":){0,7}" + IPV6_H16
+ ")?::" + ")" + ")" +
418 me
.IP6_match
= new RegExp("^(?:" + IPV6_REGEXP
+ ")$");
419 me
.IP6_cidr_match
= new RegExp("^(?:" + IPV6_REGEXP
+ ")\/([0-9]{1,3})$");
420 me
.IP6_bracket_match
= new RegExp("^\\[(" + IPV6_REGEXP
+ ")\\]");
422 me
.IP64_match
= new RegExp("^(?:" + IPV6_REGEXP
+ "|" + IPV4_REGEXP
+ ")$");
424 var DnsName_REGEXP
= "(?:(([a-zA-Z0-9]([a-zA-Z0-9\\-]*[a-zA-Z0-9])?)\\.)*([A-Za-z0-9]([A-Za-z0-9\\-]*[A-Za-z0-9])?))";
425 me
.DnsName_match
= new RegExp("^" + DnsName_REGEXP
+ "$");
427 me
.HostPort_match
= new RegExp("^(" + IPV4_REGEXP
+ "|" + DnsName_REGEXP
+ ")(:\\d+)?$");
428 me
.HostPortBrackets_match
= new RegExp("^\\[(?:" + IPV6_REGEXP
+ "|" + IPV4_REGEXP
+ "|" + DnsName_REGEXP
+ ")\\](:\\d+)?$");
429 me
.IP6_dotnotation_match
= new RegExp("^" + IPV6_REGEXP
+ "(\\.\\d+)?$");