mirror of
https://git.proxmox.com/git/proxmox-widget-toolkit
synced 2025-05-02 17:33:46 +00:00
initial import
copied from pve-manager, remove pve-manager specific code and rename 'pve' to 'proxmox'.
This commit is contained in:
commit
0bb29d3556
226
Utils.js
Normal file
226
Utils.js
Normal file
@ -0,0 +1,226 @@
|
||||
Ext.ns('Proxmox');
|
||||
Ext.ns('Proxmox.Setup');
|
||||
|
||||
// TODO: implement gettext
|
||||
function gettext(buf) { return buf; }
|
||||
|
||||
|
||||
if (!Ext.isDefined(Proxmox.Setup.auth_cookie)) {
|
||||
trow "Proxmox library not initialize";
|
||||
}
|
||||
|
||||
// avoid errors related to Accessible Rich Internet Applications
|
||||
// (access for people with disabilities)
|
||||
// TODO reenable after all components are upgraded
|
||||
Ext.enableAria = false;
|
||||
Ext.enableAriaButtons = false;
|
||||
Ext.enableAriaPanels = false;
|
||||
|
||||
// avoid errors when running without development tools
|
||||
if (!Ext.isDefined(Ext.global.console)) {
|
||||
var console = {
|
||||
dir: function() {},
|
||||
log: function() {}
|
||||
};
|
||||
}
|
||||
|
||||
Ext.Ajax.defaultHeaders = {
|
||||
'Accept': 'application/json'
|
||||
};
|
||||
|
||||
Ext.Ajax.on('beforerequest', function(conn, options) {
|
||||
if (Proxmox.CSRFPreventionToken) {
|
||||
if (!options.headers) {
|
||||
options.headers = {};
|
||||
}
|
||||
options.headers.CSRFPreventionToken = Proxmox.CSRFPreventionToken;
|
||||
}
|
||||
});
|
||||
|
||||
Ext.define('Proxmox.Utils', { utilities: {
|
||||
|
||||
// this singleton contains miscellaneous utilities
|
||||
|
||||
authOK: function() {
|
||||
return (Proxmox.UserName !== '') && Ext.util.Cookies.get(Proxmox.Setup.auth_cookie_name);
|
||||
},
|
||||
|
||||
authClear: function() {
|
||||
Ext.util.Cookies.clear(Proxmox.Setup.auth_cookie_name);
|
||||
},
|
||||
|
||||
// comp.setLoading() is buggy in ExtJS 4.0.7, so we
|
||||
// use el.mask() instead
|
||||
setErrorMask: function(comp, msg) {
|
||||
var el = comp.el;
|
||||
if (!el) {
|
||||
return;
|
||||
}
|
||||
if (!msg) {
|
||||
el.unmask();
|
||||
} else {
|
||||
if (msg === true) {
|
||||
el.mask(gettext("Loading..."));
|
||||
} else {
|
||||
el.mask(msg);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
monStoreErrors: function(me, store) {
|
||||
me.mon(store, 'beforeload', function(s, operation, eOpts) {
|
||||
if (!me.loadCount) {
|
||||
me.loadCount = 0; // make sure it is numeric
|
||||
Proxmox.Utils.setErrorMask(me, true);
|
||||
}
|
||||
});
|
||||
|
||||
// only works with 'proxmox' proxy
|
||||
me.mon(store.proxy, 'afterload', function(proxy, request, success) {
|
||||
me.loadCount++;
|
||||
|
||||
if (success) {
|
||||
Proxmox.Utils.setErrorMask(me, false);
|
||||
return;
|
||||
}
|
||||
|
||||
var msg;
|
||||
/*jslint nomen: true */
|
||||
var operation = request._operation;
|
||||
var error = operation.getError();
|
||||
if (error.statusText) {
|
||||
msg = error.statusText + ' (' + error.status + ')';
|
||||
} else {
|
||||
msg = gettext('Connection error');
|
||||
}
|
||||
Proxmox.Utils.setErrorMask(me, msg);
|
||||
});
|
||||
},
|
||||
|
||||
extractRequestError: function(result, verbose) {
|
||||
var msg = gettext('Successful');
|
||||
|
||||
if (!result.success) {
|
||||
msg = gettext("Unknown error");
|
||||
if (result.message) {
|
||||
msg = result.message;
|
||||
if (result.status) {
|
||||
msg += ' (' + result.status + ')';
|
||||
}
|
||||
}
|
||||
if (verbose && Ext.isObject(result.errors)) {
|
||||
msg += "<br>";
|
||||
Ext.Object.each(result.errors, function(prop, desc) {
|
||||
msg += "<br><b>" + Ext.htmlEncode(prop) + "</b>: " +
|
||||
Ext.htmlEncode(desc);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return msg;
|
||||
},
|
||||
|
||||
// Ext.Ajax.request
|
||||
API2Request: function(reqOpts) {
|
||||
|
||||
var newopts = Ext.apply({
|
||||
waitMsg: gettext('Please wait...')
|
||||
}, reqOpts);
|
||||
|
||||
if (!newopts.url.match(/^\/api2/)) {
|
||||
newopts.url = '/api2/extjs' + newopts.url;
|
||||
}
|
||||
delete newopts.callback;
|
||||
|
||||
var createWrapper = function(successFn, callbackFn, failureFn) {
|
||||
Ext.apply(newopts, {
|
||||
success: function(response, options) {
|
||||
if (options.waitMsgTarget) {
|
||||
options.waitMsgTarget.setLoading(false);
|
||||
}
|
||||
var result = Ext.decode(response.responseText);
|
||||
response.result = result;
|
||||
if (!result.success) {
|
||||
response.htmlStatus = Proxmox.Utils.extractRequestError(result, true);
|
||||
Ext.callback(callbackFn, options.scope, [options, false, response]);
|
||||
Ext.callback(failureFn, options.scope, [response, options]);
|
||||
return;
|
||||
}
|
||||
Ext.callback(callbackFn, options.scope, [options, true, response]);
|
||||
Ext.callback(successFn, options.scope, [response, options]);
|
||||
},
|
||||
failure: function(response, options) {
|
||||
if (options.waitMsgTarget) {
|
||||
options.waitMsgTarget.setLoading(false);
|
||||
}
|
||||
response.result = {};
|
||||
try {
|
||||
response.result = Ext.decode(response.responseText);
|
||||
} catch(e) {}
|
||||
var msg = gettext('Connection error') + ' - server offline?';
|
||||
if (response.aborted) {
|
||||
msg = gettext('Connection error') + ' - aborted.';
|
||||
} else if (response.timedout) {
|
||||
msg = gettext('Connection error') + ' - Timeout.';
|
||||
} else if (response.status && response.statusText) {
|
||||
msg = gettext('Connection error') + ' ' + response.status + ': ' + response.statusText;
|
||||
}
|
||||
response.htmlStatus = msg;
|
||||
Ext.callback(callbackFn, options.scope, [options, false, response]);
|
||||
Ext.callback(failureFn, options.scope, [response, options]);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
createWrapper(reqOpts.success, reqOpts.callback, reqOpts.failure);
|
||||
|
||||
var target = newopts.waitMsgTarget;
|
||||
if (target) {
|
||||
// Note: ExtJS bug - this does not work when component is not rendered
|
||||
target.setLoading(newopts.waitMsg);
|
||||
}
|
||||
Ext.Ajax.request(newopts);
|
||||
},
|
||||
|
||||
},
|
||||
|
||||
singleton: true,
|
||||
constructor: function() {
|
||||
var me = this;
|
||||
Ext.apply(me, me.utilities);
|
||||
|
||||
var IPV4_OCTET = "(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])";
|
||||
var IPV4_REGEXP = "(?:(?:" + IPV4_OCTET + "\\.){3}" + IPV4_OCTET + ")";
|
||||
var IPV6_H16 = "(?:[0-9a-fA-F]{1,4})";
|
||||
var IPV6_LS32 = "(?:(?:" + IPV6_H16 + ":" + IPV6_H16 + ")|" + IPV4_REGEXP + ")";
|
||||
|
||||
|
||||
me.IP4_match = new RegExp("^(?:" + IPV4_REGEXP + ")$");
|
||||
me.IP4_cidr_match = new RegExp("^(?:" + IPV4_REGEXP + ")\/([0-9]{1,2})$");
|
||||
|
||||
var IPV6_REGEXP = "(?:" +
|
||||
"(?:(?:" + "(?:" + IPV6_H16 + ":){6})" + IPV6_LS32 + ")|" +
|
||||
"(?:(?:" + "::" + "(?:" + IPV6_H16 + ":){5})" + IPV6_LS32 + ")|" +
|
||||
"(?:(?:(?:" + IPV6_H16 + ")?::" + "(?:" + IPV6_H16 + ":){4})" + IPV6_LS32 + ")|" +
|
||||
"(?:(?:(?:(?:" + IPV6_H16 + ":){0,1}" + IPV6_H16 + ")?::" + "(?:" + IPV6_H16 + ":){3})" + IPV6_LS32 + ")|" +
|
||||
"(?:(?:(?:(?:" + IPV6_H16 + ":){0,2}" + IPV6_H16 + ")?::" + "(?:" + IPV6_H16 + ":){2})" + IPV6_LS32 + ")|" +
|
||||
"(?:(?:(?:(?:" + IPV6_H16 + ":){0,3}" + IPV6_H16 + ")?::" + "(?:" + IPV6_H16 + ":){1})" + IPV6_LS32 + ")|" +
|
||||
"(?:(?:(?:(?:" + IPV6_H16 + ":){0,4}" + IPV6_H16 + ")?::" + ")" + IPV6_LS32 + ")|" +
|
||||
"(?:(?:(?:(?:" + IPV6_H16 + ":){0,5}" + IPV6_H16 + ")?::" + ")" + IPV6_H16 + ")|" +
|
||||
"(?:(?:(?:(?:" + IPV6_H16 + ":){0,7}" + IPV6_H16 + ")?::" + ")" + ")" +
|
||||
")";
|
||||
|
||||
me.IP6_match = new RegExp("^(?:" + IPV6_REGEXP + ")$");
|
||||
me.IP6_cidr_match = new RegExp("^(?:" + IPV6_REGEXP + ")\/([0-9]{1,3})$");
|
||||
me.IP6_bracket_match = new RegExp("^\\[(" + IPV6_REGEXP + ")\\]");
|
||||
|
||||
me.IP64_match = new RegExp("^(?:" + IPV6_REGEXP + "|" + IPV4_REGEXP + ")$");
|
||||
|
||||
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])?))";
|
||||
me.DnsName_match = new RegExp("^" + DnsName_REGEXP + "$");
|
||||
|
||||
me.HostPort_match = new RegExp("^(" + IPV4_REGEXP + "|" + DnsName_REGEXP + ")(:\\d+)?$");
|
||||
me.HostPortBrackets_match = new RegExp("^\\[(?:" + IPV6_REGEXP + "|" + IPV4_REGEXP + "|" + DnsName_REGEXP + ")\\](:\\d+)?$");
|
||||
me.IP6_dotnotation_match = new RegExp("^" + IPV6_REGEXP + "(\\.\\d+)?$");
|
||||
}
|
||||
});
|
114
data/DiffStore.js
Normal file
114
data/DiffStore.js
Normal file
@ -0,0 +1,114 @@
|
||||
/*
|
||||
* The DiffStore is a in-memory store acting as proxy between a real store
|
||||
* instance and a component.
|
||||
* Its purpose is to redisplay the component *only* if the data has been changed
|
||||
* inside the real store, to avoid the annoying visual flickering of using
|
||||
* the real store directly.
|
||||
*
|
||||
* Implementation:
|
||||
* The DiffStore monitors via mon() the 'load' events sent by the real store.
|
||||
* On each 'load' event, the DiffStore compares its own content with the target
|
||||
* store (call to cond_add_item()) and then fires a 'refresh' event.
|
||||
* The 'refresh' event will automatically trigger a view refresh on the component
|
||||
* who binds to this store.
|
||||
*/
|
||||
|
||||
/* Config properties:
|
||||
* rstore: the realstore which will autorefresh its content from the API
|
||||
* Only works if rstore has a model and use 'idProperty'
|
||||
* sortAfterUpdate: sort the diffstore before rendering the view
|
||||
*/
|
||||
Ext.define('Proxmox.data.DiffStore', {
|
||||
extend: 'Ext.data.Store',
|
||||
alias: 'store.diff',
|
||||
|
||||
sortAfterUpdate: false,
|
||||
|
||||
constructor: function(config) {
|
||||
var me = this;
|
||||
|
||||
config = config || {};
|
||||
|
||||
if (!config.rstore) {
|
||||
throw "no rstore specified";
|
||||
}
|
||||
|
||||
if (!config.rstore.model) {
|
||||
throw "no rstore model specified";
|
||||
}
|
||||
|
||||
var rstore = config.rstore;
|
||||
|
||||
Ext.apply(config, {
|
||||
model: rstore.model,
|
||||
proxy: { type: 'memory' }
|
||||
});
|
||||
|
||||
me.callParent([config]);
|
||||
|
||||
var first_load = true;
|
||||
|
||||
var cond_add_item = function(data, id) {
|
||||
var olditem = me.getById(id);
|
||||
if (olditem) {
|
||||
olditem.beginEdit();
|
||||
Ext.Array.each(me.model.prototype.fields, function(field) {
|
||||
if (olditem.data[field.name] !== data[field.name]) {
|
||||
olditem.set(field.name, data[field.name]);
|
||||
}
|
||||
});
|
||||
olditem.endEdit(true);
|
||||
olditem.commit();
|
||||
} else {
|
||||
var newrec = Ext.create(me.model, data);
|
||||
var pos = (me.appendAtStart && !first_load) ? 0 : me.data.length;
|
||||
me.insert(pos, newrec);
|
||||
}
|
||||
};
|
||||
|
||||
var loadFn = function(s, records, success) {
|
||||
|
||||
if (!success) {
|
||||
return;
|
||||
}
|
||||
|
||||
me.suspendEvents();
|
||||
|
||||
// getSource returns null if data is not filtered
|
||||
// if it is filtered it returns all records
|
||||
var allItems = me.getData().getSource() || me.getData();
|
||||
|
||||
// remove vanished items
|
||||
allItems.each(function(olditem) {
|
||||
var item = rstore.getById(olditem.getId());
|
||||
if (!item) {
|
||||
me.remove(olditem);
|
||||
}
|
||||
});
|
||||
|
||||
rstore.each(function(item) {
|
||||
cond_add_item(item.data, item.getId());
|
||||
});
|
||||
|
||||
me.filter();
|
||||
|
||||
if (me.sortAfterUpdate) {
|
||||
me.sort();
|
||||
}
|
||||
|
||||
first_load = false;
|
||||
|
||||
me.resumeEvents();
|
||||
me.fireEvent('refresh', me);
|
||||
me.fireEvent('datachanged', me);
|
||||
};
|
||||
|
||||
if (rstore.isLoaded()) {
|
||||
// if store is already loaded,
|
||||
// insert items instantly
|
||||
loadFn(rstore, [], true);
|
||||
}
|
||||
|
||||
me.mon(rstore, 'load', loadFn);
|
||||
}
|
||||
});
|
35
data/ObjectStore.js
Normal file
35
data/ObjectStore.js
Normal file
@ -0,0 +1,35 @@
|
||||
/* This store encapsulates data items which are organized as an Array of key-values Objects
|
||||
* ie data[0] contains something like {key: "keyboard", value: "da"}
|
||||
*
|
||||
* Designed to work with the KeyValue model and the JsonObject data reader
|
||||
*/
|
||||
Ext.define('Proxmox.data.ObjectStore', {
|
||||
extend: 'Proxmox.data.UpdateStore',
|
||||
|
||||
constructor: function(config) {
|
||||
var me = this;
|
||||
|
||||
config = config || {};
|
||||
|
||||
if (!config.storeid) {
|
||||
config.storeid = 'proxmox-store-' + (++Ext.idSeed);
|
||||
}
|
||||
|
||||
Ext.applyIf(config, {
|
||||
model: 'KeyValue',
|
||||
proxy: {
|
||||
type: 'proxmox',
|
||||
url: config.url,
|
||||
extraParams: config.extraParams,
|
||||
reader: {
|
||||
type: 'jsonobject',
|
||||
rows: config.rows,
|
||||
readArray: config.readArray,
|
||||
rootProperty: config.root || 'data'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
me.callParent([config]);
|
||||
}
|
||||
});
|
29
data/ProxmoxProxy.js
Normal file
29
data/ProxmoxProxy.js
Normal file
@ -0,0 +1,29 @@
|
||||
Ext.define('Proxmox.RestProxy', {
|
||||
extend: 'Ext.data.RestProxy',
|
||||
alias : 'proxy.proxmox',
|
||||
|
||||
pageParam : null,
|
||||
startParam: null,
|
||||
limitParam: null,
|
||||
groupParam: null,
|
||||
sortParam: null,
|
||||
filterParam: null,
|
||||
noCache : false,
|
||||
|
||||
afterRequest: function(request, success) {
|
||||
this.fireEvent('afterload', this, request, success);
|
||||
return;
|
||||
},
|
||||
|
||||
constructor: function(config) {
|
||||
|
||||
Ext.applyIf(config, {
|
||||
reader: {
|
||||
type: 'json',
|
||||
rootProperty: config.root || 'data'
|
||||
}
|
||||
});
|
||||
|
||||
this.callParent([config]);
|
||||
}
|
||||
});
|
418
data/TimezoneStore.js
Normal file
418
data/TimezoneStore.js
Normal file
@ -0,0 +1,418 @@
|
||||
Ext.define('Timezone', {
|
||||
extend: 'Ext.data.Model',
|
||||
fields: ['zone']
|
||||
});
|
||||
|
||||
Ext.define('Proxmox.data.TimezoneStore', {
|
||||
extend: 'Ext.data.Store',
|
||||
model: 'Timezone',
|
||||
data: [
|
||||
['Africa/Abidjan'],
|
||||
['Africa/Accra'],
|
||||
['Africa/Addis_Ababa'],
|
||||
['Africa/Algiers'],
|
||||
['Africa/Asmara'],
|
||||
['Africa/Bamako'],
|
||||
['Africa/Bangui'],
|
||||
['Africa/Banjul'],
|
||||
['Africa/Bissau'],
|
||||
['Africa/Blantyre'],
|
||||
['Africa/Brazzaville'],
|
||||
['Africa/Bujumbura'],
|
||||
['Africa/Cairo'],
|
||||
['Africa/Casablanca'],
|
||||
['Africa/Ceuta'],
|
||||
['Africa/Conakry'],
|
||||
['Africa/Dakar'],
|
||||
['Africa/Dar_es_Salaam'],
|
||||
['Africa/Djibouti'],
|
||||
['Africa/Douala'],
|
||||
['Africa/El_Aaiun'],
|
||||
['Africa/Freetown'],
|
||||
['Africa/Gaborone'],
|
||||
['Africa/Harare'],
|
||||
['Africa/Johannesburg'],
|
||||
['Africa/Kampala'],
|
||||
['Africa/Khartoum'],
|
||||
['Africa/Kigali'],
|
||||
['Africa/Kinshasa'],
|
||||
['Africa/Lagos'],
|
||||
['Africa/Libreville'],
|
||||
['Africa/Lome'],
|
||||
['Africa/Luanda'],
|
||||
['Africa/Lubumbashi'],
|
||||
['Africa/Lusaka'],
|
||||
['Africa/Malabo'],
|
||||
['Africa/Maputo'],
|
||||
['Africa/Maseru'],
|
||||
['Africa/Mbabane'],
|
||||
['Africa/Mogadishu'],
|
||||
['Africa/Monrovia'],
|
||||
['Africa/Nairobi'],
|
||||
['Africa/Ndjamena'],
|
||||
['Africa/Niamey'],
|
||||
['Africa/Nouakchott'],
|
||||
['Africa/Ouagadougou'],
|
||||
['Africa/Porto-Novo'],
|
||||
['Africa/Sao_Tome'],
|
||||
['Africa/Tripoli'],
|
||||
['Africa/Tunis'],
|
||||
['Africa/Windhoek'],
|
||||
['America/Adak'],
|
||||
['America/Anchorage'],
|
||||
['America/Anguilla'],
|
||||
['America/Antigua'],
|
||||
['America/Araguaina'],
|
||||
['America/Argentina/Buenos_Aires'],
|
||||
['America/Argentina/Catamarca'],
|
||||
['America/Argentina/Cordoba'],
|
||||
['America/Argentina/Jujuy'],
|
||||
['America/Argentina/La_Rioja'],
|
||||
['America/Argentina/Mendoza'],
|
||||
['America/Argentina/Rio_Gallegos'],
|
||||
['America/Argentina/Salta'],
|
||||
['America/Argentina/San_Juan'],
|
||||
['America/Argentina/San_Luis'],
|
||||
['America/Argentina/Tucuman'],
|
||||
['America/Argentina/Ushuaia'],
|
||||
['America/Aruba'],
|
||||
['America/Asuncion'],
|
||||
['America/Atikokan'],
|
||||
['America/Bahia'],
|
||||
['America/Bahia_Banderas'],
|
||||
['America/Barbados'],
|
||||
['America/Belem'],
|
||||
['America/Belize'],
|
||||
['America/Blanc-Sablon'],
|
||||
['America/Boa_Vista'],
|
||||
['America/Bogota'],
|
||||
['America/Boise'],
|
||||
['America/Cambridge_Bay'],
|
||||
['America/Campo_Grande'],
|
||||
['America/Cancun'],
|
||||
['America/Caracas'],
|
||||
['America/Cayenne'],
|
||||
['America/Cayman'],
|
||||
['America/Chicago'],
|
||||
['America/Chihuahua'],
|
||||
['America/Costa_Rica'],
|
||||
['America/Cuiaba'],
|
||||
['America/Curacao'],
|
||||
['America/Danmarkshavn'],
|
||||
['America/Dawson'],
|
||||
['America/Dawson_Creek'],
|
||||
['America/Denver'],
|
||||
['America/Detroit'],
|
||||
['America/Dominica'],
|
||||
['America/Edmonton'],
|
||||
['America/Eirunepe'],
|
||||
['America/El_Salvador'],
|
||||
['America/Fortaleza'],
|
||||
['America/Glace_Bay'],
|
||||
['America/Godthab'],
|
||||
['America/Goose_Bay'],
|
||||
['America/Grand_Turk'],
|
||||
['America/Grenada'],
|
||||
['America/Guadeloupe'],
|
||||
['America/Guatemala'],
|
||||
['America/Guayaquil'],
|
||||
['America/Guyana'],
|
||||
['America/Halifax'],
|
||||
['America/Havana'],
|
||||
['America/Hermosillo'],
|
||||
['America/Indiana/Indianapolis'],
|
||||
['America/Indiana/Knox'],
|
||||
['America/Indiana/Marengo'],
|
||||
['America/Indiana/Petersburg'],
|
||||
['America/Indiana/Tell_City'],
|
||||
['America/Indiana/Vevay'],
|
||||
['America/Indiana/Vincennes'],
|
||||
['America/Indiana/Winamac'],
|
||||
['America/Inuvik'],
|
||||
['America/Iqaluit'],
|
||||
['America/Jamaica'],
|
||||
['America/Juneau'],
|
||||
['America/Kentucky/Louisville'],
|
||||
['America/Kentucky/Monticello'],
|
||||
['America/La_Paz'],
|
||||
['America/Lima'],
|
||||
['America/Los_Angeles'],
|
||||
['America/Maceio'],
|
||||
['America/Managua'],
|
||||
['America/Manaus'],
|
||||
['America/Marigot'],
|
||||
['America/Martinique'],
|
||||
['America/Matamoros'],
|
||||
['America/Mazatlan'],
|
||||
['America/Menominee'],
|
||||
['America/Merida'],
|
||||
['America/Mexico_City'],
|
||||
['America/Miquelon'],
|
||||
['America/Moncton'],
|
||||
['America/Monterrey'],
|
||||
['America/Montevideo'],
|
||||
['America/Montreal'],
|
||||
['America/Montserrat'],
|
||||
['America/Nassau'],
|
||||
['America/New_York'],
|
||||
['America/Nipigon'],
|
||||
['America/Nome'],
|
||||
['America/Noronha'],
|
||||
['America/North_Dakota/Center'],
|
||||
['America/North_Dakota/New_Salem'],
|
||||
['America/Ojinaga'],
|
||||
['America/Panama'],
|
||||
['America/Pangnirtung'],
|
||||
['America/Paramaribo'],
|
||||
['America/Phoenix'],
|
||||
['America/Port-au-Prince'],
|
||||
['America/Port_of_Spain'],
|
||||
['America/Porto_Velho'],
|
||||
['America/Puerto_Rico'],
|
||||
['America/Rainy_River'],
|
||||
['America/Rankin_Inlet'],
|
||||
['America/Recife'],
|
||||
['America/Regina'],
|
||||
['America/Resolute'],
|
||||
['America/Rio_Branco'],
|
||||
['America/Santa_Isabel'],
|
||||
['America/Santarem'],
|
||||
['America/Santiago'],
|
||||
['America/Santo_Domingo'],
|
||||
['America/Sao_Paulo'],
|
||||
['America/Scoresbysund'],
|
||||
['America/Shiprock'],
|
||||
['America/St_Barthelemy'],
|
||||
['America/St_Johns'],
|
||||
['America/St_Kitts'],
|
||||
['America/St_Lucia'],
|
||||
['America/St_Thomas'],
|
||||
['America/St_Vincent'],
|
||||
['America/Swift_Current'],
|
||||
['America/Tegucigalpa'],
|
||||
['America/Thule'],
|
||||
['America/Thunder_Bay'],
|
||||
['America/Tijuana'],
|
||||
['America/Toronto'],
|
||||
['America/Tortola'],
|
||||
['America/Vancouver'],
|
||||
['America/Whitehorse'],
|
||||
['America/Winnipeg'],
|
||||
['America/Yakutat'],
|
||||
['America/Yellowknife'],
|
||||
['Antarctica/Casey'],
|
||||
['Antarctica/Davis'],
|
||||
['Antarctica/DumontDUrville'],
|
||||
['Antarctica/Macquarie'],
|
||||
['Antarctica/Mawson'],
|
||||
['Antarctica/McMurdo'],
|
||||
['Antarctica/Palmer'],
|
||||
['Antarctica/Rothera'],
|
||||
['Antarctica/South_Pole'],
|
||||
['Antarctica/Syowa'],
|
||||
['Antarctica/Vostok'],
|
||||
['Arctic/Longyearbyen'],
|
||||
['Asia/Aden'],
|
||||
['Asia/Almaty'],
|
||||
['Asia/Amman'],
|
||||
['Asia/Anadyr'],
|
||||
['Asia/Aqtau'],
|
||||
['Asia/Aqtobe'],
|
||||
['Asia/Ashgabat'],
|
||||
['Asia/Baghdad'],
|
||||
['Asia/Bahrain'],
|
||||
['Asia/Baku'],
|
||||
['Asia/Bangkok'],
|
||||
['Asia/Beirut'],
|
||||
['Asia/Bishkek'],
|
||||
['Asia/Brunei'],
|
||||
['Asia/Choibalsan'],
|
||||
['Asia/Chongqing'],
|
||||
['Asia/Colombo'],
|
||||
['Asia/Damascus'],
|
||||
['Asia/Dhaka'],
|
||||
['Asia/Dili'],
|
||||
['Asia/Dubai'],
|
||||
['Asia/Dushanbe'],
|
||||
['Asia/Gaza'],
|
||||
['Asia/Harbin'],
|
||||
['Asia/Ho_Chi_Minh'],
|
||||
['Asia/Hong_Kong'],
|
||||
['Asia/Hovd'],
|
||||
['Asia/Irkutsk'],
|
||||
['Asia/Jakarta'],
|
||||
['Asia/Jayapura'],
|
||||
['Asia/Jerusalem'],
|
||||
['Asia/Kabul'],
|
||||
['Asia/Kamchatka'],
|
||||
['Asia/Karachi'],
|
||||
['Asia/Kashgar'],
|
||||
['Asia/Kathmandu'],
|
||||
['Asia/Kolkata'],
|
||||
['Asia/Krasnoyarsk'],
|
||||
['Asia/Kuala_Lumpur'],
|
||||
['Asia/Kuching'],
|
||||
['Asia/Kuwait'],
|
||||
['Asia/Macau'],
|
||||
['Asia/Magadan'],
|
||||
['Asia/Makassar'],
|
||||
['Asia/Manila'],
|
||||
['Asia/Muscat'],
|
||||
['Asia/Nicosia'],
|
||||
['Asia/Novokuznetsk'],
|
||||
['Asia/Novosibirsk'],
|
||||
['Asia/Omsk'],
|
||||
['Asia/Oral'],
|
||||
['Asia/Phnom_Penh'],
|
||||
['Asia/Pontianak'],
|
||||
['Asia/Pyongyang'],
|
||||
['Asia/Qatar'],
|
||||
['Asia/Qyzylorda'],
|
||||
['Asia/Rangoon'],
|
||||
['Asia/Riyadh'],
|
||||
['Asia/Sakhalin'],
|
||||
['Asia/Samarkand'],
|
||||
['Asia/Seoul'],
|
||||
['Asia/Shanghai'],
|
||||
['Asia/Singapore'],
|
||||
['Asia/Taipei'],
|
||||
['Asia/Tashkent'],
|
||||
['Asia/Tbilisi'],
|
||||
['Asia/Tehran'],
|
||||
['Asia/Thimphu'],
|
||||
['Asia/Tokyo'],
|
||||
['Asia/Ulaanbaatar'],
|
||||
['Asia/Urumqi'],
|
||||
['Asia/Vientiane'],
|
||||
['Asia/Vladivostok'],
|
||||
['Asia/Yakutsk'],
|
||||
['Asia/Yekaterinburg'],
|
||||
['Asia/Yerevan'],
|
||||
['Atlantic/Azores'],
|
||||
['Atlantic/Bermuda'],
|
||||
['Atlantic/Canary'],
|
||||
['Atlantic/Cape_Verde'],
|
||||
['Atlantic/Faroe'],
|
||||
['Atlantic/Madeira'],
|
||||
['Atlantic/Reykjavik'],
|
||||
['Atlantic/South_Georgia'],
|
||||
['Atlantic/St_Helena'],
|
||||
['Atlantic/Stanley'],
|
||||
['Australia/Adelaide'],
|
||||
['Australia/Brisbane'],
|
||||
['Australia/Broken_Hill'],
|
||||
['Australia/Currie'],
|
||||
['Australia/Darwin'],
|
||||
['Australia/Eucla'],
|
||||
['Australia/Hobart'],
|
||||
['Australia/Lindeman'],
|
||||
['Australia/Lord_Howe'],
|
||||
['Australia/Melbourne'],
|
||||
['Australia/Perth'],
|
||||
['Australia/Sydney'],
|
||||
['Europe/Amsterdam'],
|
||||
['Europe/Andorra'],
|
||||
['Europe/Athens'],
|
||||
['Europe/Belgrade'],
|
||||
['Europe/Berlin'],
|
||||
['Europe/Bratislava'],
|
||||
['Europe/Brussels'],
|
||||
['Europe/Bucharest'],
|
||||
['Europe/Budapest'],
|
||||
['Europe/Chisinau'],
|
||||
['Europe/Copenhagen'],
|
||||
['Europe/Dublin'],
|
||||
['Europe/Gibraltar'],
|
||||
['Europe/Guernsey'],
|
||||
['Europe/Helsinki'],
|
||||
['Europe/Isle_of_Man'],
|
||||
['Europe/Istanbul'],
|
||||
['Europe/Jersey'],
|
||||
['Europe/Kaliningrad'],
|
||||
['Europe/Kiev'],
|
||||
['Europe/Lisbon'],
|
||||
['Europe/Ljubljana'],
|
||||
['Europe/London'],
|
||||
['Europe/Luxembourg'],
|
||||
['Europe/Madrid'],
|
||||
['Europe/Malta'],
|
||||
['Europe/Mariehamn'],
|
||||
['Europe/Minsk'],
|
||||
['Europe/Monaco'],
|
||||
['Europe/Moscow'],
|
||||
['Europe/Oslo'],
|
||||
['Europe/Paris'],
|
||||
['Europe/Podgorica'],
|
||||
['Europe/Prague'],
|
||||
['Europe/Riga'],
|
||||
['Europe/Rome'],
|
||||
['Europe/Samara'],
|
||||
['Europe/San_Marino'],
|
||||
['Europe/Sarajevo'],
|
||||
['Europe/Simferopol'],
|
||||
['Europe/Skopje'],
|
||||
['Europe/Sofia'],
|
||||
['Europe/Stockholm'],
|
||||
['Europe/Tallinn'],
|
||||
['Europe/Tirane'],
|
||||
['Europe/Uzhgorod'],
|
||||
['Europe/Vaduz'],
|
||||
['Europe/Vatican'],
|
||||
['Europe/Vienna'],
|
||||
['Europe/Vilnius'],
|
||||
['Europe/Volgograd'],
|
||||
['Europe/Warsaw'],
|
||||
['Europe/Zagreb'],
|
||||
['Europe/Zaporozhye'],
|
||||
['Europe/Zurich'],
|
||||
['Indian/Antananarivo'],
|
||||
['Indian/Chagos'],
|
||||
['Indian/Christmas'],
|
||||
['Indian/Cocos'],
|
||||
['Indian/Comoro'],
|
||||
['Indian/Kerguelen'],
|
||||
['Indian/Mahe'],
|
||||
['Indian/Maldives'],
|
||||
['Indian/Mauritius'],
|
||||
['Indian/Mayotte'],
|
||||
['Indian/Reunion'],
|
||||
['Pacific/Apia'],
|
||||
['Pacific/Auckland'],
|
||||
['Pacific/Chatham'],
|
||||
['Pacific/Chuuk'],
|
||||
['Pacific/Easter'],
|
||||
['Pacific/Efate'],
|
||||
['Pacific/Enderbury'],
|
||||
['Pacific/Fakaofo'],
|
||||
['Pacific/Fiji'],
|
||||
['Pacific/Funafuti'],
|
||||
['Pacific/Galapagos'],
|
||||
['Pacific/Gambier'],
|
||||
['Pacific/Guadalcanal'],
|
||||
['Pacific/Guam'],
|
||||
['Pacific/Honolulu'],
|
||||
['Pacific/Johnston'],
|
||||
['Pacific/Kiritimati'],
|
||||
['Pacific/Kosrae'],
|
||||
['Pacific/Kwajalein'],
|
||||
['Pacific/Majuro'],
|
||||
['Pacific/Marquesas'],
|
||||
['Pacific/Midway'],
|
||||
['Pacific/Nauru'],
|
||||
['Pacific/Niue'],
|
||||
['Pacific/Norfolk'],
|
||||
['Pacific/Noumea'],
|
||||
['Pacific/Pago_Pago'],
|
||||
['Pacific/Palau'],
|
||||
['Pacific/Pitcairn'],
|
||||
['Pacific/Pohnpei'],
|
||||
['Pacific/Port_Moresby'],
|
||||
['Pacific/Rarotonga'],
|
||||
['Pacific/Saipan'],
|
||||
['Pacific/Tahiti'],
|
||||
['Pacific/Tarawa'],
|
||||
['Pacific/Tongatapu'],
|
||||
['Pacific/Wake'],
|
||||
['Pacific/Wallis']
|
||||
]
|
||||
});
|
67
data/UpdateQueue.js
Normal file
67
data/UpdateQueue.js
Normal file
@ -0,0 +1,67 @@
|
||||
// Serialize load (avoid too many parallel connections)
|
||||
Ext.define('Proxmox.data.UpdateQueue', {
|
||||
singleton: true,
|
||||
|
||||
constructor : function(){
|
||||
var me = this;
|
||||
|
||||
var queue = [];
|
||||
var queue_idx = {};
|
||||
|
||||
var idle = true;
|
||||
|
||||
var start_update = function() {
|
||||
if (!idle) {
|
||||
return;
|
||||
}
|
||||
|
||||
var storeid = queue.shift();
|
||||
if (!storeid) {
|
||||
return;
|
||||
}
|
||||
var info = queue_idx[storeid];
|
||||
queue_idx[storeid] = null;
|
||||
|
||||
info.updatestart = new Date();
|
||||
|
||||
idle = false;
|
||||
info.store.load({
|
||||
callback: function(records, operation, success) {
|
||||
idle = true;
|
||||
if (info.callback) {
|
||||
var runtime = (new Date()).getTime() - info.updatestart.getTime();
|
||||
info.callback(runtime, success);
|
||||
}
|
||||
start_update();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
Ext.apply(me, {
|
||||
queue: function(store, cb) {
|
||||
var storeid = store.storeid;
|
||||
if (!storeid) {
|
||||
throw "unable to queue store without storeid";
|
||||
}
|
||||
if (!queue_idx[storeid]) {
|
||||
queue_idx[storeid] = {
|
||||
store: store,
|
||||
callback: cb
|
||||
};
|
||||
queue.push(storeid);
|
||||
}
|
||||
start_update();
|
||||
},
|
||||
unqueue: function(store) {
|
||||
var storeid = store.storeid;
|
||||
if (!storeid) {
|
||||
throw "unabel to unqueue store without storeid";
|
||||
}
|
||||
if (queue_idx[storeid]) {
|
||||
Ext.Array.remove(queue,storeid);
|
||||
queue_idx[storeid] = null;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
64
data/UpdateStore.js
Normal file
64
data/UpdateStore.js
Normal file
@ -0,0 +1,64 @@
|
||||
/* Extends the Ext.data.Store type
|
||||
* with startUpdate() and stopUpdate() methods
|
||||
* to refresh the store data in the background
|
||||
* Components using this store directly will flicker
|
||||
* due to the redisplay of the element ater 'config.interval' ms
|
||||
*
|
||||
* Note that you have to call yourself startUpdate() for the background load
|
||||
* to begin
|
||||
*/
|
||||
Ext.define('Proxmox.data.UpdateStore', {
|
||||
extend: 'Ext.data.Store',
|
||||
|
||||
isStopped: true,
|
||||
|
||||
constructor: function(config) {
|
||||
var me = this;
|
||||
|
||||
config = config || {};
|
||||
|
||||
if (!config.interval) {
|
||||
config.interval = 3000;
|
||||
}
|
||||
|
||||
if (!config.storeid) {
|
||||
throw "no storeid specified";
|
||||
}
|
||||
|
||||
var load_task = new Ext.util.DelayedTask();
|
||||
|
||||
var run_load_task = function() {
|
||||
if (me.isStopped) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (Proxmox.Utils.authOK()) {
|
||||
Proxmox.data.UpdateQueue.queue(me, function(runtime, success) {
|
||||
var interval = config.interval + runtime*2;
|
||||
load_task.delay(interval, run_load_task);
|
||||
});
|
||||
} else {
|
||||
load_task.delay(200, run_load_task);
|
||||
}
|
||||
};
|
||||
|
||||
Ext.apply(config, {
|
||||
startUpdate: function() {
|
||||
me.isStopped = false;
|
||||
run_load_task();
|
||||
},
|
||||
stopUpdate: function() {
|
||||
me.isStopped = true;
|
||||
load_task.cancel();
|
||||
Proxmox.data.UpdateQueue.unqueue(me);
|
||||
}
|
||||
});
|
||||
|
||||
me.callParent([config]);
|
||||
|
||||
me.on('destroy', function() {
|
||||
load_task.cancel();
|
||||
Proxmox.data.UpdateQueue.unqueue(me);
|
||||
});
|
||||
}
|
||||
});
|
127
data/reader/JsonObject.js
Normal file
127
data/reader/JsonObject.js
Normal file
@ -0,0 +1,127 @@
|
||||
/* A reader to store a single JSON Object (hash) into a storage.
|
||||
* Also accepts an array containing a single hash.
|
||||
*
|
||||
* So it can read:
|
||||
*
|
||||
* example1: {data1: "xyz", data2: "abc"}
|
||||
* returns [{key: "data1", value: "xyz"}, {key: "data2", value: "abc"}]
|
||||
*
|
||||
* example2: [ {data1: "xyz", data2: "abc"} ]
|
||||
* returns [{key: "data1", value: "xyz"}, {key: "data2", value: "abc"}]
|
||||
*
|
||||
* If you set 'readArray', the reader expexts the object as array:
|
||||
*
|
||||
* example3: [ { key: "data1", value: "xyz", p2: "cde" }, { key: "data2", value: "abc", p2: "efg" }]
|
||||
* returns [{key: "data1", value: "xyz", p2: "cde}, {key: "data2", value: "abc", p2: "efg"}]
|
||||
*
|
||||
* Note: The records can contain additional properties (like 'p2' above) when you use 'readArray'
|
||||
*
|
||||
* Additional feature: specify allowed properties with default values with 'rows' object
|
||||
*
|
||||
* var rows = {
|
||||
* memory: {
|
||||
* required: true,
|
||||
* defaultValue: 512
|
||||
* }
|
||||
* }
|
||||
*
|
||||
*/
|
||||
|
||||
Ext.define('Proxmox.data.reader.JsonObject', {
|
||||
extend: 'Ext.data.reader.Json',
|
||||
alias : 'reader.jsonobject',
|
||||
|
||||
readArray: false,
|
||||
|
||||
rows: undefined,
|
||||
|
||||
constructor: function(config) {
|
||||
var me = this;
|
||||
|
||||
Ext.apply(me, config || {});
|
||||
|
||||
me.callParent([config]);
|
||||
},
|
||||
|
||||
getResponseData: function(response) {
|
||||
var me = this;
|
||||
|
||||
var data = [];
|
||||
try {
|
||||
var result = Ext.decode(response.responseText);
|
||||
// get our data items inside the server response
|
||||
var root = result[me.getRootProperty()];
|
||||
|
||||
if (me.readArray) {
|
||||
|
||||
var rec_hash = {};
|
||||
Ext.Array.each(root, function(rec) {
|
||||
if (Ext.isDefined(rec.key)) {
|
||||
rec_hash[rec.key] = rec;
|
||||
}
|
||||
});
|
||||
|
||||
if (me.rows) {
|
||||
Ext.Object.each(me.rows, function(key, rowdef) {
|
||||
var rec = rec_hash[key];
|
||||
if (Ext.isDefined(rec)) {
|
||||
if (!Ext.isDefined(rec.value)) {
|
||||
rec.value = rowdef.defaultValue;
|
||||
}
|
||||
data.push(rec);
|
||||
} else if (Ext.isDefined(rowdef.defaultValue)) {
|
||||
data.push({key: key, value: rowdef.defaultValue} );
|
||||
} else if (rowdef.required) {
|
||||
data.push({key: key, value: undefined });
|
||||
}
|
||||
});
|
||||
} else {
|
||||
Ext.Array.each(root, function(rec) {
|
||||
if (Ext.isDefined(rec.key)) {
|
||||
data.push(rec);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
var org_root = root;
|
||||
|
||||
if (Ext.isArray(org_root)) {
|
||||
if (root.length == 1) {
|
||||
root = org_root[0];
|
||||
} else {
|
||||
root = {};
|
||||
}
|
||||
}
|
||||
|
||||
if (me.rows) {
|
||||
Ext.Object.each(me.rows, function(key, rowdef) {
|
||||
if (Ext.isDefined(root[key])) {
|
||||
data.push({key: key, value: root[key]});
|
||||
} else if (Ext.isDefined(rowdef.defaultValue)) {
|
||||
data.push({key: key, value: rowdef.defaultValue});
|
||||
} else if (rowdef.required) {
|
||||
data.push({key: key, value: undefined});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
Ext.Object.each(root, function(key, value) {
|
||||
data.push({key: key, value: value });
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (ex) {
|
||||
Ext.Error.raise({
|
||||
response: response,
|
||||
json: response.responseText,
|
||||
parseError: ex,
|
||||
msg: 'Unable to parse the JSON returned by the server: ' + ex.toString()
|
||||
});
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user