initial import

copied from pve-manager, remove pve-manager specific code and
rename 'pve' to 'proxmox'.
This commit is contained in:
Dietmar Maurer 2017-01-30 09:45:41 +01:00
commit 0bb29d3556
8 changed files with 1080 additions and 0 deletions

226
Utils.js Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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;
}
});